summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/auto/android/runtests_androiddeployqt.pl550
-rw-r--r--tests/auto/cmake/CMakeLists.txt2
-rw-r--r--tests/auto/cmake/cmake.pro7
-rw-r--r--tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.json1
-rw-r--r--tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.pro9
-rw-r--r--tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.cpp10
-rw-r--r--tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.h70
-rw-r--r--tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.json1
-rw-r--r--tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.pro10
-rw-r--r--tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.cpp10
-rw-r--r--tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.h70
-rw-r--r--tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.json1
-rw-r--r--tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.pro10
-rw-r--r--tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.cpp10
-rw-r--r--tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.h70
-rw-r--r--tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.json1
-rw-r--r--tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.pro10
-rw-r--r--tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.cpp10
-rw-r--r--tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.h70
-rw-r--r--tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.json1
-rw-r--r--tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.pro10
-rw-r--r--tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.cpp10
-rw-r--r--tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.h70
-rw-r--r--tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.json1
-rw-r--r--tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.pro9
-rw-r--r--tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.cpp10
-rw-r--r--tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.h70
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins.pro36
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins1/fake.cpp34
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins1/mockplugins1.pro10
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins1/qmockplugin.h72
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins2/fake.cpp34
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins2/mockplugins2.pro4
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins3/fake.cpp34
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins3/mockplugins3.pro11
-rw-r--r--tests/auto/cmake/mockplugins/mockplugins3/qmockauxplugin.h72
-rw-r--r--tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt3
-rw-r--r--tests/auto/cmake/test_import_plugins/CMakeLists.txt111
-rw-r--r--tests/auto/cmake/test_import_plugins/check.cpp.in8
-rw-r--r--tests/auto/cmake/test_import_plugins/main.cpp101
-rw-r--r--tests/auto/cmake/test_interface/CMakeLists.txt3
-rw-r--r--tests/auto/cmake/test_moc_macro_target/CMakeLists.txt4
-rw-r--r--tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro1
-rw-r--r--tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp24
-rw-r--r--tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro1
-rw-r--r--tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp57
-rw-r--r--tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp40
-rw-r--r--tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp11
-rw-r--r--tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST1
-rw-r--r--tests/auto/corelib/animation/qpauseanimation/BLACKLIST5
-rw-r--r--tests/auto/corelib/animation/qpropertyanimation/BLACKLIST6
-rw-r--r--tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST8
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp2
-rw-r--r--tests/auto/corelib/corelib.pro2
-rw-r--r--tests/auto/corelib/global/qflags/tst_qflags.cpp11
-rw-r--r--tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp161
-rw-r--r--tests/auto/corelib/global/qglobal/qglobal.c2
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp4
-rw-r--r--tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp18
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.cpp28
-rw-r--r--tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp65
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp4
-rw-r--r--tests/auto/corelib/io/largefile/tst_largefile.cpp6
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp10
-rw-r--r--tests/auto/corelib/io/qdir/tst_qdir.cpp32
-rw-r--r--tests/auto/corelib/io/qfile/BLACKLIST7
-rw-r--r--tests/auto/corelib/io/qfile/test.pro2
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp4
-rw-r--r--tests/auto/corelib/io/qfileinfo/qfileinfo.pro2
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp201
-rw-r--r--tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST3
-rw-r--r--tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp12
-rw-r--r--tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp2
-rw-r--r--tests/auto/corelib/io/qlockfile/tst_qlockfile.pro2
-rw-r--r--tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp6
-rw-r--r--tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp2
-rw-r--r--tests/auto/corelib/io/qprocess/BLACKLIST7
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro2
-rw-r--r--tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro2
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp256
-rw-r--r--tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp70
-rw-r--r--tests/auto/corelib/io/qsettings/qsettings.pro2
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp11
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp14
-rw-r--r--tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp2
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp144
-rw-r--r--tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp18
-rw-r--r--tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp20
-rw-r--r--tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp2
-rw-r--r--tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp95
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp32
-rw-r--r--tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp2
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp24
-rw-r--r--tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST3
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST6
-rw-r--r--tests/auto/corelib/kernel/qeventloop/BLACKLIST2
-rw-r--r--tests/auto/corelib/kernel/qeventloop/qeventloop.pro2
-rw-r--r--tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp6
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp16
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp6
-rw-r--r--tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp6
-rw-r--r--tests/auto/corelib/kernel/qmetatype/qmetatype.pro1
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp28
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h2
-rw-r--r--tests/auto/corelib/kernel/qobject/BLACKLIST2
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp316
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp3
-rw-r--r--tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp5
-rw-r--r--tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST4
-rw-r--r--tests/auto/corelib/kernel/qtimer/BLACKLIST5
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp147
-rw-r--r--tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp2
-rw-r--r--tests/auto/corelib/kernel/qvariant/qvariant.pro1
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp551
-rw-r--r--tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp4
-rw-r--r--tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp8
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp2
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp1
-rw-r--r--tests/auto/corelib/serialization/json/tst_qtjson.cpp70
-rw-r--r--tests/auto/corelib/serialization/qdatastream/qdatastream.pro2
-rw-r--r--tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp168
-rw-r--r--tests/auto/corelib/serialization/qtextstream/BLACKLIST2
-rw-r--r--tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp2
-rw-r--r--tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp118
-rw-r--r--tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp30
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp26
-rw-r--r--tests/auto/corelib/text/qbytearray/.gitattributes (renamed from tests/auto/corelib/tools/qbytearray/.gitattributes)0
-rw-r--r--tests/auto/corelib/text/qbytearray/.gitignore (renamed from tests/auto/corelib/tools/qbytearray/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qbytearray/android_testdata.qrc (renamed from tests/auto/corelib/tools/qbytearray/android_testdata.qrc)0
-rw-r--r--tests/auto/corelib/text/qbytearray/qbytearray.pro (renamed from tests/auto/corelib/tools/qbytearray/qbytearray.pro)0
-rw-r--r--tests/auto/corelib/text/qbytearray/rfc3252.txt (renamed from tests/auto/corelib/tools/qbytearray/rfc3252.txt)0
-rw-r--r--tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp (renamed from tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp)35
-rw-r--r--tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm (renamed from tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm)0
-rw-r--r--tests/auto/corelib/text/qbytearraylist/qbytearraylist.pro (renamed from tests/auto/corelib/tools/qbytearraylist/qbytearraylist.pro)0
-rw-r--r--tests/auto/corelib/text/qbytearraylist/tst_qbytearraylist.cpp (renamed from tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp)14
-rw-r--r--tests/auto/corelib/text/qbytearraymatcher/qbytearraymatcher.pro (renamed from tests/auto/corelib/tools/qbytearraymatcher/qbytearraymatcher.pro)0
-rw-r--r--tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp (renamed from tests/auto/corelib/tools/qbytearraymatcher/tst_qbytearraymatcher.cpp)0
-rw-r--r--tests/auto/corelib/text/qbytedatabuffer/.gitignore (renamed from tests/auto/corelib/tools/qbytedatabuffer/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qbytedatabuffer/qbytedatabuffer.pro (renamed from tests/auto/corelib/tools/qbytedatabuffer/qbytedatabuffer.pro)0
-rw-r--r--tests/auto/corelib/text/qbytedatabuffer/tst_qbytedatabuffer.cpp (renamed from tests/auto/corelib/tools/qbytedatabuffer/tst_qbytedatabuffer.cpp)0
-rw-r--r--tests/auto/corelib/text/qchar/.gitignore (renamed from tests/auto/corelib/tools/qchar/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qchar/data/NormalizationTest.txt (renamed from tests/auto/corelib/tools/qchar/data/NormalizationTest.txt)0
-rw-r--r--tests/auto/corelib/text/qchar/qchar.pro (renamed from tests/auto/corelib/tools/qchar/qchar.pro)0
-rw-r--r--tests/auto/corelib/text/qchar/testdata.qrc (renamed from tests/auto/corelib/tools/qchar/testdata.qrc)0
-rw-r--r--tests/auto/corelib/text/qchar/tst_qchar.cpp (renamed from tests/auto/corelib/tools/qchar/tst_qchar.cpp)0
-rw-r--r--tests/auto/corelib/text/qcollator/qcollator.pro (renamed from tests/auto/corelib/tools/qcollator/qcollator.pro)0
-rw-r--r--tests/auto/corelib/text/qcollator/tst_qcollator.cpp (renamed from tests/auto/corelib/tools/qcollator/tst_qcollator.cpp)6
-rw-r--r--tests/auto/corelib/text/qlatin1string/.gitignore (renamed from tests/auto/corelib/tools/qlatin1string/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qlatin1string/qlatin1string.pro (renamed from tests/auto/corelib/tools/qlatin1string/qlatin1string.pro)0
-rw-r--r--tests/auto/corelib/text/qlatin1string/tst_qlatin1string.cpp (renamed from tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp)42
-rw-r--r--tests/auto/corelib/text/qlocale/.gitignore (renamed from tests/auto/corelib/tools/qlocale/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qlocale/qlocale.pro (renamed from tests/auto/corelib/tools/qlocale/qlocale.pro)0
-rw-r--r--tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.cpp (renamed from tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.cpp)0
-rw-r--r--tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.pro (renamed from tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro)0
-rw-r--r--tests/auto/corelib/text/qlocale/test/test.pro (renamed from tests/auto/corelib/tools/qlocale/test/test.pro)0
-rw-r--r--tests/auto/corelib/text/qlocale/tst_qlocale.cpp (renamed from tests/auto/corelib/tools/qlocale/tst_qlocale.cpp)7
-rw-r--r--tests/auto/corelib/text/qregexp/.gitignore (renamed from tests/auto/corelib/tools/qregexp/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qregexp/qregexp.pro (renamed from tests/auto/corelib/tools/qregexp/qregexp.pro)0
-rw-r--r--tests/auto/corelib/text/qregexp/tst_qregexp.cpp (renamed from tests/auto/corelib/tools/qregexp/tst_qregexp.cpp)0
-rw-r--r--tests/auto/corelib/text/qregularexpression/.gitignore (renamed from tests/auto/corelib/tools/qregularexpression/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qregularexpression/qregularexpression.pro (renamed from tests/auto/corelib/tools/qregularexpression/qregularexpression.pro)0
-rw-r--r--tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp (renamed from tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp)0
-rw-r--r--tests/auto/corelib/text/qstring/.gitignore (renamed from tests/auto/corelib/tools/qstring/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qstring/double_data.h (renamed from tests/auto/corelib/tools/qstring/double_data.h)0
-rw-r--r--tests/auto/corelib/text/qstring/qstring.pro (renamed from tests/auto/corelib/tools/qstring/qstring.pro)0
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp (renamed from tests/auto/corelib/tools/qstring/tst_qstring.cpp)168
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring_mac.mm (renamed from tests/auto/corelib/tools/qstring/tst_qstring_mac.mm)0
-rw-r--r--tests/auto/corelib/text/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro (renamed from tests/auto/corelib/tools/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro)0
-rw-r--r--tests/auto/corelib/text/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp (renamed from tests/auto/corelib/tools/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/.gitignore (renamed from tests/auto/corelib/tools/qstringapisymmetry/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/qstringapisymmetry.pro (renamed from tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro)0
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp (renamed from tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp)564
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder.pro (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder.pro)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder1/qstringbuilder1.pro (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/qstringbuilder1.pro)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder2/qstringbuilder2.pro (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/qstringbuilder2.pro)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder3/qstringbuilder3.pro (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/qstringbuilder3.pro)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder4/qstringbuilder4.pro (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/qstringbuilder4.pro)0
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp (renamed from tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringiterator/qstringiterator.pro (renamed from tests/auto/corelib/tools/qstringiterator/qstringiterator.pro)0
-rw-r--r--tests/auto/corelib/text/qstringiterator/tst_qstringiterator.cpp (renamed from tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp)0
-rw-r--r--tests/auto/corelib/text/qstringlist/.gitignore (renamed from tests/auto/corelib/tools/qstringlist/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qstringlist/qstringlist.pro (renamed from tests/auto/corelib/tools/qstringlist/qstringlist.pro)0
-rw-r--r--tests/auto/corelib/text/qstringlist/tst_qstringlist.cpp (renamed from tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp)59
-rw-r--r--tests/auto/corelib/text/qstringmatcher/.gitignore (renamed from tests/auto/corelib/tools/qstringmatcher/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qstringmatcher/qstringmatcher.pro (renamed from tests/auto/corelib/tools/qstringmatcher/qstringmatcher.pro)0
-rw-r--r--tests/auto/corelib/text/qstringmatcher/tst_qstringmatcher.cpp (renamed from tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp)6
-rw-r--r--tests/auto/corelib/text/qstringref/qstringref.pro (renamed from tests/auto/corelib/tools/qstringref/qstringref.pro)0
-rw-r--r--tests/auto/corelib/text/qstringref/tst_qstringref.cpp (renamed from tests/auto/corelib/tools/qstringref/tst_qstringref.cpp)24
-rw-r--r--tests/auto/corelib/text/qstringview/.gitignore (renamed from tests/auto/corelib/tools/qstringview/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qstringview/qstringview.pro (renamed from tests/auto/corelib/tools/qstringview/qstringview.pro)0
-rw-r--r--tests/auto/corelib/text/qstringview/tst_qstringview.cpp (renamed from tests/auto/corelib/tools/qstringview/tst_qstringview.cpp)53
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/.gitignore (renamed from tests/auto/corelib/tools/qtextboundaryfinder/.gitignore)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/data/GraphemeBreakTest.txt (renamed from tests/auto/corelib/tools/qtextboundaryfinder/data/GraphemeBreakTest.txt)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/data/LineBreakTest.txt (renamed from tests/auto/corelib/tools/qtextboundaryfinder/data/LineBreakTest.txt)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/data/SentenceBreakTest.txt (renamed from tests/auto/corelib/tools/qtextboundaryfinder/data/SentenceBreakTest.txt)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/data/WordBreakTest.txt (renamed from tests/auto/corelib/tools/qtextboundaryfinder/data/WordBreakTest.txt)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/qtextboundaryfinder.pro (renamed from tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/testdata.qrc (renamed from tests/auto/corelib/tools/qtextboundaryfinder/testdata.qrc)0
-rw-r--r--tests/auto/corelib/text/qtextboundaryfinder/tst_qtextboundaryfinder.cpp (renamed from tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp)2
-rw-r--r--tests/auto/corelib/text/text.pro23
-rw-r--r--tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp53
-rw-r--r--tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp202
-rw-r--r--tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp176
-rw-r--r--tests/auto/corelib/thread/qfuture/qfuture.pro1
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp67
-rw-r--r--tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp3
-rw-r--r--tests/auto/corelib/thread/qmutex/tst_qmutex.cpp33
-rw-r--r--tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp6
-rw-r--r--tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp27
-rw-r--r--tests/auto/corelib/thread/qsemaphore/BLACKLIST2
-rw-r--r--tests/auto/corelib/thread/qthread/BLACKLIST5
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp54
-rw-r--r--tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp2
-rw-r--r--tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp8
-rw-r--r--tests/auto/corelib/thread/qthreadpool/BLACKLIST5
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp89
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp12
-rw-r--r--tests/auto/corelib/thread/qwaitcondition/BLACKLIST2
-rw-r--r--tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp32
-rw-r--r--tests/auto/corelib/time/qcalendar/qcalendar.pro5
-rw-r--r--tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp236
-rw-r--r--tests/auto/corelib/time/qdate/.gitignore (renamed from tests/auto/corelib/tools/qdate/.gitignore)0
-rw-r--r--tests/auto/corelib/time/qdate/qdate.pro (renamed from tests/auto/corelib/tools/qdate/qdate.pro)2
-rw-r--r--tests/auto/corelib/time/qdate/tst_qdate.cpp (renamed from tests/auto/corelib/tools/qdate/tst_qdate.cpp)200
-rw-r--r--tests/auto/corelib/time/qdatetime/.gitignore (renamed from tests/auto/corelib/tools/qdatetime/.gitignore)0
-rw-r--r--tests/auto/corelib/time/qdatetime/qdatetime.pro (renamed from tests/auto/corelib/tools/qdatetime/qdatetime.pro)0
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp (renamed from tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp)61
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm (renamed from tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm)0
-rw-r--r--tests/auto/corelib/time/qtime/.gitignore (renamed from tests/auto/corelib/tools/qtime/.gitignore)0
-rw-r--r--tests/auto/corelib/time/qtime/qtime.pro (renamed from tests/auto/corelib/tools/qtime/qtime.pro)0
-rw-r--r--tests/auto/corelib/time/qtime/tst_qtime.cpp (renamed from tests/auto/corelib/tools/qtime/tst_qtime.cpp)5
-rw-r--r--tests/auto/corelib/time/qtimezone/BLACKLIST (renamed from tests/auto/corelib/tools/qtimezone/BLACKLIST)0
-rw-r--r--tests/auto/corelib/time/qtimezone/qtimezone.pro (renamed from tests/auto/corelib/tools/qtimezone/qtimezone.pro)0
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp (renamed from tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp)11
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm (renamed from tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm)0
-rw-r--r--tests/auto/corelib/time/time.pro7
-rw-r--r--tests/auto/corelib/tools/collections/collections.pro2
-rw-r--r--tests/auto/corelib/tools/collections/tst_collections.cpp124
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro1
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp723
-rw-r--r--tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp65
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp58
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp2
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp79
-rw-r--r--tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp4
-rw-r--r--tests/auto/corelib/tools/qdatetime/BLACKLIST2
-rw-r--r--tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp39
-rw-r--r--tests/auto/corelib/tools/qhash/qhash.pro2
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp6
-rw-r--r--tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp36
-rw-r--r--tests/auto/corelib/tools/qline/tst_qline.cpp9
-rw-r--r--tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro3
-rw-r--r--tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp30
-rw-r--r--tests/auto/corelib/tools/qlist/qlist.pro2
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp40
-rw-r--r--tests/auto/corelib/tools/qlocale/BLACKLIST2
-rw-r--r--tests/auto/corelib/tools/qmap/qmap.pro2
-rw-r--r--tests/auto/corelib/tools/qmap/tst_qmap.cpp4
-rw-r--r--tests/auto/corelib/tools/qpair/qpair.pro3
-rw-r--r--tests/auto/corelib/tools/qpair/tst_qpair.cpp26
-rw-r--r--tests/auto/corelib/tools/qpoint/tst_qpoint.cpp7
-rw-r--r--tests/auto/corelib/tools/qpointf/tst_qpointf.cpp7
-rw-r--r--tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp42
-rw-r--r--tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp13
-rw-r--r--tests/auto/corelib/tools/qset/qset.pro4
-rw-r--r--tests/auto/corelib/tools/qset/tst_qset.cpp40
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp265
-rw-r--r--tests/auto/corelib/tools/qsize/tst_qsize.cpp44
-rw-r--r--tests/auto/corelib/tools/qsizef/tst_qsizef.cpp44
-rw-r--r--tests/auto/corelib/tools/qtimeline/BLACKLIST8
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/qvarlengtharray.pro2
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp77
-rw-r--r--tests/auto/corelib/tools/qvector/qvector.pro2
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp101
-rw-r--r--tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp19
-rw-r--r--tests/auto/corelib/tools/tools.pro25
-rw-r--r--tests/auto/dbus/qdbusabstractadaptor/qdbusabstractadaptor/BLACKLIST0
-rw-r--r--tests/auto/dbus/qdbusconnection_spyhook/BLACKLIST0
-rw-r--r--tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp4
-rw-r--r--tests/auto/gui/gui.pro1
-rw-r--r--tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp8
-rw-r--r--tests/auto/gui/image/qimage/qimage.pro2
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp30
-rw-r--r--tests/auto/gui/image/qimagereader/tst_qimagereader.cpp39
-rw-r--r--tests/auto/gui/image/qpixmap/qpixmap.pro2
-rw-r--r--tests/auto/gui/image/qpixmap/tst_qpixmap.cpp13
-rw-r--r--tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp44
-rw-r--r--tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp2
-rw-r--r--tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp10
-rw-r--r--tests/auto/gui/kernel/noqteventloop/noqteventloop.pro2
-rw-r--r--tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp36
-rw-r--r--tests/auto/gui/kernel/qdrag/tst_qdrag.cpp9
-rw-r--r--tests/auto/gui/kernel/qguiapplication/BLACKLIST5
-rw-r--r--tests/auto/gui/kernel/qguiapplication/qguiapplication.pro1
-rw-r--r--tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp54
-rw-r--r--tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST4
-rw-r--r--tests/auto/gui/kernel/qguieventloop/BLACKLIST2
-rw-r--r--tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp2
-rw-r--r--tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp4
-rw-r--r--tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp2
-rw-r--r--tests/auto/gui/kernel/qpalette/tst_qpalette.cpp8
-rw-r--r--tests/auto/gui/kernel/qtouchevent/BLACKLIST6
-rw-r--r--tests/auto/gui/kernel/qwindow/BLACKLIST28
-rw-r--r--tests/auto/gui/kernel/qwindow/qwindow.pro2
-rw-r--r--tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp4
-rw-r--r--tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp3
-rw-r--r--tests/auto/gui/painting/painting.pro1
-rw-r--r--tests/auto/gui/painting/qbrush/tst_qbrush.cpp6
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp469
-rw-r--r--tests/auto/gui/painting/qcolorspace/qcolorspace.pro9
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.iccbin0 -> 1856 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpgbin0 -> 30900 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/sRGB2014.iccbin0 -> 3024 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp448
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp94
-rw-r--r--tests/auto/gui/painting/qpathclipper/paths.cpp2
-rw-r--r--tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp13
-rw-r--r--tests/auto/gui/painting/qpen/tst_qpen.cpp8
-rw-r--r--tests/auto/gui/painting/qregion/tst_qregion.cpp24
-rw-r--r--tests/auto/gui/qopengl/BLACKLIST8
-rw-r--r--tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp6
-rw-r--r--tests/auto/gui/rhi/qrhi/data/texture.frag12
-rw-r--r--tests/auto/gui/rhi/qrhi/data/texture.vert18
-rw-r--r--tests/auto/gui/rhi/qrhi/qrhi.pro8
-rw-r--r--tests/auto/gui/rhi/qrhi/qrhi.qrc5
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp246
-rw-r--r--tests/auto/gui/rhi/qshader/data/color.vert18
-rw-r--r--tests/auto/gui/rhi/qshader/data/color.vert.qsbbin0 -> 1847 bytes
-rw-r--r--tests/auto/gui/rhi/qshader/data/color_simple.vert.qsbbin0 -> 813 bytes
-rw-r--r--tests/auto/gui/rhi/qshader/qshader.pro8
-rw-r--r--tests/auto/gui/rhi/qshader/qshader.qrc5
-rw-r--r--tests/auto/gui/rhi/qshader/tst_qshader.cpp233
-rw-r--r--tests/auto/gui/rhi/rhi.pro4
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp29
-rw-r--r--tests/auto/gui/text/qfont/BLACKLIST2
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp22
-rw-r--r--tests/auto/gui/text/qfontcache/tst_qfontcache.cpp2
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp4
-rw-r--r--tests/auto/gui/text/qglyphrun/BLACKLIST1
-rw-r--r--tests/auto/gui/text/qstatictext/tst_qstatictext.cpp2
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp29
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp153
-rw-r--r--tests/auto/gui/text/qtextdocumentlayout/BLACKLIST4
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp35
-rw-r--r--tests/auto/gui/text/qtextlist/tst_qtextlist.cpp2
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md28
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md17
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro9
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp163
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST2
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md62
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/example.md95
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md12
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md13
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro9
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp464
-rw-r--r--tests/auto/gui/text/qtexttable/qtexttable.pro2
-rw-r--r--tests/auto/gui/text/qtexttable/tst_qtexttable.cpp150
-rw-r--r--tests/auto/gui/text/text.pro4
-rw-r--r--tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp4
-rw-r--r--tests/auto/network-settings.h76
-rw-r--r--tests/auto/network/access/http2/http2srv.cpp10
-rw-r--r--tests/auto/network/access/http2/http2srv.h12
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp138
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/BLACKLIST2
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro2
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp7
-rw-r--r--tests/auto/network/access/qftp/BLACKLIST6
-rw-r--r--tests/auto/network/access/qftp/qftp.pro3
-rw-r--r--tests/auto/network/access/qftp/tst_qftp.cpp178
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro3
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp76
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp9
-rw-r--r--tests/auto/network/access/qnetworkreply/BLACKLIST133
-rw-r--r--tests/auto/network/access/qnetworkreply/test/test.pro2
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp259
-rw-r--r--tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp7
-rw-r--r--tests/auto/network/access/spdy/BLACKLIST7
-rw-r--r--tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp8
-rw-r--r--tests/auto/network/kernel/qdnslookup/BLACKLIST2
-rw-r--r--tests/auto/network/kernel/qhostaddress/qhostaddress.pro2
-rw-r--r--tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp3
-rw-r--r--tests/auto/network/kernel/qhostinfo/qhostinfo.pro2
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp3
-rw-r--r--tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp2
-rw-r--r--tests/auto/network/socket/platformsocketengine/BLACKLIST10
-rw-r--r--tests/auto/network/socket/platformsocketengine/platformsocketengine.pri2
-rw-r--r--tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp6
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/BLACKLIST4
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro5
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp49
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp7
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/BLACKLIST11
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro6
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp42
-rw-r--r--tests/auto/network/socket/qtcpserver/BLACKLIST17
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/main.cpp4
-rw-r--r--tests/auto/network/socket/qtcpserver/test/test.pro8
-rw-r--r--tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp48
-rw-r--r--tests/auto/network/socket/qtcpsocket/BLACKLIST10
-rw-r--r--tests/auto/network/socket/qtcpsocket/test/test.pro8
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp186
-rw-r--r--tests/auto/network/socket/qudpsocket/BLACKLIST26
-rw-r--r--tests/auto/network/socket/qudpsocket/clientserver/main.cpp2
-rw-r--r--tests/auto/network/socket/qudpsocket/test/test.pro6
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp22
-rw-r--r--tests/auto/network/ssl/qsslcertificate/BLACKLIST12
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp10
-rw-r--r--tests/auto/network/ssl/qsslkey/BLACKLIST9
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem30
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem30
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem30
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp150
-rw-r--r--tests/auto/network/ssl/qsslsocket/BLACKLIST6
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem16
-rw-r--r--tests/auto/network/ssl/qsslsocket/qsslsocket.pro7
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp441
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro6
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp51
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro6
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp24
-rw-r--r--tests/auto/opengl/qgl/BLACKLIST31
-rw-r--r--tests/auto/opengl/qgl/tst_qgl.cpp7
-rw-r--r--tests/auto/opengl/qglthreads/tst_qglthreads.cpp22
-rw-r--r--tests/auto/other/compiler/tst_compiler.cpp2
-rw-r--r--tests/auto/other/gestures/BLACKLIST14
-rw-r--r--tests/auto/other/lancelot/paintcommands.cpp13
-rw-r--r--tests/auto/other/networkselftest/BLACKLIST5
-rw-r--r--tests/auto/other/networkselftest/tst_networkselftest.cpp5
-rw-r--r--tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp19
-rw-r--r--tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h2
-rw-r--r--tests/auto/other/qaccessibility/qaccessibility.pro3
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp1
-rw-r--r--tests/auto/other/qaccessibilitymac/BLACKLIST2
-rw-r--r--tests/auto/other/qfocusevent/BLACKLIST6
-rw-r--r--tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST2
-rw-r--r--tests/auto/other/qobjectrace/tst_qobjectrace.cpp20
-rw-r--r--tests/auto/other/toolsupport/tst_toolsupport.cpp10
-rw-r--r--tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp8
-rw-r--r--tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp37
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_databases.h13
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp4
-rw-r--r--tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp87
-rw-r--r--tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp2
-rw-r--r--tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp7
-rw-r--r--tests/auto/testlib/initmain/initmain.pro5
-rw-r--r--tests/auto/testlib/initmain/tst_initmain.cpp56
-rw-r--r--tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp2
-rw-r--r--tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp52
-rw-r--r--tests/auto/testlib/selftests/alive/.gitignore1
-rw-r--r--tests/auto/testlib/selftests/alive/alive.pro10
-rw-r--r--tests/auto/testlib/selftests/alive/qtestalive.cpp147
-rw-r--r--tests/auto/testlib/selftests/alive/tst_alive.cpp84
-rw-r--r--tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp21
-rw-r--r--tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp8
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.lightxml12
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.tap142
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.teamcity6
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.txt10
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.xml12
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.xunitxml8
-rw-r--r--tests/auto/testlib/selftests/expected_crashes_5.txt5
-rw-r--r--tests/auto/testlib/selftests/expected_float.lightxml197
-rw-r--r--tests/auto/testlib/selftests/expected_float.tap641
-rw-r--r--tests/auto/testlib/selftests/expected_float.teamcity106
-rw-r--r--tests/auto/testlib/selftests/expected_float.txt125
-rw-r--r--tests/auto/testlib/selftests/expected_float.xml197
-rw-r--r--tests/auto/testlib/selftests/expected_float.xunitxml86
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.lightxml155
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.tap77
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.teamcity47
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.txt94
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.xml155
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.xunitxml128
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.lightxml578
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.tap151
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.teamcity61
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.txt149
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.xml581
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.xunitxml284
-rw-r--r--tests/auto/testlib/selftests/float/tst_float.cpp187
-rwxr-xr-xtests/auto/testlib/selftests/generate_expected_output.py12
-rw-r--r--tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp44
-rw-r--r--tests/auto/testlib/selftests/selftests.pri2
-rw-r--r--tests/auto/testlib/selftests/signaldumper/signaldumper.pro9
-rw-r--r--tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp417
-rw-r--r--tests/auto/testlib/selftests/silent/tst_silent.cpp21
-rw-r--r--tests/auto/testlib/selftests/sleep/tst_sleep.cpp3
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp28
-rw-r--r--tests/auto/testlib/testlib.pro1
-rw-r--r--tests/auto/testserver.pri216
-rw-r--r--tests/auto/tools/moc/cxx-attributes.h103
-rw-r--r--tests/auto/tools/moc/cxx11-enums.h18
-rw-r--r--tests/auto/tools/moc/moc.pro3
-rw-r--r--tests/auto/tools/moc/parse-defines.h11
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp83
-rw-r--r--tests/auto/tools/qmake/testcompiler.cpp18
-rw-r--r--tests/auto/tools/qmake/testcompiler.h8
-rw-r--r--tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro5
-rw-r--r--tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp4
-rw-r--r--tests/auto/tools/qmake/testdata/windows_resources/inter.inc1
-rw-r--r--tests/auto/tools/qmake/testdata/windows_resources/main.cpp1
-rw-r--r--tests/auto/tools/qmake/testdata/windows_resources/version.inc28
-rw-r--r--tests/auto/tools/qmake/testdata/windows_resources/windows_resources.pro4
-rw-r--r--tests/auto/tools/qmake/testdata/windows_resources/windows_resources.rc2
-rw-r--r--tests/auto/tools/qmake/tst_qmake.cpp53
-rw-r--r--tests/auto/tools/qmakelib/qmakelib.pro2
-rw-r--r--tests/auto/tools/rcc/data/depfile/simple.d.expected1
-rw-r--r--tests/auto/tools/rcc/data/depfile/simple.qrc6
-rw-r--r--tests/auto/tools/rcc/data/depfile/specialchar$file.txt1
-rw-r--r--tests/auto/tools/rcc/data/depfile/specialchar.d.expected1
-rw-r--r--tests/auto/tools/rcc/data/depfile/specialchar.qrc6
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected68
-rw-r--r--tests/auto/tools/rcc/tst_rcc.cpp278
-rw-r--r--tests/auto/tools/uic/baseline/dialog.ui2
-rw-r--r--tests/auto/tools/uic/baseline/dialog.ui.h2
-rw-r--r--tests/auto/tools/uic/baseline/qfiledialog.ui.h2
-rw-r--r--tests/auto/tools/uic/tst_uic.cpp166
-rw-r--r--tests/auto/widgets/dialogs/qdialog/BLACKLIST2
-rw-r--r--tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp43
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp13
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST4
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp16
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST11
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp369
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/BLACKLIST4
-rw-r--r--tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST2
-rw-r--r--tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp4
-rw-r--r--tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp4
-rw-r--r--tests/auto/widgets/effects/qgraphicseffect/BLACKLIST3
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp19
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp16
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST10
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp744
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST20
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp35
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp3
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/BLACKLIST2
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/BLACKLIST1
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp17
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro2
-rw-r--r--tests/auto/widgets/itemviews/qlistview/qlistview.pro2
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp6
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp4
-rw-r--r--tests/auto/widgets/itemviews/qtableview/BLACKLIST3
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp45
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp415
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp4
-rw-r--r--tests/auto/widgets/kernel/kernel.pro2
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp60
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp81
-rw-r--r--tests/auto/widgets/kernel/qapplication/BLACKLIST1
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp8
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp70
-rw-r--r--tests/auto/widgets/kernel/qformlayout/qformlayout.pro2
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp21
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp12
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp4
-rw-r--r--tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp750
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST34
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp64
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/BLACKLIST4
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/button.pngbin1785 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/combobox.pngbin1808 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/lineedit.pngbin953 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/mdi.pngbin3092 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/menu.pngbin1139 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/radiobutton.pngbin1498 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/slider.pngbin1074 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/mac/spinbox.pngbin1299 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/button.pngbin722 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/combobox.pngbin809 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/lineedit.pngbin530 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/menu.pngbin646 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/radiobutton.pngbin844 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/slider.pngbin575 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/images/vista/spinbox.pngbin583 -> 0 bytes
-rw-r--r--tests/auto/widgets/styles/qstyle/qstyle.pro5
-rw-r--r--tests/auto/widgets/styles/qstyle/testdata.qrc19
-rw-r--r--tests/auto/widgets/styles/qstyle/tst_qstyle.cpp124
-rw-r--r--tests/auto/widgets/util/qcompleter/BLACKLIST6
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp10
-rw-r--r--tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp32
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp27
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp46
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp6
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST4
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp26
-rw-r--r--tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp2
-rw-r--r--tests/auto/widgets/widgets/qframe/tst_qframe.cpp4
-rw-r--r--tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp2
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp20
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/BLACKLIST19
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp6
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp9
-rw-r--r--tests/auto/widgets/widgets/qmenu/BLACKLIST12
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp21
-rw-r--r--tests/auto/widgets/widgets/qmenubar/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp3
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/BLACKLIST6
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp3
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp5
-rw-r--r--tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp4
-rw-r--r--tests/auto/widgets/widgets/qscrollbar/BLACKLIST3
-rw-r--r--tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp7
-rw-r--r--tests/auto/widgets/widgets/qspinbox/BLACKLIST3
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp32
-rw-r--r--tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp2
-rw-r--r--tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro2
-rw-r--r--tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp4
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/heading.html2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/markdown.md2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/markdown.really2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/quotesAndFractions.md1
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp92
-rw-r--r--tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp37
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/BLACKLIST2
-rw-r--r--tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp3
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp4
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp12
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak5
-rw-r--r--tests/baselineserver/shared/baselineprotocol.cpp4
-rw-r--r--tests/benchmarks/corelib/corelib.pro2
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/main.cpp24
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp5
-rw-r--r--tests/benchmarks/corelib/kernel/kernel.pro3
-rw-r--r--tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp88
-rw-r--r--tests/benchmarks/corelib/text/qbytearray/main.cpp (renamed from tests/benchmarks/corelib/tools/qbytearray/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/text/qbytearray/qbytearray.pro (renamed from tests/benchmarks/corelib/tools/qbytearray/qbytearray.pro)0
-rw-r--r--tests/benchmarks/corelib/text/qchar/main.cpp (renamed from tests/benchmarks/corelib/tools/qchar/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/text/qchar/qchar.pro (renamed from tests/benchmarks/corelib/tools/qchar/qchar.pro)0
-rw-r--r--tests/benchmarks/corelib/text/qlocale/main.cpp (renamed from tests/benchmarks/corelib/tools/qlocale/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/text/qlocale/qlocale.pro (renamed from tests/benchmarks/corelib/tools/qlocale/qlocale.pro)0
-rw-r--r--tests/benchmarks/corelib/text/qregexp/main.cpp (renamed from tests/benchmarks/corelib/tools/qregexp/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/text/qregexp/qregexp.pro (renamed from tests/benchmarks/corelib/tools/qregexp/qregexp.pro)0
-rw-r--r--tests/benchmarks/corelib/text/qregexp/qregexp.qrc (renamed from tests/benchmarks/corelib/tools/qregexp/qregexp.qrc)0
-rw-r--r--tests/benchmarks/corelib/text/qstring/main.cpp (renamed from tests/benchmarks/corelib/tools/qstring/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/text/qstring/qstring.pro (renamed from tests/benchmarks/corelib/tools/qstring/qstring.pro)0
-rw-r--r--tests/benchmarks/corelib/text/qstringbuilder/main.cpp (renamed from tests/benchmarks/corelib/tools/qstringbuilder/main.cpp)2
-rw-r--r--tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro (renamed from tests/benchmarks/corelib/tools/qstringbuilder/qstringbuilder.pro)0
-rw-r--r--tests/benchmarks/corelib/text/qstringlist/.gitignore (renamed from tests/benchmarks/corelib/tools/qstringlist/.gitignore)0
-rw-r--r--tests/benchmarks/corelib/text/qstringlist/main.cpp (renamed from tests/benchmarks/corelib/tools/qstringlist/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/text/qstringlist/qstringlist.pro (renamed from tests/benchmarks/corelib/tools/qstringlist/qstringlist.pro)0
-rw-r--r--tests/benchmarks/corelib/text/text.pro9
-rw-r--r--tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro3
-rw-r--r--tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp91
-rw-r--r--tests/benchmarks/corelib/time/qdate/qdate.pro4
-rw-r--r--tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp213
-rw-r--r--tests/benchmarks/corelib/time/qdatetime/main.cpp574
-rw-r--r--tests/benchmarks/corelib/time/qdatetime/qdatetime.pro (renamed from tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro)0
-rw-r--r--tests/benchmarks/corelib/time/qtimezone/main.cpp (renamed from tests/benchmarks/corelib/tools/qtimezone/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/time/qtimezone/qtimezone.pro (renamed from tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro)0
-rw-r--r--tests/benchmarks/corelib/time/time.pro5
-rw-r--r--tests/benchmarks/corelib/tools/qdatetime/main.cpp604
-rw-r--r--tests/benchmarks/corelib/tools/qhash/paths_small_data.txt56
-rw-r--r--tests/benchmarks/corelib/tools/qvector/qrawvector.h7
-rw-r--r--tests/benchmarks/corelib/tools/tools.pro9
-rw-r--r--tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp28
-rw-r--r--tests/benchmarks/gui/image/qimagereader/qimagereader.pro2
-rw-r--r--tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp17
-rw-r--r--tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp4
-rw-r--r--tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp12
-rw-r--r--tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp2
-rw-r--r--tests/benchmarks/opengl/main.cpp5
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp1
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp2
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp2
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp2
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp5
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp12
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp5
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp6
-rw-r--r--tests/libfuzzer/gui/iccparser/iccparser.pro3
-rw-r--r--tests/libfuzzer/gui/iccparser/main.cpp37
-rw-r--r--tests/manual/diaglib/diaglib.pri2
-rw-r--r--tests/manual/diaglib/textdump.cpp3
-rw-r--r--tests/manual/highdpi/dragwidget.cpp2
-rw-r--r--tests/manual/highdpi/highdpi.pro1
-rw-r--r--tests/manual/highdpi/main.cpp89
-rw-r--r--tests/manual/keypadnavigation/main.cpp37
-rw-r--r--tests/manual/lance/main.cpp13
-rw-r--r--tests/manual/lance/widgets.h1
-rw-r--r--tests/manual/manual.pro5
-rw-r--r--tests/manual/markdown/html2md.cpp64
-rw-r--r--tests/manual/markdown/html2md.pro6
-rw-r--r--tests/manual/qcursor/qcursorhighdpi/main.cpp2
-rw-r--r--tests/manual/qgraphicslayout/flicker/window.h2
-rw-r--r--tests/manual/qnetconmonitor/qnetconmonitor.pro4
-rw-r--r--tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp220
-rw-r--r--tests/manual/qtexttableborders/main.cpp39
-rw-r--r--tests/manual/qtexttableborders/qtexttableborders.pro10
-rw-r--r--tests/manual/qtexttableborders/resources.qrc6
-rw-r--r--tests/manual/qtexttableborders/table-border-test-header.html129
-rw-r--r--tests/manual/qtexttableborders/table-border-test.html171
-rw-r--r--tests/manual/qtexttableborders/widget.cpp125
-rw-r--r--tests/manual/qtexttableborders/widget.h56
-rw-r--r--tests/manual/qtexttableborders/widget.ui79
-rw-r--r--tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp198
-rw-r--r--tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro8
-rw-r--r--tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc7
-rw-r--r--tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp213
-rw-r--r--tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro8
-rw-r--r--tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc8
-rw-r--r--tests/manual/rhi/computebuffer/buffer.comp41
-rw-r--r--tests/manual/rhi/computebuffer/buffer.comp.qsbbin0 -> 2160 bytes
-rwxr-xr-xtests/manual/rhi/computebuffer/buildshaders.bat3
-rw-r--r--tests/manual/rhi/computebuffer/computebuffer.cpp205
-rw-r--r--tests/manual/rhi/computebuffer/computebuffer.pro8
-rw-r--r--tests/manual/rhi/computebuffer/computebuffer.qrc7
-rw-r--r--tests/manual/rhi/computebuffer/main.frag8
-rw-r--r--tests/manual/rhi/computebuffer/main.frag.qsbbin0 -> 672 bytes
-rw-r--r--tests/manual/rhi/computebuffer/main.vert11
-rw-r--r--tests/manual/rhi/computebuffer/main.vert.qsbbin0 -> 852 bytes
-rwxr-xr-xtests/manual/rhi/computeimage/buildshaders.bat1
-rw-r--r--tests/manual/rhi/computeimage/computeimage.cpp228
-rw-r--r--tests/manual/rhi/computeimage/computeimage.pro8
-rw-r--r--tests/manual/rhi/computeimage/computeimage.qrc8
-rw-r--r--tests/manual/rhi/computeimage/image.comp20
-rw-r--r--tests/manual/rhi/computeimage/image.comp.qsbbin0 -> 1811 bytes
-rw-r--r--tests/manual/rhi/cubemap/buildshaders.bat2
-rw-r--r--tests/manual/rhi/cubemap/c.pngbin0 -> 27923 bytes
-rw-r--r--tests/manual/rhi/cubemap/cubemap.cpp179
-rw-r--r--tests/manual/rhi/cubemap/cubemap.frag10
-rw-r--r--tests/manual/rhi/cubemap/cubemap.frag.qsbbin0 -> 1311 bytes
-rw-r--r--tests/manual/rhi/cubemap/cubemap.pro8
-rw-r--r--tests/manual/rhi/cubemap/cubemap.qrc7
-rw-r--r--tests/manual/rhi/cubemap/cubemap.vert15
-rw-r--r--tests/manual/rhi/cubemap/cubemap.vert.qsbbin0 -> 1499 bytes
-rw-r--r--tests/manual/rhi/floattexture/floattexture.cpp328
-rw-r--r--tests/manual/rhi/floattexture/floattexture.pro8
-rw-r--r--tests/manual/rhi/floattexture/floattexture.qrc7
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp554
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro8
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc6
-rw-r--r--tests/manual/rhi/instancing/buildshaders.bat2
-rw-r--r--tests/manual/rhi/instancing/inst.frag9
-rw-r--r--tests/manual/rhi/instancing/inst.frag.qsbbin0 -> 936 bytes
-rw-r--r--tests/manual/rhi/instancing/inst.vert25
-rw-r--r--tests/manual/rhi/instancing/inst.vert.qsbbin0 -> 1792 bytes
-rw-r--r--tests/manual/rhi/instancing/instancing.cpp175
-rw-r--r--tests/manual/rhi/instancing/instancing.pro8
-rw-r--r--tests/manual/rhi/instancing/instancing.qrc6
-rw-r--r--tests/manual/rhi/mrt/buildshaders.bat2
-rw-r--r--tests/manual/rhi/mrt/mrt.cpp296
-rw-r--r--tests/manual/rhi/mrt/mrt.frag22
-rw-r--r--tests/manual/rhi/mrt/mrt.frag.qsbbin0 -> 1934 bytes
-rw-r--r--tests/manual/rhi/mrt/mrt.pro8
-rw-r--r--tests/manual/rhi/mrt/mrt.qrc8
-rw-r--r--tests/manual/rhi/mrt/mrt.vert19
-rw-r--r--tests/manual/rhi/mrt/mrt.vert.qsbbin0 -> 1633 bytes
-rw-r--r--tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp259
-rw-r--r--tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro8
-rw-r--r--tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc8
-rw-r--r--tests/manual/rhi/msaatexture/msaatexture.cpp329
-rw-r--r--tests/manual/rhi/msaatexture/msaatexture.pro8
-rw-r--r--tests/manual/rhi/msaatexture/msaatexture.qrc9
-rw-r--r--tests/manual/rhi/multiwindow/multiwindow.cpp644
-rw-r--r--tests/manual/rhi/multiwindow/multiwindow.pro8
-rw-r--r--tests/manual/rhi/multiwindow/multiwindow.qrc6
-rw-r--r--tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp833
-rw-r--r--tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro12
-rw-r--r--tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc7
-rw-r--r--tests/manual/rhi/multiwindow_threaded/window.cpp142
-rw-r--r--tests/manual/rhi/multiwindow_threaded/window.h86
-rw-r--r--tests/manual/rhi/offscreen/offscreen.cpp366
-rw-r--r--tests/manual/rhi/offscreen/offscreen.pro9
-rw-r--r--tests/manual/rhi/offscreen/offscreen.qrc6
-rw-r--r--tests/manual/rhi/qrhiprof/qrhiprof.cpp671
-rw-r--r--tests/manual/rhi/qrhiprof/qrhiprof.pro6
-rw-r--r--tests/manual/rhi/rhi.pro25
-rw-r--r--tests/manual/rhi/shadowmap/buildshaders.bat4
-rwxr-xr-xtests/manual/rhi/shadowmap/buildshaders.sh4
-rw-r--r--tests/manual/rhi/shadowmap/main.frag30
-rw-r--r--tests/manual/rhi/shadowmap/main.frag.qsbbin0 -> 2489 bytes
-rw-r--r--tests/manual/rhi/shadowmap/main.vert20
-rw-r--r--tests/manual/rhi/shadowmap/main.vert.qsbbin0 -> 1595 bytes
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.cpp304
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.frag5
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.frag.qsbbin0 -> 408 bytes
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.pro8
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.qrc8
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.vert14
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.vert.qsbbin0 -> 1215 bytes
-rw-r--r--tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdrbin0 -> 385303 bytes
-rw-r--r--tests/manual/rhi/shared/buildshaders.bat5
-rw-r--r--tests/manual/rhi/shared/bwqt224_64.pngbin0 -> 6339 bytes
-rw-r--r--tests/manual/rhi/shared/bwqt224_64_nomips.ddsbin0 -> 9712 bytes
-rw-r--r--tests/manual/rhi/shared/color.frag15
-rw-r--r--tests/manual/rhi/shared/color.frag.qsbbin0 -> 1483 bytes
-rw-r--r--tests/manual/rhi/shared/color.vert19
-rw-r--r--tests/manual/rhi/shared/color.vert.qsbbin0 -> 1648 bytes
-rw-r--r--tests/manual/rhi/shared/cube.h119
-rw-r--r--tests/manual/rhi/shared/dds_bc1.h137
-rw-r--r--tests/manual/rhi/shared/examplefw.h569
-rw-r--r--tests/manual/rhi/shared/qt256.pngbin0 -> 6208 bytes
-rw-r--r--tests/manual/rhi/shared/qt256_bc1_9mips.ddsbin0 -> 43832 bytes
-rw-r--r--tests/manual/rhi/shared/texture.frag18
-rw-r--r--tests/manual/rhi/shared/texture.frag.qsbbin0 -> 1710 bytes
-rw-r--r--tests/manual/rhi/shared/texture.vert21
-rw-r--r--tests/manual/rhi/shared/texture.vert.qsbbin0 -> 1897 bytes
-rw-r--r--tests/manual/rhi/shared/texture_ms4.frag20
-rw-r--r--tests/manual/rhi/shared/texture_ms4.frag.qsbbin0 -> 1847 bytes
-rw-r--r--tests/manual/rhi/texuploads/texuploads.cpp314
-rw-r--r--tests/manual/rhi/texuploads/texuploads.pro8
-rw-r--r--tests/manual/rhi/texuploads/texuploads.qrc7
-rw-r--r--tests/manual/rhi/triquadcube/quadrenderer.cpp148
-rw-r--r--tests/manual/rhi/triquadcube/quadrenderer.h87
-rw-r--r--tests/manual/rhi/triquadcube/texturedcuberenderer.cpp222
-rw-r--r--tests/manual/rhi/triquadcube/texturedcuberenderer.h86
-rw-r--r--tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp292
-rw-r--r--tests/manual/rhi/triquadcube/triangleoncuberenderer.h95
-rw-r--r--tests/manual/rhi/triquadcube/trianglerenderer.cpp202
-rw-r--r--tests/manual/rhi/triquadcube/trianglerenderer.h93
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.cpp281
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.pro18
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.qrc9
-rw-r--r--tests/manual/socketengine/main.cpp2
-rw-r--r--tests/manual/textrendering/glyphshaping/main.cpp2
-rw-r--r--tests/shared/filesystem.h2
-rwxr-xr-xtests/testserver/apache2/apache2.sh3
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi7
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi13
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi9
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi11
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi11
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi11
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes1
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html8380
-rwxr-xr-xtests/testserver/common/startup.sh17
-rwxr-xr-xtests/testserver/cyrus/cyrus.sh40
-rw-r--r--tests/testserver/docker-compose-bridge-network.yml157
-rw-r--r--tests/testserver/docker-compose-for-macOS.yml100
-rw-r--r--tests/testserver/docker-compose-for-windows.yml100
-rw-r--r--tests/testserver/docker-compose-host-network.yml102
-rw-r--r--tests/testserver/docker-compose.yml83
-rwxr-xr-xtests/testserver/echo/echo.sh7
-rwxr-xr-xtests/testserver/ftp-proxy/ftp-proxy.sh4
-rwxr-xr-xtests/testserver/iptables/iptables.sh34
-rw-r--r--tests/testserver/vsftpd/testdata/vsftpd.conf4
-rwxr-xr-xtests/testserver/vsftpd/vsftpd.sh4
854 files changed, 38490 insertions, 7448 deletions
diff --git a/tests/auto/android/runtests_androiddeployqt.pl b/tests/auto/android/runtests_androiddeployqt.pl
deleted file mode 100755
index 24b44cf9b2..0000000000
--- a/tests/auto/android/runtests_androiddeployqt.pl
+++ /dev/null
@@ -1,550 +0,0 @@
-#!/usr/bin/perl -w
-#############################################################################
-##
-## Copyright (C) 2012-2013 BogDan Vatra <bogdan@kde.org>
-## 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$
-##
-#############################################################################
-
-use Cwd;
-use Cwd 'abs_path';
-use File::Basename;
-use File::Temp 'tempdir';
-use File::Path 'remove_tree';
-use Getopt::Long;
-use Pod::Usage;
-use XML::Simple;
-use Term::ANSIColor;
-
-### default options
-my @stack = cwd;
-my $device_serial=""; # "-s device_serial";
-my $deployqt_device_serial=""; # "-device device_serial";
-my $log_out="xml";
-my $max_runtime = 5;
-my $className="org.qtproject.qt5.android.bindings.QtActivity";
-my $jobs = 4;
-my $testsubset = "";
-my $man = 0;
-my $help = 0;
-my $make_clean = 0;
-my $stop_on_fail = 0;
-my $time_out=400;
-my $android_toolchain_version = "4.8";
-my $host_arch = "linux-x86";
-my $android_sdk_dir = "$ENV{'ANDROID_SDK_ROOT'}";
-my $android_ndk_dir = "$ENV{'ANDROID_NDK_ROOT'}";
-my $android_to_connect = "$ENV{'ANDROID_DEVICE'}";
-my $ant_tool = `which ant`;
-my $silent = 0;
-chomp $ant_tool;
-my $strip_tool="";
-my $readelf_tool="";
-# for ci usage
-my @failures = '';
-my $total_tests = 0;
-my $total_failed = 0;
-my $failed_insignificants = 0;
-my $ci_use = 0;
-my $start = time();
-my $uninstall = 0;
-
-GetOptions('h|help' => \$help
- , man => \$man
- , 's|serial=s' => \$device_serial
- , 't|test=s' => \$testsubset
- , 'c|clean' => \$make_clean
- , 'j|jobs=i' => \$jobs
- , 'logtype=s' => \$log_out
- , 'runtime=i' => \$max_runtime
- , 'sdk=s' => \$android_sdk_dir
- , 'ndk=s' => \$android_ndk_dir
- , 'toolchain=s' => \$android_toolchain_version
- , 'host=s' => \$host_arch
- , 'ant=s' => \$ant_tool
- , 'strip=s' => \$strip_tool
- , 'readelf=s' => \$readelf_tool
- , 'testcase=s' => \$testcase
- , 'f|fail' => sub { $stop_on_fail = 1 }
- , 'silent' => sub { $silent = 1 }
- , 'ci' => sub { $ci_use = 1 }
- , 'uninstall' => sub { $uninstall = 1 }
- ) or pod2usage(2);
-pod2usage(1) if $help;
-pod2usage(-verbose => 2) if $man;
-
-if ($ci_use){
- use QMake::Project;
-}
-my $adb_tool="$android_sdk_dir/platform-tools/adb";
-
-# For CI. Nodes are connecting to test devices over IP, which is stored to env variable
-if ($android_to_connect ne ""){
- print " Found device to be connected from env: $android_to_connect \n";
- system("$adb_tool disconnect $android_to_connect");
- system("$adb_tool connect $android_to_connect");
- sleep(2);# let it connect
- system("$adb_tool -s $android_to_connect reboot &");# adb bug, it blocks forever
- sleep(15); # wait for the device to come up again
- system("$adb_tool disconnect $android_to_connect");# cleans up the left adb reboot process
- system("$adb_tool connect $android_to_connect");
- $device_serial =$android_to_connect;
-}
-
-system("$adb_tool devices") == 0 or die "No device found, please plug/start at least one device/emulator\n"; # make sure we have at least on device attached
-
-$deployqt_device_serial = "--device $device_serial" if ($device_serial);
-$device_serial = "-s $device_serial" if ($device_serial);
-$testsubset="/$testsubset" if ($testsubset);
-
-$strip_tool="$android_ndk_dir/toolchains/arm-linux-androideabi-$android_toolchain_version/prebuilt/$host_arch/bin/arm-linux-androideabi-strip" unless($strip_tool);
-$readelf_tool="$android_ndk_dir/toolchains/arm-linux-androideabi-$android_toolchain_version/prebuilt/$host_arch/bin/arm-linux-androideabi-readelf" unless($readelf_tool);
-$readelf_tool="$readelf_tool -d -w ";
-
-sub dir
-{
-# print "@stack\n";
-}
-
-sub pushd ($)
-{
- unless ( chdir $_[0] )
- {
- warn "Error: $!\n";
- return;
- }
- unshift @stack, cwd;
- dir;
-}
-
-sub popd ()
-{
- @stack > 1 and shift @stack;
- chdir $stack[0];
- dir;
-}
-
-##############################
-# Read possible insignificance
-# from pro file
-##############################
-sub check_if_insignificant
-{
- return 0 if ( !$ci_use );
- my $case = shift;
- my $insignificant = 0;
- my $prj = QMake::Project->new( 'Makefile' );
- $insignificant = $prj->test( 'insignificant_test' );
- return $insignificant;
-}
-
-##############################
-# Print output from given
-# $testresult.txt file
-##############################
-sub print_output
-{
- my $res_file = shift;
- my $case = shift;
- my $insignificant = shift;
- my $print_all = 0;
- $total_tests++;
- if (-e $res_file) {
- open my $file, $res_file or die "Could not open $res_file: $!";
- while (my $line = <$file>) {
- if ($line =~ m/^FAIL/) {
- print "$line";
- # Pretend to be like the "real" testrunner and print out
- # all steps
- $print_all = 1;
- }
- }
- close $file;
- if ($print_all) {
- # In case we are printing all, the test failed
- system("cat $res_file");
- if ($insignificant) {
- print " Testrunner: $case failed, but it is marked with insignificant_test\n";
- push (@failures ,(basename($case)." [insignificant]"));
- $failed_insignificants++;
- } else {
- $total_failed++;
- push (@failures ,(basename($case)));
- }
- } else {
- my $cmd = "sed -n 'x;\$p' ${res_file}";
- my $summary = qx(${cmd});
- if ($summary =~ m/^Totals/) {
- print "$summary";
- } else {
- print "Error: The log is incomplete. Looks like you have to increase the timeout.";
- # The test log seems inclomplete, considering the test as failed.
- if ($insignificant) {
- print " Testrunner: $case failed, but it is marked with insignificant_test\n";
- push (@failures ,(basename($case)." [insignificant]"));
- $failed_insignificants++;
- } else {
- $total_failed++;
- push (@failures ,(basename($case)));
- }
- }
- }
- } else {
- if ($insignificant) {
- print " Failed to execute $case, but it is marked with insignificant_test\n";
- push (@failures ,(basename($case)." [insignificant]"));
- $failed_insignificants++;
- } else {
- print "Failed to execute $case \n";
- $total_failed++;
- push (@failures ,(basename($case)));
- }
- }
-}
-
-##############################
-# Print summary of test run
-##############################
-
-sub print_summary
-{
- my $total = time()-$start;
- my $h = 0;
- my $m = 0;
- my $s = 0;
- my $exit = 0;
- print "=== Timing: =================== TEST RUN COMPLETED! ============================\n";
- if ($total > 60*60) {
- $h = int($total/60/60);
- $s = int($total - $h*60*60);
-
- $m = int($s/60);
- $s = 0;
- print "Total: $h hours $m minutes\n";
- } elsif ($total > 60) {
- $m = int($total/60);
- $s = int($total - $m*60);
- print "Total: $m minutes $s seconds\n";
- } else {
- $s = int($total);
- print "Total: $s seconds\n";
- }
-
- print "=== Failures: ==================================================================";
- foreach my $failed (@failures) {
- print $failed."\n";
- $exit = 1;
- }
- print "=== Totals: ".$total_tests." tests, ".($total_tests-$total_failed).
- " passes, ".$failed_insignificants.
- " insignificant fails ======================\n";
- return $exit;
-}
-
-
-sub waitForProcess
-{
- my $process=shift;
- my $action=shift;
- my $timeout=shift;
- my $sleepPeriod=shift;
- $sleepPeriod=1 if !defined($sleepPeriod);
- print "Waiting for $process ".$timeout*$sleepPeriod." seconds to" if (!$silent);
- print $action?" start...\n":" die...\n" if (!$silent);
- while ($timeout--)
- {
- my $output = `$adb_tool $device_serial shell ps 2>&1`; # get current processes
- #FIXME check why $output is not matching m/.*S $process\n/ or m/.*S $process$/ (eol)
- my $res=($output =~ m/.*S $process/)?1:0; # check the procress
- if ($action == $res)
- {
- print "... succeed\n" if (!$silent);
- return 1;
- }
- sleep($sleepPeriod);
- print "timeount in ".$timeout*$sleepPeriod." seconds\n" if (!$silent);
- }
- print "... failed\n" if (!$silent);
- return 0;
-}
-
-my $src_dir_qt=abs_path(dirname($0)."/../../..");
-my $quadruplor_dir="$src_dir_qt/tests/auto/android";
-my $qmake_path="$src_dir_qt/bin/qmake";
-my $androiddeployqt_path="$src_dir_qt/bin/androiddeployqt";
-my $tests_dir="$src_dir_qt/tests$testsubset";
-my $temp_dir=tempdir(CLEANUP => 1);
-my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
-my $output_dir=$stack[0]."/".(1900+$year)."-$mon-$mday-$hour:$min";
-mkdir($output_dir);
-unlink("latest");
-system(" ln -s $output_dir latest");
-my $sdk_api=0;
-my $output = `$adb_tool $device_serial shell getprop`; # get device properties
-if ($output =~ m/.*\[ro.build.version.sdk\]: \[(\d+)\]/)
-{
- $sdk_api=int($1);
- $sdk_api=5 if ($sdk_api>5 && $sdk_api<8);
- $sdk_api=9 if ($sdk_api>9);
-}
-
-sub checkXMLOutput
-{
- print color 'bold red';
- my $fileName = shift;
- my $XMLOutput = eval { XMLin($fileName, ForceArray => 1) };
- if (!defined($XMLOutput)) {
- print "Can't parse the $fileName file, probably the test crased.\n";
- print color 'reset';
- die "Stopping\n" if $stop_on_fail;
- return;
- }
- my $testName = $XMLOutput->{name};
- my $fail = 0;
- while (my($node_key, $node_valule) = each (%{$XMLOutput})) {
- next if $node_key ne "TestFunction";
- while (my($function_key, $function_valule) = each (%{$node_valule})) {
- while (my($test_key, $test_valule) = each (%{$function_valule})) {
- next if $test_key ne "Incident";
- for my $incident (@{$test_valule}) {
- if (($incident->{type} ne "pass") && ($incident->{type} ne "xfail")) {
- print "test $testName::$function_key failed $incident->{file}:$incident->{line}\n";
- $fail = 1;
- }
- }
- }
- }
- }
- print color 'reset';
- die "Stopping\n" if $stop_on_fail and $fail;
-}
-
-sub startTest
-{
- my $testName = shift;
- my $packageName = "org.qtproject.example.tst_$testName";
- my $intentName = "$packageName/org.qtproject.qt5.android.bindings.QtActivity";
- my $output_file = shift;
- my $insignificance = shift;
- my $get_xml= 0;
- my $get_txt= 0;
- my $testLib ="";
- if ($log_out eq "xml") {
- $testLib="-o /data/data/$packageName/output.xml,xml";
- $get_xml = 1;
- } elsif ($log_out eq "txt") {
- $testLib="-o /data/data/$packageName/output.txt,txt";
- $get_txt = 1;
- } else {
- $testLib="-o /data/data/$packageName/output.xml,xml -o /data/data/$packageName/output.txt,txt";
- $get_xml = 1;
- $get_txt = 1;
- }
-
- my $cmd="${adb_tool} ${device_serial} shell am start -e applicationArguments \"${testLib}\" -n ${intentName}";
- my $res = qx(${cmd});
- print $res if (!$silent);
- #wait to start (if it has not started and quit already)
- waitForProcess($packageName,1,10);
-
- #wait to stop
- unless(waitForProcess($packageName,0,$time_out,5))
- {
- #killProcess($packageName);
- print "Someone should kill $packageName\n";
- system("$adb_tool $device_serial uninstall $packageName") if ($uninstall);
- return 1;
- }
-
- # Wait for three seconds to allow process to write all data
- sleep(3);
-
- system("$adb_tool $device_serial pull /data/data/$packageName/output.xml $output_dir/$output_file.xml") if ($get_xml);
-
- system("$adb_tool $device_serial pull /data/data/$packageName/output.txt $output_dir/$output_file.txt") if ($get_txt);
- if ($get_txt){
- print "Test results for $packageName:\n";
- my $insig =
- print_output("$output_dir/$output_file.txt", $packageName, $insignificance);
- }
- system("$adb_tool $device_serial uninstall $packageName") if ($uninstall);
-
- checkXMLOutput("$output_dir/$output_file.xml") if ($get_xml);
- return 1;
-}
-
-########### build qt tests and benchmarks ###########
-pushd($tests_dir);
-print "Building $tests_dir \n";
-system("make distclean") if ($make_clean);
-system("$qmake_path -r") == 0 or die "Can't run qmake\n"; #exec qmake
-system("make -j$jobs") == 0 or warn "Can't build all tests\n"; #exec make
-
-my $testsFiles = "";
-if ($testcase) {
- $testsFiles=`find . -name libtst_$testcase.so`; # only tests
-} else {
- $testsFiles=`find . -name libtst_*.so`; # only tests
-}
-
-foreach (split("\n",$testsFiles))
-{
- chomp; #remove white spaces
- pushd(abs_path(dirname($_))); # cd to application dir
- my $insig = check_if_insignificant();
- my $cmd="make INSTALL_ROOT=${temp_dir} install";
- my $res = qx(${cmd});
- print $res if (!$silent);
- my $application=basename(cwd);
- if ($silent) {
- $cmd="$androiddeployqt_path --install ${deployqt_device_serial} --output ${temp_dir} --deployment debug --verbose --input android-libtst_${application}.so-deployment-settings.json >/dev/null 2>&1";
- } else {
- $cmd="$androiddeployqt_path --install ${deployqt_device_serial} --output ${temp_dir} --deployment debug --verbose --input android-libtst_${application}.so-deployment-settings.json";
- }
- $res = qx(${cmd});
- print $res if (!$silent);
- my $output_name=dirname($_);
- $output_name =~ s/\.//; # remove first "." character
- $output_name =~ s/\///; # remove first "/" character
- $output_name =~ s/\//_/g; # replace all "/" with "_"
- $output_name=$application unless($output_name);
- $time_out=$max_runtime*60/5; # 5 minutes time out for a normal test
-
- $applicationLibrary = `find $temp_dir -name libtst_bench_$application.so`;
-
- if ($applicationLibrary)
- {
- $time_out=5*60/5; # 10 minutes for a benchmark
- $application = "bench_$application";
- }
- else
- {
- $applicationLibrary = `find $temp_dir -name libtst_$application.so`;
- }
-
- if (!$applicationLibrary)
- {
- print "Can't find application binary libtst_$application.so in $temp_dir!\n";
- }
- else
- {
- startTest($application, "$output_name", $insig) or warn "Can't run $application ...\n";
- }
-
- popd();
- remove_tree( $temp_dir, {keep_root => 1} );
-}
-print_summary() if ($ci_use);
-popd();
-
-__END__
-
-=head1 NAME
-
-Script to run all qt tests/benchmarks to an android device/emulator
-
-=head1 SYNOPSIS
-
-runtests.pl [options]
-
-=head1 OPTIONS
-
-=over 8
-=item B<-f --fail>
-
-Stop the script when test fails. Default 0
-
-=item B<-s --serial = serial>
-
-Device serial number. May be empty if only one device is attached.
-
-=item B<-t --test = test_subset>
-
-Tests subset (e.g. benchmarks, auto, auto/qbuffer, etc.).
-
-=item B<-c --clean>
-
-Clean tests before building them.
-
-=item B<-j --jobs = number>
-
-Make jobs when building tests.
-
-=item B<--sdk = sdk_path>
-
-Android SDK path.
-
-=item B<--ndk = ndk_path>
-
-Android NDK path.
-
-=item B<--ant = ant_tool_path>
-
-Ant tool path.
-
-=item B<--strip = strip_tool_path>
-
-Android strip tool path, used to deploy qt libs.
-
-=item B<--readelf = readelf_tool_path>
-
-Android readelf tool path, used to check if a test application uses qt OpenGL.
-
-=item B<--logtype = xml|txt|both>
-
-The format of log file, default is xml.
-
-=item B<--runtime = minutes>
-
-The timeout period before stopping individual tests from running.
-
-=item B<-silent>
-
-Suppress output of system commands.
-
-=item B<-ci>
-
-Enables checking if test is insignificant or not. Also prints test
-summary after all tests has been executed.
-
-=item B<-uninstall>
-
-Uninstalls the test after has been executed.
-
-=item B<-h --help>
-
-Print a brief help message and exits.
-
-=item B<--man>
-
-Prints the manual page and exits.
-
-=back
-
-=head1 DESCRIPTION
-
-B<This program> will run all qt tests/benchmarks to an android device/emulator.
-
-=cut
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index 5b10a74d3f..ed900f7805 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -160,3 +160,5 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.8)
# Reason: SKIP_* properties were added in CMake 3.8 only
expect_pass(test_QTBUG-63422)
endif()
+
+expect_pass(test_import_plugins BINARY ${CMAKE_CTEST_COMMAND})
diff --git a/tests/auto/cmake/cmake.pro b/tests/auto/cmake/cmake.pro
index 9c715974f8..06509f4ad3 100644
--- a/tests/auto/cmake/cmake.pro
+++ b/tests/auto/cmake/cmake.pro
@@ -1,7 +1,12 @@
-# Cause make to do nothing.
TEMPLATE = subdirs
+# installed_cmake includes this file, and tries to add the mockplugins
+# directory relative to itself, but doesn't have its own copy of the directory.
+# So, we make the path absolute so it includes this copy of the directory
+# instead.
+SUBDIRS += $$PWD/mockplugins
+
CMAKE_QT_MODULES_UNDER_TEST = core network xml sql testlib
qtHaveModule(dbus): CMAKE_QT_MODULES_UNDER_TEST += dbus
diff --git a/tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.json b/tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.pro b/tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.pro
new file mode 100644
index 0000000000..1ccbe924ae
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock1plugin/mock1plugin.pro
@@ -0,0 +1,9 @@
+TARGET = mock1plugin
+
+HEADERS += qmock1plugin.h
+SOURCES += qmock1plugin.cpp
+QT = mockplugins1
+
+PLUGIN_TYPE = mockplugin
+PLUGIN_CLASS_NAME = QMock1Plugin
+load(qt_plugin)
diff --git a/tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.cpp b/tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.cpp
new file mode 100644
index 0000000000..2ee817d80a
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.cpp
@@ -0,0 +1,10 @@
+#include "qmock1plugin.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QMock1Plugin::pluginName() const
+{
+ return "QMock1Plugin";
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.h b/tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.h
new file mode 100644
index 0000000000..e2e114b1d9
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock1plugin/qmock1plugin.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCK1PLUGIN_H
+#define QMOCK1PLUGIN_H
+
+#include <QObject>
+#include <QtMockPlugins1/QMockPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QMock1Plugin : public QObject, public QMockPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QMockPlugin_iid FILE "mock1plugin.json")
+ Q_INTERFACES(QMockPlugin)
+public:
+ QString pluginName() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCK1PLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.json b/tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.pro b/tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.pro
new file mode 100644
index 0000000000..75dc21cf0a
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock2plugin/mock2plugin.pro
@@ -0,0 +1,10 @@
+TARGET = mock2plugin
+
+HEADERS += qmock2plugin.h
+SOURCES += qmock2plugin.cpp
+QT = mockplugins1
+
+PLUGIN_TYPE = mockplugin
+PLUGIN_CLASS_NAME = QMock2Plugin
+PLUGIN_EXTENDS = mockplugins1
+load(qt_plugin)
diff --git a/tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.cpp b/tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.cpp
new file mode 100644
index 0000000000..5b3280e884
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.cpp
@@ -0,0 +1,10 @@
+#include "qmock2plugin.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QMock2Plugin::pluginName() const
+{
+ return "QMock2Plugin";
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.h b/tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.h
new file mode 100644
index 0000000000..be99133dc8
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock2plugin/qmock2plugin.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCK2PLUGIN_H
+#define QMOCK2PLUGIN_H
+
+#include <QObject>
+#include <QtMockPlugins1/QMockPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QMock2Plugin : public QObject, public QMockPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QMockPlugin_iid FILE "mock2plugin.json")
+ Q_INTERFACES(QMockPlugin)
+public:
+ QString pluginName() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCK2PLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.json b/tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.pro b/tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.pro
new file mode 100644
index 0000000000..ed7df603bb
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock3plugin/mock3plugin.pro
@@ -0,0 +1,10 @@
+TARGET = mock3plugin
+
+HEADERS += qmock3plugin.h
+SOURCES += qmock3plugin.cpp
+QT = mockplugins1
+
+PLUGIN_TYPE = mockplugin
+PLUGIN_CLASS_NAME = QMock3Plugin
+PLUGIN_EXTENDS = mockplugins1 mockplugins2
+load(qt_plugin)
diff --git a/tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.cpp b/tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.cpp
new file mode 100644
index 0000000000..b38f854e4b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.cpp
@@ -0,0 +1,10 @@
+#include "qmock3plugin.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QMock3Plugin::pluginName() const
+{
+ return "QMock3Plugin";
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.h b/tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.h
new file mode 100644
index 0000000000..08d1aa68ce
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock3plugin/qmock3plugin.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCK3PLUGIN_H
+#define QMOCK3PLUGIN_H
+
+#include <QObject>
+#include <QtMockPlugins1/QMockPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QMock3Plugin : public QObject, public QMockPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QMockPlugin_iid FILE "mock3plugin.json")
+ Q_INTERFACES(QMockPlugin)
+public:
+ QString pluginName() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCK3PLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.json b/tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.pro b/tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.pro
new file mode 100644
index 0000000000..4dd2d6c547
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock4plugin/mock4plugin.pro
@@ -0,0 +1,10 @@
+TARGET = mock4plugin
+
+HEADERS += qmock4plugin.h
+SOURCES += qmock4plugin.cpp
+QT = mockplugins1
+
+PLUGIN_TYPE = mockplugin
+PLUGIN_CLASS_NAME = QMock4Plugin
+PLUGIN_EXTENDS = -
+load(qt_plugin)
diff --git a/tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.cpp b/tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.cpp
new file mode 100644
index 0000000000..5deaf7f43f
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.cpp
@@ -0,0 +1,10 @@
+#include "qmock4plugin.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QMock4Plugin::pluginName() const
+{
+ return "QMock4Plugin";
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.h b/tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.h
new file mode 100644
index 0000000000..0776bef002
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock4plugin/qmock4plugin.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCK4PLUGIN_H
+#define QMOCK4PLUGIN_H
+
+#include <QObject>
+#include <QtMockPlugins1/QMockPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QMock4Plugin : public QObject, public QMockPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QMockPlugin_iid FILE "mock4plugin.json")
+ Q_INTERFACES(QMockPlugin)
+public:
+ QString pluginName() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCK4PLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.json b/tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.pro b/tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.pro
new file mode 100644
index 0000000000..29496868fe
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock5plugin/mock5plugin.pro
@@ -0,0 +1,10 @@
+TARGET = mock5plugin
+
+HEADERS += qmock5plugin.h
+SOURCES += qmock5plugin.cpp
+QT = mockplugins3
+
+PLUGIN_TYPE = mockplugin
+PLUGIN_CLASS_NAME = QMock5Plugin
+PLUGIN_EXTENDS = -
+load(qt_plugin)
diff --git a/tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.cpp b/tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.cpp
new file mode 100644
index 0000000000..c5b4620516
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.cpp
@@ -0,0 +1,10 @@
+#include "qmock5plugin.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QMock5Plugin::pluginName() const
+{
+ return "QMock5Plugin";
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.h b/tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.h
new file mode 100644
index 0000000000..2f387da203
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock5plugin/qmock5plugin.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCK5PLUGIN_H
+#define QMOCK5PLUGIN_H
+
+#include <QObject>
+#include <QtMockPlugins1/QMockPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QMock5Plugin : public QObject, public QMockPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QMockPlugin_iid FILE "mock5plugin.json")
+ Q_INTERFACES(QMockPlugin)
+public:
+ QString pluginName() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCK5PLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.json b/tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.pro b/tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.pro
new file mode 100644
index 0000000000..140f198811
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock6plugin/mock6plugin.pro
@@ -0,0 +1,9 @@
+TARGET = mock6plugin
+
+HEADERS += qmock6plugin.h
+SOURCES += qmock6plugin.cpp
+QT = mockplugins3
+
+PLUGIN_TYPE = mockauxplugin
+PLUGIN_CLASS_NAME = QMock6Plugin
+load(qt_plugin)
diff --git a/tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.cpp b/tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.cpp
new file mode 100644
index 0000000000..4a0329c68a
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.cpp
@@ -0,0 +1,10 @@
+#include "qmock6plugin.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QMock6Plugin::pluginName() const
+{
+ return "QMock6Plugin";
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.h b/tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.h
new file mode 100644
index 0000000000..6b29b6703b
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mock6plugin/qmock6plugin.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCK6PLUGIN_H
+#define QMOCK6PLUGIN_H
+
+#include <QObject>
+#include <QtMockPlugins3/QMockAuxPlugin>
+
+QT_BEGIN_NAMESPACE
+
+class QMock6Plugin : public QObject, public QMockAuxPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QMockAuxPlugin_iid FILE "mock6plugin.json")
+ Q_INTERFACES(QMockAuxPlugin)
+public:
+ QString pluginName() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMOCK6PLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mockplugins.pro b/tests/auto/cmake/mockplugins/mockplugins.pro
new file mode 100644
index 0000000000..830d130a05
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins.pro
@@ -0,0 +1,36 @@
+TEMPLATE = subdirs
+
+src_mock1plugin.subdir = $$PWD/mock1plugin
+src_mock1plugin.target = sub-mockplugin1
+src_mock1plugin.depends = mockplugins1
+
+src_mock2plugin.subdir = $$PWD/mock2plugin
+src_mock2plugin.target = sub-mockplugin2
+src_mock2plugin.depends = mockplugins1
+
+src_mock3plugin.subdir = $$PWD/mock3plugin
+src_mock3plugin.target = sub-mockplugin3
+src_mock3plugin.depends = mockplugins1
+
+src_mock4plugin.subdir = $$PWD/mock4plugin
+src_mock4plugin.target = sub-mockplugin4
+src_mock4plugin.depends = mockplugins1
+
+src_mock5plugin.subdir = $$PWD/mock5plugin
+src_mock5plugin.target = sub-mockplugin5
+src_mock5plugin.depends = mockplugins3
+
+src_mock6plugin.subdir = $$PWD/mock6plugin
+src_mock6plugin.target = sub-mockplugin6
+src_mock6plugin.depends = mockplugins3
+
+SUBDIRS += \
+ mockplugins1 \
+ mockplugins2 \
+ mockplugins3 \
+ src_mock1plugin \
+ src_mock2plugin \
+ src_mock3plugin \
+ src_mock4plugin \
+ src_mock5plugin \
+ src_mock6plugin
diff --git a/tests/auto/cmake/mockplugins/mockplugins1/fake.cpp b/tests/auto/cmake/mockplugins/mockplugins1/fake.cpp
new file mode 100644
index 0000000000..f95eba6055
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins1/fake.cpp
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtGlobal>
+
+// Empty exported function needed to create .lib on Windows.
+Q_DECL_EXPORT void mockplugins1_foo() {
+
+}
diff --git a/tests/auto/cmake/mockplugins/mockplugins1/mockplugins1.pro b/tests/auto/cmake/mockplugins/mockplugins1/mockplugins1.pro
new file mode 100644
index 0000000000..dd98937ee3
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins1/mockplugins1.pro
@@ -0,0 +1,10 @@
+TARGET = QtMockPlugins1
+QT = core
+MODULE_PLUGIN_TYPES = mockplugin
+
+# Fake a git_build, to force qmake to run syncqt.pl when doing a standalone tests build
+# like it is done in Coin, otherwise module headers would not be generated.
+CONFIG += git_build
+HEADERS += qmockplugin.h
+SOURCES += fake.cpp # Needed to make libtool / ar happy on macOS
+load(qt_module)
diff --git a/tests/auto/cmake/mockplugins/mockplugins1/qmockplugin.h b/tests/auto/cmake/mockplugins/mockplugins1/qmockplugin.h
new file mode 100644
index 0000000000..9427ae9212
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins1/qmockplugin.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCKPLUGIN_H
+#define QMOCKPLUGIN_H
+
+#include <QString>
+#include <QtPlugin>
+
+QT_BEGIN_NAMESPACE
+
+#define QMockPlugin_iid "org.qt-project.Qt.Tests.QMockPlugin"
+
+class QMockPlugin
+{
+public:
+ virtual ~QMockPlugin() {}
+ virtual QString pluginName() const = 0;
+};
+
+Q_DECLARE_INTERFACE(QMockPlugin, QMockPlugin_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMOCKPLUGIN_H
diff --git a/tests/auto/cmake/mockplugins/mockplugins2/fake.cpp b/tests/auto/cmake/mockplugins/mockplugins2/fake.cpp
new file mode 100644
index 0000000000..384623d646
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins2/fake.cpp
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtGlobal>
+
+// Empty exported function needed to create .lib on Windows.
+Q_DECL_EXPORT void mockplugins2_foo() {
+
+}
diff --git a/tests/auto/cmake/mockplugins/mockplugins2/mockplugins2.pro b/tests/auto/cmake/mockplugins/mockplugins2/mockplugins2.pro
new file mode 100644
index 0000000000..1dd03391e8
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins2/mockplugins2.pro
@@ -0,0 +1,4 @@
+TARGET = QtMockPlugins2
+QT = core
+SOURCES += fake.cpp # Needed to make libtool / ar happy on macOS
+load(qt_module)
diff --git a/tests/auto/cmake/mockplugins/mockplugins3/fake.cpp b/tests/auto/cmake/mockplugins/mockplugins3/fake.cpp
new file mode 100644
index 0000000000..9ec2b42181
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins3/fake.cpp
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtGlobal>
+
+// Empty exported function needed to create .lib on Windows.
+Q_DECL_EXPORT void mockplugins3_foo() {
+
+}
diff --git a/tests/auto/cmake/mockplugins/mockplugins3/mockplugins3.pro b/tests/auto/cmake/mockplugins/mockplugins3/mockplugins3.pro
new file mode 100644
index 0000000000..3651abaafa
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins3/mockplugins3.pro
@@ -0,0 +1,11 @@
+TARGET = QtMockPlugins3
+QT = core
+MODULE_PLUGIN_TYPES = mockauxplugin
+
+# Fake a git_build, to force qmake to run syncqt.pl when doing a standalone tests build
+# like it is done in Coin, otherwise module headers would not be generated.
+CONFIG += git_build
+HEADERS += qmockauxplugin.h
+SOURCES += fake.cpp # Needed to make libtool / ar happy on macOS
+
+load(qt_module)
diff --git a/tests/auto/cmake/mockplugins/mockplugins3/qmockauxplugin.h b/tests/auto/cmake/mockplugins/mockplugins3/qmockauxplugin.h
new file mode 100644
index 0000000000..25e4762bac
--- /dev/null
+++ b/tests/auto/cmake/mockplugins/mockplugins3/qmockauxplugin.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOCKAUXPLUGIN_H
+#define QMOCKAUXPLUGIN_H
+
+#include <QString>
+#include <QtPlugin>
+
+QT_BEGIN_NAMESPACE
+
+#define QMockAuxPlugin_iid "org.qt-project.Qt.Tests.QMockAuxPlugin"
+
+class QMockAuxPlugin
+{
+public:
+ virtual ~QMockAuxPlugin() {}
+ virtual QString pluginName() const = 0;
+};
+
+Q_DECLARE_INTERFACE(QMockAuxPlugin, QMockAuxPlugin_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMOCKAUXPLUGIN_H
diff --git a/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt b/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt
index a0b82caee4..b9b9756699 100644
--- a/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt
+++ b/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 2.8)
project(test_dependent_modules)
+# Need to set the policy to link to qtmain.lib automatically.
+cmake_policy(SET CMP0020 NEW)
+
find_package(Qt5Widgets REQUIRED)
set(CMAKE_AUTOMOC ON)
diff --git a/tests/auto/cmake/test_import_plugins/CMakeLists.txt b/tests/auto/cmake/test_import_plugins/CMakeLists.txt
new file mode 100644
index 0000000000..a793fe211d
--- /dev/null
+++ b/tests/auto/cmake/test_import_plugins/CMakeLists.txt
@@ -0,0 +1,111 @@
+
+cmake_minimum_required(VERSION 3.1)
+
+project(import_plugins_advanced)
+enable_testing()
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/FindPackageHints.cmake")
+ include("${CMAKE_CURRENT_LIST_DIR}/FindPackageHints.cmake")
+endif()
+
+# Need to find Qt5Core explicitly because the MockPlugins1 and MockPlugins2 config files
+# are in a different directory (the source dir) when doing a standalone tests build,
+# whereas Core is in the installed directory, and due to NO_DEFAULT_PATH being used
+# for the Core dependency call in Qt5MockPlugins, Core would not be found in the source
+# dir.
+find_package(Qt5 COMPONENTS Core REQUIRED HINTS ${Qt5Tests_PREFIX_PATH})
+get_target_property(qt_is_static Qt5::Core TYPE)
+
+# For a similar reason, we need to find the MockPlugins packages not via COMPONENTS argument,
+# but directly, because the location of Qt5Config.cmake is in the installed dir, while
+# the MockPlugins are in the source dir, and Qt5Config only looks for packages relative
+# to its own location.
+# The packages are still successfuly found, because the CMAKE_PREFIX_PATH populated by qmake
+# contains both the installed Qt dir, and the Qt source dir.
+find_package(Qt5MockPlugins1 REQUIRED HINTS ${Qt5Tests_PREFIX_PATH})
+find_package(Qt5MockPlugins2 REQUIRED HINTS ${Qt5Tests_PREFIX_PATH})
+
+function(create_test_executable TARGET_NAME)
+ set(CHECK_FILE ${CMAKE_BINARY_DIR}/${TARGET_NAME}_check.cpp)
+
+ set(EXPECTED_PLUGINS)
+ foreach(_p ${ARGN})
+ string(APPEND EXPECTED_PLUGINS " \"${_p}\",\n")
+ endforeach()
+ configure_file("${CMAKE_SOURCE_DIR}/check.cpp.in" ${CHECK_FILE})
+
+ add_executable(${TARGET_NAME} main.cpp ${CHECK_FILE})
+ target_link_libraries(${TARGET_NAME} Qt5::MockPlugins1)
+ add_test(test_${TARGET_NAME} ${TARGET_NAME})
+endfunction()
+
+create_test_executable(default QMock1Plugin QMock2Plugin)
+# No call to qt5_import_plugins() for the default
+
+# TODO This test is known to fail because CMake currently doesn't have a way to
+# implement its own equivalent of the PLUGIN_EXTENDS mechanism at generate-
+# time (meaning a library only gets linked if a set of other libraries are
+# *also* linked.) CMake 3.14 or beyond may have such a mechanism, but until
+# then, this test is expected to fail, because QMock3Plugin is not being
+# linked even though MockPlugins2 is present.
+create_test_executable(default_link QMock1Plugin QMock2Plugin QMock3Plugin)
+target_link_libraries(default_link Qt5::MockPlugins2)
+set_property(TEST test_default_link PROPERTY DISABLED 1)
+# No call to qt5_import_plugins() for the default
+
+create_test_executable(manual QMock1Plugin QMock2Plugin QMock3Plugin QMock4Plugin)
+qt5_import_plugins(manual
+ INCLUDE Qt5::QMock3Plugin Qt5::QMock4Plugin
+)
+
+create_test_executable(manual_genex QMock1Plugin QMock2Plugin QMock3Plugin)
+qt5_import_plugins(manual_genex
+ INCLUDE $<1:Qt5::QMock3Plugin> $<0:Qt5::QMock4Plugin>
+)
+
+create_test_executable(blacklist QMock1Plugin)
+qt5_import_plugins(blacklist
+ EXCLUDE Qt5::QMock2Plugin Qt5::QMock3Plugin
+)
+
+create_test_executable(blacklist_genex QMock1Plugin)
+qt5_import_plugins(blacklist_genex
+ EXCLUDE $<1:Qt5::QMock2Plugin> $<1:Qt5::QMock3Plugin> $<0:Qt5::QMock1Plugin>
+)
+
+create_test_executable(override QMock3Plugin QMock4Plugin)
+qt5_import_plugins(override
+ INCLUDE_BY_TYPE mockplugin Qt5::QMock3Plugin Qt5::QMock4Plugin
+)
+
+create_test_executable(override_genex QMock3Plugin)
+qt5_import_plugins(override_genex
+ INCLUDE_BY_TYPE mockplugin $<1:Qt5::QMock3Plugin> $<0:Qt5::QMock4Plugin>
+)
+
+create_test_executable(override_mix QMock2Plugin QMock3Plugin)
+qt5_import_plugins(override_mix
+ INCLUDE Qt5::QMock2Plugin
+ INCLUDE_BY_TYPE mockplugin Qt5::QMock3Plugin
+)
+
+if(NOT WIN32)
+ # Compiling an empty static array fails on Windows.
+ create_test_executable(none)
+ qt5_import_plugins(none
+ EXCLUDE_BY_TYPE mockplugin
+ )
+endif()
+
+create_test_executable(none_mix QMock3Plugin QMock4Plugin)
+qt5_import_plugins(none_mix
+ INCLUDE Qt5::QMock3Plugin Qt5::QMock4Plugin
+ EXCLUDE_BY_TYPE mockplugin
+)
+
+create_test_executable(recursive QMock5Plugin QMock6Plugin)
+qt5_import_plugins(recursive
+ INCLUDE_BY_TYPE mockplugin Qt5::QMock5Plugin
+)
diff --git a/tests/auto/cmake/test_import_plugins/check.cpp.in b/tests/auto/cmake/test_import_plugins/check.cpp.in
new file mode 100644
index 0000000000..df6ea03d2d
--- /dev/null
+++ b/tests/auto/cmake/test_import_plugins/check.cpp.in
@@ -0,0 +1,8 @@
+#include <QString>
+#include <cstddef>
+
+QString expectedPlugins[] = {
+@EXPECTED_PLUGINS@
+};
+
+std::size_t numExpectedPlugins = sizeof(expectedPlugins) / sizeof(numExpectedPlugins);
diff --git a/tests/auto/cmake/test_import_plugins/main.cpp b/tests/auto/cmake/test_import_plugins/main.cpp
new file mode 100644
index 0000000000..9fcc81754b
--- /dev/null
+++ b/tests/auto/cmake/test_import_plugins/main.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Kitware, Inc.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QPluginLoader>
+#include <QSet>
+#include <QString>
+#include <QVector>
+
+#include <cstddef>
+#include <iostream>
+
+extern QString expectedPlugins[];
+extern std::size_t numExpectedPlugins;
+
+int main(int argc, char **argv)
+{
+#ifdef QT_STATIC
+ QSet<QString> expectedPluginSet;
+ for (std::size_t i = 0; i < numExpectedPlugins; i++) {
+ expectedPluginSet.insert(expectedPlugins[i]);
+ }
+
+ QVector<QStaticPlugin> plugins = QPluginLoader::staticPlugins();
+ QSet<QString> actualPluginSet;
+ for (QStaticPlugin plugin : plugins) {
+ actualPluginSet.insert(plugin.metaData()["className"].toString());
+ }
+
+ if (expectedPluginSet != actualPluginSet) {
+ std::cerr << "Loaded plugins do not match what was expected!" << std::endl
+ << "Expected plugins:" << std::endl;
+
+ QList<QString> expectedPluginList = expectedPluginSet.toList();
+ expectedPluginList.sort();
+ for (QString plugin : expectedPluginList) {
+ std::cerr << (actualPluginSet.contains(plugin) ? " " : "- ")
+ << plugin.toStdString() << std::endl;
+ }
+
+ std::cerr << std::endl << "Actual plugins:" << std::endl;
+
+ QList<QString> actualPluginList = actualPluginSet.toList();
+ actualPluginList.sort();
+ for (QString plugin : actualPluginList) {
+ std::cerr << (expectedPluginSet.contains(plugin) ? " " : "+ ")
+ << plugin.toStdString() << std::endl;
+ }
+
+ return 1;
+ }
+
+#endif
+ return 0;
+}
diff --git a/tests/auto/cmake/test_interface/CMakeLists.txt b/tests/auto/cmake/test_interface/CMakeLists.txt
index 2af80ea448..fdd1aacc10 100644
--- a/tests/auto/cmake/test_interface/CMakeLists.txt
+++ b/tests/auto/cmake/test_interface/CMakeLists.txt
@@ -25,6 +25,9 @@ int main(int,char**) { QWidget w; w.show(); return 0; }
"
)
+# Fix try_compile to inherit the parent configuration.
+set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}")
+
# The try_compile works because Qt5::Widgets is listed in the LINK_LIBRARIES,
# which causes the includes, defines and appropriate PIC flag to be used.
try_compile(_TRY_COMPILE_RES "${CMAKE_CURRENT_BINARY_DIR}/try_compile-test"
diff --git a/tests/auto/cmake/test_moc_macro_target/CMakeLists.txt b/tests/auto/cmake/test_moc_macro_target/CMakeLists.txt
index e97ac199e8..f3299060fd 100644
--- a/tests/auto/cmake/test_moc_macro_target/CMakeLists.txt
+++ b/tests/auto/cmake/test_moc_macro_target/CMakeLists.txt
@@ -11,13 +11,13 @@ qt5_generate_moc(main_gen_test.cpp
"${CMAKE_CURRENT_BINARY_DIR}/main_gen_test.moc"
TARGET Qt5GenerateMacroTest
)
-add_executable(Qt5GenerateMacroTest WIN32 main_gen_test.cpp "${CMAKE_CURRENT_BINARY_DIR}/main_gen_test.moc")
+add_executable(Qt5GenerateMacroTest main_gen_test.cpp "${CMAKE_CURRENT_BINARY_DIR}/main_gen_test.moc")
target_include_directories(Qt5GenerateMacroTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/interface")
target_link_libraries(Qt5GenerateMacroTest Qt5::Core)
qt5_wrap_cpp(moc_file mywrapobject.h
TARGET Qt5WrapMacroTest
)
-add_executable(Qt5WrapMacroTest WIN32 main_wrap_test.cpp ${moc_file})
+add_executable(Qt5WrapMacroTest main_wrap_test.cpp ${moc_file})
target_include_directories(Qt5WrapMacroTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/interface")
target_link_libraries(Qt5WrapMacroTest Qt5::Core)
diff --git a/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro b/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro
index f3684faa61..15345d40db 100644
--- a/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro
+++ b/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro
@@ -3,3 +3,4 @@ TARGET = tst_qtconcurrentfilter
QT = core testlib concurrent
SOURCES = tst_qtconcurrentfilter.cpp
DEFINES += QT_STRICT_ITERATORS
+DEFINES -= QT_NO_LINKED_LIST
diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
index 2e698e6615..3c77b1ba0b 100644
--- a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
+++ b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
@@ -88,7 +88,7 @@ QAtomicInt iterations;
class PrintFor : public IterateKernel<TestIterator, void>
{
public:
- PrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); }
+ PrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); }
bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
iterations.fetchAndAddRelaxed(end - begin);
@@ -107,7 +107,7 @@ public:
class SleepPrintFor : public IterateKernel<TestIterator, void>
{
public:
- SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); }
+ SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); }
inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
QTest::qSleep(200);
@@ -127,7 +127,7 @@ public:
void tst_QtConcurrentIterateKernel::instantiate()
{
startThreadEngine(new PrintFor(0, 40)).startBlocking();
- QCOMPARE(iterations.load(), 40);
+ QCOMPARE(iterations.loadRelaxed(), 40);
}
void tst_QtConcurrentIterateKernel::cancel()
@@ -138,8 +138,8 @@ void tst_QtConcurrentIterateKernel::cancel()
f.waitForFinished();
QVERIFY(f.isCanceled());
// the threads might run one iteration each before they are canceled.
- QVERIFY2(iterations.load() <= QThread::idealThreadCount(),
- (QByteArray::number(iterations.load()) + ' ' + QByteArray::number(QThread::idealThreadCount())));
+ QVERIFY2(iterations.loadRelaxed() <= QThread::idealThreadCount(),
+ (QByteArray::number(iterations.loadRelaxed()) + ' ' + QByteArray::number(QThread::idealThreadCount())));
}
}
@@ -147,7 +147,7 @@ QAtomicInt counter;
class CountFor : public IterateKernel<TestIterator, void>
{
public:
- CountFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); }
+ CountFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); }
inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
counter.fetchAndAddRelaxed(end - begin);
@@ -164,10 +164,10 @@ void tst_QtConcurrentIterateKernel::stresstest()
const int iterations = 1000;
const int times = 50;
for (int i = 0; i < times; ++i) {
- counter.store(0);
+ counter.storeRelaxed(0);
CountFor f(0, iterations);
f.startBlocking();
- QCOMPARE(counter.load(), iterations);
+ QCOMPARE(counter.loadRelaxed(), iterations);
}
}
@@ -186,7 +186,7 @@ public:
// this class throttles between iterations 100 and 200,
// and then records how many threads that run between
// iterations 140 and 160.
- ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); throttling = false; }
+ ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); throttling = false; }
inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
if (200 >= begin && 200 < end) {
@@ -217,7 +217,7 @@ public:
bool shouldThrottleThread()
{
- const int load = iterations.load();
+ const int load = iterations.loadRelaxed();
return (load > 100 && load < 200);
}
bool throttling;
@@ -226,14 +226,14 @@ public:
void tst_QtConcurrentIterateKernel::throttling()
{
const int totalIterations = 400;
- iterations.store(0);
+ iterations.storeRelaxed(0);
threads.clear();
ThrottleFor f(0, totalIterations);
f.startBlocking();
- QCOMPARE(iterations.load(), totalIterations);
+ QCOMPARE(iterations.loadRelaxed(), totalIterations);
QCOMPARE(threads.count(), 1);
diff --git a/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro b/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro
index fd8fd0a74a..717d103e44 100644
--- a/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro
+++ b/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro
@@ -3,6 +3,7 @@ TARGET = tst_qtconcurrentmap
QT = core testlib concurrent
SOURCES = tst_qtconcurrentmap.cpp
DEFINES += QT_STRICT_ITERATORS
+DEFINES -= QT_NO_LINKED_LIST
# Force C++17 if available
contains(QT_CONFIG, c++1z): CONFIG += c++1z
diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
index b864b065e6..383de0b2ce 100644
--- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
+++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
@@ -127,14 +127,11 @@ void tst_QtConcurrentMap::map()
QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished();
QCOMPARE(numberList, QList<Number>() << 4 << 8 << 12);
-#ifdef Q_COMPILER_LAMBDA
// lambda
QtConcurrent::map(list, [](int &x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 128 << 256 << 384);
QtConcurrent::map(list.begin(), list.end(), [](int &x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 256 << 512 << 768);
-#endif
-
}
// functors don't take arguments by reference, making these no-ops
@@ -160,13 +157,11 @@ void tst_QtConcurrentMap::map()
QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished();
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
-#ifdef Q_COMPILER_LAMBDA
// lambda
QtConcurrent::map(list, [](int x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QtConcurrent::map(list.begin(), list.end(), [](int x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
-#endif
}
// Linked lists and forward iterators
@@ -2026,12 +2021,12 @@ int fn(int &i)
return i;
}
-int fnConstNoExcept(const int &i) Q_DECL_NOTHROW
+int fnConstNoExcept(const int &i) noexcept
{
return i;
}
-int fnNoExcept(int &i) Q_DECL_NOTHROW
+int fnNoExcept(int &i) noexcept
{
return i;
}
@@ -2046,12 +2041,12 @@ QString changeType(int &)
return QString();
}
-QString changeTypeConstNoExcept(const int &) Q_DECL_NOTHROW
+QString changeTypeConstNoExcept(const int &) noexcept
{
return QString();
}
-QString changeTypeNoExcept(int &) Q_DECL_NOTHROW
+QString changeTypeNoExcept(int &) noexcept
{
return QString();
}
@@ -2066,12 +2061,12 @@ int changeTypeQStringList(QStringList &)
return 0;
}
-int changeTypeQStringListConstNoExcept(const QStringList &) Q_DECL_NOTHROW
+int changeTypeQStringListConstNoExcept(const QStringList &) noexcept
{
return 0;
}
-int changeTypeQStringListNoExcept(QStringList &) Q_DECL_NOTHROW
+int changeTypeQStringListNoExcept(QStringList &) noexcept
{
return 0;
}
@@ -2101,22 +2096,22 @@ public:
return QString();
}
- MemFnTester fnNoExcept() Q_DECL_NOTHROW
+ MemFnTester fnNoExcept() noexcept
{
return MemFnTester();
}
- MemFnTester fnConstNoExcept() const Q_DECL_NOTHROW
+ MemFnTester fnConstNoExcept() const noexcept
{
return MemFnTester();
}
- QString changeTypeNoExcept() Q_DECL_NOTHROW
+ QString changeTypeNoExcept() noexcept
{
return QString();
}
- QString changeTypeConstNoExcept() const Q_DECL_NOTHROW
+ QString changeTypeConstNoExcept() const noexcept
{
return QString();
}
@@ -2186,8 +2181,8 @@ public:
void updatePeak()
{
forever {
- const int localPeak = peakInstanceCount.load();
- const int localCurrent = currentInstanceCount.load();
+ const int localPeak = peakInstanceCount.loadRelaxed();
+ const int localCurrent = currentInstanceCount.loadRelaxed();
if (localCurrent <= localPeak)
break;
if (peakInstanceCount.testAndSetOrdered(localPeak, localCurrent))
@@ -2225,35 +2220,35 @@ void tst_QtConcurrentMap::throttling()
const int allowedTemporaries = QThread::idealThreadCount() * 40;
{
- currentInstanceCount.store(0);
- peakInstanceCount.store(0);
+ currentInstanceCount.storeRelaxed(0);
+ peakInstanceCount.storeRelaxed(0);
QList<InstanceCounter> instances;
for (int i = 0; i < itemcount; ++i)
instances.append(InstanceCounter());
- QCOMPARE(currentInstanceCount.load(), itemcount);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
int results = QtConcurrent::blockingMappedReduced(instances, slowMap, fastReduce);
QCOMPARE(results, itemcount);
- QCOMPARE(currentInstanceCount.load(), itemcount);
- QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
+ QVERIFY(peakInstanceCount.loadRelaxed() < itemcount + allowedTemporaries);
}
{
- QCOMPARE(currentInstanceCount.load(), 0);
- peakInstanceCount.store(0);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), 0);
+ peakInstanceCount.storeRelaxed(0);
QList<InstanceCounter> instances;
for (int i = 0; i < itemcount; ++i)
instances.append(InstanceCounter());
- QCOMPARE(currentInstanceCount.load(), itemcount);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
int results = QtConcurrent::blockingMappedReduced(instances, fastMap, slowReduce);
QCOMPARE(results, itemcount);
- QCOMPARE(currentInstanceCount.load(), itemcount);
- QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
+ QVERIFY(peakInstanceCount.loadRelaxed() < itemcount + allowedTemporaries);
}
}
@@ -2385,8 +2380,8 @@ InstanceCounter ic_fn(const InstanceCounter & ic)
// assigned over with operator ==
void tst_QtConcurrentMap::qFutureAssignmentLeak()
{
- currentInstanceCount.store(0);
- peakInstanceCount.store(0);
+ currentInstanceCount.storeRelaxed(0);
+ peakInstanceCount.storeRelaxed(0);
QFuture<InstanceCounter> future;
{
QList<InstanceCounter> list;
@@ -2405,9 +2400,9 @@ void tst_QtConcurrentMap::qFutureAssignmentLeak()
// Use QTRY_COMPARE because QtConcurrent::ThreadEngine::asynchronousFinish()
// deletes its internals after signaling finished, so it might still be holding
// on to copies of InstanceCounter for a short while.
- QTRY_COMPARE(currentInstanceCount.load(), 1000);
+ QTRY_COMPARE(currentInstanceCount.loadRelaxed(), 1000);
future = QFuture<InstanceCounter>();
- QTRY_COMPARE(currentInstanceCount.load(), 0);
+ QTRY_COMPARE(currentInstanceCount.loadRelaxed(), 0);
}
inline void increment(int &num)
diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
index 1596a9fafd..a4eb2936b5 100644
--- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
+++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
@@ -48,12 +48,8 @@ private slots:
#ifndef QT_NO_EXCEPTIONS
void exceptions();
#endif
-#ifdef Q_COMPILER_DECLTYPE
void functor();
-#endif
-#ifdef Q_COMPILER_LAMBDA
void lambda();
-#endif
};
void light()
@@ -126,23 +122,23 @@ public:
class ANoExcept
{
public:
- int member0() Q_DECL_NOTHROW { return 10; }
- int member1(int in) Q_DECL_NOTHROW { return in; }
+ int member0() noexcept { return 10; }
+ int member1(int in) noexcept { return in; }
typedef int result_type;
- int operator()() Q_DECL_NOTHROW { return 10; }
- int operator()(int in) Q_DECL_NOTHROW { return in; }
+ int operator()() noexcept { return 10; }
+ int operator()(int in) noexcept { return in; }
};
class AConstNoExcept
{
public:
- int member0() const Q_DECL_NOTHROW { return 10; }
- int member1(int in) const Q_DECL_NOTHROW { return in; }
+ int member0() const noexcept { return 10; }
+ int member1(int in) const noexcept { return in; }
typedef int result_type;
- int operator()() const Q_DECL_NOTHROW { return 10; }
- int operator()(int in) const Q_DECL_NOTHROW { return in; }
+ int operator()() const noexcept { return 10; }
+ int operator()(int in) const noexcept { return in; }
};
void tst_QtConcurrentRun::returnValue()
@@ -510,17 +506,17 @@ void tst_QtConcurrentRun::recursive()
int levels = 15;
for (int i = 0; i < QThread::idealThreadCount(); ++i) {
- count.store(0);
+ count.storeRelaxed(0);
QThreadPool::globalInstance()->setMaxThreadCount(i);
recursiveRun(levels);
- QCOMPARE(count.load(), (int)std::pow(2.0, levels) - 1);
+ QCOMPARE(count.loadRelaxed(), (int)std::pow(2.0, levels) - 1);
}
for (int i = 0; i < QThread::idealThreadCount(); ++i) {
- count.store(0);
+ count.storeRelaxed(0);
QThreadPool::globalInstance()->setMaxThreadCount(i);
recursiveResult(levels);
- QCOMPARE(count.load(), (int)std::pow(2.0, levels) - 1);
+ QCOMPARE(count.loadRelaxed(), (int)std::pow(2.0, levels) - 1);
}
}
@@ -574,7 +570,7 @@ public:
static QAtomicInt cancel;
void run() override {
int iter = 60;
- while (--iter && !cancel.load())
+ while (--iter && !cancel.loadRelaxed())
QThread::currentThread()->msleep(25);
}
};
@@ -642,13 +638,12 @@ void tst_QtConcurrentRun::exceptions()
caught = true;
}
- SlowTask::cancel.store(true);
+ SlowTask::cancel.storeRelaxed(true);
QVERIFY2(caught, "did not get exception");
}
#endif
-#ifdef Q_COMPILER_DECLTYPE
// Compiler supports decltype
struct Functor {
int operator()() { return 42; }
@@ -706,9 +701,7 @@ void tst_QtConcurrentRun::functor()
QtConcurrent::run(&pool, f, 1,2,3,4,5).waitForFinished();
}
}
-#endif
-#ifdef Q_COMPILER_LAMBDA
// Compiler supports lambda
void tst_QtConcurrentRun::lambda()
{
@@ -717,14 +710,12 @@ void tst_QtConcurrentRun::lambda()
QCOMPARE(QtConcurrent::run([](int a, double b){ return a + b; }, 12, 15).result(), double(12+15));
QCOMPARE(QtConcurrent::run([](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5);
-#ifdef Q_COMPILER_INITIALIZER_LISTS
{
QString str { "Hello World Foo" };
QFuture<QStringList> f1 = QtConcurrent::run([&](){ return str.split(' '); });
auto r = f1.result();
QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
}
-#endif
// and now with explicit pool:
QThreadPool pool;
@@ -733,16 +724,13 @@ void tst_QtConcurrentRun::lambda()
QCOMPARE(QtConcurrent::run(&pool, [](int a, double b){ return a + b; }, 12, 15).result(), double(12+15));
QCOMPARE(QtConcurrent::run(&pool, [](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5);
-#ifdef Q_COMPILER_INITIALIZER_LISTS
{
QString str { "Hello World Foo" };
QFuture<QStringList> f1 = QtConcurrent::run(&pool, [&](){ return str.split(' '); });
auto r = f1.result();
QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
}
-#endif
}
-#endif
QTEST_MAIN(tst_QtConcurrentRun)
#include "tst_qtconcurrentrun.moc"
diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
index a68f7d5a4e..d4c669cddc 100644
--- a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
+++ b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
@@ -28,6 +28,7 @@
#include <qtconcurrentthreadengine.h>
#include <qexception.h>
#include <QThread>
+#include <QElapsedTimer>
#include <QtTest/QtTest>
using namespace QtConcurrent;
@@ -186,7 +187,7 @@ class ThrottleAlwaysUser : public ThreadEngine<void>
public:
ThrottleAlwaysUser()
{
- count.store(initialCount = 100);
+ count.storeRelaxed(initialCount = 100);
finishing = false;
}
@@ -198,7 +199,7 @@ public:
ThreadFunctionResult threadFunction()
{
forever {
- const int local = count.load();
+ const int local = count.loadRelaxed();
if (local == 0) {
finishing = true;
return ThreadFinished;
@@ -223,13 +224,13 @@ void tst_QtConcurrentThreadEngine::throttle()
for (int i = 0; i < repeats; ++i) {
QFuture<void> f = (new ThrottleAlwaysUser())->startAsynchronously();
f.waitForFinished();
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
for (int i = 0; i < repeats; ++i) {
ThrottleAlwaysUser t;
t.startBlocking();
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
}
@@ -382,7 +383,7 @@ void tst_QtConcurrentThreadEngine::cancelQueuedSlowUser()
{
const int times = 100;
- QTime t;
+ QElapsedTimer t;
t.start();
{
diff --git a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
index b5b37b4498..3e42a737df 100644
--- a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
+++ b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
@@ -1,3 +1,2 @@
[deleteChildrenWithRunningGroup]
-osx-10.12
osx-10.13
diff --git a/tests/auto/corelib/animation/qpauseanimation/BLACKLIST b/tests/auto/corelib/animation/qpauseanimation/BLACKLIST
index e223ec82e2..33cd53d788 100644
--- a/tests/auto/corelib/animation/qpauseanimation/BLACKLIST
+++ b/tests/auto/corelib/animation/qpauseanimation/BLACKLIST
@@ -1,6 +1,5 @@
[pauseAndPropertyAnimations]
-*
-[multipleSequentialGroups]
osx
-[noTimerUpdates]
+[multipleSequentialGroups]
osx
+
diff --git a/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST b/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST
deleted file mode 100644
index a8719b241a..0000000000
--- a/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST
+++ /dev/null
@@ -1,6 +0,0 @@
-[statesAndSignals:normal animation]
-windows
-[startBackwardWithoutEndValue]
-windows
-[startWithoutStartValue]
-osx
diff --git a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
index 4c999ff88f..e516c0e826 100644
--- a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
+++ b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
@@ -1,8 +1,6 @@
-[startGroupWithRunningChild]
-windows
[finishWithUncontrolledAnimation]
-windows
-osx-10.12
+windows-10 msvc-2015
osx-10.13
[groupWithZeroDurationAnimations]
-osx
+osx-10.13
+
diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
index 6cadebfd7f..78b6449a69 100644
--- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
+++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
@@ -263,7 +263,7 @@ void tst_QTextCodec::fromUnicode()
If the encoding is a superset of ASCII, test that the byte
array is correct (no off by one, no trailing '\0').
*/
- QByteArray result = codec->fromUnicode(QStringViewLiteral("abc"));
+ QByteArray result = codec->fromUnicode(u"abc");
if (result.startsWith('a')) {
QCOMPARE(result.size(), 3);
QCOMPARE(result, QByteArray("abc"));
diff --git a/tests/auto/corelib/corelib.pro b/tests/auto/corelib/corelib.pro
index 44e1c519b0..d696e174aa 100644
--- a/tests/auto/corelib/corelib.pro
+++ b/tests/auto/corelib/corelib.pro
@@ -13,5 +13,7 @@ SUBDIRS = \
plugin \
serialization \
statemachine \
+ text \
thread \
+ time \
tools
diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp
index 72b086350e..1568855032 100644
--- a/tests/auto/corelib/global/qflags/tst_qflags.cpp
+++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp
@@ -142,7 +142,6 @@ void tst_QFlags::signedness()
std::is_signed<Qt::Alignment::Int>::value));
}
-#if defined(Q_COMPILER_CLASS_ENUM)
enum class MyStrictEnum { StrictZero, StrictOne, StrictTwo, StrictFour=4 };
Q_DECLARE_FLAGS( MyStrictFlags, MyStrictEnum )
Q_DECLARE_OPERATORS_FOR_FLAGS( MyStrictFlags )
@@ -154,11 +153,9 @@ Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isComplex );
Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isStatic );
Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isLarge );
Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isPointer );
-#endif
void tst_QFlags::classEnum()
{
-#if defined(Q_COMPILER_CLASS_ENUM)
// The main aim of the test is making sure it compiles
// The QCOMPARE are there as an extra
MyStrictEnum e1 = MyStrictEnum::StrictOne;
@@ -257,27 +254,19 @@ void tst_QFlags::classEnum()
// Just to make sure it compiles
if (false)
qDebug() << f3;
-#endif
}
void tst_QFlags::initializerLists()
{
-#if defined(Q_COMPILER_INITIALIZER_LISTS)
Qt::MouseButtons bts = { Qt::LeftButton, Qt::RightButton };
QVERIFY(bts.testFlag(Qt::LeftButton));
QVERIFY(bts.testFlag(Qt::RightButton));
QVERIFY(!bts.testFlag(Qt::MiddleButton));
-#if defined(Q_COMPILER_CLASS_ENUM)
MyStrictNoOpFlags flags = { MyStrictNoOpEnum::StrictOne, MyStrictNoOpEnum::StrictFour };
QVERIFY(flags.testFlag(MyStrictNoOpEnum::StrictOne));
QVERIFY(flags.testFlag(MyStrictNoOpEnum::StrictFour));
QVERIFY(!flags.testFlag(MyStrictNoOpEnum::StrictTwo));
-#endif // Q_COMPILER_CLASS_ENUM
-
-#else
- QSKIP("This test requires C++11 initializer_list support.");
-#endif // Q_COMPILER_INITIALIZER_LISTS
}
void tst_QFlags::testSetFlags()
diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
index b73a297245..5c7737085e 100644
--- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
+++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 by Southwest Research Institute (R)
** Contact: https://www.qt.io/licensing/
**
@@ -48,6 +49,7 @@ private slots:
void arithOps();
void floatToFloat16();
void floatFromFloat16();
+ void limits();
};
void tst_qfloat16::fuzzyCompare_data()
@@ -347,5 +349,164 @@ void tst_qfloat16::floatFromFloat16()
QCOMPARE(out[i], expected[i]);
}
+static qfloat16 powf16(qfloat16 base, int raise)
+{
+ const qfloat16 one(1.f);
+ if (raise < 0) {
+ raise = -raise;
+ base = one / base;
+ }
+ qfloat16 answer = (raise & 1) ? base : one;
+ while (raise > 0) {
+ raise >>= 1;
+ base *= base;
+ if (raise & 1)
+ answer *= base;
+ }
+ return answer;
+}
+
+void tst_qfloat16::limits()
+{
+ // *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy
+ // comparison, and we need exact here.
+ using Bounds = std::numeric_limits<qfloat16>;
+ QVERIFY(Bounds::is_specialized);
+ QVERIFY(Bounds::is_signed);
+ QVERIFY(!Bounds::is_integer);
+ QVERIFY(!Bounds::is_exact);
+ QVERIFY(Bounds::is_iec559);
+ QVERIFY(Bounds::is_bounded);
+ QVERIFY(!Bounds::is_modulo);
+ QVERIFY(!Bounds::traps);
+ QVERIFY(Bounds::has_infinity);
+ QVERIFY(Bounds::has_quiet_NaN);
+ QVERIFY(Bounds::has_signaling_NaN);
+ QCOMPARE(Bounds::has_denorm, std::denorm_present);
+ QCOMPARE(Bounds::round_style, std::round_to_nearest);
+ QCOMPARE(Bounds::radix, 2);
+ // Untested: has_denorm_loss
+
+ // A few common values:
+ const qfloat16 zero(0), one(1), ten(10);
+ QVERIFY(qIsFinite(zero));
+ QVERIFY(!qIsInf(zero));
+ QVERIFY(!qIsNaN(zero));
+ QCOMPARE(qFpClassify(zero), FP_ZERO);
+ QVERIFY(qIsFinite(one));
+ QVERIFY(!qIsInf(one));
+ QCOMPARE(qFpClassify(one), FP_NORMAL);
+ QVERIFY(!qIsNaN(one));
+ QVERIFY(qIsFinite(ten));
+ QVERIFY(!qIsInf(ten));
+ QVERIFY(!qIsNaN(ten));
+ QCOMPARE(qFpClassify(ten), FP_NORMAL);
+
+ // digits in the mantissa, including the implicit 1 before the binary dot at its left:
+ QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1)));
+ QVERIFY(qfloat16(1 << Bounds::digits) + one == qfloat16(1 << Bounds::digits));
+
+ // There is a wilful of-by-one in how m(ax|in)_exponent are defined; they're
+ // the lowest and highest n for which radix^{n-1} are normal and finite.
+ const qfloat16 two(Bounds::radix);
+ qfloat16 bit = powf16(two, Bounds::max_exponent - 1);
+ QVERIFY(qIsFinite(bit));
+ QVERIFY(qIsInf(bit * two));
+ bit = powf16(two, Bounds::min_exponent - 1);
+ QVERIFY(bit.isNormal());
+ QCOMPARE(qFpClassify(bit), FP_NORMAL);
+ QVERIFY(!(bit / two).isNormal());
+ QCOMPARE(qFpClassify(bit / two), FP_SUBNORMAL);
+ QVERIFY(bit / two > zero);
+
+ // Base ten (with no matching off-by-one idiocy):
+ // the lowest negative number n such that 10^n is a valid normalized value
+ qfloat16 low10(powf16(ten, Bounds::min_exponent10));
+ QVERIFY(low10 > zero);
+ QVERIFY(low10.isNormal());
+ low10 /= ten;
+ QVERIFY(low10 == zero || !low10.isNormal());
+ // the largest positive number n such that 10^n is a representable finite value
+ qfloat16 high10(powf16(ten, Bounds::max_exponent10));
+ QVERIFY(high10 > zero);
+ QVERIFY(qIsFinite(high10));
+ QVERIFY(!qIsFinite(high10 * ten));
+ QCOMPARE(qFpClassify(high10), FP_NORMAL);
+
+ // How many digits are significant ? (Casts avoid linker errors ...)
+ QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits:
+ qfloat16 below(9.785e-4f), above(9.794e-4f);
+#if 0 // Sadly, the QEMU x-compile for arm64 "optimises" comparisons:
+ const bool overOptimised = false;
+#else
+ const bool overOptimised = (below != above);
+ if (overOptimised)
+ QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+#endif // (but it did, so should, pass everywhere else, confirming digits10 is indeed 3).
+ QVERIFY(below == above);
+ QCOMPARE(int(Bounds::max_digits10), 5); // we need 5 to distinguish these two:
+ QVERIFY(qfloat16(1000.5f) != qfloat16(1001.4f));
+
+ // Actual limiting values of the type:
+ const qfloat16 rose(one + Bounds::epsilon());
+ QVERIFY(rose > one);
+ if (overOptimised)
+ QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ QVERIFY(one + Bounds::epsilon() / rose == one);
+ QVERIFY(qIsInf(Bounds::infinity()));
+ QVERIFY(!qIsNaN(Bounds::infinity()));
+ QVERIFY(!qIsFinite(Bounds::infinity()));
+ QCOMPARE(Bounds::infinity(), Bounds::infinity());
+ QCOMPARE(qFpClassify(Bounds::infinity()), FP_INFINITE);
+
+ QVERIFY(Bounds::infinity() > -Bounds::infinity());
+ QVERIFY(Bounds::infinity() > zero);
+ QVERIFY(qIsInf(-Bounds::infinity()));
+ QVERIFY(!qIsNaN(-Bounds::infinity()));
+ QVERIFY(!qIsFinite(-Bounds::infinity()));
+ QCOMPARE(-Bounds::infinity(), -Bounds::infinity());
+ QCOMPARE(qFpClassify(-Bounds::infinity()), FP_INFINITE);
+
+ QVERIFY(-Bounds::infinity() < zero);
+ QVERIFY(qIsNaN(Bounds::quiet_NaN()));
+ QVERIFY(!qIsInf(Bounds::quiet_NaN()));
+ QVERIFY(!qIsFinite(Bounds::quiet_NaN()));
+ QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN()));
+ QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN());
+ QCOMPARE(qFpClassify(Bounds::quiet_NaN()), FP_NAN);
+
+ QVERIFY(Bounds::max() > zero);
+ QVERIFY(qIsFinite(Bounds::max()));
+ QVERIFY(!qIsInf(Bounds::max()));
+ QVERIFY(!qIsNaN(Bounds::max()));
+ QVERIFY(qIsInf(Bounds::max() * rose));
+ QCOMPARE(qFpClassify(Bounds::max()), FP_NORMAL);
+
+ QVERIFY(Bounds::lowest() < zero);
+ QVERIFY(qIsFinite(Bounds::lowest()));
+ QVERIFY(!qIsInf(Bounds::lowest()));
+ QVERIFY(!qIsNaN(Bounds::lowest()));
+ QVERIFY(qIsInf(Bounds::lowest() * rose));
+ QCOMPARE(qFpClassify(Bounds::lowest()), FP_NORMAL);
+
+ QVERIFY(Bounds::min() > zero);
+ QVERIFY(Bounds::min().isNormal());
+ QVERIFY(!(Bounds::min() / rose).isNormal());
+ QVERIFY(qIsFinite(Bounds::min()));
+ QVERIFY(!qIsInf(Bounds::min()));
+ QVERIFY(!qIsNaN(Bounds::min()));
+ QCOMPARE(qFpClassify(Bounds::min()), FP_NORMAL);
+
+ QVERIFY(Bounds::denorm_min() > zero);
+ QVERIFY(!Bounds::denorm_min().isNormal());
+ QVERIFY(qIsFinite(Bounds::denorm_min()));
+ QVERIFY(!qIsInf(Bounds::denorm_min()));
+ QVERIFY(!qIsNaN(Bounds::denorm_min()));
+ if (overOptimised)
+ QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ QCOMPARE(Bounds::denorm_min() / rose, zero);
+ QCOMPARE(qFpClassify(Bounds::denorm_min()), FP_SUBNORMAL);
+}
+
QTEST_APPLESS_MAIN(tst_qfloat16)
#include "tst_qfloat16.moc"
diff --git a/tests/auto/corelib/global/qglobal/qglobal.c b/tests/auto/corelib/global/qglobal/qglobal.c
index 0719c4b921..c7124454d0 100644
--- a/tests/auto/corelib/global/qglobal/qglobal.c
+++ b/tests/auto/corelib/global/qglobal/qglobal.c
@@ -85,7 +85,7 @@ int tst_QtVersion()
return QT_VERSION;
}
-const char *tst_qVersion() Q_DECL_NOTHROW
+const char *tst_qVersion() Q_DECL_NOEXCEPT
{
#if !defined(QT_NAMESPACE)
return qVersion();
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 7800a101ec..b33dec8a61 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -456,12 +456,8 @@ typedef int (Empty::*memFun) ();
} while (false) \
/**/
-#ifdef Q_COMPILER_RVALUE_REFS
#define TEST_AlignOf_RValueRef(type, alignment) \
TEST_AlignOf_impl(type, alignment)
-#else
-#define TEST_AlignOf_RValueRef(type, alignment) do {} while (false)
-#endif
#define TEST_AlignOf_impl(type, alignment) \
do { \
diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
index 2d7db813dd..820a0b999b 100644
--- a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
+++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
@@ -145,7 +145,7 @@ void tst_QGlobalStatic::exception()
exceptionCaught = true;
}
QVERIFY(exceptionCaught);
- QCOMPARE(Q_QGS_throwingGS::guard.load(), 0);
+ QCOMPARE(Q_QGS_throwingGS::guard.loadRelaxed(), 0);
QVERIFY(!throwingGS.exists());
QVERIFY(!throwingGS.isDestroyed());
}
@@ -154,10 +154,10 @@ QBasicAtomicInt exceptionControlVar = Q_BASIC_ATOMIC_INITIALIZER(1);
Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, exceptionGS, (exceptionControlVar))
void tst_QGlobalStatic::catchExceptionAndRetry()
{
- if (exceptionControlVar.load() != 1)
+ if (exceptionControlVar.loadRelaxed() != 1)
QSKIP("This test cannot be run more than once");
- ThrowingType::constructedCount.store(0);
- ThrowingType::destructedCount.store(0);
+ ThrowingType::constructedCount.storeRelaxed(0);
+ ThrowingType::destructedCount.storeRelaxed(0);
bool exceptionCaught = false;
try {
@@ -165,11 +165,11 @@ void tst_QGlobalStatic::catchExceptionAndRetry()
} catch (int) {
exceptionCaught = true;
}
- QCOMPARE(ThrowingType::constructedCount.load(), 1);
+ QCOMPARE(ThrowingType::constructedCount.loadRelaxed(), 1);
QVERIFY(exceptionCaught);
exceptionGS();
- QCOMPARE(ThrowingType::constructedCount.load(), 2);
+ QCOMPARE(ThrowingType::constructedCount.loadRelaxed(), 2);
}
QBasicAtomicInt threadStressTestControlVar = Q_BASIC_ATOMIC_INITIALIZER(5);
@@ -194,9 +194,9 @@ void tst_QGlobalStatic::threadStressTest()
}
};
- ThrowingType::constructedCount.store(0);
- ThrowingType::destructedCount.store(0);
- int expectedConstructionCount = threadStressTestControlVar.load() + 1;
+ ThrowingType::constructedCount.storeRelaxed(0);
+ ThrowingType::destructedCount.storeRelaxed(0);
+ int expectedConstructionCount = threadStressTestControlVar.loadRelaxed() + 1;
if (expectedConstructionCount <= 0)
QSKIP("This test cannot be run more than once");
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
index d3ed1a6d0d..17d0f86728 100644
--- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -48,8 +48,10 @@ private slots:
void defaultHandler();
void installMessageHandler();
+#if QT_DEPRECATED_SINCE(5, 0)
void installMsgHandler();
void installBothHandler();
+#endif
#ifdef QT_BUILD_INTERNAL
void cleanupFuncinfo_data();
@@ -112,7 +114,9 @@ void tst_qmessagehandler::initTestCase()
void tst_qmessagehandler::cleanup()
{
+#if QT_DEPRECATED_SINCE(5, 0)
qInstallMsgHandler(0);
+#endif
qInstallMessageHandler((QtMessageHandler)0);
s_type = QtFatalMsg;
s_file = 0;
@@ -143,6 +147,7 @@ void tst_qmessagehandler::installMessageHandler()
QCOMPARE((void*)myHandler, (void*)customMessageHandler);
}
+#if QT_DEPRECATED_SINCE(5, 0)
void tst_qmessagehandler::installMsgHandler()
{
QtMsgHandler oldHandler = qInstallMsgHandler(customMsgHandler);
@@ -172,6 +177,7 @@ void tst_qmessagehandler::installBothHandler()
QCOMPARE(s_function, Q_FUNC_INFO);
QCOMPARE(s_line, line);
}
+#endif
# define ADD(x) QTest::newRow(x) << Q_FUNC_INFO << x;
@@ -254,19 +260,15 @@ public:
int rvalue() && { ADD("TestClass1::rvalue"); return 0; }
int const_rvalue() const && { ADD("TestClass1::const_rvalue"); return 0; }
#endif
-#ifdef Q_COMPILER_DECLTYPE
int decltype_param(int x = 0, decltype(x) = 0) { ADD("TestClass1::decltype_param"); return x; }
template<typename T> int decltype_template_param(T x = 0, decltype(x) = 0)
{ ADD("TestClass1::decltype_template_param"); return x; }
template<typename T> void decltype_template_param2(T x, decltype(x + QString()))
{ ADD("TestClass1::decltype_template_param2"); }
-# ifdef Q_COMPILER_AUTO_FUNCTION
auto decltype_return(int x = 0) -> decltype(x)
{ ADD("TestClass1::decltype_return"); return x; }
template <typename T> auto decltype_template_return(T x = 0) -> decltype(x)
{ ADD("TestClass1::decltype_template_return"); return x; }
-# endif
-#endif
public:
TestClass1()
@@ -323,15 +325,11 @@ public:
std::move(*this).rvalue();
std::move(*this).const_rvalue();
#endif
-#ifdef Q_COMPILER_DECLTYPE
decltype_param();
decltype_template_param(0);
decltype_template_param2(QByteArray(), QString());
-# ifdef Q_COMPILER_AUTO_FUNCTION
decltype_return();
decltype_template_return(0);
-# endif
-#endif
}
};
@@ -878,12 +876,14 @@ void tst_qmessagehandler::setMessagePattern()
#endif
// make sure there is no QT_MESSAGE_PATTERN in the environment
- QStringList environment = m_baseEnvironment;
- QMutableListIterator<QString> iter(environment);
- while (iter.hasNext()) {
- if (iter.next().startsWith("QT_MESSAGE_PATTERN"))
- iter.remove();
- }
+ QStringList environment;
+ environment.reserve(m_baseEnvironment.size());
+ const auto doesNotStartWith = [](QLatin1String s) {
+ return [s](const QString &str) { return !str.startsWith(s); };
+ };
+ std::copy_if(m_baseEnvironment.cbegin(), m_baseEnvironment.cend(),
+ std::back_inserter(environment),
+ doesNotStartWith(QLatin1String("QT_MESSAGE_PATTERN")));
process.setEnvironment(environment);
process.start(appExe);
diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
index 03300c6dbe..0a84b1fdd8 100644
--- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
+++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -42,7 +42,8 @@ class tst_QNumeric: public QObject
private slots:
void fuzzyCompare_data();
void fuzzyCompare();
- void qNan();
+ void qNanInf();
+ void classifyfp();
void floatDistance_data();
void floatDistance();
void floatDistance_double_data();
@@ -91,7 +92,7 @@ void tst_QNumeric::fuzzyCompare()
# pragma GCC optimize "no-fast-math"
#endif
-void tst_QNumeric::qNan()
+void tst_QNumeric::qNanInf()
{
#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404)
QSKIP("Non-conformant fast math mode is enabled, cannot run test");
@@ -99,9 +100,16 @@ void tst_QNumeric::qNan()
double nan = qQNaN();
QVERIFY(!(0 > nan));
QVERIFY(!(0 < nan));
+ QVERIFY(!(0 == nan));
+ QVERIFY(!(nan == nan));
QVERIFY(qIsNaN(nan));
QVERIFY(qIsNaN(nan + 1));
QVERIFY(qIsNaN(-nan));
+ QVERIFY(qIsNaN(1.0 / nan));
+ QVERIFY(qIsNaN(0.0 / nan));
+ QVERIFY(qIsNaN(0.0 * nan));
+ QCOMPARE(nan, nan);
+ QCOMPARE(nan, -nan);
Q_STATIC_ASSERT(sizeof(double) == 8);
#ifdef Q_LITTLE_ENDIAN
@@ -113,17 +121,56 @@ void tst_QNumeric::qNan()
QVERIFY(!qIsFinite(nan));
QVERIFY(!qIsInf(nan));
QVERIFY(qIsNaN(nan));
+ QVERIFY(qIsNaN(-nan));
+ QVERIFY(!(nan == nan));
+ QVERIFY(qIsNaN(0.0 * nan));
+ QCOMPARE(qFpClassify(nan), FP_NAN);
+ QCOMPARE(nan, nan);
+ QCOMPARE(nan, -nan);
+ QCOMPARE(nan, qQNaN());
double inf = qInf();
QVERIFY(inf > 0);
QVERIFY(-inf < 0);
QVERIFY(qIsInf(inf));
+ QCOMPARE(inf, inf);
+ QCOMPARE(-inf, -inf);
QVERIFY(qIsInf(-inf));
- QVERIFY(qIsInf(2*inf));
- QCOMPARE(1/inf, 0.0);
- QVERIFY(qIsNaN(0*nan));
- QVERIFY(qIsNaN(0*inf));
- QVERIFY(qFuzzyCompare(1/inf, 0.0));
+ QVERIFY(qIsInf(inf + 1));
+ QVERIFY(qIsInf(inf - 1));
+ QVERIFY(qIsInf(inf * 2.0));
+ QVERIFY(qIsInf(inf / 2.0));
+ QVERIFY(qFuzzyCompare(1.0 / inf, 0.0));
+ QCOMPARE(1.0 / inf, 0.0);
+ QVERIFY(qIsNaN(0.0 * inf));
+}
+
+void tst_QNumeric::classifyfp()
+{
+ QCOMPARE(qFpClassify(qQNaN()), FP_NAN);
+
+ QCOMPARE(qFpClassify(qInf()), FP_INFINITE);
+ QCOMPARE(qFpClassify(-qInf()), FP_INFINITE);
+ QCOMPARE(qFpClassify(DBL_MAX * 2.0), FP_INFINITE);
+ QCOMPARE(qFpClassify(FLT_MAX * 2.f), FP_INFINITE);
+ QCOMPARE(qFpClassify(DBL_MAX * -2.0), FP_INFINITE);
+ QCOMPARE(qFpClassify(FLT_MAX * -2.f), FP_INFINITE);
+
+ QCOMPARE(qFpClassify(1.0), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(-DBL_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(-DBL_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN / 2.0), FP_SUBNORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN / -2.0), FP_SUBNORMAL);
+
+ QCOMPARE(qFpClassify(1.f), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(-FLT_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(-FLT_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN / 2.f), FP_SUBNORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN / -2.f), FP_SUBNORMAL);
}
void tst_QNumeric::floatDistance_data()
@@ -461,13 +508,13 @@ template <typename Int> static void mulOverflow_template()
QCOMPARE(mul_overflow(Int(max / 2), Int(3), &r), true);
QCOMPARE(mul_overflow(mid1, Int(mid2 + 1), &r), true);
QCOMPARE(mul_overflow(Int(max / 2 + 2), Int(2), &r), true);
+ QCOMPARE(mul_overflow(Int(max - max / 2), Int(2), &r), true);
QCOMPARE(mul_overflow(Int(1ULL << (std::numeric_limits<Int>::digits - 1)), Int(2), &r), true);
if (min) {
QCOMPARE(mul_overflow(min, Int(2), &r), true);
QCOMPARE(mul_overflow(Int(min / 2), Int(3), &r), true);
QCOMPARE(mul_overflow(Int(min / 2 - 1), Int(2), &r), true);
- QCOMPARE(mul_overflow(Int(min + min/2), Int(2), &r), true);
}
#endif
}
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
index 7c04611823..e238be1de3 100644
--- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
+++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
@@ -57,7 +57,7 @@ static const double RandomValueFP = double(0.3010463714599609);
static void setRNGControl(uint v)
{
#ifdef QT_BUILD_INTERNAL
- qt_randomdevice_control.store(v);
+ qt_randomdevice_control.storeRelaxed(v);
#else
Q_UNUSED(v);
#endif
@@ -511,7 +511,7 @@ void tst_QRandomGenerator::generateNonContiguous()
QFETCH(uint, control);
RandomGenerator rng(control);
- QLinkedList<quint64> list = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ std::list<quint64> list(8);
auto longerArrayCheck = [&] {
QRandomGenerator().generate(list.begin(), list.end());
return find_if(list.begin(), list.end(), [&](quint64 cur) {
diff --git a/tests/auto/corelib/io/largefile/tst_largefile.cpp b/tests/auto/corelib/io/largefile/tst_largefile.cpp
index dca7672b8e..e6d2f10c16 100644
--- a/tests/auto/corelib/io/largefile/tst_largefile.cpp
+++ b/tests/auto/corelib/io/largefile/tst_largefile.cpp
@@ -28,7 +28,6 @@
#include <QTest>
-#include <QtAlgorithms>
#include <QFile>
#include <QFileInfo>
#include <QRandomGenerator>
@@ -36,6 +35,7 @@
#include <QDebug>
+#include <algorithm>
#include <cstdlib>
#include <cstdio>
@@ -489,13 +489,13 @@ void tst_LargeFile::mapFile()
// Keep full block mapped to facilitate OS and/or internal reuse by Qt.
uchar *baseAddress = largeFile.map(position, blockSize);
QVERIFY( baseAddress );
- QVERIFY( qEqual(block.begin(), block.end(), reinterpret_cast<char*>(baseAddress)) );
+ QVERIFY( std::equal(block.begin(), block.end(), reinterpret_cast<char*>(baseAddress)) );
for (int offset = 1; offset < blockSize; ++offset) {
uchar *address = largeFile.map(position + offset, blockSize - offset);
QVERIFY( address );
- if ( !qEqual(block.begin() + offset, block.end(), reinterpret_cast<char*>(address)) ) {
+ if ( !std::equal(block.begin() + offset, block.end(), reinterpret_cast<char*>(address)) ) {
qDebug() << "Expected:" << block.toHex();
qDebug() << "Actual :" << QByteArray(reinterpret_cast<char*>(address), blockSize).toHex();
QVERIFY(false);
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 7b8b1df166..584e66a7db 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -309,7 +309,7 @@ void tst_QDebug::stateSaver() const
QDebug d = qDebug();
{
QDebugStateSaver saver(d);
- d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42;
+ d.nospace() << Qt::hex << Qt::right << qSetFieldWidth(3) << qSetPadChar('0') << 42;
}
d << 42;
}
@@ -327,7 +327,7 @@ void tst_QDebug::stateSaver() const
{
QDebug d = qDebug();
- d.noquote().nospace() << QStringLiteral("Hello") << hex << 42;
+ d.noquote().nospace() << QStringLiteral("Hello") << Qt::hex << 42;
{
QDebugStateSaver saver(d);
d.resetFormat();
@@ -506,7 +506,7 @@ void tst_QDebug::qDebugQStringView() const
{
QLatin1String file, function;
int line = 0;
- const QStringView inView = QStringViewLiteral("input");
+ const QStringView inView = u"input";
MessageHandlerSetter mhs(myMessageHandler);
{ qDebug() << inView; }
@@ -660,7 +660,7 @@ void tst_QDebug::textStreamModifiers() const
QString file, function;
int line = 0;
MessageHandlerSetter mhs(myMessageHandler);
- { qDebug() << hex << short(0xf) << int(0xf) << unsigned(0xf) << long(0xf) << qint64(0xf) << quint64(0xf); }
+ { qDebug() << Qt::hex << short(0xf) << int(0xf) << unsigned(0xf) << long(0xf) << qint64(0xf) << quint64(0xf); }
#ifndef QT_NO_MESSAGELOGCONTEXT
file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
#endif
@@ -678,7 +678,7 @@ void tst_QDebug::resetFormat() const
MessageHandlerSetter mhs(myMessageHandler);
{
QDebug d = qDebug();
- d.nospace().noquote() << hex << int(0xf);
+ d.nospace().noquote() << Qt::hex << int(0xf);
d.resetFormat() << int(0xf) << QStringLiteral("foo");
}
#ifndef QT_NO_MESSAGELOGCONTEXT
diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp
index b703a8839f..52e7ebadb1 100644
--- a/tests/auto/corelib/io/qdir/tst_qdir.cpp
+++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp
@@ -349,21 +349,21 @@ void tst_QDir::mkdirRmdir_data()
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("recurse");
- QStringList dirs;
- dirs << "testdir/one"
- << "testdir/two/three/four"
- << "testdir/../testdir/three";
- QTest::newRow("plain") << QDir::currentPath() + "/" + dirs.at(0) << false;
- QTest::newRow("recursive") << QDir::currentPath() + "/" + dirs.at(1) << true;
- QTest::newRow("with-..") << QDir::currentPath() + "/" + dirs.at(2) << false;
-
- QTest::newRow("relative-plain") << dirs.at(0) << false;
- QTest::newRow("relative-recursive") << dirs.at(1) << true;
- QTest::newRow("relative-with-..") << dirs.at(2) << false;
-
- // Ensure that none of these directories already exist
- for (int i = 0; i < dirs.count(); ++i)
- QVERIFY(!QFile::exists(dirs.at(i)));
+ const struct {
+ const char *name; // shall have a prefix added
+ const char *path; // relative
+ bool recurse;
+ } cases[] = {
+ { "plain", "testdir/one", false },
+ { "recursive", "testdir/two/three/four", true },
+ { "with-..", "testdir/../testdir/three", false },
+ };
+
+ for (const auto &it : cases) {
+ QVERIFY(!QFile::exists(it.path));
+ QTest::addRow("absolute-%s", it.name) << (QDir::currentPath() + "/") + it.path << it.recurse;
+ QTest::addRow("relative-%s", it.name) << QString::fromLatin1(it.path) << it.recurse;
+ }
}
void tst_QDir::mkdirRmdir()
@@ -1268,6 +1268,7 @@ tst_QDir::cleanPath_data()
QTest::newRow("drive-above-root") << "A:/.." << "A:/..";
QTest::newRow("unc-server-up") << "//server/path/.." << "//server";
QTest::newRow("unc-server-above-root") << "//server/.." << "//server/..";
+ QTest::newRow("longpath") << "\\\\?\\d:\\" << "d:/";
#else
QTest::newRow("data15") << "//c:/foo" << "/c:/foo";
#endif // non-windows
@@ -1745,6 +1746,7 @@ void tst_QDir::nativeSeparators()
QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("/")), QString("/"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\")), QString("/"));
+ QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\\\?\\C:\\")), QString("C:/"));
#else
QCOMPARE(QDir::toNativeSeparators(QLatin1String("/")), QString("/"));
QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\"));
diff --git a/tests/auto/corelib/io/qfile/BLACKLIST b/tests/auto/corelib/io/qfile/BLACKLIST
deleted file mode 100644
index 8366667166..0000000000
--- a/tests/auto/corelib/io/qfile/BLACKLIST
+++ /dev/null
@@ -1,7 +0,0 @@
-# QTBUG-48455
-[readLineStdin]
-msvc-2015 ci
-msvc-2017 ci
-[readLineStdin_lineByLine]
-msvc-2015 ci
-msvc-2017 ci
diff --git a/tests/auto/corelib/io/qfile/test.pro b/tests/auto/corelib/io/qfile/test.pro
index 95389ab3e2..7a2767bf3c 100644
--- a/tests/auto/corelib/io/qfile/test.pro
+++ b/tests/auto/corelib/io/qfile/test.pro
@@ -23,4 +23,4 @@ TESTDATA += \
Makefile forCopying.txt forRenaming.txt \
resources/file1.ext1
-win32:!winrt: LIBS += -lole32 -luuid
+win32:!winrt: QMAKE_USE += ole32 uuid
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 678a80c3f7..4f010f37c2 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2099,7 +2099,7 @@ void tst_QFile::i18nFileName()
QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData());
QTextStream ts(&file);
ts.setCodec("UTF-8");
- ts << fileName << endl;
+ ts << fileName << Qt::endl;
}
{
QFile file(fileName);
@@ -2149,7 +2149,7 @@ void tst_QFile::longFileName()
QFile file(fileName);
QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData());
QTextStream ts(&file);
- ts << fileName << endl;
+ ts << fileName << Qt::endl;
}
{
QFile file(fileName);
diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
index 496729f9f1..d181d16a3e 100644
--- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
+++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
@@ -5,4 +5,4 @@ SOURCES = tst_qfileinfo.cpp
RESOURCES += qfileinfo.qrc \
testdata.qrc
-win32:!winrt: LIBS += -ladvapi32 -lnetapi32
+win32:!winrt: QMAKE_USE += advapi32 netapi32
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index 646fb2078a..16fcafa248 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -237,6 +237,15 @@ private slots:
void isSymLink_data();
void isSymLink();
+ void isSymbolicLink_data();
+ void isSymbolicLink();
+
+ void isShortcut_data();
+ void isShortcut();
+
+ void link_data();
+ void link();
+
void isHidden_data();
void isHidden();
#if defined(Q_OS_MAC)
@@ -1036,7 +1045,9 @@ void tst_QFileInfo::systemFiles()
QCOMPARE(fi.metadataChangeTime(), fi.lastModified()); // On Windows, they're the same
QVERIFY(fi.birthTime().isValid());
QVERIFY(fi.birthTime() <= fi.lastModified());
+#if QT_DEPRECATED_SINCE(5, 10)
QCOMPARE(fi.created(), fi.birthTime()); // On Windows, they're the same
+#endif
}
void tst_QFileInfo::compare_data()
@@ -1184,7 +1195,7 @@ void tst_QFileInfo::fileTimes()
QTest::qSleep(sleepTime);
beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
QTextStream ts(&file);
- ts << fileName << endl;
+ ts << fileName << Qt::endl;
}
{
QFileInfo fileInfo(fileName);
@@ -1261,7 +1272,7 @@ void tst_QFileInfo::fakeFileTimes_data()
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);
+ QTest::newRow("XP-bug") << QDateTime::fromSecsSinceEpoch(1269593170);
}
void tst_QFileInfo::fakeFileTimes()
@@ -1335,6 +1346,176 @@ void tst_QFileInfo::isSymLink()
#endif
}
+void tst_QFileInfo::isShortcut_data()
+{
+ QFile::remove("link.lnk");
+ QFile::remove("symlink.lnk");
+ QFile::remove("link");
+ QFile::remove("symlink");
+ QFile::remove("directory.lnk");
+ QFile::remove("directory");
+
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("isShortcut");
+
+ QFile regularFile(m_sourceFile);
+ QTest::newRow("regular")
+ << regularFile.fileName() << false;
+ QTest::newRow("directory")
+ << QDir::currentPath() << false;
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ // windows shortcuts
+ QVERIFY(regularFile.link("link.lnk"));
+ QTest::newRow("shortcut")
+ << "link.lnk" << true;
+ QVERIFY(regularFile.link("link"));
+ QTest::newRow("invalid-shortcut")
+ << "link" << false;
+ QVERIFY(QFile::link(QDir::currentPath(), "directory.lnk"));
+ QTest::newRow("directory-shortcut")
+ << "directory.lnk" << true;
+#endif
+}
+
+void tst_QFileInfo::isShortcut()
+{
+ QFETCH(QString, path);
+ QFETCH(bool, isShortcut);
+
+ QFileInfo fi(path);
+ QCOMPARE(fi.isShortcut(), isShortcut);
+}
+
+void tst_QFileInfo::isSymbolicLink_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("isSymbolicLink");
+
+ QFile regularFile(m_sourceFile);
+ QTest::newRow("regular")
+ << regularFile.fileName() << false;
+ QTest::newRow("directory")
+ << QDir::currentPath() << false;
+
+#ifndef Q_NO_SYMLINKS
+#if defined(Q_OS_WIN)
+#if !defined(Q_OS_WINRT)
+ QString errorMessage;
+ const DWORD creationResult = createSymbolicLink("symlink", m_sourceFile, &errorMessage);
+ if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
+ QWARN(msgInsufficientPrivileges(errorMessage));
+ } else {
+ QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ QTest::newRow("NTFS-symlink")
+ << "symlink" << true;
+ }
+#endif // !Q_OS_WINRT
+#else // Unix:
+ QVERIFY(regularFile.link("symlink.lnk"));
+ QTest::newRow("symlink.lnk")
+ << "symlink.lnk" << true;
+ QVERIFY(regularFile.link("symlink"));
+ QTest::newRow("symlink")
+ << "symlink" << true;
+ QVERIFY(QFile::link(QDir::currentPath(), "directory"));
+ QTest::newRow("directory-symlink")
+ << "directory" << true;
+#endif
+#endif // !Q_NO_SYMLINKS
+}
+
+void tst_QFileInfo::isSymbolicLink()
+{
+ QFETCH(QString, path);
+ QFETCH(bool, isSymbolicLink);
+
+ QFileInfo fi(path);
+ QCOMPARE(fi.isSymbolicLink(), isSymbolicLink);
+}
+
+void tst_QFileInfo::link_data()
+{
+ QFile::remove("link");
+ QFile::remove("link.lnk");
+ QFile::remove("brokenlink");
+ QFile::remove("brokenlink.lnk");
+ QFile::remove("dummyfile");
+ QFile::remove("relative/link");
+
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("isShortcut");
+ QTest::addColumn<bool>("isSymbolicLink");
+ QTest::addColumn<QString>("linkTarget");
+
+ QFile file1(m_sourceFile);
+ QFile file2("dummyfile");
+ file2.open(QIODevice::WriteOnly);
+
+ QTest::newRow("existent file") << m_sourceFile << false << false << "";
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ // windows shortcuts
+ QVERIFY(file1.link("link.lnk"));
+ QTest::newRow("link.lnk")
+ << "link.lnk" << true << false << QFileInfo(m_sourceFile).absoluteFilePath();
+
+ QVERIFY(file2.link("brokenlink.lnk"));
+ QTest::newRow("broken link.lnk")
+ << "brokenlink.lnk" << true << false << QFileInfo("dummyfile").absoluteFilePath();
+#endif
+
+#ifndef Q_NO_SYMLINKS
+#if defined(Q_OS_WIN)
+#if !defined(Q_OS_WINRT)
+ QString errorMessage;
+ DWORD creationResult = createSymbolicLink("link", m_sourceFile, &errorMessage);
+ if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
+ QWARN(msgInsufficientPrivileges(errorMessage));
+ } else {
+ QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ QTest::newRow("link")
+ << "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
+ }
+
+ creationResult = createSymbolicLink("brokenlink", "dummyfile", &errorMessage);
+ if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
+ QWARN(msgInsufficientPrivileges(errorMessage));
+ } else {
+ QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ QTest::newRow("broken link")
+ << "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
+ }
+#endif // !Q_OS_WINRT
+#else // Unix:
+ QVERIFY(file1.link("link"));
+ QTest::newRow("link")
+ << "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
+
+ QVERIFY(file2.link("brokenlink"));
+ QTest::newRow("broken link")
+ << "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
+
+ QDir::current().mkdir("relative");
+ QFile::link("../dummyfile", "relative/link");
+ QTest::newRow("relative link")
+ << "relative/link" << false << true << QFileInfo("dummyfile").absoluteFilePath();
+#endif
+#endif // !Q_NO_SYMLINKS
+ file2.remove();
+}
+
+void tst_QFileInfo::link()
+{
+ QFETCH(QString, path);
+ QFETCH(bool, isShortcut);
+ QFETCH(bool, isSymbolicLink);
+ QFETCH(QString, linkTarget);
+
+ QFileInfo fi(path);
+ QCOMPARE(fi.isShortcut(), isShortcut);
+ QCOMPARE(fi.isSymbolicLink(), isSymbolicLink);
+ QCOMPARE(fi.symLinkTarget(), linkTarget);
+}
+
void tst_QFileInfo::isHidden_data()
{
QTest::addColumn<QString>("path");
@@ -1636,7 +1817,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
QFileInfo fi(path);
- const bool actualIsSymLink = fi.isSymLink();
+ const bool actualIsSymLink = fi.isSymbolicLink();
const QString actualSymLinkTarget = isSymLink ? fi.symLinkTarget() : QString();
const QString actualCanonicalFilePath = isSymLink ? fi.canonicalFilePath() : QString();
// Ensure that junctions, mountpoints are removed. If this fails, do not remove
@@ -1665,14 +1846,16 @@ void tst_QFileInfo::brokenShortcut()
file.close();
QFileInfo info(linkName);
- QVERIFY(info.isSymLink());
+ QVERIFY(!info.isSymbolicLink());
+ QVERIFY(info.isShortcut());
QVERIFY(!info.exists());
QFile::remove(linkName);
QDir current; // QTBUG-21863
QVERIFY(current.mkdir(linkName));
QFileInfo dirInfo(linkName);
- QVERIFY(!dirInfo.isSymLink());
+ QVERIFY(!dirInfo.isSymbolicLink());
+ QVERIFY(!dirInfo.isShortcut());
QVERIFY(dirInfo.isDir());
current.rmdir(linkName);
}
@@ -1915,7 +2098,7 @@ void tst_QFileInfo::owner()
DWORD bufSize = 1024;
if (GetUserNameW(usernameBuf, &bufSize)) {
userName = QString::fromWCharArray(usernameBuf);
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && IsUserAdmin()) {
+ if (IsUserAdmin()) {
// Special case : If the user is a member of Administrators group, all files
// created by the current user are owned by the Administrators group.
LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
@@ -2029,7 +2212,8 @@ static void stateCheck(const QFileInfo &info, const QString &dirname, const QStr
QVERIFY(!info.isHidden());
QVERIFY(!info.isFile());
QVERIFY(!info.isDir());
- QVERIFY(!info.isSymLink());
+ QVERIFY(!info.isSymbolicLink());
+ QVERIFY(!info.isShortcut());
QVERIFY(!info.isBundle());
QVERIFY(!info.isRoot());
QCOMPARE(info.isNativePath(), !filename.isEmpty());
@@ -2042,7 +2226,9 @@ static void stateCheck(const QFileInfo &info, const QString &dirname, const QStr
QCOMPARE(info.permissions(), QFile::Permissions());
+#if QT_DEPRECATED_SINCE(5, 10)
QVERIFY(!info.created().isValid());
+#endif
QVERIFY(!info.birthTime().isValid());
QVERIFY(!info.metadataChangeTime().isValid());
QVERIFY(!info.lastRead().isValid());
@@ -2084,5 +2270,6 @@ void tst_QFileInfo::nonExistingFile()
stateCheck(info, dirname, filename);
}
+
QTEST_MAIN(tst_QFileInfo)
#include "tst_qfileinfo.moc"
diff --git a/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST b/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST
index 90b714758a..457499591d 100644
--- a/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST
+++ b/tests/auto/corelib/io/qfilesystemwatcher/BLACKLIST
@@ -1,6 +1,7 @@
# QTBUG-33574 QTBUG-30943
[signalsEmittedAfterFileMoved]
-windows
+windows-7sp1
+windows-10
[watchFileAndItsDirectory:native backend-testfile]
osx
windows
diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
index 67ffa91e57..cdd1f6361e 100644
--- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
+++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
@@ -46,11 +46,13 @@ public:
tst_QFileSystemWatcher();
private slots:
+#ifdef QT_BUILD_INTERNAL
void basicTest_data();
void basicTest();
void watchDirectory_data();
void watchDirectory();
+#endif
void addPath();
void removePath();
@@ -58,8 +60,10 @@ private slots:
void removePaths();
void removePathsFilesInSameDirectory();
+#ifdef QT_BUILD_INTERNAL
void watchFileAndItsDirectory_data() { basicTest_data(); }
void watchFileAndItsDirectory();
+#endif
void nonExistingFile();
@@ -67,8 +71,10 @@ private slots:
void destroyAfterQCoreApplication();
+#ifdef QT_BUILD_INTERNAL
void QTBUG2331();
void QTBUG2331_data() { basicTest_data(); }
+#endif
void signalsEmittedAfterFileMoved();
@@ -90,6 +96,7 @@ tst_QFileSystemWatcher::tst_QFileSystemWatcher()
#endif
}
+#ifdef QT_BUILD_INTERNAL
void tst_QFileSystemWatcher::basicTest_data()
{
QTest::addColumn<QString>("backend");
@@ -360,6 +367,7 @@ void tst_QFileSystemWatcher::watchDirectory()
for (const auto &testDirName : testDirs)
QVERIFY(temporaryDir.rmdir(testDirName));
}
+#endif // QT_BUILD_INTERNAL
void tst_QFileSystemWatcher::addPath()
{
@@ -502,6 +510,7 @@ void tst_QFileSystemWatcher::removePathsFilesInSameDirectory()
QCOMPARE(watcher.files().size(), 0);
}
+#ifdef QT_BUILD_INTERNAL
static QByteArray msgFileOperationFailed(const char *what, const QFile &f)
{
return what + QByteArrayLiteral(" failed on \"")
@@ -601,6 +610,7 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory()
QVERIFY(temporaryDir.rmdir(testDirName));
}
+#endif // QT_BUILD_INTERNAL
void tst_QFileSystemWatcher::nonExistingFile()
{
@@ -673,6 +683,7 @@ void tst_QFileSystemWatcher::destroyAfterQCoreApplication()
QTest::qWait(30);
}
+#ifdef QT_BUILD_INTERNAL
// regression test for QTBUG2331.
// essentially, on windows, directories were not unwatched after being deleted
// from the disk, causing all sorts of interesting problems.
@@ -696,6 +707,7 @@ void tst_QFileSystemWatcher::QTBUG2331()
QTRY_COMPARE(changedSpy.count(), 1);
QCOMPARE(watcher.directories(), QStringList());
}
+#endif // QT_BUILD_INTERNAL
class SignalReceiver : public QObject
{
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
index eeeb3bc6e2..8703b15dda 100644
--- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
@@ -496,7 +496,7 @@ void tst_QLockFile::noPermissionsWindows()
QSKIP("This test is for desktop Windows only");
#endif
#ifdef Q_OS_WIN
- if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows7)
QSKIP("This test requires at least Windows 7");
#endif
if (const int p = processProperties()) {
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
index da2660fd02..e33e22b36f 100644
--- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
@@ -3,4 +3,4 @@ TARGET = tst_qlockfile
SOURCES += tst_qlockfile.cpp
QT = core-private testlib concurrent
-win32:!winrt:LIBS += -ladvapi32
+win32:!winrt: QMAKE_USE += advapi32
diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
index 11a9b3f189..79ac6b0fc4 100644
--- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
+++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
@@ -104,7 +104,7 @@ public:
for (int a = 0; a < _configitemEntryOrder.count(); a++) {
out << _configitemEntryOrder[a]
<< " = "
- << _values.value(_configitemEntryOrder[a]) << endl;
+ << _values.value(_configitemEntryOrder[a]) << Qt::endl;
}
out.flush();
return ret.toLatin1();
@@ -369,11 +369,9 @@ private slots:
}
Q_LOGGING_CATEGORY(TST_MACRO_1, "tst.macro.1")
-#ifdef Q_COMPILER_VARIADIC_MACROS
Q_LOGGING_CATEGORY(TST_MACRO_2, "tst.macro.2", QtDebugMsg)
Q_LOGGING_CATEGORY(TST_MACRO_3, "tst.macro.3", QtFatalMsg)
Q_LOGGING_CATEGORY(TST_MACRO_4, "tst.macro.4", QtInfoMsg)
-#endif
void QLoggingCategoryMacro()
{
@@ -384,7 +382,6 @@ private slots:
QCOMPARE(cat1.isWarningEnabled(), true);
QCOMPARE(cat1.isCriticalEnabled(), true);
-#ifdef Q_COMPILER_VARIADIC_MACROS
const QLoggingCategory &cat2 = TST_MACRO_2();
QCOMPARE(cat2.categoryName(), "tst.macro.2");
QCOMPARE(cat2.isDebugEnabled(), true);
@@ -405,7 +402,6 @@ private slots:
QCOMPARE(cat4.isInfoEnabled(), true);
QCOMPARE(cat4.isWarningEnabled(), true);
QCOMPARE(cat4.isCriticalEnabled(), true);
-#endif
}
void qCDebugMacros()
diff --git a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
index 569c610e24..b05c89a8bb 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::noDebugOutput() const
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 debugString = dt.toString(u"yyyy-MM-dd HH:mm:ss.zzz t").toLatin1();
const QByteArray message = "QDateTime(" + debugString + " Qt::LocalTime)";
QTest::ignoreMessage(QtWarningMsg, message.constData());
qWarning() << dt;
diff --git a/tests/auto/corelib/io/qprocess/BLACKLIST b/tests/auto/corelib/io/qprocess/BLACKLIST
index b355bb0f75..682bcbc60c 100644
--- a/tests/auto/corelib/io/qprocess/BLACKLIST
+++ b/tests/auto/corelib/io/qprocess/BLACKLIST
@@ -2,8 +2,5 @@
redhatenterpriselinuxworkstation-6.6
# QTBUG-48455
[fileWriterProcess]
-msvc-2015 ci
-msvc-2017 ci
-[softExitInSlots]
-# QTBUG-66903
-windows
+windows-10 msvc-2017
+
diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro
index 935f43630c..e41ed0a425 100644
--- a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro
+++ b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro
@@ -1,6 +1,6 @@
win32 {
SOURCES = main_win.cpp
- LIBS += -luser32
+ QMAKE_USE += user32
}
CONFIG -= qt app_bundle
diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
index 2cfcb4794e..964c47f6ae 100644
--- a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
+++ b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
@@ -1,6 +1,6 @@
win32 {
SOURCES = main_win.cpp
- LIBS += -luser32
+ QMAKE_USE += user32
}
unix {
SOURCES = main_unix.cpp
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index c51994c1c1..e799369c8a 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -32,6 +32,7 @@
#include <QtTest/QtTest>
#include <QtCore/QProcess>
#include <QtCore/QDir>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QThread>
#include <QtCore/QTemporaryDir>
@@ -150,6 +151,13 @@ private slots:
void failToStartEmptyArgs_data();
void failToStartEmptyArgs();
+#if QT_DEPRECATED_SINCE(5, 13)
+ void crashTest2_deprecated();
+ void restartProcessDeadlock_deprecated();
+ void waitForReadyReadInAReadyReadSlot_deprecated();
+ void finishProcessBeforeReadingDone_deprecated();
+#endif
+
protected slots:
void readFromProcess();
void exitLoopSlot();
@@ -186,12 +194,20 @@ void tst_QProcess::getSetCheck()
QProcess obj1;
// ProcessChannelMode QProcess::readChannelMode()
// void QProcess::setProcessChannelMode(ProcessChannelMode)
+#if QT_DEPRECATED_SINCE(5, 13)
obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels));
QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.readChannelMode());
obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels));
QCOMPARE(QProcess::ProcessChannelMode(QProcess::MergedChannels), obj1.readChannelMode());
obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels));
QCOMPARE(QProcess::ProcessChannelMode(QProcess::ForwardedChannels), obj1.readChannelMode());
+#endif
+ obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels));
+ QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.processChannelMode());
+ obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels));
+ QCOMPARE(QProcess::ProcessChannelMode(QProcess::MergedChannels), obj1.processChannelMode());
+ obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels));
+ QCOMPARE(QProcess::ProcessChannelMode(QProcess::ForwardedChannels), obj1.processChannelMode());
// ProcessChannel QProcess::readChannel()
// void QProcess::setReadChannel(ProcessChannel)
@@ -334,12 +350,14 @@ void tst_QProcess::crashTest()
qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
QSignalSpy spy(process.data(), &QProcess::errorOccurred);
- QSignalSpy spy2(process.data(), static_cast<QProcessErrorSignal>(&QProcess::error));
- QSignalSpy spy3(process.data(), static_cast<QProcessFinishedSignal2>(&QProcess::finished));
-
+ QSignalSpy spy2(process.data(), static_cast<QProcessFinishedSignal2>(&QProcess::finished));
QVERIFY(spy.isValid());
QVERIFY(spy2.isValid());
+
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy spy3(process.data(), static_cast<QProcessErrorSignal>(&QProcess::error));
QVERIFY(spy3.isValid());
+#endif
QVERIFY(process->waitForFinished(30000));
@@ -347,10 +365,12 @@ void tst_QProcess::crashTest()
QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed);
QCOMPARE(spy2.count(), 1);
- QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy2.at(0).at(0).constData()), QProcess::Crashed);
+ QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit);
+#if QT_DEPRECATED_SINCE(5, 6)
QCOMPARE(spy3.count(), 1);
- QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy3.at(0).at(1).constData()), QProcess::CrashExit);
+ QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy3.at(0).at(0).constData()), QProcess::Crashed);
+#endif
QCOMPARE(process->exitStatus(), QProcess::CrashExit);
@@ -378,7 +398,7 @@ void tst_QProcess::crashTest2()
QVERIFY(spy.isValid());
QVERIFY(spy2.isValid());
- QObject::connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ QObject::connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished),
this, &tst_QProcess::exitLoopSlot);
QTestEventLoop::instance().enterLoop(30);
@@ -420,7 +440,7 @@ void tst_QProcess::echoTest()
process.write(input);
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
do {
QVERIFY(process.isOpen());
@@ -479,7 +499,7 @@ void tst_QProcess::echoTest2()
QVERIFY(spy1.isValid());
QVERIFY(spy2.isValid());
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
forever {
QTestEventLoop::instance().enterLoop(1);
@@ -644,9 +664,11 @@ void tst_QProcess::readTimeoutAndThenCrash()
qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
QSignalSpy spy(&process, &QProcess::errorOccurred);
- QSignalSpy spy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
QVERIFY(spy.isValid());
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy spy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
QVERIFY(spy2.isValid());
+#endif
process.kill();
@@ -655,8 +677,10 @@ void tst_QProcess::readTimeoutAndThenCrash()
QCOMPARE(spy.count(), 1);
QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed);
+#if QT_DEPRECATED_SINCE(5, 6)
QCOMPARE(spy2.count(), 1);
QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy2.at(0).at(0).constData()), QProcess::Crashed);
+#endif
}
void tst_QProcess::waitForFinished()
@@ -696,12 +720,11 @@ void tst_QProcess::deadWhileReading()
void tst_QProcess::restartProcessDeadlock()
{
-
// The purpose of this test is to detect whether restarting a
// process in the finished() connected slot causes a deadlock
// because of the way QProcessManager uses its locks.
QProcess process;
- connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished),
this, &tst_QProcess::restartProcess);
process.start("testProcessEcho/testProcessEcho");
@@ -709,7 +732,7 @@ void tst_QProcess::restartProcessDeadlock()
QCOMPARE(process.write("", 1), qlonglong(1));
QVERIFY(process.waitForFinished(5000));
- QObject::disconnect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), nullptr, nullptr);
+ QObject::disconnect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), nullptr, nullptr);
QCOMPARE(process.write("", 1), qlonglong(1));
QVERIFY(process.waitForFinished(5000));
@@ -1026,7 +1049,7 @@ void tst_QProcess::mergedChannels()
{
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
- QCOMPARE(process.readChannelMode(), QProcess::MergedChannels);
+ QCOMPARE(process.processChannelMode(), QProcess::MergedChannels);
process.start("testProcessEcho2/testProcessEcho2");
@@ -1154,7 +1177,7 @@ protected:
exitCode = 90210;
QProcess process;
- connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished),
this, &TestThread::catchExitCode, Qt::DirectConnection);
process.start("testProcessEcho/testProcessEcho");
@@ -1228,7 +1251,7 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlot()
{
QProcess process;
connect(&process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot);
- connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished),
this, &tst_QProcess::exitLoopSlot);
bytesAvailable = 0;
@@ -1467,15 +1490,19 @@ void tst_QProcess::failToStart()
QProcess process;
QSignalSpy stateSpy(&process, &QProcess::stateChanged);
QSignalSpy errorSpy(&process, &QProcess::errorOccurred);
- QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
- QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
- QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
-
+ QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
QVERIFY(stateSpy.isValid());
QVERIFY(errorSpy.isValid());
- QVERIFY(errorSpy2.isValid());
QVERIFY(finishedSpy.isValid());
+
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
+ QVERIFY(errorSpy2.isValid());
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
+ QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
QVERIFY(finishedSpy2.isValid());
+#endif
// OS X and HP-UX have a really low default process limit (~100), so spawning
// to many processes here will cause test failures later on.
@@ -1490,7 +1517,9 @@ void tst_QProcess::failToStart()
for (int j = 0; j < 8; ++j) {
for (int i = 0; i < attempts; ++i) {
QCOMPARE(errorSpy.count(), j * attempts + i);
+#if QT_DEPRECATED_SINCE(5, 6)
QCOMPARE(errorSpy2.count(), j * attempts + i);
+#endif
process.start("/blurp");
switch (j) {
@@ -1515,9 +1544,13 @@ void tst_QProcess::failToStart()
QCOMPARE(process.error(), QProcess::FailedToStart);
QCOMPARE(errorSpy.count(), j * attempts + i + 1);
- QCOMPARE(errorSpy2.count(), j * attempts + i + 1);
QCOMPARE(finishedSpy.count(), 0);
+#if QT_DEPRECATED_SINCE(5, 6)
+ QCOMPARE(errorSpy2.count(), j * attempts + i + 1);
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
QCOMPARE(finishedSpy2.count(), 0);
+#endif
int it = j * attempts + i + 1;
@@ -1536,14 +1569,18 @@ void tst_QProcess::failToStartWithWait()
QProcess process;
QEventLoop loop;
QSignalSpy errorSpy(&process, &QProcess::errorOccurred);
- QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
- QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
- QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
-
+ QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
QVERIFY(errorSpy.isValid());
- QVERIFY(errorSpy2.isValid());
QVERIFY(finishedSpy.isValid());
+
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
+ QVERIFY(errorSpy2.isValid());
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
+ QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
QVERIFY(finishedSpy2.isValid());
+#endif
for (int i = 0; i < 50; ++i) {
process.start("/blurp", QStringList() << "-v" << "-debug");
@@ -1551,9 +1588,14 @@ void tst_QProcess::failToStartWithWait()
QCOMPARE(process.error(), QProcess::FailedToStart);
QCOMPARE(errorSpy.count(), i + 1);
- QCOMPARE(errorSpy2.count(), i + 1);
QCOMPARE(finishedSpy.count(), 0);
+#if QT_DEPRECATED_SINCE(5, 6)
+ QCOMPARE(errorSpy2.count(), i + 1);
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
QCOMPARE(finishedSpy2.count(), 0);
+#endif
+
}
}
@@ -1565,14 +1607,18 @@ void tst_QProcess::failToStartWithEventLoop()
QProcess process;
QEventLoop loop;
QSignalSpy errorSpy(&process, &QProcess::errorOccurred);
- QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
- QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
- QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
-
+ QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
QVERIFY(errorSpy.isValid());
- QVERIFY(errorSpy2.isValid());
QVERIFY(finishedSpy.isValid());
+
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
+ QVERIFY(errorSpy2.isValid());
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
+ QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
QVERIFY(finishedSpy2.isValid());
+#endif
// The error signal may be emitted before start() returns
connect(&process, &QProcess::errorOccurred, &loop, &QEventLoop::quit, Qt::QueuedConnection);
@@ -1585,9 +1631,13 @@ void tst_QProcess::failToStartWithEventLoop()
QCOMPARE(process.error(), QProcess::FailedToStart);
QCOMPARE(errorSpy.count(), i + 1);
- QCOMPARE(errorSpy2.count(), i + 1);
QCOMPARE(finishedSpy.count(), 0);
+#if QT_DEPRECATED_SINCE(5, 6)
+ QCOMPARE(errorSpy2.count(), i + 1);
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
QCOMPARE(finishedSpy2.count(), 0);
+#endif
}
}
@@ -1605,8 +1655,12 @@ void tst_QProcess::failToStartEmptyArgs()
qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
QProcess process;
- QSignalSpy errorSpy(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
+ QSignalSpy errorSpy(&process, static_cast<QProcessErrorSignal>(&QProcess::errorOccurred));
QVERIFY(errorSpy.isValid());
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
+ QVERIFY(errorSpy2.isValid());
+#endif
switch (startOverload) {
case 0:
@@ -1624,6 +1678,9 @@ void tst_QProcess::failToStartEmptyArgs()
QVERIFY(!process.waitForStarted());
QCOMPARE(errorSpy.count(), 1);
+#if QT_DEPRECATED_SINCE(5, 6)
+ QCOMPARE(errorSpy2.count(), 1);
+#endif
QCOMPARE(process.error(), QProcess::FailedToStart);
}
@@ -1855,24 +1912,32 @@ void tst_QProcess::waitForReadyReadForNonexistantProcess()
QProcess process;
QSignalSpy errorSpy(&process, &QProcess::errorOccurred);
+ QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
+ QVERIFY(errorSpy.isValid());
+ QVERIFY(finishedSpy.isValid());
+
+#if QT_DEPRECATED_SINCE(5, 6)
QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
+ QVERIFY(errorSpy2.isValid());
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
QSignalSpy finishedSpy1(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished));
- QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
-
- QVERIFY(errorSpy.isValid());
- QVERIFY(errorSpy2.isValid());
QVERIFY(finishedSpy1.isValid());
- QVERIFY(finishedSpy2.isValid());
+#endif
QVERIFY(!process.waitForReadyRead()); // used to crash
process.start("doesntexist");
QVERIFY(!process.waitForReadyRead());
QCOMPARE(errorSpy.count(), 1);
QCOMPARE(errorSpy.at(0).at(0).toInt(), 0);
+ QCOMPARE(finishedSpy.count(), 0);
+#if QT_DEPRECATED_SINCE(5, 6)
QCOMPARE(errorSpy2.count(), 1);
QCOMPARE(errorSpy2.at(0).at(0).toInt(), 0);
+#endif
+#if QT_DEPRECATED_SINCE(5, 13)
QCOMPARE(finishedSpy1.count(), 0);
- QCOMPARE(finishedSpy2.count(), 0);
+#endif
}
void tst_QProcess::setStandardInputFile()
@@ -2072,7 +2137,7 @@ void tst_QProcess::fileWriterProcess()
stdinStr += line;
}
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
const QString fileName = m_temporaryDir.path() + QLatin1String("/fileWriterProcess.txt");
const QString binary = QDir::currentPath() + QLatin1String("/fileWriterProcess/fileWriterProcess");
@@ -2303,14 +2368,18 @@ void tst_QProcess::invalidProgramString()
qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
QSignalSpy spy(&process, &QProcess::errorOccurred);
- QSignalSpy spy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
QVERIFY(spy.isValid());
+#if QT_DEPRECATED_SINCE(5, 6)
+ QSignalSpy spy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error));
QVERIFY(spy2.isValid());
+#endif
process.start(programString);
QCOMPARE(process.error(), QProcess::FailedToStart);
QCOMPARE(spy.count(), 1);
+#if QT_DEPRECATED_SINCE(5, 6)
QCOMPARE(spy2.count(), 1);
+#endif
QVERIFY(!QProcess::startDetached(programString));
}
@@ -2364,7 +2433,7 @@ void tst_QProcess::finishProcessBeforeReadingDone()
QProcess process;
BlockOnReadStdOut blocker(&process);
QEventLoop loop;
- connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished),
&loop, &QEventLoop::quit);
process.start("testProcessOutput/testProcessOutput");
QVERIFY(process.waitForStarted());
@@ -2510,5 +2579,106 @@ void tst_QProcess::processEventsInAReadyReadSlot()
QVERIFY(process.waitForFinished());
}
+#if QT_DEPRECATED_SINCE(5, 13)
+
+void tst_QProcess::crashTest2_deprecated()
+{
+ QProcess process;
+ process.start("testProcessCrash/testProcessCrash");
+ QVERIFY(process.waitForStarted(5000));
+
+ qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
+ qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
+
+ QSignalSpy spy(&process, static_cast<QProcessErrorSignal>(&QProcess::errorOccurred));
+ QSignalSpy spy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished));
+
+ QVERIFY(spy.isValid());
+ QVERIFY(spy2.isValid());
+
+ QObject::connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ this, &tst_QProcess::exitLoopSlot);
+
+ QTestEventLoop::instance().enterLoop(30);
+ if (QTestEventLoop::instance().timeout())
+ QFAIL("Failed to detect crash : operation timed out");
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed);
+
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit);
+
+ QCOMPARE(process.exitStatus(), QProcess::CrashExit);
+}
+
+void tst_QProcess::restartProcessDeadlock_deprecated()
+{
+ // The purpose of this test is to detect whether restarting a
+ // process in the finished() connected slot causes a deadlock
+ // because of the way QProcessManager uses its locks.
+ QProcess process;
+ connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ this, &tst_QProcess::restartProcess);
+
+ process.start("testProcessEcho/testProcessEcho");
+
+ QCOMPARE(process.write("", 1), qlonglong(1));
+ QVERIFY(process.waitForFinished(5000));
+
+ QObject::disconnect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), nullptr, nullptr);
+
+ QCOMPARE(process.write("", 1), qlonglong(1));
+ QVERIFY(process.waitForFinished(5000));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+void tst_QProcess::waitForReadyReadInAReadyReadSlot_deprecated()
+{
+ QProcess process;
+ connect(&process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot);
+ connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ this, &tst_QProcess::exitLoopSlot);
+ bytesAvailable = 0;
+
+ process.start("testProcessEcho/testProcessEcho");
+ QVERIFY(process.waitForStarted(5000));
+
+ QSignalSpy spy(&process, &QProcess::readyRead);
+ QVERIFY(spy.isValid());
+ process.write("foo");
+ QTestEventLoop::instance().enterLoop(30);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(spy.count(), 1);
+
+ process.disconnect();
+ QVERIFY(process.waitForFinished(5000));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+ QVERIFY(process.bytesAvailable() > bytesAvailable);
+}
+
+void tst_QProcess::finishProcessBeforeReadingDone_deprecated()
+{
+ QProcess process;
+ BlockOnReadStdOut blocker(&process);
+ QEventLoop loop;
+ connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished),
+ &loop, &QEventLoop::quit);
+ process.start("testProcessOutput/testProcessOutput");
+ QVERIFY(process.waitForStarted());
+ loop.exec();
+ QStringList lines = QString::fromLocal8Bit(process.readAllStandardOutput()).split(
+ QRegExp(QStringLiteral("[\r\n]")), QString::SkipEmptyParts);
+ QVERIFY(!lines.isEmpty());
+ QCOMPARE(lines.last(), QStringLiteral("10239 -this is a number"));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+#endif
+
QTEST_MAIN(tst_QProcess)
#include "tst_qprocess.moc"
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
index 0b50c391b8..44c8c4b681 100644
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -55,6 +55,10 @@ private slots:
void checkStructure();
void searchPath_data();
void searchPath();
+#if QT_DEPRECATED_SINCE(5, 13)
+ void searchPath_deprecated_data();
+ void searchPath_deprecated();
+#endif
void doubleSlashInRoot();
void setLocale();
void lastModified();
@@ -420,6 +424,58 @@ void tst_QResourceEngine::checkStructure()
void tst_QResourceEngine::searchPath_data()
{
+ auto searchPath = QFileInfo(QFINDTESTDATA("testqrc")).canonicalFilePath();
+
+ QTest::addColumn<QString>("searchPathPrefix");
+ QTest::addColumn<QString>("searchPath");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QByteArray>("expected");
+
+ QTest::newRow("no_search_path")
+ << QString()
+ << QString()
+ << ":search_file.txt"
+ << QByteArray("root\n");
+ QTest::newRow("path1")
+ << "searchpath1"
+ << searchPath
+ << "searchpath1:searchpath1/search_file.txt"
+ << QByteArray("path1\n");
+ QTest::newRow("no_search_path2")
+ << QString()
+ << QString()
+ << ":/search_file.txt"
+ << QByteArray("root\n");
+ QTest::newRow("path2")
+ << "searchpath2"
+ << searchPath + "/searchpath2"
+ << "searchpath2:search_file.txt"
+ << QByteArray("path2\n");
+}
+
+void tst_QResourceEngine::searchPath()
+{
+ QFETCH(QString, searchPathPrefix);
+ QFETCH(QString, searchPath);
+ QFETCH(QString, file);
+ QFETCH(QByteArray, expected);
+
+ if (!searchPath.isEmpty())
+ QDir::addSearchPath(searchPathPrefix, searchPath);
+ QFile qf(file);
+ QVERIFY(qf.open(QFile::ReadOnly));
+ QByteArray actual = qf.readAll();
+
+ actual.replace('\r', "");
+
+ QCOMPARE(actual, expected);
+ qf.close();
+}
+
+#if QT_DEPRECATED_SINCE(5, 13)
+
+void tst_QResourceEngine::searchPath_deprecated_data()
+{
QTest::addColumn<QString>("searchPath");
QTest::addColumn<QString>("file");
QTest::addColumn<QByteArray>("expected");
@@ -438,7 +494,7 @@ void tst_QResourceEngine::searchPath_data()
<< QByteArray("path2\n");
}
-void tst_QResourceEngine::searchPath()
+void tst_QResourceEngine::searchPath_deprecated()
{
QFETCH(QString, searchPath);
QFETCH(QString, file);
@@ -456,6 +512,8 @@ void tst_QResourceEngine::searchPath()
qf.close();
}
+#endif
+
void tst_QResourceEngine::checkUnregisterResource_data()
{
QTest::addColumn<QString>("rcc_file");
@@ -505,15 +563,15 @@ void tst_QResourceEngine::setLocale()
// default constructed QResource gets the default locale
QResource resource;
resource.setFileName("aliasdir/aliasdir.txt");
- QVERIFY(!resource.isCompressed());
+ QCOMPARE(resource.compressionAlgorithm(), QResource::NoCompression);
// change the default locale and make sure it doesn't affect the resource
QLocale::setDefault(QLocale("de_CH"));
- QVERIFY(!resource.isCompressed());
+ QCOMPARE(resource.compressionAlgorithm(), QResource::NoCompression);
// then explicitly set the locale on qresource
resource.setLocale(QLocale("de_CH"));
- QVERIFY(resource.isCompressed());
+ QVERIFY(resource.compressionAlgorithm() != QResource::NoCompression);
// the reset the default locale back
QLocale::setDefault(QLocale::system());
diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro
index 79552b62df..98ea337e7f 100644
--- a/tests/auto/corelib/io/qsettings/qsettings.pro
+++ b/tests/auto/corelib/io/qsettings/qsettings.pro
@@ -5,7 +5,7 @@ SOURCES = tst_qsettings.cpp
RESOURCES += qsettings.qrc
INCLUDEPATH += $$PWD/../../kernel/qmetatype
-msvc: LIBS += advapi32.lib
+msvc: QMAKE_USE += advapi32
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 8b69518ef7..289590a233 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -311,8 +311,11 @@ void tst_QSettings::initTestCase()
void tst_QSettings::cleanupTestFiles()
{
- QSettings::setSystemIniPath(settingsPath("__system__"));
- QSettings::setUserIniPath(settingsPath("__user__"));
+ QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, settingsPath("__system__"));
+ QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, settingsPath("__system__"));
+
+ QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath("__user__"));
+ QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, settingsPath("__user__"));
QDir settingsDir(settingsPath());
if (settingsDir.exists())
@@ -1363,7 +1366,9 @@ void tst_QSettings::testVariantTypes()
if (format >= QSettings::InvalidFormat) {
testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QKeySequence, KeySequence);
} else {
- testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QString, String);
+ testVal("keysequence",
+ QKeySequence(Qt::ControlModifier + Qt::Key_F1).toString(QKeySequence::NativeText),
+ QString, String);
}
#undef testVal
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index 1379c788d1..56d924dcc6 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -32,8 +32,8 @@
#include <qstandardpaths.h>
#include <qfileinfo.h>
#include <qsysinfo.h>
-#include <qregexp.h>
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+#include <qregularexpression.h>
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
# include <qt_windows.h>
#endif
@@ -131,7 +131,7 @@ static const char * const enumNames[MaxStandardLocation + 1 - int(QStandardPaths
void tst_qstandardpaths::initTestCase()
{
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// Disable WOW64 redirection, see testFindExecutable()
if (QSysInfo::buildCpuArchitecture() != QSysInfo::currentCpuArchitecture()) {
void *oldMode;
@@ -140,7 +140,7 @@ void tst_qstandardpaths::initTestCase()
qErrnoWarning("Wow64DisableWow64FsRedirection() failed");
QVERIFY(disabledDisableWow64FsRedirection);
}
-#endif // Q_OS_WIN && !Q_OS_WINRT && !Q_OS_WINCE
+#endif // Q_OS_WIN && !Q_OS_WINRT
QVERIFY2(m_localConfigTempDir.isValid(), qPrintable(m_localConfigTempDir.errorString()));
QVERIFY2(m_globalConfigTempDir.isValid(), qPrintable(m_globalConfigTempDir.errorString()));
QVERIFY2(m_localAppTempDir.isValid(), qPrintable(m_localAppTempDir.errorString()));
@@ -566,7 +566,8 @@ void tst_qstandardpaths::testAllWritableLocations()
void tst_qstandardpaths::testCleanPath()
{
- const QRegExp filter(QStringLiteral("\\\\"));
+#if QT_CONFIG(regularexpression)
+ const QRegularExpression filter(QStringLiteral("\\\\"));
QVERIFY(filter.isValid());
for (int i = 0; i <= QStandardPaths::GenericCacheLocation; ++i) {
const QStringList paths = QStandardPaths::standardLocations(QStandardPaths::StandardLocation(i));
@@ -574,6 +575,9 @@ void tst_qstandardpaths::testCleanPath()
qPrintable(QString::fromLatin1("Backslash found in %1 %2")
.arg(i).arg(paths.join(QLatin1Char(',')))));
}
+#else
+ QSKIP("regularexpression feature disabled");
+#endif
}
void tst_qstandardpaths::testXdgPathCleanup()
diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
index b8f67c7d37..00417fffa0 100644
--- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
+++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
@@ -215,7 +215,7 @@ void tst_QTemporaryFile::fileTemplate()
if (!fileTemplate.isEmpty())
file.setFileTemplate(fileTemplate);
- QCOMPARE(file.open(), true);
+ QVERIFY2(file.open(), qPrintable(file.errorString()));
QString fileName = QFileInfo(file).fileName();
if (prefix.length())
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 9c106c7f58..3123c42326 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -136,8 +136,8 @@ private slots:
void emptyQueryOrFragment();
void hasFragment_data();
void hasFragment();
- void setEncodedFragment_data();
- void setEncodedFragment();
+ void setFragment_data();
+ void setFragment();
void fromEncoded();
void stripTrailingSlash_data();
void stripTrailingSlash();
@@ -350,15 +350,15 @@ void tst_QUrl::comparison()
// 6.2.2.1 Make sure hexdecimal characters in percent encoding are
// treated case-insensitively
QUrl url5;
- url5.setEncodedQuery("a=%2a");
+ url5.setQuery(QLatin1String("a=%2a"));
QUrl url6;
- url6.setEncodedQuery("a=%2A");
+ url6.setQuery(QLatin1String("a=%2A"));
QCOMPARE(url5, url6);
QUrl url7;
- url7.setEncodedQuery("a=C");
+ url7.setQuery(QLatin1String("a=C"));
QUrl url8;
- url8.setEncodedQuery("a=c");
+ url8.setQuery(QLatin1String("a=c"));
QVERIFY(url7 != url8);
QVERIFY(url7 < url8);
@@ -502,7 +502,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString::fromLatin1("file"));
QCOMPARE(url.path(), QString::fromLatin1("/"));
- QVERIFY(url.encodedQuery().isEmpty());
+ QVERIFY(url.query().isEmpty());
QVERIFY(url.userInfo().isEmpty());
QVERIFY(url.authority().isEmpty());
QVERIFY(url.fragment().isEmpty());
@@ -517,7 +517,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString::fromLatin1("http"));
QCOMPARE(url.path(), QString());
- QVERIFY(url.encodedQuery().isEmpty());
+ QVERIFY(url.query().isEmpty());
QVERIFY(url.userInfo().isEmpty());
QVERIFY(url.fragment().isEmpty());
QCOMPARE(url.host(), QString::fromLatin1("www.foo.bar"));
@@ -536,7 +536,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString::fromLatin1("http"));
QCOMPARE(url.path(), QString());
- QVERIFY(url.encodedQuery().isEmpty());
+ QVERIFY(url.query().isEmpty());
QCOMPARE(url.userName(), QString::fromLatin1("user:"));
QCOMPARE(url.password(), QString::fromLatin1("pass@"));
QCOMPARE(url.userInfo(), QString::fromLatin1("user%3A:pass@"));
@@ -781,7 +781,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString("http"));
QCOMPARE(url.host(), QString("1.2.3.4"));
- QCOMPARE(url.encodedQuery(), QByteArray("foo"));
+ QCOMPARE(url.query(QUrl::FullyEncoded), QLatin1String("foo"));
}
{
QUrl url;
@@ -798,13 +798,13 @@ void tst_QUrl::setUrl()
QCOMPARE(url.scheme(), QString("data"));
QCOMPARE(url.host(), QString());
QCOMPARE(url.path(), QString("text/javascript,d5 = 'five\\u0027s';"));
- QCOMPARE(url.encodedPath().constData(), "text/javascript,d5%20%3D%20'five%5Cu0027s'%3B");
+ QCOMPARE(url.path(QUrl::FullyEncoded), QLatin1String("text/javascript,d5%20%3D%20'five%5Cu0027s'%3B"));
}
{
// invalid port number
QUrl url;
- url.setEncodedUrl("foo://tel:2147483648");
+ url.setUrl(QLatin1String("foo://tel:2147483648"), QUrl::StrictMode);
QVERIFY(!url.isValid());
}
@@ -1144,7 +1144,7 @@ void tst_QUrl::toString_constructed_data()
QTest::addColumn<QString>("host");
QTest::addColumn<int>("port");
QTest::addColumn<QString>("path");
- QTest::addColumn<QByteArray>("query");
+ QTest::addColumn<QString>("query");
QTest::addColumn<QString>("fragment");
QTest::addColumn<QString>("asString");
QTest::addColumn<QByteArray>("asEncoded");
@@ -1153,19 +1153,19 @@ void tst_QUrl::toString_constructed_data()
QString n("");
QTest::newRow("data1") << n << n << n << QString::fromLatin1("qt-project.org") << -1 << QString::fromLatin1("/index.html")
- << QByteArray() << n << QString::fromLatin1("//qt-project.org/index.html")
+ << QString() << n << QString::fromLatin1("//qt-project.org/index.html")
<< QByteArray("//qt-project.org/index.html") << 0u;
- QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QByteArray()
+ QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QString()
<< n << QString::fromLatin1("file:///root") << QByteArray("file:///root") << 0u;
QTest::newRow("userAndPass") << QString::fromLatin1("http") << QString::fromLatin1("dfaure") << QString::fromLatin1("kde")
- << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
+ << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n
<< QString::fromLatin1("http://dfaure:kde@kde.org:443/") << QByteArray("http://dfaure:kde@kde.org:443/")
<< 0u;
QTest::newRow("PassWithoutUser") << QString::fromLatin1("http") << n << QString::fromLatin1("kde")
- << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
+ << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n
<< QString::fromLatin1("http://:kde@kde.org:443/") << QByteArray("http://:kde@kde.org:443/") << 0u;
QTest::newRow("PassWithoutUser-RemovePassword") << QString::fromLatin1("http") << n << QString::fromLatin1("kde")
- << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
+ << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n
<< QString::fromLatin1("http://kde.org:443/") << QByteArray("http://kde.org:443/")
<< uint(QUrl::RemovePassword);
}
@@ -1178,7 +1178,7 @@ void tst_QUrl::toString_constructed()
QFETCH(QString, host);
QFETCH(int, port);
QFETCH(QString, path);
- QFETCH(QByteArray, query);
+ QFETCH(QString, query);
QFETCH(QString, fragment);
QFETCH(QString, asString);
QFETCH(QByteArray, asEncoded);
@@ -1198,7 +1198,7 @@ void tst_QUrl::toString_constructed()
if (!path.isEmpty())
url.setPath(path);
if (!query.isEmpty())
- url.setEncodedQuery(query);
+ url.setQuery(query, QUrl::StrictMode);
if (!fragment.isEmpty())
url.setFragment(fragment);
@@ -1757,7 +1757,7 @@ void tst_QUrl::symmetry()
QCOMPARE(url.host(QUrl::EncodeUnicode | QUrl::EncodeSpaces), QString::fromUtf8("www.xn--rksmrgs-5wao1o.se"));
QCOMPARE(url.path(), QString::fromLatin1("/pub"));
// this will be encoded ...
- QCOMPARE(url.encodedQuery().constData(), QString::fromLatin1("a=b&a=d%C3%B8&a=f").toLatin1().constData());
+ QCOMPARE(url.query(QUrl::FullyEncoded), QLatin1String("a=b&a=d%C3%B8&a=f"));
QCOMPARE(url.fragment(), QString::fromUtf8("vræl"));
QUrl onlyHost("//qt-project.org");
@@ -2009,7 +2009,7 @@ void tst_QUrl::hasQuery()
QUrl qurl(url);
QCOMPARE(qurl.hasQuery(), trueFalse);
- QCOMPARE(qurl.encodedQuery().isNull(), !trueFalse);
+ QCOMPARE(qurl.query().isNull(), !trueFalse);
}
void tst_QUrl::nameprep()
@@ -2192,10 +2192,12 @@ void tst_QUrl::schemeValidator_data()
QTest::newRow("percent-encoded") << "%68%74%%74%70://example.com" << false << "%68%74%%74%70";
static const char controls[] = "!\"$&'()*,;<=>[\\]^_`{|}~";
- for (size_t i = 0; i < sizeof(controls) - 1; ++i)
- QTest::newRow(("with-" + QByteArray(1, controls[i])).constData())
- << QString("pre%1post://example.com/").arg(QLatin1Char(controls[i]))
- << false << QString("pre%1post").arg(QLatin1Char(controls[i]));
+ for (char control : controls) {
+ const QString scheme = QLatin1String("pre") + QLatin1Char(control) + QLatin1String("post");
+ QTest::newRow((QByteArrayLiteral("with-") + control).constData())
+ << (scheme + QLatin1String("://example.com/"))
+ << false << scheme;
+ }
}
void tst_QUrl::schemeValidator()
@@ -2342,7 +2344,7 @@ void tst_QUrl::tolerantParser()
QVERIFY(url.isValid());
QVERIFY(!url.toString().isEmpty());
QCOMPARE(url.path(), QString("/path with spaces.html"));
- url.setEncodedUrl("http://www.example.com/path%20with spaces.html", QUrl::StrictMode);
+ url.setUrl(QLatin1String("http://www.example.com/path%20with spaces.html"), QUrl::StrictMode);
QVERIFY(!url.isValid());
QVERIFY(url.toString().isEmpty());
}
@@ -2392,36 +2394,36 @@ void tst_QUrl::tolerantParser()
QCOMPARE(url.toEncoded(), QByteArray("%25hello.com/f%25"));
QCOMPARE(url.toString(), QString("%25hello.com/f%25"));
- url.setEncodedUrl("http://www.host.com/foo.php?P0=[2006-3-8]");
+ url.setUrl(QLatin1String("http://www.host.com/foo.php?P0=[2006-3-8]"), QUrl::StrictMode);
QVERIFY(url.isValid());
QVERIFY(!url.toString().isEmpty());
- url.setEncodedUrl("http://foo.bar/[image][1].jpg");
+ url.setUrl(QLatin1String("http://foo.bar/[image][1].jpg"), QUrl::StrictMode);
QVERIFY(url.isValid());
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("http://foo.bar/[image][1].jpg"));
QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/[image][1].jpg"));
QCOMPARE(url.toString(), QString("http://foo.bar/[image][1].jpg"));
- url.setEncodedUrl("http://foo.bar/%5Bimage%5D%5B1%5D.jpg");
+ url.setUrl(QLatin1String("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"), QUrl::StrictMode);
QVERIFY(url.isValid());
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
QCOMPARE(url.toString(), QString("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
- url.setEncodedUrl("//[::56:56:56:56:56:56:56]");
+ url.setUrl(QLatin1String("//[::56:56:56:56:56:56:56]"), QUrl::StrictMode);
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("//[0:56:56:56:56:56:56:56]"));
QCOMPARE(url.toEncoded(), QByteArray("//[0:56:56:56:56:56:56:56]"));
- url.setEncodedUrl("data:text/css,div%20{%20border-right:%20solid;%20}");
+ url.setUrl(QLatin1String("data:text/css,div%20{%20border-right:%20solid;%20}"), QUrl::TolerantMode);
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("data:text/css,div%20%7B%20border-right:%20solid;%20%7D"));
QCOMPARE(url.toEncoded(), QByteArray("data:text/css,div%20%7B%20border-right:%20solid;%20%7D"));
QCOMPARE(url.toString(), QString("data:text/css,div %7B border-right: solid; %7D"));
}
{
- QByteArray tsdgeos("http://google.com/c?c=Translation+%C2%BB+trunk|");
+ const QString tsdgeos = QLatin1String("http://google.com/c?c=Translation+%C2%BB+trunk|");
QUrl tsdgeosQUrl;
- tsdgeosQUrl.setEncodedUrl(tsdgeos, QUrl::TolerantMode);
+ tsdgeosQUrl.setUrl(tsdgeos, QUrl::TolerantMode);
QVERIFY(tsdgeosQUrl.isValid()); // failed in Qt-4.4, works in Qt-4.5
QByteArray tsdgeosExpected("http://google.com/c?c=Translation+%C2%BB+trunk%7C");
QCOMPARE(QString(tsdgeosQUrl.toEncoded()), QString(tsdgeosExpected));
@@ -2626,31 +2628,31 @@ void tst_QUrl::emptyQueryOrFragment()
// start with an empty one
QUrl url("http://www.foo.bar/baz");
QVERIFY(!url.hasQuery());
- QVERIFY(url.encodedQuery().isNull());
+ QVERIFY(url.query().isNull());
// add encodedQuery
url.setQuery("abc=def");
QVERIFY(url.hasQuery());
QCOMPARE(url.query(), QString(QLatin1String("abc=def")));
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def")));
- url.setEncodedQuery("abc=def");
+ url.setQuery(QLatin1String("abc=def"));
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def")));
// remove encodedQuery
url.setQuery(QString());
QVERIFY(!url.hasQuery());
- QVERIFY(url.encodedQuery().isNull());
+ QVERIFY(url.query().isNull());
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz")));
- url.setEncodedQuery(QByteArray());
+ url.setQuery(QString());
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz")));
// add empty encodedQuery
url.setQuery("");
QVERIFY(url.hasQuery());
- QVERIFY(url.encodedQuery().isEmpty());
- QVERIFY(!url.encodedQuery().isNull());
+ QVERIFY(url.query().isEmpty());
+ QVERIFY(!url.query().isNull());
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?")));
- url.setEncodedQuery("");
+ url.setQuery(QLatin1String(""));
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?")));
}
}
@@ -2682,35 +2684,33 @@ void tst_QUrl::hasFragment()
QCOMPARE(qurl.fragment().isNull(), !trueFalse);
}
-void tst_QUrl::setEncodedFragment_data()
+void tst_QUrl::setFragment_data()
{
- QTest::addColumn<QByteArray>("base");
- QTest::addColumn<QByteArray>("fragment");
- QTest::addColumn<QByteArray>("expected");
+ QTest::addColumn<QString>("base");
+ QTest::addColumn<QString>("fragment");
+ QTest::addColumn<QString>("expected");
- typedef QByteArray BA;
- QTest::newRow("null") << BA("http://www.kde.org") << BA() << BA("http://www.kde.org");
- QTest::newRow("empty") << BA("http://www.kde.org") << BA("") << BA("http://www.kde.org#");
- QTest::newRow("basic test") << BA("http://www.kde.org") << BA("abc") << BA("http://www.kde.org#abc");
- QTest::newRow("initial url has fragment") << BA("http://www.kde.org#old") << BA("new") << BA("http://www.kde.org#new");
- QTest::newRow("encoded fragment") << BA("http://www.kde.org") << BA("a%20c") << BA("http://www.kde.org#a%20c");
- QTest::newRow("with #") << BA("http://www.kde.org") << BA("a#b") << BA("http://www.kde.org#a%23b"); // toString uses "a#b"
- QTest::newRow("unicode") << BA("http://www.kde.org") << BA("\xc3\xa9") << BA("http://www.kde.org#%C3%A9");
- QTest::newRow("binary") << BA("http://www.kde.org") << BA("\x00\xc0\x80", 3) << BA("http://www.kde.org#%00%C0%80");
+ QTest::newRow("null") << QString::fromLatin1("http://www.kde.org") << QString() << QString::fromLatin1("http://www.kde.org");
+ QTest::newRow("empty") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("") << QString::fromLatin1("http://www.kde.org#");
+ QTest::newRow("basic test") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("abc") << QString::fromLatin1("http://www.kde.org#abc");
+ QTest::newRow("initial url has fragment") << QString::fromLatin1("http://www.kde.org#old") << QString::fromLatin1("new") << QString::fromLatin1("http://www.kde.org#new");
+ QTest::newRow("encoded fragment") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("a%20c") << QString::fromLatin1("http://www.kde.org#a%20c");
+ QTest::newRow("with #") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("a#b") << QString::fromLatin1("http://www.kde.org#a%23b"); // toString uses "a#b"
+ QTest::newRow("unicode") << QString::fromLatin1("http://www.kde.org") << QString::fromUtf8("\xc3\xa9") << QString::fromLatin1("http://www.kde.org#%C3%A9");
}
-void tst_QUrl::setEncodedFragment()
+void tst_QUrl::setFragment()
{
- QFETCH(QByteArray, base);
- QFETCH(QByteArray, fragment);
- QFETCH(QByteArray, expected);
+ QFETCH(QString, base);
+ QFETCH(QString, fragment);
+ QFETCH(QString, expected);
QUrl u;
- u.setEncodedUrl(base, QUrl::TolerantMode);
+ u.setUrl(base, QUrl::TolerantMode);
QVERIFY(u.isValid());
- u.setEncodedFragment(fragment);
+ u.setFragment(fragment);
QVERIFY(u.isValid());
QCOMPARE(!fragment.isNull(), u.hasFragment());
- QCOMPARE(QString::fromLatin1(u.toEncoded()), QString::fromLatin1(expected));
+ QCOMPARE(QString::fromUtf8(u.toEncoded()), expected);
}
void tst_QUrl::fromEncoded()
@@ -3258,14 +3258,14 @@ void tst_QUrl::isEmptyForEncodedUrl()
{
{
QUrl url;
- url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode);
+ url.setUrl(QLatin1String("LABEL=USB_STICK"), QUrl::TolerantMode);
QVERIFY( url.isValid() );
QCOMPARE( url.path(), QString("LABEL=USB_STICK") );
QVERIFY( !url.isEmpty() );
}
{
QUrl url;
- url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode);
+ url.setUrl(QLatin1String("LABEL=USB_STICK"), QUrl::TolerantMode);
QVERIFY( url.isValid() );
QVERIFY( !url.isEmpty() );
QCOMPARE( url.path(), QString("LABEL=USB_STICK") );
@@ -3277,7 +3277,7 @@ void tst_QUrl::isEmptyForEncodedUrl()
void tst_QUrl::toEncodedNotUsingUninitializedPath()
{
QUrl url;
- url.setEncodedPath("/test.txt");
+ url.setPath(QLatin1String("/test.txt"));
url.setHost("example.com");
QCOMPARE(url.toEncoded().constData(), "//example.com/test.txt");
@@ -3657,17 +3657,6 @@ void tst_QUrl::componentEncodings()
QCOMPARE(url.toString(formatting),
(((QString(toString ))))); // the weird () and space is to align the output
- if (formatting == QUrl::FullyEncoded) {
- QCOMPARE(url.encodedUserName(), userName.toUtf8());
- QCOMPARE(url.encodedPassword(), password.toUtf8());
- // no encodedUserInfo
- QCOMPARE(url.encodedHost(), host.toUtf8());
- // no encodedAuthority
- QCOMPARE(url.encodedPath(), path.toUtf8());
- QCOMPARE(url.encodedQuery(), query.toUtf8());
- QCOMPARE(url.encodedFragment(), fragment.toUtf8());
- }
-
// repeat with the URL we got from toString
QUrl url2(toString);
QCOMPARE(url2.userName(formatting), userName);
@@ -4087,13 +4076,12 @@ public:
QVector<QUrl> m_urls;
};
-static const UrlStorage * s_urlStorage = 0;
+static const UrlStorage * s_urlStorage = nullptr;
void tst_QUrl::testThreadingHelper()
{
const UrlStorage* storage = s_urlStorage;
- for (int i = 0 ; i < storage->m_urls.size(); ++i ) {
- const QUrl& u = storage->m_urls.at(i);
+ for (const auto &u : storage->m_urls) {
// QVERIFY/QCOMPARE trigger race conditions in helgrind
if (!u.isValid())
qFatal("invalid url");
diff --git a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
index b960ca9220..f305edb2c5 100644
--- a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
@@ -309,7 +309,8 @@ bool QtTestModel::moveColumns(const QModelIndex &sourceParent, int src, int cnt,
void QtTestModel::reset()
{
- QAbstractItemModel::reset();
+ QAbstractItemModel::beginResetModel();
+ QAbstractItemModel::endResetModel();
}
bool QtTestModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
@@ -1785,13 +1786,12 @@ class ModelWithCustomRole : public QStringListModel
{
Q_OBJECT
public:
- ModelWithCustomRole(QObject *parent = 0)
- : QStringListModel(parent)
- {
- QHash<int, QByteArray> roleNames_ = roleNames();
- roleNames_.insert(Qt::UserRole + 1, "custom");
- setRoleNames(roleNames_);
- }
+ using QStringListModel::QStringListModel;
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {{Qt::UserRole + 1, QByteArrayLiteral("custom")}};
+ }
};
ListenerObject::ListenerObject(QAbstractProxyModel *parent)
@@ -1830,7 +1830,7 @@ void ListenerObject::slotAboutToBeReset()
void ListenerObject::slotReset()
{
- foreach (const QModelIndex &idx, m_persistentIndexes) {
+ for (const auto &idx : qAsConst(m_persistentIndexes)) {
QVERIFY(!idx.isValid());
}
}
diff --git a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp
index 886941bff6..adb93b7a75 100644
--- a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp
@@ -313,11 +313,12 @@ public:
CustomRole2
};
- StandardItemModelWithCustomRoleNames() {
- QHash<int, QByteArray> _roleNames = roleNames();
- _roleNames.insert(CustomRole1, "custom1");
- _roleNames.insert(CustomRole2, "custom2");
- setRoleNames(_roleNames);
+ QHash<int, QByteArray> roleNames() const override
+ {
+ auto result = QStandardItemModel::roleNames();
+ result.insert(CustomRole1, QByteArrayLiteral("custom1"));
+ result.insert(CustomRole2, QByteArrayLiteral("custom2"));
+ return result;
}
};
@@ -329,11 +330,10 @@ public:
AnotherCustomRole2
};
- AnotherStandardItemModelWithCustomRoleNames() {
- QHash<int, QByteArray> _roleNames = roleNames();
- _roleNames.insert(AnotherCustomRole1, "another_custom1");
- _roleNames.insert(AnotherCustomRole2, "another_custom2");
- setRoleNames(_roleNames);
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {{AnotherCustomRole1, QByteArrayLiteral("another_custom1")},
+ {AnotherCustomRole2, QByteArrayLiteral("another_custom2")}};
}
};
diff --git a/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp b/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
index dbc7173028..354190e754 100644
--- a/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
+++ b/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
@@ -153,7 +153,7 @@ QAbstractItemModel *ModelsToTest::createModel(const QString &modelType)
QStandardItemModel *standardItemModel = new QStandardItemModel;
model->setSourceModel(standardItemModel);
populateTestArea(model);
- model->setFilterRegExp(QRegExp("(^$|I.*)"));
+ model->setFilterRegularExpression(QRegularExpression("(^$|I.*)"));
return model;
}
diff --git a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp
index 6fbaa28d69..c74101928a 100644
--- a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp
@@ -32,6 +32,9 @@
#include <algorithm>
+Q_DECLARE_METATYPE(QItemSelectionModel::SelectionFlag)
+Q_DECLARE_METATYPE(Qt::SortOrder)
+
class tst_QItemSelectionModel : public QObject
{
Q_OBJECT
@@ -1463,7 +1466,7 @@ void tst_QItemSelectionModel::persistentselections()
QFETCH(IntList, insertColumns);
QFETCH(IntList, deleteRows);
QFETCH(IntList, deleteColumns);
- QFETCH(PairList, expectedList);
+ QFETCH(const PairList, expectedList);
// make sure the model is sane (5x5)
QCOMPARE(model->rowCount(QModelIndex()), 5);
@@ -1504,7 +1507,7 @@ void tst_QItemSelectionModel::persistentselections()
// check that the selected items are the correct number and indexes
QModelIndexList selectedList = selection->selectedIndexes();
QCOMPARE(selectedList.count(), expectedList.count());
- foreach(IntPair pair, expectedList) {
+ for (const auto &pair : expectedList) {
QModelIndex index = model->index(pair.first, pair.second, QModelIndex());
QVERIFY(selectedList.contains(index));
}
@@ -1679,7 +1682,7 @@ void tst_QItemSelectionModel::modelLayoutChanged_data()
{
QTest::addColumn<IntListList>("items");
QTest::addColumn<IntPairPairList>("initialSelectedRanges");
- QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<Qt::SortOrder>("sortOrder");
QTest::addColumn<int>("sortColumn");
QTest::addColumn<IntPairPairList>("expectedSelectedRanges");
@@ -1689,7 +1692,7 @@ void tst_QItemSelectionModel::modelLayoutChanged_data()
<< (IntList() << 3 << 2 << 1 << 0))
<< (IntPairPairList()
<< IntPairPair(IntPair(0, 0), IntPair(3, 1)))
- << int(Qt::DescendingOrder)
+ << Qt::DescendingOrder
<< 0
<< (IntPairPairList()
<< IntPairPair(IntPair(0, 0), IntPair(3, 1)));
@@ -1699,7 +1702,7 @@ void tst_QItemSelectionModel::modelLayoutChanged_data()
<< (IntList() << 3 << 2 << 1 << 0))
<< (IntPairPairList()
<< IntPairPair(IntPair(0, 0), IntPair(1, 1)))
- << int(Qt::DescendingOrder)
+ << Qt::DescendingOrder
<< 0
<< (IntPairPairList()
<< IntPairPair(IntPair(2, 0), IntPair(3, 1)));
@@ -1709,7 +1712,7 @@ void tst_QItemSelectionModel::modelLayoutChanged_data()
<< (IntList() << 3 << 2 << 1 << 0))
<< (IntPairPairList()
<< IntPairPair(IntPair(1, 0), IntPair(2, 1)))
- << int(Qt::DescendingOrder)
+ << Qt::DescendingOrder
<< 0
<< (IntPairPairList()
<< IntPairPair(IntPair(1, 0), IntPair(2, 1)));
@@ -1720,7 +1723,7 @@ void tst_QItemSelectionModel::modelLayoutChanged_data()
<< (IntPairPairList()
<< IntPairPair(IntPair(1, 0), IntPair(1, 1))
<< IntPairPair(IntPair(3, 0), IntPair(3, 1)))
- << int(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (IntPairPairList()
<< IntPairPair(IntPair(0, 0), IntPair(0, 1))
@@ -1730,8 +1733,8 @@ void tst_QItemSelectionModel::modelLayoutChanged_data()
void tst_QItemSelectionModel::modelLayoutChanged()
{
QFETCH(IntListList, items);
- QFETCH(IntPairPairList, initialSelectedRanges);
- QFETCH(int, sortOrder);
+ QFETCH(const IntPairPairList, initialSelectedRanges);
+ QFETCH(Qt::SortOrder, sortOrder);
QFETCH(int, sortColumn);
QFETCH(IntPairPairList, expectedSelectedRanges);
@@ -1746,9 +1749,9 @@ void tst_QItemSelectionModel::modelLayoutChanged()
// select initial ranges
QItemSelectionModel selectionModel(&model);
- foreach (IntPairPair range, initialSelectedRanges) {
- IntPair tl = range.first;
- IntPair br = range.second;
+ for (const auto &range : initialSelectedRanges) {
+ const auto &tl = range.first;
+ const auto &br = range.second;
QItemSelection selection(
model.index(tl.first, tl.second),
model.index(br.first, br.second));
@@ -1756,7 +1759,7 @@ void tst_QItemSelectionModel::modelLayoutChanged()
}
// sort the model
- model.sort(sortColumn, Qt::SortOrder(sortOrder));
+ model.sort(sortColumn, sortOrder);
// verify that selection is as expected
QItemSelection selection = selectionModel.selection();
@@ -2126,43 +2129,43 @@ void tst_QItemSelectionModel::merge_data()
{
QTest::addColumn<QItemSelection>("init");
QTest::addColumn<QItemSelection>("other");
- QTest::addColumn<int>("command");
+ QTest::addColumn<QItemSelectionModel::SelectionFlag>("command");
QTest::addColumn<QItemSelection>("result");
QTest::newRow("Simple select")
<< QItemSelection()
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
- << int(QItemSelectionModel::Select)
+ << QItemSelectionModel::Select
<< QItemSelection(model->index(2, 1) , model->index(3, 4));
QTest::newRow("Simple deselect")
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
- << int(QItemSelectionModel::Deselect)
+ << QItemSelectionModel::Deselect
<< QItemSelection();
QTest::newRow("Simple Toggle deselect")
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
- << int(QItemSelectionModel::Toggle)
+ << QItemSelectionModel::Toggle
<< QItemSelection();
QTest::newRow("Simple Toggle select")
<< QItemSelection()
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
- << int(QItemSelectionModel::Toggle)
+ << QItemSelectionModel::Toggle
<< QItemSelection(model->index(2, 1) , model->index(3, 4));
QTest::newRow("Add select")
<< QItemSelection(model->index(2, 1) , model->index(3, 3))
<< QItemSelection(model->index(2, 2) , model->index(3, 4))
- << int(QItemSelectionModel::Select)
+ << QItemSelectionModel::Select
<< QItemSelection(model->index(2, 1) , model->index(3, 4));
QTest::newRow("Deselect")
<< QItemSelection(model->index(2, 1) , model->index(3, 4))
<< QItemSelection(model->index(2, 2) , model->index(3, 4))
- << int(QItemSelectionModel::Deselect)
+ << QItemSelectionModel::Deselect
<< QItemSelection(model->index(2, 1) , model->index(3, 1));
QItemSelection r1(model->index(2, 1) , model->index(3, 1));
@@ -2170,7 +2173,7 @@ void tst_QItemSelectionModel::merge_data()
QTest::newRow("Toggle")
<< QItemSelection(model->index(2, 1) , model->index(3, 3))
<< QItemSelection(model->index(2, 2) , model->index(3, 4))
- << int(QItemSelectionModel::Toggle)
+ << QItemSelectionModel::Toggle
<< r1;
}
@@ -2178,15 +2181,18 @@ void tst_QItemSelectionModel::merge()
{
QFETCH(QItemSelection, init);
QFETCH(QItemSelection, other);
- QFETCH(int, command);
+ QFETCH(QItemSelectionModel::SelectionFlag, command);
QFETCH(QItemSelection, result);
- init.merge(other, QItemSelectionModel::SelectionFlags(command));
+ init.merge(other, command);
- foreach(const QModelIndex &idx, init.indexes())
- QVERIFY(result.contains(idx));
- foreach(const QModelIndex &idx, result.indexes())
- QVERIFY(init.contains(idx));
+ auto verify = [](const QModelIndexList &a, const QItemSelection &b)
+ {
+ for (const QModelIndex &idx : a)
+ QVERIFY(b.contains(idx));
+ };
+ verify(init.indexes(), result);
+ verify(result.indexes(), init);
}
void tst_QItemSelectionModel::isRowSelected()
@@ -2211,8 +2217,8 @@ void tst_QItemSelectionModel::childrenDeselectionSignal()
}
QModelIndex root = model.index(0,0);
- QModelIndex par = root.child(0,0);
- QModelIndex sel = par.child(0,0);
+ QModelIndex par = model.index(0, 0, root);
+ QModelIndex sel = model.index(0, 0, par);
QItemSelectionModel selectionModel(&model);
selectionModel.select(sel, QItemSelectionModel::SelectCurrent);
@@ -2240,9 +2246,9 @@ void tst_QItemSelectionModel::childrenDeselectionSignal()
}
}
- sel = model.index(0, 0).child(0, 0);
+ sel = model.index(0, 0, model.index(0, 0));
selectionModel.select(sel, QItemSelectionModel::Select);
- QModelIndex sel2 = model.index(1, 0).child(0, 0);
+ QModelIndex sel2 = model.index(0, 0, model.index(1, 0));
selectionModel.select(sel2, QItemSelectionModel::Select);
QVERIFY(selectionModel.selection().contains(sel));
@@ -2264,24 +2270,23 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected1()
QCOMPARE(model.rowCount(), 3);
QCOMPARE(proxy.rowCount(), 3);
- proxy.setFilterRegExp( QRegExp("f"));
+ proxy.setFilterRegularExpression(QRegularExpression("f"));
QCOMPARE(proxy.rowCount(), 2);
- QList<QPersistentModelIndex> indexList;
- indexList << proxy.index(0,0) << proxy.index(1,0);
- selection.select( QItemSelection(indexList.first(), indexList.last()), QItemSelectionModel::Select);
+ const QList<QPersistentModelIndex> indexList({proxy.index(0,0), proxy.index(1,0)});
+ selection.select(QItemSelection(indexList.first(), indexList.last()), QItemSelectionModel::Select);
//let's check the selection hasn't changed
QCOMPARE(selection.selectedIndexes().count(), indexList.count());
- foreach(QPersistentModelIndex index, indexList)
+ for (const auto &index : indexList)
QVERIFY(selection.isSelected(index));
- proxy.setFilterRegExp(QRegExp());
+ proxy.setFilterRegularExpression(QRegularExpression());
QCOMPARE(proxy.rowCount(), 3);
//let's check the selection hasn't changed
QCOMPARE(selection.selectedIndexes().count(), indexList.count());
- foreach(QPersistentModelIndex index, indexList)
+ for (const auto &index : indexList)
QVERIFY(selection.isSelected(index));
}
@@ -2321,9 +2326,8 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected2()
selection.select( QItemSelection(proxy.index(0,0), proxy.index(proxy.rowCount() - 1, proxy.columnCount() - 1)), QItemSelectionModel::Select);
- QList<QPersistentModelIndex> indexList;
- foreach(const QModelIndex &id, selection.selectedIndexes())
- indexList << id;
+ const auto selIndexes = selection.selectedIndexes();
+ const QList<QPersistentModelIndex> indexList(selIndexes.begin(), selIndexes.end());
proxy.filtering = false;
proxy.invalidate();
@@ -2331,7 +2335,7 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected2()
//let's check the selection hasn't changed
QCOMPARE(selection.selectedIndexes().count(), indexList.count());
- foreach(QPersistentModelIndex index, indexList)
+ for (const auto &index : indexList)
QVERIFY(selection.isSelected(index));
}
@@ -2375,7 +2379,8 @@ public:
public slots:
void selectionChanged(const QItemSelection & /* selected */, const QItemSelection &deselected)
{
- foreach(const QModelIndex &index, deselected.indexes()) {
+ const auto deselIndexes = deselected.indexes();
+ for (const auto &index : deselIndexes) {
QVERIFY(!m_itemSelectionModel->selection().contains(index));
}
QCOMPARE(m_itemSelectionModel->selection().size(), 2);
@@ -2633,9 +2638,9 @@ private slots:
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
- foreach(const QItemSelectionRange &range, selected)
+ for (const auto &range : selected)
QVERIFY(range.isValid());
- foreach(const QItemSelectionRange &range, deselected)
+ for (const auto &range : deselected)
QVERIFY(range.isValid());
}
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
index ccce5a44e5..624187349b 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
@@ -829,7 +829,7 @@ void tst_QSortFilterProxyModel::removeRows_data()
void tst_QSortFilterProxyModel::removeRows()
{
- QFETCH(QStringList, initial);
+ QFETCH(const QStringList, initial);
QFETCH(int, sortOrder);
QFETCH(QString, filter);
QFETCH(int, position);
@@ -843,7 +843,7 @@ void tst_QSortFilterProxyModel::removeRows()
proxy.setSourceModel(&model);
// prepare model
- foreach (QString s, initial)
+ for (const auto &s : initial)
model.appendRow(new QStandardItem(s));
if (sortOrder != -1)
@@ -3035,15 +3035,15 @@ void tst_QSortFilterProxyModel::removeRowsRecursive()
QList<QPersistentModelIndex> sourceIndexes;
QList<QPersistentModelIndex> proxyIndexes;
- foreach (QStandardItem *item, items) {
+ for (const auto item : qAsConst(items)) {
QModelIndex idx = item->index();
sourceIndexes << idx;
proxyIndexes << proxy.mapFromSource(idx);
}
- foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ for (const auto &pidx : qAsConst(sourceIndexes))
QVERIFY(pidx.isValid());
- foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ for (const auto &pidx : qAsConst(proxyIndexes))
QVERIFY(pidx.isValid());
QList<QStandardItem*> itemRow = pItem1->takeRow(0);
@@ -3051,9 +3051,9 @@ void tst_QSortFilterProxyModel::removeRowsRecursive()
QCOMPARE(itemRow.count(), 1);
QCOMPARE(itemRow.first(), pItem11);
- foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ for (const auto &pidx : qAsConst(sourceIndexes))
QVERIFY(!pidx.isValid());
- foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ for (const auto &pidx : qAsConst(proxyIndexes))
QVERIFY(!pidx.isValid());
delete pItem11;
@@ -3280,10 +3280,8 @@ void tst_QSortFilterProxyModel::testMultipleProxiesWithSelection()
static bool isValid(const QItemSelection &selection)
{
- foreach (const QItemSelectionRange &range, selection)
- if (!range.isValid())
- return false;
- return true;
+ return std::all_of(selection.begin(), selection.end(),
+ [](const QItemSelectionRange &range) { return range.isValid(); });
}
void tst_QSortFilterProxyModel::mapSelectionFromSource()
@@ -3737,14 +3735,16 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
QVERIFY(beforeParents.first() == proxy.mapFromSource(model.indexFromItem(model.invisibleRootItem()->child(1))));
- QList<QPersistentModelIndex> proxy2BeforeList = proxy2ParentsAboutToBeChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
- QList<QPersistentModelIndex> proxy2AfterList = proxy2ParentsChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
+ const QList<QPersistentModelIndex> proxy2BeforeList =
+ proxy2ParentsAboutToBeChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
+ const QList<QPersistentModelIndex> proxy2AfterList =
+ proxy2ParentsChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
QCOMPARE(proxy2BeforeList.size(), beforeParents.size());
QCOMPARE(proxy2AfterList.size(), afterParents.size());
- foreach (const QPersistentModelIndex &idx, proxy2BeforeList)
+ for (const QPersistentModelIndex &idx : proxy2BeforeList)
QVERIFY(beforeParents.contains(proxy2.mapToSource(idx)));
- foreach (const QPersistentModelIndex &idx, proxy2AfterList)
+ for (const QPersistentModelIndex &idx : proxy2AfterList)
QVERIFY(afterParents.contains(proxy2.mapToSource(idx)));
}
@@ -3977,7 +3977,7 @@ void tst_QSortFilterProxyModel::hierarchyFilterInvalidation()
QTreeView view;
view.setModel(&proxy);
- view.setCurrentIndex(proxy.index(2, 0).child(0, 0));
+ view.setCurrentIndex(proxy.index(0, 0, proxy.index(2, 0)));
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
index 0b8686560c..3919472b96 100644
--- a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
@@ -333,7 +333,7 @@ template <class C>
C sorted(C c)
{
std::sort(c.begin(), c.end());
- return qMove(c);
+ return std::move(c);
}
void tst_QStringListModel::setData_emits_both_roles()
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index 6adb393ddd..39c90f69b4 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -611,7 +611,7 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
TestApplication app(argc, argv);
ProcessEventsAlwaysSendsPostedEventsObject object;
- QTime t;
+ QElapsedTimer t;
t.start();
int i = 1;
do {
@@ -775,49 +775,49 @@ private slots:
QCoreApplicationPrivate *privateClass = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
{
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
// Test with a lock active so that the refcount doesn't drop to zero during these tests, causing a quit.
// (until we exit the scope)
QEventLoopLocker locker;
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
JobObject *job1 = new JobObject(this);
- QCOMPARE(privateClass->quitLockRef.load(), 2);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
delete job1;
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
job1 = new JobObject(this);
- QCOMPARE(privateClass->quitLockRef.load(), 2);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
JobObject *job2 = new JobObject(this);
- QCOMPARE(privateClass->quitLockRef.load(), 3);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 3);
delete job1;
- QCOMPARE(privateClass->quitLockRef.load(), 2);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
JobObject *job3 = new JobObject(job2);
Q_UNUSED(job3);
- QCOMPARE(privateClass->quitLockRef.load(), 3);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 3);
JobObject *job4 = new JobObject(job2);
Q_UNUSED(job4);
- QCOMPARE(privateClass->quitLockRef.load(), 4);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 4);
delete job2;
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
}
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
}
};
diff --git a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
index 4dd71ca9f4..569880e1db 100644
--- a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
+++ b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
@@ -1,4 +1,3 @@
[elapsed]
-windows
-osx-10.12
osx-10.13
+windows-10
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST b/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
deleted file mode 100644
index 06588188d4..0000000000
--- a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
+++ /dev/null
@@ -1,6 +0,0 @@
-[sendPostedEvents]
-windows
-[registerTimer]
-windows
-winrt
-osx
diff --git a/tests/auto/corelib/kernel/qeventloop/BLACKLIST b/tests/auto/corelib/kernel/qeventloop/BLACKLIST
deleted file mode 100644
index 6ea6314b0a..0000000000
--- a/tests/auto/corelib/kernel/qeventloop/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[testQuitLock]
-windows
diff --git a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro
index 295a42aa9c..159761c0c6 100644
--- a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro
+++ b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro
@@ -3,6 +3,6 @@ TARGET = tst_qeventloop
QT = core network testlib core-private
SOURCES = $$PWD/tst_qeventloop.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
qtConfig(glib): DEFINES += HAVE_GLIB
diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
index 482ed8d130..1f0b8d4b4e 100644
--- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
+++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
@@ -638,16 +638,16 @@ void tst_QEventLoop::testQuitLock()
QEventLoopPrivate* privateClass = static_cast<QEventLoopPrivate*>(QObjectPrivate::get(&eventLoop));
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
JobObject *job1 = new JobObject(&eventLoop, this);
job1->start(500);
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
eventLoop.exec();
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
job1 = new JobObject(&eventLoop, this);
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 89a06b358e..60000316cc 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -507,6 +507,7 @@ public slots:
{ QObject::moveToThread(t); }
void slotWithUnregisteredParameterType(MyUnregisteredType);
+ void slotWithOneUnregisteredParameterType(QString a1, MyUnregisteredType a2);
CountedStruct throwingSlot(const CountedStruct &, CountedStruct s2) {
#ifndef QT_NO_EXCEPTIONS
@@ -520,7 +521,7 @@ public slots:
QVector<QtTestObject *> o5, QList<QtTestObject *> o6)
{
slotResult = QLatin1String("slotWithRegistrableArgument:") + o1->slotResult + o2->slotResult
- + o3->slotResult + o4.data()->slotResult + QString::number(o5.size())
+ + o3->slotResult + o4.toStrongRef()->slotResult + QString::number(o5.size())
+ QString::number(o6.size());
}
@@ -604,6 +605,9 @@ void QtTestObject::testSender()
void QtTestObject::slotWithUnregisteredParameterType(MyUnregisteredType)
{ slotResult = "slotWithUnregisteredReturnType"; }
+void QtTestObject::slotWithOneUnregisteredParameterType(QString a1, MyUnregisteredType)
+{ slotResult = "slotWithUnregisteredReturnType-" + a1; }
+
void QtTestObject::staticFunction0()
{
staticResult = "staticFunction0";
@@ -885,6 +889,16 @@ void tst_QMetaObject::invokeQueuedMetaMember()
QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithUnregisteredParameterType", Qt::QueuedConnection, Q_ARG(MyUnregisteredType, t)));
QVERIFY(obj.slotResult.isEmpty());
}
+
+ obj.slotResult.clear();
+ {
+ QString a1("Cannot happen");
+ MyUnregisteredType t;
+ QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyUnregisteredType'");
+ QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithOneUnregisteredParameterType", Qt::QueuedConnection,
+ Q_ARG(QString, a1), Q_ARG(MyUnregisteredType, t)));
+ QVERIFY(obj.slotResult.isEmpty());
+ }
}
void tst_QMetaObject::invokeQueuedPointer()
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 56623773a2..9fe7d63727 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -1322,8 +1322,8 @@ bool tst_QMetaObjectBuilder::sameMetaObject
return false;
}
- const QMetaObject * const *objects1 = meta1->d.relatedMetaObjects;
- const QMetaObject * const *objects2 = meta2->d.relatedMetaObjects;
+ const auto *objects1 = meta1->d.relatedMetaObjects;
+ const auto *objects2 = meta2->d.relatedMetaObjects;
if (objects1 && !objects2)
return false;
if (objects2 && !objects1)
@@ -1391,7 +1391,7 @@ private:
};
QMetaObject TestObject::staticMetaObject = {
- { 0, 0, 0, 0, 0, 0 }
+ { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }
};
TestObject::TestObject(QObject *parent)
diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
index 681a5d0146..cc67fc7884 100644
--- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
+++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
@@ -130,7 +130,7 @@ public:
QString m_value;
void setValue(const QString &value) { m_value = value; }
QString getValue() { return m_value; }
- void resetValue() { m_value = QLatin1Literal("reset"); }
+ void resetValue() { m_value = QLatin1String("reset"); }
};
void tst_QMetaProperty::gadget()
@@ -140,7 +140,7 @@ void tst_QMetaProperty::gadget()
QVERIFY(valueProp.isValid());
{
MyGadget g;
- QString hello = QLatin1Literal("hello");
+ QString hello = QLatin1String("hello");
QVERIFY(valueProp.writeOnGadget(&g, hello));
QCOMPARE(g.m_value, QLatin1String("hello"));
QCOMPARE(valueProp.readOnGadget(&g), QVariant(hello));
@@ -242,7 +242,7 @@ void tst_QMetaProperty::conversion()
QCOMPARE(custom.str, QString());
// or reset resetable
QVERIFY(value7P.write(this, QVariant()));
- QCOMPARE(value7, QLatin1Literal("reset"));
+ QCOMPARE(value7, QLatin1String("reset"));
}
QTEST_MAIN(tst_QMetaProperty)
diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
index 56b8c071c3..4856b138c3 100644
--- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
+++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
@@ -5,6 +5,7 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qmetatype.cpp
TESTDATA=./typeFlags.bin
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+DEFINES -= QT_NO_LINKED_LIST
msvc|winrt {
# Prevents "fatal error C1128: number of sections exceeded object file format limit".
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index e2bb7dab2a..12c29a6e13 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -1499,7 +1499,7 @@ public:
typedef MyObject* MyObjectPtr;
Q_DECLARE_METATYPE(MyObjectPtr)
-#if defined(Q_COMPILER_VARIADIC_MACROS) && !defined(TST_QMETATYPE_BROKEN_COMPILER)
+#if !defined(TST_QMETATYPE_BROKEN_COMPILER)
static QByteArray createTypeName(const char *begin, const char *va)
{
QByteArray tn(begin);
@@ -1697,7 +1697,7 @@ void tst_QMetaType::automaticTemplateRegistration()
QVERIFY(qRegisterMetaType<UnregisteredTypeList>("UnregisteredTypeList") > 0);
}
-#if defined(Q_COMPILER_VARIADIC_MACROS) && !defined(TST_QMETATYPE_BROKEN_COMPILER)
+#if !defined(TST_QMETATYPE_BROKEN_COMPILER)
#define FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
F(bool) \
@@ -1776,7 +1776,7 @@ void tst_QMetaType::automaticTemplateRegistration()
CREATE_AND_VERIFY_CONTAINER(QHash, void*, void*)
CREATE_AND_VERIFY_CONTAINER(QHash, const void*, const void*)
-#endif // Q_COMPILER_VARIADIC_MACROS
+#endif // !defined(TST_QMETATYPE_BROKEN_COMPILER)
#define TEST_OWNING_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE, FLAG_TEST, FROMVARIANTFUNCTION) \
{ \
@@ -1807,16 +1807,36 @@ void tst_QMetaType::automaticTemplateRegistration()
QCOMPARE(extractedPtr.data()->objectName(), sp.data()->objectName()); \
}
+#if QT_DEPRECATED_SINCE(5, 0)
TEST_NONOWNING_SMARTPOINTER(QWeakPointer, QObject, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_NONOWNING_SMARTPOINTER(QWeakPointer, QFile, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_NONOWNING_SMARTPOINTER(QWeakPointer, QTemporaryFile, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_NONOWNING_SMARTPOINTER(QWeakPointer, MyObject, WeakPointerToQObject, qWeakPointerFromVariant)
+#endif
TEST_NONOWNING_SMARTPOINTER(QPointer, QObject, TrackingPointerToQObject, qPointerFromVariant)
TEST_NONOWNING_SMARTPOINTER(QPointer, QFile, TrackingPointerToQObject, qPointerFromVariant)
TEST_NONOWNING_SMARTPOINTER(QPointer, QTemporaryFile, TrackingPointerToQObject, qPointerFromVariant)
TEST_NONOWNING_SMARTPOINTER(QPointer, MyObject, TrackingPointerToQObject, qPointerFromVariant)
#undef TEST_NONOWNING_SMARTPOINTER
+
+
+#define TEST_WEAK_SMARTPOINTER(ELEMENT_TYPE, FLAG_TEST) \
+ { \
+ ELEMENT_TYPE elem; \
+ QSharedPointer < ELEMENT_TYPE > shared(new ELEMENT_TYPE); \
+ QWeakPointer < ELEMENT_TYPE > sp(shared); \
+ sp.toStrongRef()->setObjectName("Test name"); \
+ QVariant v = QVariant::fromValue(sp); \
+ QCOMPARE(v.typeName(), "QWeakPointer<" #ELEMENT_TYPE ">"); \
+ QVERIFY(QMetaType::typeFlags(::qMetaTypeId<QWeakPointer < ELEMENT_TYPE > >()) & QMetaType::FLAG_TEST); \
+ }
+
+ TEST_WEAK_SMARTPOINTER(QObject, WeakPointerToQObject)
+ TEST_WEAK_SMARTPOINTER(QFile, WeakPointerToQObject)
+ TEST_WEAK_SMARTPOINTER(QTemporaryFile, WeakPointerToQObject)
+ TEST_WEAK_SMARTPOINTER(MyObject, WeakPointerToQObject)
+#undef TEST_WEAK_SMARTPOINTER
}
template <typename T>
@@ -2565,9 +2585,7 @@ Q_DECLARE_METATYPE(UndefinedFunction0);
Q_DECLARE_METATYPE(UndefinedFunction1);
Q_DECLARE_METATYPE(UndefinedFunction2);
Q_DECLARE_METATYPE(UndefinedFunction3);
-#ifdef Q_COMPILER_VARIADIC_TEMPLATES
Q_DECLARE_METATYPE(UndefinedFunction4);
-#endif
QTEST_MAIN(tst_QMetaType)
#include "tst_qmetatype.moc"
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 6bda9638f7..22bcb69ac9 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -236,7 +236,7 @@ template<> struct TestValueFactory<QMetaType::QRegExp> {
template<> struct TestValueFactory<QMetaType::QRegularExpression> {
static QRegularExpression *create()
{
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
return new QRegularExpression("abc.*def");
#else
return 0;
diff --git a/tests/auto/corelib/kernel/qobject/BLACKLIST b/tests/auto/corelib/kernel/qobject/BLACKLIST
deleted file mode 100644
index 0887a73b4c..0000000000
--- a/tests/auto/corelib/kernel/qobject/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[moveToThread]
-windows
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 31268c5cf3..a805bfb747 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -32,7 +32,6 @@
#include <qcoreapplication.h>
#include <qpointer.h>
#include <qtimer.h>
-#include <qregexp.h>
#include <qregularexpression.h>
#include <qmetaobject.h>
#include <qvariant.h>
@@ -82,7 +81,9 @@ private slots:
void senderTest();
void declareInterface();
void qpointerResetBeforeDestroyedSignal();
+#ifndef QT_NO_USERDATA
void testUserData();
+#endif
void childDeletesItsSibling();
void dynamicProperties();
void floatProperty();
@@ -154,6 +155,8 @@ private slots:
void mutableFunctor();
void checkArgumentsForNarrowing();
void nullReceiver();
+ void functorReferencesConnection();
+ void disconnectDisconnects();
};
struct QObjectCreatedOnShutdown
@@ -535,91 +538,91 @@ void tst_QObject::findChildren()
QObject *op = 0;
- op = qFindChild<QObject*>(&o, "o1");
+ op = o.findChild<QObject*>("o1");
QCOMPARE(op, &o1);
- op = qFindChild<QObject*>(&o, "o2");
+ op = o.findChild<QObject*>("o2");
QCOMPARE(op, &o2);
- op = qFindChild<QObject*>(&o, "o11");
+ op = o.findChild<QObject*>("o11");
QCOMPARE(op, &o11);
- op = qFindChild<QObject*>(&o, "o12");
+ op = o.findChild<QObject*>("o12");
QCOMPARE(op, &o12);
- op = qFindChild<QObject*>(&o, "o111");
+ op = o.findChild<QObject*>("o111");
QCOMPARE(op, &o111);
- op = qFindChild<QObject*>(&o, "t1");
+ op = o.findChild<QObject*>("t1");
QCOMPARE(op, static_cast<QObject *>(&t1));
- op = qFindChild<QObject*>(&o, "t121");
+ op = o.findChild<QObject*>("t121");
QCOMPARE(op, static_cast<QObject *>(&t121));
- op = qFindChild<QTimer*>(&o, "t1");
+ op = o.findChild<QTimer*>("t1");
QCOMPARE(op, static_cast<QObject *>(&t1));
- op = qFindChild<QTimer*>(&o, "t121");
+ op = o.findChild<QTimer*>("t121");
QCOMPARE(op, static_cast<QObject *>(&t121));
- op = qFindChild<QTimer*>(&o, "o12");
+ op = o.findChild<QTimer*>("o12");
QCOMPARE(op, static_cast<QObject *>(0));
- op = qFindChild<QObject*>(&o, "o");
+ op = o.findChild<QObject*>("o");
QCOMPARE(op, static_cast<QObject *>(0));
- op = qFindChild<QObject*>(&o, "harry");
+ op = o.findChild<QObject*>("harry");
QCOMPARE(op, static_cast<QObject *>(0));
- op = qFindChild<QObject*>(&o, "o1");
+ op = o.findChild<QObject*>("o1");
QCOMPARE(op, &o1);
QList<QObject*> l;
QList<QTimer*> tl;
- l = qFindChildren<QObject*>(&o, "o1");
+ l = o.findChildren<QObject*>("o1");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o1);
- l = qFindChildren<QObject*>(&o, "o2");
+ l = o.findChildren<QObject*>("o2");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o2);
- l = qFindChildren<QObject*>(&o, "o11");
+ l = o.findChildren<QObject*>("o11");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o11);
- l = qFindChildren<QObject*>(&o, "o12");
+ l = o.findChildren<QObject*>("o12");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o12);
- l = qFindChildren<QObject*>(&o, "o111");
+ l = o.findChildren<QObject*>("o111");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o111);
- l = qFindChildren<QObject*>(&o, "t1");
+ l = o.findChildren<QObject*>("t1");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
- l = qFindChildren<QObject*>(&o, "t121");
+ l = o.findChildren<QObject*>("t121");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), static_cast<QObject *>(&t121));
- tl = qFindChildren<QTimer*>(&o, "t1");
+ tl = o.findChildren<QTimer*>("t1");
QCOMPARE(tl.size(), 1);
QCOMPARE(tl.at(0), &t1);
- tl = qFindChildren<QTimer*>(&o, "t121");
+ tl = o.findChildren<QTimer*>("t121");
QCOMPARE(tl.size(), 1);
QCOMPARE(tl.at(0), &t121);
- l = qFindChildren<QObject*>(&o, "o");
+ l = o.findChildren<QObject*>("o");
QCOMPARE(l.size(), 0);
- l = qFindChildren<QObject*>(&o, "harry");
+ l = o.findChildren<QObject*>("harry");
QCOMPARE(l.size(), 0);
- tl = qFindChildren<QTimer*>(&o, "o12");
+ tl = o.findChildren<QTimer*>("o12");
QCOMPARE(tl.size(), 0);
- l = qFindChildren<QObject*>(&o, "o1");
+ l = o.findChildren<QObject*>("o1");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o1);
- l = qFindChildren<QObject*>(&o, QRegExp("o.*"));
+ l = o.findChildren<QObject*>(QRegularExpression("^o.*$"));
QCOMPARE(l.size(), 5);
QVERIFY(l.contains(&o1));
QVERIFY(l.contains(&o2));
QVERIFY(l.contains(&o11));
QVERIFY(l.contains(&o12));
QVERIFY(l.contains(&o111));
- l = qFindChildren<QObject*>(&o, QRegExp("t.*"));
+ l = o.findChildren<QObject*>(QRegularExpression("t.*"));
QCOMPARE(l.size(), 2);
QVERIFY(l.contains(&t1));
QVERIFY(l.contains(&t121));
- tl = qFindChildren<QTimer*>(&o, QRegExp(".*"));
+ tl = o.findChildren<QTimer*>(QRegularExpression("^.*$"));
QCOMPARE(tl.size(), 3);
QVERIFY(tl.contains(&t1));
QVERIFY(tl.contains(&t121));
- tl = qFindChildren<QTimer*>(&o, QRegExp("o.*"));
+ tl = o.findChildren<QTimer*>(QRegularExpression("^o.*$"));
QCOMPARE(tl.size(), 0);
- l = qFindChildren<QObject*>(&o, QRegExp("harry"));
+ l = o.findChildren<QObject*>(QRegularExpression("^harry$"));
QCOMPARE(l.size(), 0);
l = o.findChildren<QObject*>(QRegularExpression("o.*"));
@@ -643,18 +646,18 @@ void tst_QObject::findChildren()
QCOMPARE(l.size(), 0);
// empty and null string check
- op = qFindChild<QObject*>(&o);
+ op = o.findChild<QObject*>();
QCOMPARE(op, &o1);
- op = qFindChild<QObject*>(&o, "");
+ op = o.findChild<QObject*>("");
QCOMPARE(op, &unnamed);
- op = qFindChild<QObject*>(&o, "unnamed");
+ op = o.findChild<QObject*>("unnamed");
QCOMPARE(op, static_cast<QObject *>(0));
- l = qFindChildren<QObject*>(&o);
+ l = o.findChildren<QObject*>();
QCOMPARE(l.size(), 9);
- l = qFindChildren<QObject*>(&o, "");
+ l = o.findChildren<QObject*>("");
QCOMPARE(l.size(), 2);
- l = qFindChildren<QObject*>(&o, "unnamed");
+ l = o.findChildren<QObject*>("unnamed");
QCOMPARE(l.size(), 0);
tl = o.findChildren<QTimer *>("t1");
@@ -722,19 +725,19 @@ void tst_QObject::findChildren()
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o1);
- l = o.findChildren<QObject*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
+ l = o.findChildren<QObject*>(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(l.size(), 2);
QVERIFY(l.contains(&o1));
QVERIFY(l.contains(&o2));
- l = o.findChildren<QObject*>(QRegExp("t.*"), Qt::FindDirectChildrenOnly);
+ l = o.findChildren<QObject*>(QRegularExpression("^t.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(l.size(), 1);
QVERIFY(l.contains(&t1));
- tl = o.findChildren<QTimer*>(QRegExp(".*"), Qt::FindDirectChildrenOnly);
+ tl = o.findChildren<QTimer*>(QRegularExpression("^.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(tl.size(), 2);
QVERIFY(tl.contains(&t1));
- tl = o.findChildren<QTimer*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
+ tl = o.findChildren<QTimer*>(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(tl.size(), 0);
- l = o.findChildren<QObject*>(QRegExp("harry"), Qt::FindDirectChildrenOnly);
+ l = o.findChildren<QObject*>(QRegularExpression("^harry$"), Qt::FindDirectChildrenOnly);
QCOMPARE(l.size(), 0);
// empty and null string check
@@ -1033,18 +1036,16 @@ public Q_SLOTS:
void tst_QObject::connectNotify_connectSlotsByName()
{
ConnectByNameNotifyReceiverObject testObject;
- QList<ConnectByNameNotifySenderObject *> senders =
- qFindChildren<ConnectByNameNotifySenderObject *>(&testObject);
- for (int i = 0; i < senders.size(); ++i) {
- ConnectByNameNotifySenderObject *o = senders.at(i);
+ const QList<ConnectByNameNotifySenderObject *> senders =
+ testObject.findChildren<ConnectByNameNotifySenderObject *>();
+ for (ConnectByNameNotifySenderObject *o : senders) {
QVERIFY(o->connectedSignals.isEmpty());
QVERIFY(o->disconnectedSignals.isEmpty());
}
QMetaObject::connectSlotsByName(&testObject);
- for (int i = 0; i < senders.size(); ++i) {
- ConnectByNameNotifySenderObject *o = senders.at(i);
+ for (ConnectByNameNotifySenderObject *o : senders) {
QCOMPARE(o->connectedSignals.size(), 1);
QCOMPARE(o->connectedSignals.at(0), QMetaMethod::fromSignal(&ConnectByNameNotifySenderObject::signal1));
QVERIFY(o->disconnectedSignals.isEmpty());
@@ -1400,6 +1401,7 @@ struct CustomType
CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3)
{ ++instanceCount; playWithObjects(); }
~CustomType() { --instanceCount; playWithObjects(); }
+ CustomType &operator=(const CustomType &) = default;
int i1, i2, i3;
int value() { return i1 + i2 + i3; }
@@ -1629,7 +1631,7 @@ void tst_QObject::thread()
QObject object;
// thread affinity for objects with no parent should be the
// current thread
- QVERIFY(object.thread() != 0);
+ QVERIFY(object.thread() != nullptr);
QCOMPARE(object.thread(), currentThread);
// children inherit their parent's thread
QObject child(&object);
@@ -1641,7 +1643,7 @@ void tst_QObject::thread()
{
TestThread thr;
- QVERIFY(thr.thread() != 0);
+ QVERIFY(thr.thread() != nullptr);
QCOMPARE(thr.thread(), currentThread);
thr.object = &object;
@@ -1800,8 +1802,8 @@ void tst_QObject::moveToThread()
QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
thread.wait();
- QVERIFY(opointer == 0);
- QVERIFY(cpointer == 0);
+ QVERIFY(opointer == nullptr);
+ QVERIFY(cpointer == nullptr);
}
{
@@ -2339,6 +2341,7 @@ void tst_QObject::declareInterface()
}
+#ifndef QT_NO_USERDATA
class CustomData : public QObjectUserData
{
public:
@@ -2377,10 +2380,11 @@ void tst_QObject::testUserData()
for (int i=0; i<USER_DATA_COUNT; ++i) {
int id = user_data_ids[i];
CustomData *data = static_cast<CustomData *>(my_test_object.userData(id));
- QVERIFY(data != 0);
+ QVERIFY(data != nullptr);
QCOMPARE(data->id, id);
}
}
+#endif // QT_NO_USERDATA
class DestroyedListener : public QObject
{
@@ -3409,12 +3413,11 @@ void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit()
void tst_QObject::dumpObjectInfo()
{
QObject a, b;
- QObject::connect(&a, SIGNAL(destroyed(QObject*)), &b, SLOT(deleteLater()));
- a.disconnect(&b);
+ QObject::connect(&a, &QObject::destroyed, &b, &QObject::deleteLater);
QTest::ignoreMessage(QtDebugMsg, "OBJECT QObject::unnamed");
QTest::ignoreMessage(QtDebugMsg, " SIGNALS OUT");
QTest::ignoreMessage(QtDebugMsg, " signal: destroyed(QObject*)");
- QTest::ignoreMessage(QtDebugMsg, " <Disconnected receiver>");
+ QTest::ignoreMessage(QtDebugMsg, " <functor or function pointer>");
QTest::ignoreMessage(QtDebugMsg, " SIGNALS IN");
QTest::ignoreMessage(QtDebugMsg, " <None>");
a.dumpObjectInfo(); // should not crash
@@ -3626,7 +3629,7 @@ class OverloadObject : public QObject
void sig(int i, int j = 12);
void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const;
void other(int a = 0);
- void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0);
+ void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = nullptr);
void sig(double r = 0.5);
public slots:
void slo(int i, int j = 43)
@@ -4793,13 +4796,13 @@ class LotsOfSignalsAndSlots: public QObject
public slots:
void slot_v() {}
- void slot_v_noexcept() Q_DECL_NOTHROW {}
+ void slot_v_noexcept() noexcept {}
void slot_vi(int) {}
- void slot_vi_noexcept() Q_DECL_NOTHROW {}
+ void slot_vi_noexcept() noexcept {}
void slot_vii(int, int) {}
void slot_viii(int, int, int) {}
int slot_i() { return 0; }
- int slot_i_noexcept() Q_DECL_NOTHROW { return 0; }
+ int slot_i_noexcept() noexcept { return 0; }
int slot_ii(int) { return 0; }
int slot_iii(int, int) { return 0; }
int slot_iiii(int, int, int) { return 0; }
@@ -4813,18 +4816,18 @@ class LotsOfSignalsAndSlots: public QObject
void slot_vPFvvE(fptr) {}
void const_slot_v() const {};
- void const_slot_v_noexcept() const Q_DECL_NOTHROW {}
+ void const_slot_v_noexcept() const noexcept {}
void const_slot_vi(int) const {};
- void const_slot_vi_noexcept(int) const Q_DECL_NOTHROW {}
+ void const_slot_vi_noexcept(int) const noexcept {}
static void static_slot_v() {}
- static void static_slot_v_noexcept() Q_DECL_NOTHROW {}
+ static void static_slot_v_noexcept() noexcept {}
static void static_slot_vi(int) {}
- static void static_slot_vi_noexcept(int) Q_DECL_NOTHROW {}
+ static void static_slot_vi_noexcept(int) noexcept {}
static void static_slot_vii(int, int) {}
static void static_slot_viii(int, int, int) {}
static int static_slot_i() { return 0; }
- static int static_slot_i_noexcept() Q_DECL_NOTHROW { return 0; }
+ static int static_slot_i_noexcept() noexcept { return 0; }
static int static_slot_ii(int) { return 0; }
static int static_slot_iii(int, int) { return 0; }
static int static_slot_iiii(int, int, int) { return 0; }
@@ -4987,11 +4990,11 @@ void tst_QObject::connectCxx0xTypeMatching()
}
-void receiverFunction_noexcept() Q_DECL_NOTHROW {}
-struct Functor_noexcept { void operator()() Q_DECL_NOTHROW {} };
+void receiverFunction_noexcept() noexcept {}
+struct Functor_noexcept { void operator()() noexcept {} };
void tst_QObject::connectCxx17Noexcept()
{
- // this is about connecting signals to slots with the Q_DECL_NOTHROW qualifier
+ // this is about connecting signals to slots with the noexcept qualifier
// as semantics changed due to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html
typedef LotsOfSignalsAndSlots Foo;
Foo obj;
@@ -5981,7 +5984,7 @@ void ConnectToPrivateSlot::test(SenderObject* obj1) {
obj1->signal1();
QCOMPARE(d->receivedCount, 1);
QCOMPARE(d->receivedValue, QVariant());
- obj1->signal7(666, QLatin1Literal("_"));
+ obj1->signal7(666, QLatin1String("_"));
QCOMPARE(d->receivedCount, 2);
QCOMPARE(d->receivedValue, QVariant(666));
QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection));
@@ -6028,7 +6031,6 @@ void tst_QObject::connectFunctorArgDifference()
QStringListModel model;
connect(&model, &QStringListModel::rowsInserted, SlotFunctor());
-#if defined(Q_COMPILER_LAMBDA)
connect(&timer, &QTimer::timeout, [=](){});
connect(&timer, &QTimer::objectNameChanged, [=](const QString &){});
connect(qApp, &QCoreApplication::aboutToQuit, [=](){});
@@ -6036,7 +6038,6 @@ void tst_QObject::connectFunctorArgDifference()
connect(&timer, &QTimer::objectNameChanged, [=](){});
connect(&model, &QStringListModel::rowsInserted, [=](){});
connect(&model, &QStringListModel::rowsInserted, [=](const QModelIndex &){});
-#endif
QVERIFY(true);
}
@@ -6074,7 +6075,6 @@ void tst_QObject::connectFunctorQueued()
e.exec();
QCOMPARE(status, 2);
-#if defined(Q_COMPILER_LAMBDA)
status = 1;
connect(&obj, &SenderObject::signal1, this, [&status] { status = 2; }, Qt::QueuedConnection);
@@ -6082,7 +6082,6 @@ void tst_QObject::connectFunctorQueued()
QCOMPARE(status, 1);
e.exec();
QCOMPARE(status, 2);
-#endif
}
void tst_QObject::connectFunctorWithContext()
@@ -6116,7 +6115,6 @@ void tst_QObject::connectFunctorWithContext()
e.exec();
QCOMPARE(status, 2);
-#if defined(Q_COMPILER_LAMBDA)
status = 1;
connect(&obj, &SenderObject::signal1, this, [this, &status, &obj] { status = 2; QCOMPARE(sender(), &obj); }, Qt::QueuedConnection);
@@ -6124,7 +6122,6 @@ void tst_QObject::connectFunctorWithContext()
QCOMPARE(status, 1);
e.exec();
QCOMPARE(status, 2);
-#endif
// Free
context->deleteLater();
@@ -6434,7 +6431,7 @@ void connectFunctorOverload_impl(Signal signal, int expOverload, QList<QVariant>
void tst_QObject::connectFunctorOverloads()
{
-#if defined (Q_COMPILER_DECLTYPE) && defined (Q_COMPILER_VARIADIC_TEMPLATES)
+#if defined (Q_COMPILER_VARIADIC_TEMPLATES)
connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_ii, 1,
(QList<QVariant>() << 1 << 2));
connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_iiS, 1,
@@ -6608,7 +6605,6 @@ void tst_QObject::disconnectDoesNotLeakFunctor()
}
QCOMPARE(countedStructObjectsCount, 0);
{
-#if defined(Q_COMPILER_LAMBDA)
CountedStruct s;
QCOMPARE(countedStructObjectsCount, 1);
QTimer timer;
@@ -6618,7 +6614,6 @@ void tst_QObject::disconnectDoesNotLeakFunctor()
QCOMPARE(countedStructObjectsCount, 2);
QVERIFY(QObject::disconnect(c));
QCOMPARE(countedStructObjectsCount, 1);
-#endif // Q_COMPILER_LAMBDA
}
QCOMPARE(countedStructObjectsCount, 0);
}
@@ -6666,7 +6661,6 @@ void tst_QObject::contextDoesNotLeakFunctor()
}
QCOMPARE(countedStructObjectsCount, 0);
{
-#if defined(Q_COMPILER_LAMBDA)
CountedStruct s;
QEventLoop e;
ContextObject *context = new ContextObject;
@@ -6679,7 +6673,6 @@ void tst_QObject::contextDoesNotLeakFunctor()
context->deleteLater();
e.exec();
QCOMPARE(countedStructObjectsCount, 1);
-#endif // Q_COMPILER_LAMBDA
}
QCOMPARE(countedStructObjectsCount, 0);
}
@@ -7487,6 +7480,167 @@ void tst_QObject::nullReceiver()
QVERIFY(!connect(&o, SIGNAL(destroyed()), nullObj, SLOT(deleteLater())));
}
+void tst_QObject::functorReferencesConnection()
+{
+ countedStructObjectsCount = 0;
+ QMetaObject::Connection globalCon;
+ {
+ GetSenderObject obj;
+ CountedStruct counted(&obj);
+ QCOMPARE(countedStructObjectsCount, 1);
+ auto c = QSharedPointer<QMetaObject::Connection>::create();
+ int slotCalled = 0;
+ *c = connect(&obj, &GetSenderObject::aSignal, &obj, [&slotCalled, c, counted] {
+ QObject::disconnect(*c);
+ slotCalled++;
+ });
+ globalCon = *c; // keep a handle to the connection somewhere;
+ QVERIFY(globalCon);
+ QCOMPARE(countedStructObjectsCount, 2);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ QVERIFY(!globalCon);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+
+ {
+ GetSenderObject obj;
+ CountedStruct counted(&obj);
+ QCOMPARE(countedStructObjectsCount, 1);
+ auto *rec = new QObject;
+ int slotCalled = 0;
+ globalCon = connect(&obj, &GetSenderObject::aSignal, rec, [&slotCalled, rec, counted] {
+ delete rec;
+ slotCalled++;
+ });
+ QCOMPARE(countedStructObjectsCount, 2);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ QVERIFY(!globalCon);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+ {
+ int slotCalled = 0;
+ QEventLoop eventLoop;
+ {
+ // Sender will be destroyed when the labda goes out of scope lambda, so it will exit the event loop
+ auto sender = QSharedPointer<GetSenderObject>::create();
+ connect(sender.data(), &QObject::destroyed, &eventLoop, &QEventLoop::quit, Qt::QueuedConnection);
+ globalCon = connect(sender.data(), &GetSenderObject::aSignal, this, [&slotCalled, sender, &globalCon, this] {
+ ++slotCalled;
+ // This signal will be connected, but should never be called as the sender will be destroyed before
+ auto c2 = connect(sender.data(), &GetSenderObject::aSignal, [] { QFAIL("Should not be called"); });
+ QVERIFY(c2);
+ QVERIFY(QObject::disconnect(sender.data(), nullptr, this, nullptr));
+ QVERIFY(!globalCon); // this connection has been disconnected
+ QVERIFY(c2); // sender should not have been deleted yet, only after the emission is done
+ });
+ QMetaObject::invokeMethod(sender.data(), &GetSenderObject::triggerSignal, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(sender.data(), &GetSenderObject::triggerSignal, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(sender.data(), &GetSenderObject::triggerSignal, Qt::QueuedConnection);
+ }
+ eventLoop.exec();
+ QCOMPARE(slotCalled, 1);
+ }
+
+ {
+ GetSenderObject obj;
+ CountedStruct counted(&obj);
+ QCOMPARE(countedStructObjectsCount, 1);
+ auto c1 = QSharedPointer<QMetaObject::Connection>::create();
+ auto c2 = QSharedPointer<QMetaObject::Connection>::create();
+ int slot1Called = 0;
+ int slot3Called = 0;
+ *c1 = connect(&obj, &GetSenderObject::aSignal, &obj, [&slot1Called, &slot3Called, &obj, c1, c2, counted] {
+ auto c3 = connect(&obj, &GetSenderObject::aSignal, [counted, &slot3Called] {
+ slot3Called++;
+ });
+ // top-level + the one in the 3 others lambdas
+ QCOMPARE(countedStructObjectsCount, 4);
+ QObject::disconnect(*c2);
+ slot1Called++;
+ });
+ connect(&obj, &GetSenderObject::aSignal, [] {}); // just a dummy signal to fill the connection list
+ *c2 = connect(&obj, &GetSenderObject::aSignal, [counted, c2] { QFAIL("should not be called"); });
+ QVERIFY(c1 && c2);
+ QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c2
+ obj.triggerSignal();
+ QCOMPARE(slot1Called, 1);
+ QCOMPARE(slot3Called, 0);
+ QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c3
+ QObject::disconnect(*c1);
+ QCOMPARE(countedStructObjectsCount, 2); // top-level + c3
+ obj.triggerSignal();
+ QCOMPARE(slot1Called, 1);
+ QCOMPARE(slot3Called, 1);
+ }
+ {
+ struct DestroyEmit {
+ Q_DISABLE_COPY(DestroyEmit);
+ explicit DestroyEmit(SenderObject *obj) : obj(obj) {}
+ SenderObject *obj;
+ ~DestroyEmit() {
+ obj->emitSignal1();
+ }
+ };
+ SenderObject obj;
+ int slot1Called = 0;
+ int slot2Called = 0;
+ int slot3Called = 0;
+ auto c1 = QSharedPointer<QMetaObject::Connection>::create();
+ auto de = QSharedPointer<DestroyEmit>::create(&obj);
+ *c1 = connect(&obj, &SenderObject::signal1, [&slot1Called, &slot3Called, de, c1, &obj] {
+ connect(&obj, &SenderObject::signal1, [&slot3Called] { slot3Called++; });
+ slot1Called++;
+ QObject::disconnect(*c1);
+ });
+ de.clear();
+ connect(&obj, &SenderObject::signal1, [&slot2Called] { slot2Called++; });
+ obj.emitSignal1();
+ QCOMPARE(slot1Called, 1);
+ QCOMPARE(slot2Called, 2); // because also called from ~DestroyEmit
+ QCOMPARE(slot3Called, 1);
+ }
+}
+
+void tst_QObject::disconnectDisconnects()
+{
+ // Test what happens if the destructor of an functor slot also disconnects more slot;
+
+ SenderObject s1;
+ QScopedPointer<QObject> receiver(new QObject);
+
+ auto s2 = QSharedPointer<SenderObject>::create();
+ QPointer<QObject> s2_tracker = s2.data();
+ int count = 0;
+ connect(&s1, &SenderObject::signal1, [&count] { count++; }); // α
+ connect(&s1, &SenderObject::signal1, receiver.data(), [s2] { QFAIL("!!"); }); // β
+ connect(s2.data(), &SenderObject::signal1, receiver.data(), [] { QFAIL("!!"); });
+ connect(&s1, &SenderObject::signal2, receiver.data(), [] { QFAIL("!!"); });
+ connect(s2.data(), &SenderObject::signal2, receiver.data(), [] { QFAIL("!!"); });
+ connect(&s1, &SenderObject::signal1, [&count] { count++; }); // γ
+ connect(&s1, &SenderObject::signal2, [&count] { count++; }); // δ
+ s2.clear();
+
+ QVERIFY(s2_tracker);
+ receiver
+ .reset(); // this will delete the receiver which must also delete s2 as β is disconnected
+ QVERIFY(!s2_tracker);
+ // test that the data structures are still in order
+ s1.emitSignal1();
+ QCOMPARE(count, 2); // α + γ
+ s1.emitSignal2();
+ QCOMPARE(count, 3); // + δ
+}
+
// Test for QtPrivate::HasQ_OBJECT_Macro
Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value);
Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value);
diff --git a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
index 55deb8eb1a..fa2d5e3723 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
@@ -34,6 +34,7 @@
#include <QSharedMemory>
#include <QTest>
#include <QThread>
+#include <QElapsedTimer>
#define EXISTING_SHARE "existing"
#define EXISTING_SIZE 1024
@@ -645,7 +646,7 @@ public:
char *memory = (char*)producer.data();
memory[1] = '0';
- QTime timer;
+ QElapsedTimer timer;
timer.start();
int i = 0;
while (i < 5 && timer.elapsed() < 5000) {
diff --git a/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp b/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp
index fd18f00cd0..39b03ade61 100644
--- a/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp
+++ b/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp
@@ -66,7 +66,6 @@ void tst_QSignalBlocker::signalBlocking()
void tst_QSignalBlocker::moveAssignment()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QObject o1, o2;
// move-assignment: both block other objects
@@ -157,10 +156,6 @@ void tst_QSignalBlocker::moveAssignment()
QVERIFY(!o1.signalsBlocked());
QVERIFY(!o2.signalsBlocked());
-
-#else
- QSKIP("This compiler is not in C++11 mode or doesn't support move semantics");
-#endif // Q_COMPILER_RVALUE_REFS
}
QTEST_MAIN(tst_QSignalBlocker)
diff --git a/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST b/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST
index e68bf84268..f2e5e78592 100644
--- a/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST
+++ b/tests/auto/corelib/kernel/qsocketnotifier/BLACKLIST
@@ -1,3 +1,3 @@
[unexpectedDisconnection]
-windows
-osx
+windows-7sp1
+windows-10 msvc-2015
diff --git a/tests/auto/corelib/kernel/qtimer/BLACKLIST b/tests/auto/corelib/kernel/qtimer/BLACKLIST
deleted file mode 100644
index 16cbab4587..0000000000
--- a/tests/auto/corelib/kernel/qtimer/BLACKLIST
+++ /dev/null
@@ -1,5 +0,0 @@
-[remainingTime]
-windows
-osx
-[basic_chrono]
-osx
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 3b10547dc4..8e0bdac520 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -38,6 +38,7 @@
#include <qtimer.h>
#include <qthread.h>
+#include <qelapsedtimer.h>
#if defined Q_OS_UNIX
#include <unistd.h>
@@ -46,7 +47,11 @@
class tst_QTimer : public QObject
{
Q_OBJECT
+public:
+ static void initMain();
+
private slots:
+ void cleanupTestCase();
void zeroTimer();
void singleShotTimeout();
void timeout();
@@ -73,7 +78,12 @@ private slots:
void recurseOnTimeoutAndStopTimer();
void singleShotToFunctors();
void singleShot_chrono();
+ void singleShot_static();
void crossThreadSingleShotToFunctor();
+ void timerOrder();
+ void timerOrder_data();
+ void timerOrderBackgroundThread();
+ void timerOrderBackgroundThread_data() { timerOrder_data(); }
void dontBlockEvents();
void postedEventsShouldNotStarveTimers();
@@ -521,7 +531,7 @@ public:
QBasicTimer m_timer;
int m_interval;
- QTime m_startedTime;
+ QElapsedTimer m_elapsedTimer;
QEventLoop eventLoop;
inline RestartedTimerFiresTooSoonObject()
@@ -533,7 +543,7 @@ public:
static int interval = 1000;
m_interval = interval;
- m_startedTime.start();
+ m_elapsedTimer.start();
m_timer.start(interval, this);
// alternate between single-shot and 1 sec
@@ -547,7 +557,7 @@ public:
m_timer.stop();
- int elapsed = m_startedTime.elapsed();
+ int elapsed = m_elapsedTimer.elapsed();
if (elapsed < m_interval / 2) {
// severely too early!
@@ -585,10 +595,10 @@ public:
public slots:
void longLastingSlot()
{
- // Don't use timers for this, because we are testing them.
- QTime time;
- time.start();
- while (time.elapsed() < 200) {
+ // Don't use QTimer for this, because we are testing it.
+ QElapsedTimer control;
+ control.start();
+ while (control.elapsed() < 200) {
for (int c = 0; c < 100000; c++) {} // Mindless looping.
}
if (++count >= 2) {
@@ -768,7 +778,7 @@ public:
quitEventLoop_noexcept();
}
- static void quitEventLoop_noexcept() Q_DECL_NOTHROW
+ static void quitEventLoop_noexcept() noexcept
{
QVERIFY(!_e.isNull());
_e->quit();
@@ -1033,5 +1043,126 @@ void tst_QTimer::callOnTimeout()
QVERIFY(!connection);
}
+class OrderHelper : public QObject
+{
+ Q_OBJECT
+public:
+ enum CallType
+ {
+ String,
+ PMF,
+ Functor,
+ FunctorNoCtx
+ };
+ Q_ENUM(CallType)
+ QVector<CallType> calls;
+
+ void triggerCall(CallType callType)
+ {
+ switch (callType)
+ {
+ case String:
+ QTimer::singleShot(0, this, SLOT(stringSlot()));
+ break;
+ case PMF:
+ QTimer::singleShot(0, this, &OrderHelper::pmfSlot);
+ break;
+ case Functor:
+ QTimer::singleShot(0, this, [this]() { functorSlot(); });
+ break;
+ case FunctorNoCtx:
+ QTimer::singleShot(0, [this]() { functorNoCtxSlot(); });
+ break;
+ }
+ }
+
+public slots:
+ void stringSlot() { calls << String; }
+ void pmfSlot() { calls << PMF; }
+ void functorSlot() { calls << Functor; }
+ void functorNoCtxSlot() { calls << FunctorNoCtx; }
+};
+
+Q_DECLARE_METATYPE(OrderHelper::CallType)
+
+void tst_QTimer::timerOrder()
+{
+ QFETCH(QVector<OrderHelper::CallType>, calls);
+
+ OrderHelper helper;
+
+ for (const auto call : calls)
+ helper.triggerCall(call);
+
+ QTRY_COMPARE(helper.calls, calls);
+}
+
+void tst_QTimer::timerOrder_data()
+{
+ QTest::addColumn<QVector<OrderHelper::CallType>>("calls");
+
+ QVector<OrderHelper::CallType> calls = {
+ OrderHelper::String, OrderHelper::PMF,
+ OrderHelper::Functor, OrderHelper::FunctorNoCtx
+ };
+ std::sort(calls.begin(), calls.end());
+
+ int permutation = 0;
+ do {
+ QTest::addRow("permutation=%d", permutation) << calls;
+ ++permutation;
+ } while (std::next_permutation(calls.begin(), calls.end()));
+}
+
+void tst_QTimer::timerOrderBackgroundThread()
+{
+#if !QT_CONFIG(cxx11_future)
+ QSKIP("This test requires QThread::create");
+#else
+ auto *thread = QThread::create([this]() { timerOrder(); });
+ thread->start();
+ QVERIFY(thread->wait());
+ delete thread;
+#endif
+}
+
+struct StaticSingleShotUser
+{
+ StaticSingleShotUser()
+ {
+ for (auto call : calls())
+ helper.triggerCall(call);
+ }
+ OrderHelper helper;
+
+ static QVector<OrderHelper::CallType> calls()
+ {
+ return {OrderHelper::String, OrderHelper::PMF,
+ OrderHelper::Functor, OrderHelper::FunctorNoCtx};
+ }
+};
+
+// NOTE: to prevent any static initialization order fiasco, we implement
+// initMain() to instantiate staticSingleShotUser before qApp
+
+static StaticSingleShotUser *s_staticSingleShotUser = nullptr;
+
+void tst_QTimer::initMain()
+{
+ s_staticSingleShotUser = new StaticSingleShotUser;
+}
+
+void tst_QTimer::cleanupTestCase()
+{
+ delete s_staticSingleShotUser;
+}
+
+void tst_QTimer::singleShot_static()
+{
+ QCoreApplication::processEvents();
+ QCOMPARE(s_staticSingleShotUser->helper.calls, s_staticSingleShotUser->calls());
+}
+
QTEST_MAIN(tst_QTimer)
+
#include "tst_qtimer.moc"
diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
index 40a29c723c..b3efa97dbd 100644
--- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
+++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
@@ -310,7 +310,7 @@ struct TranslateThread : public QThread
void run() {
bool startSignalled = false;
- while (terminate.load() == 0) {
+ while (terminate.loadRelaxed() == 0) {
const QString result = QCoreApplication::translate("QPushButton", "Hello %n world(s)!", 0, 0);
if (!startSignalled) {
diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro
index a620be0091..0b5280df86 100644
--- a/tests/auto/corelib/kernel/qvariant/qvariant.pro
+++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro
@@ -5,6 +5,7 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qvariant.cpp
RESOURCES += qvariant.qrc
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+DEFINES -= QT_NO_LINKED_LIST
qtConfig(c++14): CONFIG += c++14
qtConfig(c++1z): CONFIG += c++1z
!qtConfig(doubleconversion):!qtConfig(system-doubleconversion) {
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 4da34c407e..074cb07092 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -59,12 +59,6 @@
class CustomNonQObject;
-#if defined(Q_COMPILER_CLASS_ENUM)
-#define ENUM_SIZE(X) : X
-#else
-#define ENUM_SIZE(X)
-#endif
-
class tst_QVariant : public QObject
{
Q_OBJECT
@@ -82,15 +76,15 @@ public:
enum MetaEnumTest_Enum1 : qint64 { MetaEnumTest_Enum1_value = 42, MetaEnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
Q_ENUM(MetaEnumTest_Enum1)
- enum MetaEnumTest_Enum3 ENUM_SIZE(qint64) { MetaEnumTest_Enum3_value = -47, MetaEnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5, MetaEnumTest_Enum3_bigNegValue = -(Q_INT64_C(1) << 56) - 3 };
+ enum MetaEnumTest_Enum3 : qint64 { MetaEnumTest_Enum3_value = -47, MetaEnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5, MetaEnumTest_Enum3_bigNegValue = -(Q_INT64_C(1) << 56) - 3 };
Q_ENUM(MetaEnumTest_Enum3)
- enum MetaEnumTest_Enum4 ENUM_SIZE(quint64) { MetaEnumTest_Enum4_value = 47, MetaEnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
+ enum MetaEnumTest_Enum4 : quint64 { MetaEnumTest_Enum4_value = 47, MetaEnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
Q_ENUM(MetaEnumTest_Enum4)
- enum MetaEnumTest_Enum5 ENUM_SIZE(uint) { MetaEnumTest_Enum5_value = 47 };
+ enum MetaEnumTest_Enum5 : uint { MetaEnumTest_Enum5_value = 47 };
Q_ENUM(MetaEnumTest_Enum5)
- enum MetaEnumTest_Enum6 ENUM_SIZE(uchar) { MetaEnumTest_Enum6_value = 47 };
+ enum MetaEnumTest_Enum6 : uchar { MetaEnumTest_Enum6_value = 47 };
Q_ENUM(MetaEnumTest_Enum6)
- enum MetaEnumTest_Enum8 ENUM_SIZE(short) { MetaEnumTest_Enum8_value = 47 };
+ enum MetaEnumTest_Enum8 : short { MetaEnumTest_Enum8_value = 47 };
Q_ENUM(MetaEnumTest_Enum8)
private slots:
@@ -385,9 +379,13 @@ void tst_QVariant::isNull()
QString str1;
QVariant var1( str1 );
QVERIFY( var1.isNull() );
-
+#if QT_DEPRECATED_SINCE(5, 9)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QVariant var2( QString::null );
+QT_WARNING_POP
QVERIFY( var2.isNull() );
+#endif
QVariant var3( QString( "blah" ) );
QVERIFY( !var3.isNull() );
@@ -406,10 +404,19 @@ void tst_QVariant::isNull()
QVERIFY( var6.isNull() );
QVariant varLL( (qlonglong)0 );
QVERIFY( !varLL.isNull() );
+
+#if QT_DEPRECATED_SINCE(5, 9)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QVariant var7(QString::null);
+QT_WARNING_POP
QVERIFY(var7.isNull());
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
var7 = QVariant::fromValue<QString>(QString::null);
+QT_WARNING_POP
QVERIFY(var7.isNull());
+#endif
QVariant var8(QMetaType::Nullptr, nullptr);
QVERIFY(var8.isNull());
@@ -431,6 +438,9 @@ void tst_QVariant::isNull()
QVERIFY(var11.isNull());
QVERIFY(QVariant::fromValue<int*>(nullptr).isNull());
+
+ QVariant var12(QVariant::fromValue<QString>(QString()));
+ QVERIFY(var12.isNull());
}
void tst_QVariant::swap()
@@ -1728,281 +1738,281 @@ void tst_QVariant::compareNumbers_data() const
QTest::newRow("bool3") << QVariant(false) << QVariant(true) << -1;
QTest::newRow("bool4") << QVariant(true) << QVariant(false) << +1;
- QTest::newRow("char1") << qVariantFromValue(char(0)) << qVariantFromValue(char(0)) << 0;
- QTest::newRow("char2") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(CHAR_MAX) << 0;
- QTest::newRow("char3") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(CHAR_MIN) << 0;
- QTest::newRow("char4") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(CHAR_MAX) << -1;
- QTest::newRow("char5") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(CHAR_MIN) << +1;
-
- QTest::newRow("schar1") << qVariantFromValue(schar(0)) << qVariantFromValue(schar(0)) << 0;
- QTest::newRow("schar2") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(SCHAR_MAX) << 0;
- QTest::newRow("schar3") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(SCHAR_MIN) << 0;
- QTest::newRow("schar4") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(SCHAR_MAX) << -1;
- QTest::newRow("schar5") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(SCHAR_MIN) << +1;
-
- QTest::newRow("uchar1") << qVariantFromValue(uchar(0)) << qVariantFromValue(uchar(0)) << 0;
- QTest::newRow("uchar2") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(UCHAR_MAX) << 0;
- QTest::newRow("uchar3") << qVariantFromValue(uchar(0)) << qVariantFromValue(UCHAR_MAX) << -1;
- QTest::newRow("uchar4") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(uchar(0)) << +1;
-
- QTest::newRow("short1") << qVariantFromValue(short(0)) << qVariantFromValue(short(0)) << 0;
- QTest::newRow("short2") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(SHRT_MAX) << 0;
- QTest::newRow("short3") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(SHRT_MIN) << 0;
- QTest::newRow("short4") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(SHRT_MAX) << -1;
- QTest::newRow("short5") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(SHRT_MIN) << +1;
-
- QTest::newRow("ushort1") << qVariantFromValue(ushort(0)) << qVariantFromValue(ushort(0)) << 0;
- QTest::newRow("ushort2") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(USHRT_MAX) << 0;
- QTest::newRow("ushort3") << qVariantFromValue(ushort(0)) << qVariantFromValue(USHRT_MAX) << -1;
- QTest::newRow("ushort4") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(ushort(0)) << +1;
-
- QTest::newRow("int1") << qVariantFromValue(int(0)) << qVariantFromValue(int(0)) << 0;
- QTest::newRow("int2") << qVariantFromValue(INT_MAX) << qVariantFromValue(INT_MAX) << 0;
- QTest::newRow("int3") << qVariantFromValue(INT_MIN) << qVariantFromValue(INT_MIN) << 0;
- QTest::newRow("int4") << qVariantFromValue(INT_MIN) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("int5") << qVariantFromValue(INT_MAX) << qVariantFromValue(INT_MIN) << +1;
-
- QTest::newRow("uint1") << qVariantFromValue(uint(0)) << qVariantFromValue(uint(0)) << 0;
- QTest::newRow("uint2") << qVariantFromValue(UINT_MAX) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("uint3") << qVariantFromValue(uint(0)) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("uint4") << qVariantFromValue(UINT_MAX) << qVariantFromValue(uint(0)) << +1;
-
- QTest::newRow("long1") << qVariantFromValue(long(0)) << qVariantFromValue(long(0)) << 0;
- QTest::newRow("long2") << qVariantFromValue(LONG_MAX) << qVariantFromValue(LONG_MAX) << 0;
- QTest::newRow("long3") << qVariantFromValue(LONG_MIN) << qVariantFromValue(LONG_MIN) << 0;
- QTest::newRow("long4") << qVariantFromValue(LONG_MIN) << qVariantFromValue(LONG_MAX) << -1;
- QTest::newRow("long5") << qVariantFromValue(LONG_MAX) << qVariantFromValue(LONG_MIN) << +1;
-
- QTest::newRow("ulong1") << qVariantFromValue(ulong(0)) << qVariantFromValue(ulong(0)) << 0;
- QTest::newRow("ulong2") << qVariantFromValue(ULONG_MAX) << qVariantFromValue(ULONG_MAX) << 0;
- QTest::newRow("ulong3") << qVariantFromValue(ulong(0)) << qVariantFromValue(ULONG_MAX) << -1;
- QTest::newRow("ulong4") << qVariantFromValue(ULONG_MAX) << qVariantFromValue(ulong(0)) << +1;
-
- QTest::newRow("llong1") << qVariantFromValue(qlonglong(0)) << qVariantFromValue(qlonglong(0)) << 0;
- QTest::newRow("llong2") << qVariantFromValue(LLONG_MAX) << qVariantFromValue(LLONG_MAX) << 0;
- QTest::newRow("llong3") << qVariantFromValue(LLONG_MIN) << qVariantFromValue(LLONG_MIN) << 0;
- QTest::newRow("llong4") << qVariantFromValue(LLONG_MIN) << qVariantFromValue(LLONG_MAX) << -1;
- QTest::newRow("llong5") << qVariantFromValue(LLONG_MAX) << qVariantFromValue(LLONG_MIN) << +1;
-
- QTest::newRow("ullong1") << qVariantFromValue(qulonglong(0)) << qVariantFromValue(qulonglong(0)) << 0;
- QTest::newRow("ullong2") << qVariantFromValue(ULLONG_MAX) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("ullong3") << qVariantFromValue(qulonglong(0)) << qVariantFromValue(ULLONG_MAX) << -1;
- QTest::newRow("ullong4") << qVariantFromValue(ULLONG_MAX) << qVariantFromValue(qulonglong(0)) << +1;
-
- QTest::newRow("float1") << qVariantFromValue(0.f) << qVariantFromValue(0.f) << 0;
- QTest::newRow("float2") << qVariantFromValue(-1.f) << qVariantFromValue(0.f) << -1;
- QTest::newRow("float3") << qVariantFromValue(0.f) << qVariantFromValue(-1.f) << +1;
- QTest::newRow("float4") << qVariantFromValue(-float(qInf())) << qVariantFromValue(0.f) << -1;
- QTest::newRow("float5") << qVariantFromValue(0.f) << qVariantFromValue(-float(qInf())) << +1;
- QTest::newRow("float6") << qVariantFromValue(-float(qInf())) << qVariantFromValue(-float(qInf())) << 0;
- QTest::newRow("float7") << qVariantFromValue(float(qInf())) << qVariantFromValue(float(qInf())) << 0;
-
- QTest::newRow("double1") << qVariantFromValue(0.) << qVariantFromValue(0.) << 0;
- QTest::newRow("double2") << qVariantFromValue(-1.) << qVariantFromValue(0.) << -1;
- QTest::newRow("double3") << qVariantFromValue(0.) << qVariantFromValue(-1.) << +1;
- QTest::newRow("double4") << qVariantFromValue(-qInf()) << qVariantFromValue(0.) << -1;
- QTest::newRow("double5") << qVariantFromValue(0.) << qVariantFromValue(-qInf()) << +1;
- QTest::newRow("double6") << qVariantFromValue(-double(qInf())) << qVariantFromValue(-qInf()) << 0;
- QTest::newRow("double7") << qVariantFromValue(qInf()) << qVariantFromValue(qInf()) << 0;
- QTest::newRow("double8") << qVariantFromValue(-qInf()) << qVariantFromValue(qInf()) << -1;
- QTest::newRow("double9") << qVariantFromValue(qQNaN()) << qVariantFromValue(0.) << INT_MAX;
- QTest::newRow("double10") << qVariantFromValue(0.) << qVariantFromValue(qQNaN()) << INT_MAX;
- QTest::newRow("double11") << qVariantFromValue(qQNaN()) << qVariantFromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("char1") << QVariant::fromValue(char(0)) << QVariant::fromValue(char(0)) << 0;
+ QTest::newRow("char2") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(CHAR_MAX) << 0;
+ QTest::newRow("char3") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(CHAR_MIN) << 0;
+ QTest::newRow("char4") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(CHAR_MAX) << -1;
+ QTest::newRow("char5") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(CHAR_MIN) << +1;
+
+ QTest::newRow("schar1") << QVariant::fromValue(schar(0)) << QVariant::fromValue(schar(0)) << 0;
+ QTest::newRow("schar2") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(SCHAR_MAX) << 0;
+ QTest::newRow("schar3") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(SCHAR_MIN) << 0;
+ QTest::newRow("schar4") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(SCHAR_MAX) << -1;
+ QTest::newRow("schar5") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(SCHAR_MIN) << +1;
+
+ QTest::newRow("uchar1") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(uchar(0)) << 0;
+ QTest::newRow("uchar2") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(UCHAR_MAX) << 0;
+ QTest::newRow("uchar3") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(UCHAR_MAX) << -1;
+ QTest::newRow("uchar4") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(uchar(0)) << +1;
+
+ QTest::newRow("short1") << QVariant::fromValue(short(0)) << QVariant::fromValue(short(0)) << 0;
+ QTest::newRow("short2") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(SHRT_MAX) << 0;
+ QTest::newRow("short3") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(SHRT_MIN) << 0;
+ QTest::newRow("short4") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(SHRT_MAX) << -1;
+ QTest::newRow("short5") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(SHRT_MIN) << +1;
+
+ QTest::newRow("ushort1") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(ushort(0)) << 0;
+ QTest::newRow("ushort2") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(USHRT_MAX) << 0;
+ QTest::newRow("ushort3") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(USHRT_MAX) << -1;
+ QTest::newRow("ushort4") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(ushort(0)) << +1;
+
+ QTest::newRow("int1") << QVariant::fromValue(int(0)) << QVariant::fromValue(int(0)) << 0;
+ QTest::newRow("int2") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(INT_MAX) << 0;
+ QTest::newRow("int3") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(INT_MIN) << 0;
+ QTest::newRow("int4") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("int5") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(INT_MIN) << +1;
+
+ QTest::newRow("uint1") << QVariant::fromValue(uint(0)) << QVariant::fromValue(uint(0)) << 0;
+ QTest::newRow("uint2") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("uint3") << QVariant::fromValue(uint(0)) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("uint4") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(uint(0)) << +1;
+
+ QTest::newRow("long1") << QVariant::fromValue(long(0)) << QVariant::fromValue(long(0)) << 0;
+ QTest::newRow("long2") << QVariant::fromValue(LONG_MAX) << QVariant::fromValue(LONG_MAX) << 0;
+ QTest::newRow("long3") << QVariant::fromValue(LONG_MIN) << QVariant::fromValue(LONG_MIN) << 0;
+ QTest::newRow("long4") << QVariant::fromValue(LONG_MIN) << QVariant::fromValue(LONG_MAX) << -1;
+ QTest::newRow("long5") << QVariant::fromValue(LONG_MAX) << QVariant::fromValue(LONG_MIN) << +1;
+
+ QTest::newRow("ulong1") << QVariant::fromValue(ulong(0)) << QVariant::fromValue(ulong(0)) << 0;
+ QTest::newRow("ulong2") << QVariant::fromValue(ULONG_MAX) << QVariant::fromValue(ULONG_MAX) << 0;
+ QTest::newRow("ulong3") << QVariant::fromValue(ulong(0)) << QVariant::fromValue(ULONG_MAX) << -1;
+ QTest::newRow("ulong4") << QVariant::fromValue(ULONG_MAX) << QVariant::fromValue(ulong(0)) << +1;
+
+ QTest::newRow("llong1") << QVariant::fromValue(qlonglong(0)) << QVariant::fromValue(qlonglong(0)) << 0;
+ QTest::newRow("llong2") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(LLONG_MAX) << 0;
+ QTest::newRow("llong3") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(LLONG_MIN) << 0;
+ QTest::newRow("llong4") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(LLONG_MAX) << -1;
+ QTest::newRow("llong5") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(LLONG_MIN) << +1;
+
+ QTest::newRow("ullong1") << QVariant::fromValue(qulonglong(0)) << QVariant::fromValue(qulonglong(0)) << 0;
+ QTest::newRow("ullong2") << QVariant::fromValue(ULLONG_MAX) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("ullong3") << QVariant::fromValue(qulonglong(0)) << QVariant::fromValue(ULLONG_MAX) << -1;
+ QTest::newRow("ullong4") << QVariant::fromValue(ULLONG_MAX) << QVariant::fromValue(qulonglong(0)) << +1;
+
+ QTest::newRow("float1") << QVariant::fromValue(0.f) << QVariant::fromValue(0.f) << 0;
+ QTest::newRow("float2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0.f) << -1;
+ QTest::newRow("float3") << QVariant::fromValue(0.f) << QVariant::fromValue(-1.f) << +1;
+ QTest::newRow("float4") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(0.f) << -1;
+ QTest::newRow("float5") << QVariant::fromValue(0.f) << QVariant::fromValue(-float(qInf())) << +1;
+ QTest::newRow("float6") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(-float(qInf())) << 0;
+ QTest::newRow("float7") << QVariant::fromValue(float(qInf())) << QVariant::fromValue(float(qInf())) << 0;
+
+ QTest::newRow("double1") << QVariant::fromValue(0.) << QVariant::fromValue(0.) << 0;
+ QTest::newRow("double2") << QVariant::fromValue(-1.) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("double3") << QVariant::fromValue(0.) << QVariant::fromValue(-1.) << +1;
+ QTest::newRow("double4") << QVariant::fromValue(-qInf()) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("double5") << QVariant::fromValue(0.) << QVariant::fromValue(-qInf()) << +1;
+ QTest::newRow("double6") << QVariant::fromValue(-double(qInf())) << QVariant::fromValue(-qInf()) << 0;
+ QTest::newRow("double7") << QVariant::fromValue(qInf()) << QVariant::fromValue(qInf()) << 0;
+ QTest::newRow("double8") << QVariant::fromValue(-qInf()) << QVariant::fromValue(qInf()) << -1;
+ QTest::newRow("double9") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(0.) << INT_MAX;
+ QTest::newRow("double10") << QVariant::fromValue(0.) << QVariant::fromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("double11") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(qQNaN()) << INT_MAX;
// mixed comparisons
// fp + fp
- QTest::newRow("float+double1") << qVariantFromValue(0.f) << qVariantFromValue(0.) << 0;
- QTest::newRow("float+double2") << qVariantFromValue(-1.f) << qVariantFromValue(0.) << -1;
- QTest::newRow("float+double3") << qVariantFromValue(0.f) << qVariantFromValue(-1.) << +1;
- QTest::newRow("float+double4") << qVariantFromValue(-float(qInf())) << qVariantFromValue(0.) << -1;
- QTest::newRow("float+double5") << qVariantFromValue(0.f) << qVariantFromValue(-qInf()) << +1;
- QTest::newRow("float+double6") << qVariantFromValue(-float(qInf())) << qVariantFromValue(-qInf()) << 0;
- QTest::newRow("float+double7") << qVariantFromValue(float(qInf())) << qVariantFromValue(qInf()) << 0;
- QTest::newRow("float+double8") << qVariantFromValue(-float(qInf())) << qVariantFromValue(qInf()) << -1;
- QTest::newRow("float+double9") << qVariantFromValue(qQNaN()) << qVariantFromValue(0.) << INT_MAX;
- QTest::newRow("float+double10") << qVariantFromValue(0.) << qVariantFromValue(qQNaN()) << INT_MAX;
- QTest::newRow("float+double11") << qVariantFromValue(qQNaN()) << qVariantFromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("float+double1") << QVariant::fromValue(0.f) << QVariant::fromValue(0.) << 0;
+ QTest::newRow("float+double2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("float+double3") << QVariant::fromValue(0.f) << QVariant::fromValue(-1.) << +1;
+ QTest::newRow("float+double4") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("float+double5") << QVariant::fromValue(0.f) << QVariant::fromValue(-qInf()) << +1;
+ QTest::newRow("float+double6") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(-qInf()) << 0;
+ QTest::newRow("float+double7") << QVariant::fromValue(float(qInf())) << QVariant::fromValue(qInf()) << 0;
+ QTest::newRow("float+double8") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(qInf()) << -1;
+ QTest::newRow("float+double9") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(0.) << INT_MAX;
+ QTest::newRow("float+double10") << QVariant::fromValue(0.) << QVariant::fromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("float+double11") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(qQNaN()) << INT_MAX;
// fp + int
- QTest::newRow("float+int1") << qVariantFromValue(0.f) << qVariantFromValue(0) << 0;
- QTest::newRow("double+int1") << qVariantFromValue(0.) << qVariantFromValue(0) << 0;
- QTest::newRow("float+int2") << qVariantFromValue(-1.f) << qVariantFromValue(0) << -1;
- QTest::newRow("double+int2") << qVariantFromValue(-1.) << qVariantFromValue(0) << -1;
- QTest::newRow("float+int3") << qVariantFromValue(0.f) << qVariantFromValue(-1) << +1;
- QTest::newRow("double+int3") << qVariantFromValue(0.) << qVariantFromValue(-1) << +1;
- QTest::newRow("float+int4") << qVariantFromValue(1.5f) << qVariantFromValue(1) << +1;
- QTest::newRow("double+int4") << qVariantFromValue(1.5) << qVariantFromValue(1) << +1;
- QTest::newRow("double+int5") << qVariantFromValue(qInf()) << qVariantFromValue(1) << +1;
+ QTest::newRow("float+int1") << QVariant::fromValue(0.f) << QVariant::fromValue(0) << 0;
+ QTest::newRow("double+int1") << QVariant::fromValue(0.) << QVariant::fromValue(0) << 0;
+ QTest::newRow("float+int2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0) << -1;
+ QTest::newRow("double+int2") << QVariant::fromValue(-1.) << QVariant::fromValue(0) << -1;
+ QTest::newRow("float+int3") << QVariant::fromValue(0.f) << QVariant::fromValue(-1) << +1;
+ QTest::newRow("double+int3") << QVariant::fromValue(0.) << QVariant::fromValue(-1) << +1;
+ QTest::newRow("float+int4") << QVariant::fromValue(1.5f) << QVariant::fromValue(1) << +1;
+ QTest::newRow("double+int4") << QVariant::fromValue(1.5) << QVariant::fromValue(1) << +1;
+ QTest::newRow("double+int5") << QVariant::fromValue(qInf()) << QVariant::fromValue(1) << +1;
// fp + uint
- QTest::newRow("float+uint1") << qVariantFromValue(0.f) << qVariantFromValue(0U) << 0;
- QTest::newRow("double+uint1") << qVariantFromValue(0.) << qVariantFromValue(0U) << 0;
- QTest::newRow("float+uint2") << qVariantFromValue(-1.f) << qVariantFromValue(0U) << -1;
- QTest::newRow("double+uint2") << qVariantFromValue(-1.) << qVariantFromValue(0U) << -1;
- QTest::newRow("float+uint3") << qVariantFromValue(0.f) << qVariantFromValue(1U) << -1;
- QTest::newRow("double+uint3") << qVariantFromValue(0.) << qVariantFromValue(1U) << -1;
- QTest::newRow("float+uint4") << qVariantFromValue(1.5f) << qVariantFromValue(1U) << +1;
- QTest::newRow("double+uint4") << qVariantFromValue(1.5) << qVariantFromValue(1U) << +1;
+ QTest::newRow("float+uint1") << QVariant::fromValue(0.f) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("double+uint1") << QVariant::fromValue(0.) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("float+uint2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0U) << -1;
+ QTest::newRow("double+uint2") << QVariant::fromValue(-1.) << QVariant::fromValue(0U) << -1;
+ QTest::newRow("float+uint3") << QVariant::fromValue(0.f) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("double+uint3") << QVariant::fromValue(0.) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("float+uint4") << QVariant::fromValue(1.5f) << QVariant::fromValue(1U) << +1;
+ QTest::newRow("double+uint4") << QVariant::fromValue(1.5) << QVariant::fromValue(1U) << +1;
// lower ranked + int
- QTest::newRow("bool+int1") << qVariantFromValue(false) << qVariantFromValue(0) << 0;
- QTest::newRow("bool+int2") << qVariantFromValue(false) << qVariantFromValue(1) << -1;
- QTest::newRow("bool+int3") << qVariantFromValue(true) << qVariantFromValue(0) << +1;
- QTest::newRow("bool+int4") << qVariantFromValue(true) << qVariantFromValue(1) << 0;
- QTest::newRow("bool+int5") << qVariantFromValue(true) << qVariantFromValue(2) << -1;
-
- QTest::newRow("char+int1") << qVariantFromValue(char(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("char+int2") << qVariantFromValue(char(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("char+int3") << qVariantFromValue(char(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("char+int4") << qVariantFromValue(char(1)) << qVariantFromValue(1) << 0;
+ QTest::newRow("bool+int1") << QVariant::fromValue(false) << QVariant::fromValue(0) << 0;
+ QTest::newRow("bool+int2") << QVariant::fromValue(false) << QVariant::fromValue(1) << -1;
+ QTest::newRow("bool+int3") << QVariant::fromValue(true) << QVariant::fromValue(0) << +1;
+ QTest::newRow("bool+int4") << QVariant::fromValue(true) << QVariant::fromValue(1) << 0;
+ QTest::newRow("bool+int5") << QVariant::fromValue(true) << QVariant::fromValue(2) << -1;
+
+ QTest::newRow("char+int1") << QVariant::fromValue(char(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("char+int2") << QVariant::fromValue(char(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("char+int3") << QVariant::fromValue(char(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("char+int4") << QVariant::fromValue(char(1)) << QVariant::fromValue(1) << 0;
if (std::numeric_limits<char>::is_signed) {
- QTest::newRow("char+int5") << qVariantFromValue(char(-1)) << qVariantFromValue(0) << -1;
- QTest::newRow("char+int6") << qVariantFromValue(char(-1)) << qVariantFromValue(-1) << 0;
- }
-
- QTest::newRow("schar+int1") << qVariantFromValue(schar(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("schar+int2") << qVariantFromValue(schar(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("schar+int3") << qVariantFromValue(schar(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("schar+int4") << qVariantFromValue(schar(1)) << qVariantFromValue(1) << 0;
- QTest::newRow("schar+int5") << qVariantFromValue(schar(-1)) << qVariantFromValue(0) << -1;
- QTest::newRow("schar+int6") << qVariantFromValue(schar(-1)) << qVariantFromValue(-1) << 0;
-
- QTest::newRow("uchar+int1") << qVariantFromValue(uchar(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("uchar+int2") << qVariantFromValue(uchar(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("uchar+int3") << qVariantFromValue(uchar(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("uchar+int4") << qVariantFromValue(uchar(1)) << qVariantFromValue(1) << 0;
-
- QTest::newRow("short+int1") << qVariantFromValue(short(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("short+int2") << qVariantFromValue(short(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("short+int3") << qVariantFromValue(short(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("short+int4") << qVariantFromValue(short(1)) << qVariantFromValue(1) << 0;
- QTest::newRow("short+int5") << qVariantFromValue(short(-1)) << qVariantFromValue(0) << -1;
- QTest::newRow("short+int6") << qVariantFromValue(short(-1)) << qVariantFromValue(-1) << 0;
-
- QTest::newRow("ushort+int1") << qVariantFromValue(ushort(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("ushort+int2") << qVariantFromValue(ushort(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("ushort+int3") << qVariantFromValue(ushort(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("ushort+int4") << qVariantFromValue(ushort(1)) << qVariantFromValue(1) << 0;
+ QTest::newRow("char+int5") << QVariant::fromValue(char(-1)) << QVariant::fromValue(0) << -1;
+ QTest::newRow("char+int6") << QVariant::fromValue(char(-1)) << QVariant::fromValue(-1) << 0;
+ }
+
+ QTest::newRow("schar+int1") << QVariant::fromValue(schar(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("schar+int2") << QVariant::fromValue(schar(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("schar+int3") << QVariant::fromValue(schar(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("schar+int4") << QVariant::fromValue(schar(1)) << QVariant::fromValue(1) << 0;
+ QTest::newRow("schar+int5") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(0) << -1;
+ QTest::newRow("schar+int6") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(-1) << 0;
+
+ QTest::newRow("uchar+int1") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("uchar+int2") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("uchar+int3") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("uchar+int4") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(1) << 0;
+
+ QTest::newRow("short+int1") << QVariant::fromValue(short(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("short+int2") << QVariant::fromValue(short(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("short+int3") << QVariant::fromValue(short(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("short+int4") << QVariant::fromValue(short(1)) << QVariant::fromValue(1) << 0;
+ QTest::newRow("short+int5") << QVariant::fromValue(short(-1)) << QVariant::fromValue(0) << -1;
+ QTest::newRow("short+int6") << QVariant::fromValue(short(-1)) << QVariant::fromValue(-1) << 0;
+
+ QTest::newRow("ushort+int1") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("ushort+int2") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("ushort+int3") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("ushort+int4") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(1) << 0;
// lower ranked + uint (without sign change)
- QTest::newRow("bool+uint1") << qVariantFromValue(false) << qVariantFromValue(0U) << 0;
- QTest::newRow("bool+uint2") << qVariantFromValue(false) << qVariantFromValue(1U) << -1;
- QTest::newRow("bool+uint3") << qVariantFromValue(true) << qVariantFromValue(0U) << +1;
- QTest::newRow("bool+uint4") << qVariantFromValue(true) << qVariantFromValue(1U) << 0;
- QTest::newRow("bool+uint5") << qVariantFromValue(true) << qVariantFromValue(2U) << -1;
-
- QTest::newRow("char+uint1") << qVariantFromValue(char(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("char+uint2") << qVariantFromValue(char(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("char+uint3") << qVariantFromValue(char(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("char+uint4") << qVariantFromValue(char(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("schar+uint1") << qVariantFromValue(schar(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("schar+uint2") << qVariantFromValue(schar(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("schar+uint3") << qVariantFromValue(schar(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("schar+uint4") << qVariantFromValue(schar(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("uchar+uint1") << qVariantFromValue(uchar(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("uchar+uint2") << qVariantFromValue(uchar(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("uchar+uint3") << qVariantFromValue(uchar(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("uchar+uint4") << qVariantFromValue(uchar(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("short+uint1") << qVariantFromValue(short(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("short+uint2") << qVariantFromValue(short(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("short+uint3") << qVariantFromValue(short(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("short+uint4") << qVariantFromValue(short(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("ushort+uint1") << qVariantFromValue(ushort(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("ushort+uint2") << qVariantFromValue(ushort(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("ushort+uint3") << qVariantFromValue(ushort(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("ushort+uint4") << qVariantFromValue(ushort(1)) << qVariantFromValue(1U) << 0;
+ QTest::newRow("bool+uint1") << QVariant::fromValue(false) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("bool+uint2") << QVariant::fromValue(false) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("bool+uint3") << QVariant::fromValue(true) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("bool+uint4") << QVariant::fromValue(true) << QVariant::fromValue(1U) << 0;
+ QTest::newRow("bool+uint5") << QVariant::fromValue(true) << QVariant::fromValue(2U) << -1;
+
+ QTest::newRow("char+uint1") << QVariant::fromValue(char(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("char+uint2") << QVariant::fromValue(char(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("char+uint3") << QVariant::fromValue(char(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("char+uint4") << QVariant::fromValue(char(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("schar+uint1") << QVariant::fromValue(schar(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("schar+uint2") << QVariant::fromValue(schar(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("schar+uint3") << QVariant::fromValue(schar(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("schar+uint4") << QVariant::fromValue(schar(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("uchar+uint1") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("uchar+uint2") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("uchar+uint3") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("uchar+uint4") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("short+uint1") << QVariant::fromValue(short(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("short+uint2") << QVariant::fromValue(short(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("short+uint3") << QVariant::fromValue(short(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("short+uint4") << QVariant::fromValue(short(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("ushort+uint1") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("ushort+uint2") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("ushort+uint3") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("ushort+uint4") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(1U) << 0;
// int + qlonglong
- QTest::newRow("int+qlonglong1") << qVariantFromValue(0) << qVariantFromValue(Q_INT64_C(0)) << 0;
- QTest::newRow("int+qlonglong2") << qVariantFromValue(1) << qVariantFromValue(Q_INT64_C(0)) << +1;
- QTest::newRow("int+qlonglong3") << qVariantFromValue(0) << qVariantFromValue(Q_INT64_C(1)) << -1;
- QTest::newRow("int+qlonglong4") << qVariantFromValue(1) << qVariantFromValue(Q_INT64_C(1)) << 0;
- QTest::newRow("int+qlonglong5") << qVariantFromValue(0) << qVariantFromValue(Q_INT64_C(-1)) << +1;
- QTest::newRow("int+qlonglong6") << qVariantFromValue(-1) << qVariantFromValue(Q_INT64_C(0)) << -1;
- QTest::newRow("int+qlonglong7") << qVariantFromValue(-1) << qVariantFromValue(Q_INT64_C(-1)) << 0;
+ QTest::newRow("int+qlonglong1") << QVariant::fromValue(0) << QVariant::fromValue(Q_INT64_C(0)) << 0;
+ QTest::newRow("int+qlonglong2") << QVariant::fromValue(1) << QVariant::fromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("int+qlonglong3") << QVariant::fromValue(0) << QVariant::fromValue(Q_INT64_C(1)) << -1;
+ QTest::newRow("int+qlonglong4") << QVariant::fromValue(1) << QVariant::fromValue(Q_INT64_C(1)) << 0;
+ QTest::newRow("int+qlonglong5") << QVariant::fromValue(0) << QVariant::fromValue(Q_INT64_C(-1)) << +1;
+ QTest::newRow("int+qlonglong6") << QVariant::fromValue(-1) << QVariant::fromValue(Q_INT64_C(0)) << -1;
+ QTest::newRow("int+qlonglong7") << QVariant::fromValue(-1) << QVariant::fromValue(Q_INT64_C(-1)) << 0;
// uint + qulonglong
- QTest::newRow("uint+qulonglong1") << qVariantFromValue(0U) << qVariantFromValue(Q_UINT64_C(0)) << 0;
- QTest::newRow("uint+qulonglong2") << qVariantFromValue(1U) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("uint+qulonglong3") << qVariantFromValue(0U) << qVariantFromValue(Q_UINT64_C(1)) << -1;
- QTest::newRow("uint+qulonglong4") << qVariantFromValue(1U) << qVariantFromValue(Q_UINT64_C(1)) << 0;
+ QTest::newRow("uint+qulonglong1") << QVariant::fromValue(0U) << QVariant::fromValue(Q_UINT64_C(0)) << 0;
+ QTest::newRow("uint+qulonglong2") << QVariant::fromValue(1U) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("uint+qulonglong3") << QVariant::fromValue(0U) << QVariant::fromValue(Q_UINT64_C(1)) << -1;
+ QTest::newRow("uint+qulonglong4") << QVariant::fromValue(1U) << QVariant::fromValue(Q_UINT64_C(1)) << 0;
// int + uint (without sign change)
- QTest::newRow("int+uint1") << qVariantFromValue(0) << qVariantFromValue(0U) << 0;
- QTest::newRow("int+uint2") << qVariantFromValue(1) << qVariantFromValue(0U) << +1;
- QTest::newRow("int+uint3") << qVariantFromValue(0) << qVariantFromValue(1U) << -1;
- QTest::newRow("int+uint4") << qVariantFromValue(1) << qVariantFromValue(1U) << 0;
+ QTest::newRow("int+uint1") << QVariant::fromValue(0) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("int+uint2") << QVariant::fromValue(1) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("int+uint3") << QVariant::fromValue(0) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("int+uint4") << QVariant::fromValue(1) << QVariant::fromValue(1U) << 0;
// uint + qlonglong
- QTest::newRow("uint+qlonglong1") << qVariantFromValue(0U) << qVariantFromValue(Q_INT64_C(0)) << 0;
- QTest::newRow("uint+qlonglong2") << qVariantFromValue(1U) << qVariantFromValue(Q_INT64_C(0)) << +1;
- QTest::newRow("uint+qlonglong3") << qVariantFromValue(0U) << qVariantFromValue(Q_INT64_C(1)) << -1;
- QTest::newRow("uint+qlonglong4") << qVariantFromValue(1U) << qVariantFromValue(Q_INT64_C(1)) << 0;
- QTest::newRow("uint+qlonglong5") << qVariantFromValue(0U) << qVariantFromValue(Q_INT64_C(-1)) << +1;
+ QTest::newRow("uint+qlonglong1") << QVariant::fromValue(0U) << QVariant::fromValue(Q_INT64_C(0)) << 0;
+ QTest::newRow("uint+qlonglong2") << QVariant::fromValue(1U) << QVariant::fromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("uint+qlonglong3") << QVariant::fromValue(0U) << QVariant::fromValue(Q_INT64_C(1)) << -1;
+ QTest::newRow("uint+qlonglong4") << QVariant::fromValue(1U) << QVariant::fromValue(Q_INT64_C(1)) << 0;
+ QTest::newRow("uint+qlonglong5") << QVariant::fromValue(0U) << QVariant::fromValue(Q_INT64_C(-1)) << +1;
// boundary conditions
- QTest::newRow("charmax+intmax") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("charmax+uintmax") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("scharmax+intmax") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("scharmax+uintmax") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("ucharmax+intmax") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("ucharmax+uintmax") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("shortmax+intmax") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("shortmax+uintmax") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("ushortmax+intmax") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("ushortmax+uintmax") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(UINT_MAX) << -1;
-
- QTest::newRow("intmin+qlonglongmin") << qVariantFromValue(INT_MIN) << qVariantFromValue(LLONG_MIN) << +1;
- QTest::newRow("intmax+uintmax") << qVariantFromValue(INT_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("intmax+qlonglongmax") << qVariantFromValue(INT_MAX) << qVariantFromValue(LLONG_MAX) << -1;
- QTest::newRow("uintmax+qlonglongmax") << qVariantFromValue(UINT_MAX) << qVariantFromValue(LLONG_MAX) << -1;
- QTest::newRow("intmax+qulonglongmax") << qVariantFromValue(INT_MAX) << qVariantFromValue(ULLONG_MAX) << -1;
- QTest::newRow("qlonglongmax+qulonglongmax") << qVariantFromValue(LLONG_MAX) << qVariantFromValue(ULLONG_MAX) << -1;
- QTest::newRow("uintmax+qlonglongmin") << qVariantFromValue(UINT_MAX) << qVariantFromValue(LLONG_MIN) << +1;
+ QTest::newRow("charmax+intmax") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("charmax+uintmax") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("scharmax+intmax") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("scharmax+uintmax") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("ucharmax+intmax") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("ucharmax+uintmax") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("shortmax+intmax") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("shortmax+uintmax") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("ushortmax+intmax") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("ushortmax+uintmax") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+
+ QTest::newRow("intmin+qlonglongmin") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(LLONG_MIN) << +1;
+ QTest::newRow("intmax+uintmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("intmax+qlonglongmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(LLONG_MAX) << -1;
+ QTest::newRow("uintmax+qlonglongmax") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(LLONG_MAX) << -1;
+ QTest::newRow("intmax+qulonglongmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(ULLONG_MAX) << -1;
+ QTest::newRow("qlonglongmax+qulonglongmax") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(ULLONG_MAX) << -1;
+ QTest::newRow("uintmax+qlonglongmin") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(LLONG_MIN) << +1;
// check for no sign-extension issues
- QTest::newRow("ushortmax+intzero") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(0) << +1;
- QTest::newRow("ushortmax+qlonglongzero") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(Q_INT64_C(0)) << +1;
- QTest::newRow("uintmax+qlonglongzero") << qVariantFromValue(UINT_MAX) << qVariantFromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("ushortmax+intzero") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(0) << +1;
+ QTest::newRow("ushortmax+qlonglongzero") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("uintmax+qlonglongzero") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(Q_INT64_C(0)) << +1;
// sign changes
// the tests below check that a signed negative number sign-changes to a non-zero unsigned number and that
// signed -1 sign-changes to unsigned maximum (all bits set, ~0). This works on two's complement machines
// (all that Qt supports), and would also work on one's complement.
if (std::numeric_limits<char>::is_signed) {
- QTest::newRow("signchange-char+uint") << qVariantFromValue(char(-1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-char+uintmax") << qVariantFromValue(char(-1)) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-charmin+uint") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-char+qulonglong") << qVariantFromValue(char(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-char+qulonglongmax") << qVariantFromValue(char(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-charmin+qulonglong") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- }
- QTest::newRow("signchange-schar+uint") << qVariantFromValue(schar(-1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-schar+uintmax") << qVariantFromValue(schar(-1)) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-scharmin+uint") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-schar+qulonglong") << qVariantFromValue(schar(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-schar+qulonglongmax") << qVariantFromValue(schar(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-scharmin+qulonglong") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-short+uint") << qVariantFromValue(short(-1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-short+uintmax") << qVariantFromValue(short(-1)) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-shortmin+uint") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-short+qulonglong") << qVariantFromValue(short(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-short+qulonglongmax") << qVariantFromValue(short(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-shortmin+qulonglong") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-int+uint") << qVariantFromValue(-1) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-int+uintmax") << qVariantFromValue(-1) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-intmin+uint") << qVariantFromValue(INT_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-int+qulonglong") << qVariantFromValue(-1) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-int+qulonglongmax") << qVariantFromValue(-1) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-intmin+qulonglong") << qVariantFromValue(INT_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-char+uint") << QVariant::fromValue(char(-1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-char+uintmax") << QVariant::fromValue(char(-1)) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-charmin+uint") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-char+qulonglong") << QVariant::fromValue(char(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-char+qulonglongmax") << QVariant::fromValue(char(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-charmin+qulonglong") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ }
+ QTest::newRow("signchange-schar+uint") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-schar+uintmax") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-scharmin+uint") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-schar+qulonglong") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-schar+qulonglongmax") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-scharmin+qulonglong") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-short+uint") << QVariant::fromValue(short(-1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-short+uintmax") << QVariant::fromValue(short(-1)) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-shortmin+uint") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-short+qulonglong") << QVariant::fromValue(short(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-short+qulonglongmax") << QVariant::fromValue(short(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-shortmin+qulonglong") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-int+uint") << QVariant::fromValue(-1) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-int+uintmax") << QVariant::fromValue(-1) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-intmin+uint") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-int+qulonglong") << QVariant::fromValue(-1) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-int+qulonglongmax") << QVariant::fromValue(-1) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-intmin+qulonglong") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
// no qlonglong+uint, since that should promote to qlonglong and then the comparison is signed (tested above)
- QTest::newRow("signchange-qlonglong+qulonglong") << qVariantFromValue(Q_INT64_C(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-qlonglong+qulonglongmax") << qVariantFromValue(Q_INT64_C(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-qlonglongmin+qulonglong") << qVariantFromValue(LLONG_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-qlonglong+qulonglong") << QVariant::fromValue(Q_INT64_C(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-qlonglong+qulonglongmax") << QVariant::fromValue(Q_INT64_C(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-qlonglongmin+qulonglong") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
}
void tst_QVariant::compareNumbers() const
@@ -2761,6 +2771,14 @@ void tst_QVariant::qvariant_cast_QObject_derived()
QCOMPARE(data.value<CustomQObjectDerived *>(), object);
QCOMPARE(data.value<CustomQObject *>(), object);
}
+ {
+ QObject *object = new CustomQObjectDerivedNoMetaType(this);
+ QVariant data = QVariant::fromValue(object);
+ QVERIFY(data.canConvert<CustomQObjectDerivedNoMetaType*>());
+ QVERIFY(data.convert(qMetaTypeId<CustomQObjectDerivedNoMetaType*>()));
+ QCOMPARE(data.value<CustomQObjectDerivedNoMetaType*>(), object);
+ QCOMPARE(data.isNull(), false);
+ }
}
struct QObjectWrapper
@@ -2861,13 +2879,26 @@ void tst_QVariant::qvariant_cast_QObject_wrapper()
QVERIFY(spVar.canConvert<QObject*>());
QCOMPARE(f, spVar.value<QObject*>());
}
+#if QT_DEPRECATED_SINCE(5, 0)
{
QFile *f = new QFile(this);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QWeakPointer<QFile> sp(f);
+QT_WARNING_POP
QVariant spVar = QVariant::fromValue(sp);
QVERIFY(spVar.canConvert<QObject*>());
QCOMPARE(f, spVar.value<QObject*>());
}
+#endif
+ {
+ QFile *f = new QFile(this);
+ QSharedPointer<QObject> sp(f);
+ QWeakPointer<QObject> wp = sp;
+ QVariant wpVar = QVariant::fromValue(wp);
+ QVERIFY(wpVar.canConvert<QObject*>());
+ QCOMPARE(f, wpVar.value<QObject*>());
+ }
{
QFile *f = new QFile(this);
QSharedPointer<QFile> sp(f);
@@ -3943,7 +3974,7 @@ void tst_QVariant::userConversion()
QVERIFY(!(QMetaType::hasRegisteredConverterFunction<QString, Convertible>()));
Convertible c = { 123 };
- QVariant v = qVariantFromValue(c);
+ QVariant v = QVariant::fromValue(c);
bool ok;
v.toInt(&ok);
@@ -3977,7 +4008,7 @@ void tst_QVariant::userConversion()
QVERIFY(!(QMetaType::hasRegisteredConverterFunction<QString, BigConvertible>()));
BigConvertible c = { 123, 0, 0 };
- QVariant v = qVariantFromValue(c);
+ QVariant v = QVariant::fromValue(c);
bool ok;
v.toInt(&ok);
@@ -4692,7 +4723,6 @@ Q_DECLARE_METATYPE(EnumTest_Enum0)
enum EnumTest_Enum1 : qint64 { EnumTest_Enum1_value = 42, EnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
Q_DECLARE_METATYPE(EnumTest_Enum1)
-#if defined(Q_COMPILER_CLASS_ENUM)
enum EnumTest_Enum3 : qint64 { EnumTest_Enum3_value = -47, EnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5 };
Q_DECLARE_METATYPE(EnumTest_Enum3)
enum EnumTest_Enum4 : quint64 { EnumTest_Enum4_value = 47, EnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
@@ -4705,7 +4735,6 @@ enum class EnumTest_Enum7 { EnumTest_Enum7_value = 47, ensureSignedEnum7 = -1 };
Q_DECLARE_METATYPE(EnumTest_Enum7)
enum EnumTest_Enum8 : short { EnumTest_Enum8_value = 47 };
Q_DECLARE_METATYPE(EnumTest_Enum8)
-#endif
template<typename Enum> void testVariant(Enum value, bool *ok)
{
@@ -4764,7 +4793,6 @@ void tst_QVariant::enums()
QVERIFY(ok);
testVariant(EnumTest_Enum1_bigValue, &ok);
QVERIFY(ok);
-#if defined(Q_COMPILER_CLASS_ENUM)
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_bigValue, &ok);
@@ -4783,7 +4811,6 @@ void tst_QVariant::enums()
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
QVERIFY(ok);
-#endif
}
template<typename Enum> void testVariantMeta(Enum value, bool *ok, const char *string)
diff --git a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
index c74bce3b5b..e1357245f3 100644
--- a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
+++ b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
@@ -91,11 +91,7 @@ static QStringList qMimeTypeGlobPatterns()
// ------------------------------------------------------------------------------------------------
-#ifndef Q_COMPILER_RVALUE_REFS
-QMIMETYPE_BUILDER
-#else
QMIMETYPE_BUILDER_FROM_RVALUE_REFS
-#endif
// ------------------------------------------------------------------------------------------------
diff --git a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
index c9c9202a80..e0d09b0813 100644
--- a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
+++ b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
@@ -30,7 +30,7 @@
#include <QtTest/QtTest>
#include <qdir.h>
#include <qlibrary.h>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
// Helper macros to let us know if some suffixes and prefixes are valid
@@ -414,10 +414,12 @@ void tst_QLibrary::errorString()
QFAIL(qPrintable(QString("Unknown operation: %1").arg(operation)));
break;
}
- QRegExp re(errorString);
+#if QT_CONFIG(regularexpression)
+ QRegularExpression re(QRegularExpression::anchoredPattern(errorString));
QString libErrorString = lib.errorString();
+ QVERIFY2(re.match(libErrorString).hasMatch(), qPrintable(libErrorString));
+#endif
QVERIFY(!lib.isLoaded() || lib.unload());
- QVERIFY2(re.exactMatch(libErrorString), qPrintable(libErrorString));
QCOMPARE(ok, success);
}
diff --git a/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp b/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp
index d891839b1e..6d163ea336 100644
--- a/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp
@@ -31,7 +31,7 @@
class StaticPlugin : public QObject
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "SomeIID")
+ Q_PLUGIN_METADATA(IID "SomeIID" URI "qt.test.pluginloader.staticplugin")
public:
StaticPlugin() {}
};
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index 85763b0388..c4a366d7c6 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -553,6 +553,7 @@ void tst_QPluginLoader::staticPlugins()
QCOMPARE(metaData.value("version").toInt() / 0x100, QT_VERSION / 0x100);
QCOMPARE(metaData.value("IID").toString(), "SomeIID");
QCOMPARE(metaData.value("ExtraMetaData"), QJsonArray({ "StaticPlugin", "foo" }));
+ QCOMPARE(metaData.value("URI").toString(), "qt.test.pluginloader.staticplugin");
}
diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
index 8907704a33..57aa67c142 100644
--- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
@@ -436,6 +436,8 @@ void tst_QtJson::testObjectSimple()
object.insert("boolean", true);
QCOMPARE(object.value("boolean").toBool(), true);
QCOMPARE(object.value(QLatin1String("boolean")).toBool(), true);
+ QJsonObject object2 = object;
+ QJsonObject object3 = object;
QStringList keys = object.keys();
QVERIFY2(keys.contains("number"), "key number not found");
@@ -461,6 +463,40 @@ void tst_QtJson::testObjectSimple()
object.insert("string", QString::fromLatin1("foo"));
QVERIFY2(object.value(QLatin1String("string")).toString() != before, "value should have been updated");
+ // same tests again but with QStringView keys
+ object2.insert(QStringView(u"value"), value);
+ QCOMPARE(object2.value("value"), value);
+
+ size = object2.size();
+ object2.remove(QStringView(u"boolean"));
+ QCOMPARE(object2.size(), size - 1);
+ QVERIFY2(!object2.contains(QStringView(u"boolean")), "key boolean should have been removed");
+
+ taken = object2.take(QStringView(u"value"));
+ QCOMPARE(taken, value);
+ QVERIFY2(!object2.contains("value"), "key value should have been removed");
+
+ before = object2.value("string").toString();
+ object2.insert(QStringView(u"string"), QString::fromLatin1("foo"));
+ QVERIFY2(object2.value(QStringView(u"string")).toString() != before, "value should have been updated");
+
+ // same tests again but with QLatin1String keys
+ object3.insert(QLatin1String("value"), value);
+ QCOMPARE(object3.value("value"), value);
+
+ size = object3.size();
+ object3.remove(QLatin1String("boolean"));
+ QCOMPARE(object3.size(), size - 1);
+ QVERIFY2(!object3.contains("boolean"), "key boolean should have been removed");
+
+ taken = object3.take(QLatin1String("value"));
+ QCOMPARE(taken, value);
+ QVERIFY2(!object3.contains("value"), "key value should have been removed");
+
+ before = object3.value("string").toString();
+ object3.insert(QLatin1String("string"), QString::fromLatin1("foo"));
+ QVERIFY2(object3.value(QLatin1String("string")).toString() != before, "value should have been updated");
+
size = object.size();
QJsonObject subobject;
subobject.insert("number", 42);
@@ -1096,6 +1132,8 @@ void tst_QtJson::undefinedValues()
QJsonObject object;
object.insert("Key", QJsonValue(QJsonValue::Undefined));
QCOMPARE(object.size(), 0);
+ object["Key"] = QJsonValue(QJsonValue::Undefined);
+ QCOMPARE(object.size(), 0);
object.insert("Key", QLatin1String("Value"));
QCOMPARE(object.size(), 1);
@@ -2698,6 +2736,8 @@ void tst_QtJson::longStrings()
// test around 15 and 16 bit boundaries, as these are limits
// in the data structures (for Latin1String in qjson_p.h)
QString s(0x7ff0, 'a');
+ QByteArray ba(0x7ff0, 'a');
+ ba.append(0x8010 - 0x7ff0, 'c');
for (int i = 0x7ff0; i < 0x8010; i++) {
s.append(QLatin1Char('c'));
@@ -2714,9 +2754,21 @@ void tst_QtJson::longStrings()
/* ... and a QByteArray from the QJsonDocument */
QByteArray a2 = d2.toJson();
QCOMPARE(a1, a2);
+
+ // Test long keys
+ QJsonObject o1, o2;
+ o1[s] = 42;
+ o2[QLatin1String(ba.data(), i + 1)] = 42;
+ d1.setObject(o1);
+ d2.setObject(o2);
+ a1 = d1.toJson();
+ a2 = d2.toJson();
+ QCOMPARE(a1, a2);
}
s = QString(0xfff0, 'a');
+ ba = QByteArray(0xfff0, 'a');
+ ba.append(0x10010 - 0xfff0, 'c');
for (int i = 0xfff0; i < 0x10010; i++) {
s.append(QLatin1Char('c'));
@@ -2733,6 +2785,16 @@ void tst_QtJson::longStrings()
/* ... and a QByteArray from the QJsonDocument */
QByteArray a2 = d2.toJson();
QCOMPARE(a1, a2);
+
+ // Test long keys
+ QJsonObject o1, o2;
+ o1[s] = 42;
+ o2[QLatin1String(ba.data(), i + 1)] = 42;
+ d1.setObject(o1);
+ d2.setObject(o2);
+ a1 = d1.toJson();
+ a2 = d2.toJson();
+ QCOMPARE(a1, a2);
}
}
@@ -2755,9 +2817,6 @@ void tst_QtJson::testJsonValueRefDefault()
void tst_QtJson::arrayInitializerList()
{
-#ifndef Q_COMPILER_INITIALIZER_LISTS
- QSKIP("initializer_list is enabled only with c++11 support");
-#else
QVERIFY(QJsonArray{}.isEmpty());
QCOMPARE(QJsonArray{"one"}.count(), 1);
QCOMPARE(QJsonArray{1}.count(), 1);
@@ -2803,14 +2862,10 @@ void tst_QtJson::arrayInitializerList()
QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1));
}
}
-#endif
}
void tst_QtJson::objectInitializerList()
{
-#ifndef Q_COMPILER_INITIALIZER_LISTS
- QSKIP("initializer_list is enabled only with c++11 support");
-#else
QVERIFY(QJsonObject{}.isEmpty());
{ // one property
@@ -2850,7 +2905,6 @@ void tst_QtJson::objectInitializerList()
QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue"));
QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1));
}
-#endif
}
void tst_QtJson::unicodeKeys()
diff --git a/tests/auto/corelib/serialization/qdatastream/qdatastream.pro b/tests/auto/corelib/serialization/qdatastream/qdatastream.pro
index 25f8b889a0..469d689f3f 100644
--- a/tests/auto/corelib/serialization/qdatastream/qdatastream.pro
+++ b/tests/auto/corelib/serialization/qdatastream/qdatastream.pro
@@ -3,6 +3,8 @@ TARGET = tst_qdatastream
QT += testlib
SOURCES = tst_qdatastream.cpp
+DEFINES -= QT_NO_LINKED_LIST
+
TESTDATA += datastream.q42
android:!android-embedded {
diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
index 3ad1794176..8197c386c5 100644
--- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
@@ -113,6 +113,11 @@ private slots:
void stream_QRegExp_data();
void stream_QRegExp();
+#if QT_CONFIG(regularexpression)
+ void stream_QRegularExpression_data();
+ void stream_QRegularExpression();
+#endif
+
void stream_Map_data();
void stream_Map();
@@ -181,6 +186,8 @@ private slots:
void streamRealDataTypes();
+ void enumTest();
+
void floatingPointPrecision();
void compatibility_Qt5();
@@ -219,6 +226,9 @@ private:
void writeQSize(QDataStream *s);
void writeQString(QDataStream* dev);
void writeQRegExp(QDataStream* dev);
+#if QT_CONFIG(regularexpression)
+ void writeQRegularExpression(QDataStream *dev);
+#endif
void writeMap(QDataStream* dev);
void writeHash(QDataStream* dev);
void writeqint64(QDataStream *s);
@@ -248,6 +258,9 @@ private:
void readQSize(QDataStream *s);
void readQString(QDataStream *s);
void readQRegExp(QDataStream *s);
+#if QT_CONFIG(regularexpression)
+ void readQRegularExpression(QDataStream *s);
+#endif
void readMap(QDataStream *s);
void readHash(QDataStream *s);
void readqint64(QDataStream *s);
@@ -559,6 +572,69 @@ void tst_QDataStream::readQRegExp(QDataStream *s)
// ************************************
+#if QT_CONFIG(regularexpression)
+static QRegularExpression QRegularExpressionData(int index)
+{
+ switch (index) {
+ case 0: return QRegularExpression();
+ case 1: return QRegularExpression("");
+ case 2: return QRegularExpression("A", QRegularExpression::CaseInsensitiveOption);
+ case 3: return QRegularExpression(QRegularExpression::wildcardToRegularExpression("ABCDE FGHI"));
+ case 4: return QRegularExpression(QRegularExpression::anchoredPattern("This is a long string"), QRegularExpression::CaseInsensitiveOption);
+ case 5: return QRegularExpression("And again a string with a \nCRLF", QRegularExpression::CaseInsensitiveOption);
+ case 6: return QRegularExpression("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRESTUVWXYZ 1234567890 ~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/", QRegularExpression::InvertedGreedinessOption);
+ }
+ return QRegularExpression("foo");
+}
+#define MAX_QREGULAREXPRESSION_DATA 7
+
+void tst_QDataStream::stream_QRegularExpression_data()
+{
+ stream_data(MAX_QREGULAREXPRESSION_DATA);
+}
+
+void tst_QDataStream::stream_QRegularExpression()
+{
+ STREAM_IMPL(QRegularExpression);
+}
+
+void tst_QDataStream::writeQRegularExpression(QDataStream* s)
+{
+ QRegularExpression test(QRegularExpressionData(dataIndex(QTest::currentDataTag())));
+ *s << test;
+ *s << QString("Her er det noe tekst");
+ *s << test;
+ *s << QString("nonempty");
+ *s << test;
+ *s << QVariant(test);
+}
+
+void tst_QDataStream::readQRegularExpression(QDataStream *s)
+{
+ QRegularExpression R;
+ QString S;
+ QVariant V;
+ QRegularExpression test(QRegularExpressionData(dataIndex(QTest::currentDataTag())));
+
+ *s >> R;
+
+ QCOMPARE(R, test);
+ *s >> S;
+ QCOMPARE(S, QString("Her er det noe tekst"));
+ *s >> R;
+ QCOMPARE(R, test);
+ *s >> S;
+ QCOMPARE(S, QString("nonempty"));
+ *s >> R;
+ QCOMPARE(R, test);
+ *s >> V;
+ QCOMPARE(V.type(), QVariant::RegularExpression);
+ QCOMPARE(V.toRegularExpression(), test);
+}
+#endif //QT_CONFIG(regularexpression)
+
+// ************************************
+
typedef QMap<int, QString> Map;
static Map MapData(int index)
@@ -2315,10 +2391,10 @@ void tst_QDataStream::setVersion()
if (vers == 1) {
for (int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
- QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Foreground)
- == inPal1.color((QPalette::ColorGroup)grp, QPalette::Foreground));
- QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Background)
- == inPal1.color((QPalette::ColorGroup)grp, QPalette::Background));
+ QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::WindowText)
+ == inPal1.color((QPalette::ColorGroup)grp, QPalette::WindowText));
+ QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Window)
+ == inPal1.color((QPalette::ColorGroup)grp, QPalette::Window));
QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Light)
== inPal1.color((QPalette::ColorGroup)grp, QPalette::Light));
QVERIFY(pal1.color((QPalette::ColorGroup)grp, QPalette::Dark)
@@ -3441,6 +3517,90 @@ void tst_QDataStream::floatingPointNaN()
}
}
+void tst_QDataStream::enumTest()
+{
+ QByteArray ba;
+
+ enum class E1 : qint8
+ {
+ A,
+ B,
+ C
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E1::A;
+ QCOMPARE(ba.size(), int(sizeof(E1)));
+ }
+ {
+ QDataStream stream(ba);
+ E1 e;
+ stream >> e;
+ QCOMPARE(e, E1::A);
+ }
+ ba.clear();
+
+ enum class E2 : qint16
+ {
+ A,
+ B,
+ C
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E2::B;
+ QCOMPARE(ba.size(), int(sizeof(E2)));
+ }
+ {
+ QDataStream stream(ba);
+ E2 e;
+ stream >> e;
+ QCOMPARE(e, E2::B);
+ }
+ ba.clear();
+
+ enum class E4 : qint32
+ {
+ A,
+ B,
+ C
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E4::C;
+ QCOMPARE(ba.size(), int(sizeof(E4)));
+ }
+ {
+ QDataStream stream(ba);
+ E4 e;
+ stream >> e;
+ QCOMPARE(e, E4::C);
+ }
+ ba.clear();
+
+
+ enum E
+ {
+ A,
+ B,
+ C,
+ D
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E::D;
+ QCOMPARE(ba.size(), 4);
+ }
+ {
+ QDataStream stream(ba);
+ E e;
+ stream >> e;
+ QCOMPARE(e, E::D);
+ }
+ ba.clear();
+
+}
+
void tst_QDataStream::floatingPointPrecision()
{
QByteArray ba;
diff --git a/tests/auto/corelib/serialization/qtextstream/BLACKLIST b/tests/auto/corelib/serialization/qtextstream/BLACKLIST
index b54b53cd74..674569e204 100644
--- a/tests/auto/corelib/serialization/qtextstream/BLACKLIST
+++ b/tests/auto/corelib/serialization/qtextstream/BLACKLIST
@@ -1,3 +1,3 @@
[stillOpenWhenAtEnd]
-windows
+windows-7sp1
winrt
diff --git a/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp b/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp
index 41ea5e56f0..2d4aa452ca 100644
--- a/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp
+++ b/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
do {
line = qin.readLine();
if (!line.isNull())
- qerr << line << flush;
+ qerr << line << Qt::flush;
} while (!line.isNull());
return 0;
}
diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
index 8bb35554c8..6381ce5ed0 100644
--- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
+++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
@@ -35,6 +35,7 @@
#include <QBuffer>
#include <QByteArray>
#include <QDebug>
+#include <QElapsedTimer>
#include <QFile>
#include <QTcpSocket>
#include <QTemporaryDir>
@@ -245,7 +246,7 @@ private:
void runOnExit()
{
QByteArray buffer;
- QTextStream(&buffer) << "This will try to use QTextCodec::codecForLocale" << endl;
+ QTextStream(&buffer) << "This will try to use QTextCodec::codecForLocale" << Qt::endl;
}
Q_DESTRUCTOR_FUNCTION(runOnExit)
@@ -996,7 +997,7 @@ struct CompareIndicesForArray
void tst_QTextStream::performance()
{
// Phase #1 - test speed of reading a huge text file with QFile.
- QTime stopWatch;
+ QElapsedTimer stopWatch;
const int N = 3;
const char * readMethods[N] = {
@@ -1102,7 +1103,7 @@ void tst_QTextStream::hexTest()
QByteArray array;
QTextStream stream(&array);
- stream << showbase << hex << number;
+ stream << Qt::showbase << Qt::hex << number;
stream.flush();
QCOMPARE(array, data);
}
@@ -1132,7 +1133,7 @@ void tst_QTextStream::binTest()
QByteArray array;
QTextStream stream(&array);
- stream << showbase << bin << number;
+ stream << Qt::showbase << Qt::bin << number;
stream.flush();
QCOMPARE(array.constData(), data.constData());
}
@@ -1155,7 +1156,7 @@ void tst_QTextStream::octTest()
QByteArray array;
QTextStream stream(&array);
- stream << showbase << oct << number;
+ stream << Qt::showbase << Qt::oct << number;
stream.flush();
QCOMPARE(array, data);
}
@@ -1196,7 +1197,7 @@ void tst_QTextStream::ws_manipulator()
QTextStream stream(&string);
char a, b, c, d;
- stream >> a >> ws >> b >> ws >> c >> ws >> d;
+ stream >> a >> Qt::ws >> b >> Qt::ws >> c >> Qt::ws >> d;
QCOMPARE(a, 'a');
QCOMPARE(b, 'b');
QCOMPARE(c, 'c');
@@ -1506,9 +1507,9 @@ void tst_QTextStream::readStdin()
stdinProcess.setReadChannel(QProcess::StandardError);
QTextStream stream(&stdinProcess);
- stream << "1" << endl;
- stream << "2" << endl;
- stream << "3" << endl;
+ stream << "1" << Qt::endl;
+ stream << "2" << Qt::endl;
+ stream << "3" << Qt::endl;
stdinProcess.closeWriteChannel();
@@ -1534,7 +1535,7 @@ void tst_QTextStream::readAllFromStdin()
QTextStream stream(&stdinProcess);
stream.setCodec("ISO-8859-1");
- stream << "hello world" << flush;
+ stream << "hello world" << Qt::flush;
stdinProcess.closeWriteChannel();
@@ -1623,18 +1624,18 @@ void tst_QTextStream::forcePoint()
{
QString str;
QTextStream stream(&str);
- stream << fixed << forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
+ stream << Qt::fixed << Qt::forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
QCOMPARE(str, QString("1.000000 1 0 -1.000000 -1"));
str.clear();
stream.seek(0);
- stream << scientific << forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
+ stream << Qt::scientific << Qt::forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
QCOMPARE(str, QString("1.000000e+00 1 0 -1.000000e+00 -1"));
str.clear();
stream.seek(0);
stream.setRealNumberNotation(QTextStream::SmartNotation);
- stream << forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
+ stream << Qt::forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
QCOMPARE(str, QString("1.00000 1 0 -1.00000 -1"));
}
@@ -1644,7 +1645,7 @@ void tst_QTextStream::forceSign()
{
QString str;
QTextStream stream(&str);
- stream << forcesign << 1.2 << ' ' << -1.2 << ' ' << 0;
+ stream << Qt::forcesign << 1.2 << ' ' << -1.2 << ' ' << 0;
QCOMPARE(str, QString("+1.2 -1.2 +0"));
}
@@ -1663,19 +1664,22 @@ void tst_QTextStream::read0d0d0a()
Q_DECLARE_METATYPE(QTextStreamFunction);
+// Also tests that we can have namespaces that conflict with our QTextStream constants.
+namespace ws {
QTextStream &noop(QTextStream &s) { return s; }
+}
void tst_QTextStream::numeralCase_data()
{
- QTextStreamFunction noop_ = noop;
- QTextStreamFunction bin_ = bin;
- QTextStreamFunction oct_ = oct;
- QTextStreamFunction hex_ = hex;
- QTextStreamFunction base = showbase;
- QTextStreamFunction ucb = uppercasebase;
- QTextStreamFunction lcb = lowercasebase;
- QTextStreamFunction ucd = uppercasedigits;
- QTextStreamFunction lcd = lowercasedigits;
+ QTextStreamFunction noop_ = ws::noop;
+ QTextStreamFunction bin = Qt::bin;
+ QTextStreamFunction oct = Qt::oct;
+ QTextStreamFunction hex = Qt::hex;
+ QTextStreamFunction base = Qt::showbase;
+ QTextStreamFunction ucb = Qt::uppercasebase;
+ QTextStreamFunction lcb = Qt::lowercasebase;
+ QTextStreamFunction ucd = Qt::uppercasedigits;
+ QTextStreamFunction lcd = Qt::lowercasedigits;
QTest::addColumn<QTextStreamFunction>("func1");
QTest::addColumn<QTextStreamFunction>("func2");
@@ -1686,30 +1690,30 @@ void tst_QTextStream::numeralCase_data()
QTest::newRow("dec 1") << noop_ << noop_ << noop_ << noop_ << 31 << "31";
QTest::newRow("dec 2") << noop_ << base << noop_ << noop_ << 31 << "31";
- QTest::newRow("hex 1") << hex_ << noop_ << noop_ << noop_ << 31 << "1f";
- QTest::newRow("hex 2") << hex_ << noop_ << noop_ << lcd << 31 << "1f";
- QTest::newRow("hex 3") << hex_ << noop_ << ucb << noop_ << 31 << "1f";
- QTest::newRow("hex 4") << hex_ << noop_ << noop_ << ucd << 31 << "1F";
- QTest::newRow("hex 5") << hex_ << noop_ << lcb << ucd << 31 << "1F";
- QTest::newRow("hex 6") << hex_ << noop_ << ucb << ucd << 31 << "1F";
- QTest::newRow("hex 7") << hex_ << base << noop_ << noop_ << 31 << "0x1f";
- QTest::newRow("hex 8") << hex_ << base << lcb << lcd << 31 << "0x1f";
- QTest::newRow("hex 9") << hex_ << base << ucb << noop_ << 31 << "0X1f";
- QTest::newRow("hex 10") << hex_ << base << ucb << lcd << 31 << "0X1f";
- QTest::newRow("hex 11") << hex_ << base << noop_ << ucd << 31 << "0x1F";
- QTest::newRow("hex 12") << hex_ << base << lcb << ucd << 31 << "0x1F";
- QTest::newRow("hex 13") << hex_ << base << ucb << ucd << 31 << "0X1F";
-
- QTest::newRow("bin 1") << bin_ << noop_ << noop_ << noop_ << 31 << "11111";
- QTest::newRow("bin 2") << bin_ << base << noop_ << noop_ << 31 << "0b11111";
- QTest::newRow("bin 3") << bin_ << base << lcb << noop_ << 31 << "0b11111";
- QTest::newRow("bin 4") << bin_ << base << ucb << noop_ << 31 << "0B11111";
- QTest::newRow("bin 5") << bin_ << base << noop_ << ucd << 31 << "0b11111";
- QTest::newRow("bin 6") << bin_ << base << lcb << ucd << 31 << "0b11111";
- QTest::newRow("bin 7") << bin_ << base << ucb << ucd << 31 << "0B11111";
-
- QTest::newRow("oct 1") << oct_ << noop_ << noop_ << noop_ << 31 << "37";
- QTest::newRow("oct 2") << oct_ << base << noop_ << noop_ << 31 << "037";
+ QTest::newRow("hex 1") << hex << noop_ << noop_ << noop_ << 31 << "1f";
+ QTest::newRow("hex 2") << hex << noop_ << noop_ << lcd << 31 << "1f";
+ QTest::newRow("hex 3") << hex << noop_ << ucb << noop_ << 31 << "1f";
+ QTest::newRow("hex 4") << hex << noop_ << noop_ << ucd << 31 << "1F";
+ QTest::newRow("hex 5") << hex << noop_ << lcb << ucd << 31 << "1F";
+ QTest::newRow("hex 6") << hex << noop_ << ucb << ucd << 31 << "1F";
+ QTest::newRow("hex 7") << hex << base << noop_ << noop_ << 31 << "0x1f";
+ QTest::newRow("hex 8") << hex << base << lcb << lcd << 31 << "0x1f";
+ QTest::newRow("hex 9") << hex << base << ucb << noop_ << 31 << "0X1f";
+ QTest::newRow("hex 10") << hex << base << ucb << lcd << 31 << "0X1f";
+ QTest::newRow("hex 11") << hex << base << noop_ << ucd << 31 << "0x1F";
+ QTest::newRow("hex 12") << hex << base << lcb << ucd << 31 << "0x1F";
+ QTest::newRow("hex 13") << hex << base << ucb << ucd << 31 << "0X1F";
+
+ QTest::newRow("bin 1") << bin << noop_ << noop_ << noop_ << 31 << "11111";
+ QTest::newRow("bin 2") << bin << base << noop_ << noop_ << 31 << "0b11111";
+ QTest::newRow("bin 3") << bin << base << lcb << noop_ << 31 << "0b11111";
+ QTest::newRow("bin 4") << bin << base << ucb << noop_ << 31 << "0B11111";
+ QTest::newRow("bin 5") << bin << base << noop_ << ucd << 31 << "0b11111";
+ QTest::newRow("bin 6") << bin << base << lcb << ucd << 31 << "0b11111";
+ QTest::newRow("bin 7") << bin << base << ucb << ucd << 31 << "0B11111";
+
+ QTest::newRow("oct 1") << oct << noop_ << noop_ << noop_ << 31 << "37";
+ QTest::newRow("oct 2") << oct << base << noop_ << noop_ << 31 << "037";
}
void tst_QTextStream::numeralCase()
@@ -1782,9 +1786,9 @@ void tst_QTextStream::nanInf()
QString s;
QTextStream out(&s);
out << qInf() << ' ' << -qInf() << ' ' << qQNaN()
- << uppercasedigits << ' '
+ << Qt::uppercasedigits << ' '
<< qInf() << ' ' << -qInf() << ' ' << qQNaN()
- << flush;
+ << Qt::flush;
QCOMPARE(s, QString("inf -inf nan INF -INF NAN"));
}
@@ -1821,7 +1825,7 @@ void tst_QTextStream::utf8IncompleteAtBufferBoundary()
out.setFieldWidth(3);
for (int i = 0; i < 1000; ++i) {
- out << i << lineContents << endl;
+ out << i << lineContents << Qt::endl;
}
}
data.close();
@@ -1859,9 +1863,9 @@ void tst_QTextStream::writeSeekWriteNoBOM()
int number = 0;
QString sizeStr = QLatin1String("Size=")
+ QString::number(number).rightJustified(10, QLatin1Char('0'));
- stream << sizeStr << endl;
- stream << "Version=" << QString::number(14) << endl;
- stream << "blah blah blah" << endl;
+ stream << sizeStr << Qt::endl;
+ stream << "Version=" << QString::number(14) << Qt::endl;
+ stream << "blah blah blah" << Qt::endl;
stream.flush();
QCOMPARE(out.buffer().constData(), "Size=0000000000\nVersion=14\nblah blah blah\n");
@@ -1871,7 +1875,7 @@ void tst_QTextStream::writeSeekWriteNoBOM()
stream.seek(0);
sizeStr = QLatin1String("Size=")
+ QString::number(number).rightJustified(10, QLatin1Char('0'));
- stream << sizeStr << endl;
+ stream << sizeStr << Qt::endl;
stream.flush();
// Check buffer is still OK
@@ -2582,7 +2586,7 @@ void tst_QTextStream::stringview_write_operator_ToDevice()
QBuffer buf;
buf.open(QBuffer::WriteOnly);
QTextStream stream(&buf);
- const QStringView expected = QStringViewLiteral("expectedStringView");
+ const QStringView expected = u"expectedStringView";
stream << expected;
stream.flush();
QCOMPARE(buf.buffer().constData(), "expectedStringView");
@@ -2723,7 +2727,7 @@ void tst_QTextStream::generateBOM()
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-16LE"));
- stream << "Hello" << endl;
+ stream << "Hello" << Qt::endl;
file.close();
QVERIFY(file.open(QFile::ReadOnly));
@@ -2737,7 +2741,7 @@ void tst_QTextStream::generateBOM()
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-16LE"));
- stream << bom << "Hello" << endl;
+ stream << Qt::bom << "Hello" << Qt::endl;
file.close();
QVERIFY(file.open(QFile::ReadOnly));
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index 8fdf91b090..92a0d8bbfa 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -115,7 +115,7 @@ static QByteArray makeCanonical(const QString &filename,
writeDtd << "<!DOCTYPE ";
writeDtd << docType;
writeDtd << " [";
- writeDtd << endl;
+ writeDtd << Qt::endl;
for (const QXmlStreamNotationDeclaration &notation : sorted_by_name(notationDeclarations)) {
writeDtd << "<!NOTATION ";
writeDtd << notation.name().toString();
@@ -134,11 +134,11 @@ static QByteArray makeCanonical(const QString &filename,
}
}
writeDtd << '>';
- writeDtd << endl;
+ writeDtd << Qt::endl;
}
writeDtd << "]>";
- writeDtd << endl;
+ writeDtd << Qt::endl;
writer.writeDTD(dtd);
}
} else if (reader.isStartElement()) {
@@ -253,7 +253,7 @@ public:
qFatal("%s: aId must not be an empty string", Q_FUNC_INFO);
}
- void swap(MissedBaseline &other) Q_DECL_NOTHROW
+ void swap(MissedBaseline &other) noexcept
{
qSwap(id, other.id);
qSwap(expected, other.expected);
@@ -740,7 +740,7 @@ QByteArray tst_QXmlStream::readFile(const QString &filename)
const auto attributes = reader.attributes();
if (attributes.size()) {
for (const QXmlStreamAttribute &attribute : attributes) {
- writer << endl << " Attribute(";
+ writer << Qt::endl << " Attribute(";
if (!attribute.name().isEmpty())
writer << " name=\"" << attribute.name().toString() << '"';
if (!attribute.namespaceUri().isEmpty())
@@ -751,37 +751,37 @@ QByteArray tst_QXmlStream::readFile(const QString &filename)
writer << " prefix=\"" << attribute.prefix().toString() << '"';
if (!attribute.value().isEmpty())
writer << " value=\"" << attribute.value().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
const auto namespaceDeclarations = reader.namespaceDeclarations();
if (namespaceDeclarations.size()) {
for (const QXmlStreamNamespaceDeclaration &namespaceDeclaration : namespaceDeclarations) {
- writer << endl << " NamespaceDeclaration(";
+ writer << Qt::endl << " NamespaceDeclaration(";
if (!namespaceDeclaration.prefix().isEmpty())
writer << " prefix=\"" << namespaceDeclaration.prefix().toString() << '"';
if (!namespaceDeclaration.namespaceUri().isEmpty())
writer << " namespaceUri=\"" << namespaceDeclaration.namespaceUri().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
const auto notationDeclarations = reader.notationDeclarations();
if (notationDeclarations.size()) {
for (const QXmlStreamNotationDeclaration &notationDeclaration : notationDeclarations) {
- writer << endl << " NotationDeclaration(";
+ writer << Qt::endl << " NotationDeclaration(";
if (!notationDeclaration.name().isEmpty())
writer << " name=\"" << notationDeclaration.name().toString() << '"';
if (!notationDeclaration.systemId().isEmpty())
writer << " systemId=\"" << notationDeclaration.systemId().toString() << '"';
if (!notationDeclaration.publicId().isEmpty())
writer << " publicId=\"" << notationDeclaration.publicId().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
const auto entityDeclarations = reader.entityDeclarations();
if (entityDeclarations.size()) {
for (const QXmlStreamEntityDeclaration &entityDeclaration : entityDeclarations) {
- writer << endl << " EntityDeclaration(";
+ writer << Qt::endl << " EntityDeclaration(";
if (!entityDeclaration.name().isEmpty())
writer << " name=\"" << entityDeclaration.name().toString() << '"';
if (!entityDeclaration.notationName().isEmpty())
@@ -792,13 +792,13 @@ QByteArray tst_QXmlStream::readFile(const QString &filename)
writer << " publicId=\"" << entityDeclaration.publicId().toString() << '"';
if (!entityDeclaration.value().isEmpty())
writer << " value=\"" << entityDeclaration.value().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
if (reader.hasError())
- writer << "ERROR: " << reader.errorString() << endl;
+ writer << "ERROR: " << reader.errorString() << Qt::endl;
return outarray;
}
@@ -1169,7 +1169,7 @@ int main(int argc, char *argv[])
bool error = false;
QByteArray canonical = makeCanonical(argv[2], "doc", error);
QTextStream myStdOut(stdout);
- myStdOut << canonical << endl;
+ myStdOut << canonical << Qt::endl;
exit(0);
}
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 810698fb4e..72a6f0360d 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -336,7 +336,9 @@ void tst_QStateMachine::transitionToRootState()
TEST_ACTIVE_CHANGED(initialState, 1);
machine.postEvent(new QEvent(QEvent::User));
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initial'");
+ QTest::ignoreMessage(QtWarningMsg,
+ "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine 'machine' is not 'ExclusiveStates'!");
QCoreApplication::processEvents();
QVERIFY(machine.configuration().isEmpty());
QVERIFY(!machine.isRunning());
@@ -1061,7 +1063,8 @@ void tst_QStateMachine::transitionToStateNotInGraph()
initialState->addTransition(&independentState);
machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initialState'");
+ QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine '' is not 'ExclusiveStates'!");
QCoreApplication::processEvents();
QCOMPARE(machine.isRunning(), false);
@@ -1734,13 +1737,13 @@ protected:
if (e->type() != QEvent::Type(QEvent::User+2))
return false;
StringEvent *se = static_cast<StringEvent*>(e);
- return (m_value == se->value) && (!m_cond.isValid() || (m_cond.indexIn(m_value) != -1));
+ return (m_value == se->value) && (!m_cond.isValid() || m_cond.match(m_value).hasMatch());
}
virtual void onTransition(QEvent *) {}
private:
QString m_value;
- QRegExp m_cond;
+ QRegularExpression m_cond;
};
class StringEventPoster : public QState
@@ -2099,6 +2102,8 @@ void tst_QStateMachine::parallelRootState()
QSignalSpy finishedSpy(&machine, &QStateMachine::finished);
QVERIFY(finishedSpy.isValid());
machine.start();
+ QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine '' is not 'ExclusiveStates'!");
QTRY_COMPARE(startedSpy.count(), 1);
QCOMPARE(machine.configuration().size(), 4);
QVERIFY(machine.configuration().contains(s1));
@@ -3310,14 +3315,15 @@ void tst_QStateMachine::targetStateWithNoParent()
QVERIFY(runningSpy.isValid());
machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 's1'");
+ QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine '' is not 'ExclusiveStates'!");
TEST_ACTIVE_CHANGED(s1, 2);
QTRY_COMPARE(startedSpy.count(), 1);
QCOMPARE(machine.isRunning(), false);
QCOMPARE(stoppedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 0);
TEST_RUNNING_CHANGED_STARTED_STOPPED;
- QCOMPARE(machine.error(), QStateMachine::NoCommonAncestorForTransitionError);
+ QCOMPARE(machine.error(), QStateMachine::StateMachineChildModeSetToParallelError);
}
void tst_QStateMachine::targetStateDeleted()
@@ -6680,13 +6686,13 @@ void tst_QStateMachine::dontProcessSlotsWhenMachineIsNotRunning()
} emitter;
initialState.addTransition(&emitter, &Emitter::signalWithNoArg, &finalState);
- QTimer::singleShot(0, [&]() {
- metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
- metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
- });
machine.addState(&initialState);
machine.addState(&finalState);
machine.setInitialState(&initialState);
+ connect(&machine, &QStateMachine::started, &emitter, [&]() {
+ metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
+ metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
+ });
connect(&machine, &QStateMachine::finished, &emitter.thread, &QThread::quit);
machine.start();
QSignalSpy emittedSpy(&emitter, &SignalEmitter::signalWithNoArg);
diff --git a/tests/auto/corelib/tools/qbytearray/.gitattributes b/tests/auto/corelib/text/qbytearray/.gitattributes
index e04709aa2e..e04709aa2e 100644
--- a/tests/auto/corelib/tools/qbytearray/.gitattributes
+++ b/tests/auto/corelib/text/qbytearray/.gitattributes
diff --git a/tests/auto/corelib/tools/qbytearray/.gitignore b/tests/auto/corelib/text/qbytearray/.gitignore
index 3de7c3fab5..3de7c3fab5 100644
--- a/tests/auto/corelib/tools/qbytearray/.gitignore
+++ b/tests/auto/corelib/text/qbytearray/.gitignore
diff --git a/tests/auto/corelib/tools/qbytearray/android_testdata.qrc b/tests/auto/corelib/text/qbytearray/android_testdata.qrc
index 5d42f0f627..5d42f0f627 100644
--- a/tests/auto/corelib/tools/qbytearray/android_testdata.qrc
+++ b/tests/auto/corelib/text/qbytearray/android_testdata.qrc
diff --git a/tests/auto/corelib/tools/qbytearray/qbytearray.pro b/tests/auto/corelib/text/qbytearray/qbytearray.pro
index c2101b0611..c2101b0611 100644
--- a/tests/auto/corelib/tools/qbytearray/qbytearray.pro
+++ b/tests/auto/corelib/text/qbytearray/qbytearray.pro
diff --git a/tests/auto/corelib/tools/qbytearray/rfc3252.txt b/tests/auto/corelib/text/qbytearray/rfc3252.txt
index b80c61bf0a..b80c61bf0a 100644
--- a/tests/auto/corelib/tools/qbytearray/rfc3252.txt
+++ b/tests/auto/corelib/text/qbytearray/rfc3252.txt
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
index 1ed41793dc..90dfcaef25 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
@@ -138,9 +138,7 @@ private slots:
void reserveExtended();
void movablity_data();
void movablity();
-#if defined(Q_COMPILER_LAMBDA)
void literals();
-#endif
void toUpperLower_data();
void toUpperLower();
void isUpper();
@@ -1361,6 +1359,9 @@ void tst_QByteArray::toDouble_data()
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;
+
+ QTest::newRow("raw, null plus junk") << QByteArray::fromRawData("1.2\0 junk", 9) << 0.0 << false;
+ QTest::newRow("raw, null-terminator not included") << QByteArray::fromRawData("2.3", 3) << 2.3 << true;
}
void tst_QByteArray::toDouble()
@@ -1934,7 +1935,7 @@ void tst_QByteArray::repeatedSignature() const
{
/* repated() should be a const member. */
const QByteArray string;
- string.repeated(3);
+ (void)string.repeated(3);
}
void tst_QByteArray::repeated() const
@@ -2126,7 +2127,7 @@ void tst_QByteArray::movablity()
{
QFETCH(QByteArray, array);
- QVERIFY(!QTypeInfo<QByteArray>::isStatic);
+ Q_STATIC_ASSERT(!QTypeInfo<QByteArray>::isStatic);
const int size = array.size();
const bool isEmpty = array.isEmpty();
@@ -2138,7 +2139,7 @@ void tst_QByteArray::movablity()
// we need only memory space not the instance
memSpace.~QByteArray();
// move array -> memSpace
- memcpy(&memSpace, &array, sizeof(QByteArray));
+ memcpy((void *)&memSpace, (const void *)&array, sizeof(QByteArray));
// reconstruct empty QByteArray
new (&array) QByteArray;
@@ -2148,8 +2149,8 @@ void tst_QByteArray::movablity()
QCOMPARE(memSpace.capacity(), capacity);
// try to not crash
- memSpace.toLower();
- memSpace.toUpper();
+ (void)memSpace.toLower();
+ (void)memSpace.toUpper();
memSpace.prepend('a');
memSpace.append("b", 1);
memSpace.squeeze();
@@ -2165,7 +2166,7 @@ void tst_QByteArray::movablity()
// move back memSpace -> array
array.~QByteArray();
- memcpy(&array, &memSpace, sizeof(QByteArray));
+ memcpy((void *)&array, (const void *)&memSpace, sizeof(QByteArray));
// reconstruct empty QByteArray
new (&memSpace) QByteArray;
@@ -2189,7 +2190,6 @@ void tst_QByteArray::movablity()
QVERIFY(true);
}
-#if defined(Q_COMPILER_LAMBDA)
// Only tested on c++0x compliant compiler or gcc
void tst_QByteArray::literals()
{
@@ -2210,7 +2210,6 @@ void tst_QByteArray::literals()
QVERIFY(str2.constData() == s);
QVERIFY(str2.data() != s);
}
-#endif
void tst_QByteArray::toUpperLower_data()
{
@@ -2242,28 +2241,28 @@ void tst_QByteArray::toUpperLower()
QCOMPARE(input.toLower(), lower);
QByteArray copy = input;
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
copy = input;
copy.detach();
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
copy = input;
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = input;
copy.detach();
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = lower;
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = lower;
copy.detach();
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = upper;
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
copy = upper;
copy.detach();
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
}
void tst_QByteArray::isUpper()
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm b/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm
index 98146e3525..98146e3525 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm
+++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm
diff --git a/tests/auto/corelib/tools/qbytearraylist/qbytearraylist.pro b/tests/auto/corelib/text/qbytearraylist/qbytearraylist.pro
index 6c05c288cf..6c05c288cf 100644
--- a/tests/auto/corelib/tools/qbytearraylist/qbytearraylist.pro
+++ b/tests/auto/corelib/text/qbytearraylist/qbytearraylist.pro
diff --git a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp b/tests/auto/corelib/text/qbytearraylist/tst_qbytearraylist.cpp
index 2d2c536453..09ce41337e 100644
--- a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp
+++ b/tests/auto/corelib/text/qbytearraylist/tst_qbytearraylist.cpp
@@ -194,22 +194,22 @@ void tst_QByteArrayList::operator_plus() const
{
QByteArrayList bal1 = lhs;
const QByteArrayList bal2 = rhs;
- QCOMPARE(qMove(bal1) + bal2, expectedResult);
+ QCOMPARE(std::move(bal1) + bal2, expectedResult);
}
{
QList<QByteArray> lba1 = lhs;
const QByteArrayList bal2 = rhs;
- QCOMPARE(qMove(lba1) + bal2, expectedResult);
+ QCOMPARE(std::move(lba1) + bal2, expectedResult);
}
{
QByteArrayList bal1 = lhs;
const QList<QByteArray> lba2 = rhs;
- QCOMPARE(qMove(bal1) + lba2, expectedResult);
+ QCOMPARE(std::move(bal1) + lba2, expectedResult);
}
{
QList<QByteArray> lba1 = lhs;
const QList<QByteArray> lba2 = rhs;
- QCOMPARE(qMove(lba1) + lba2, QList<QByteArray>(expectedResult)); // check we don't mess with old code
+ QCOMPARE(std::move(lba1) + lba2, QList<QByteArray>(expectedResult)); // check we don't mess with old code
}
// operator += for const lvalues
@@ -232,7 +232,7 @@ void tst_QByteArrayList::operator_plus() const
QByteArrayList t1 = lhs;
QByteArrayList t2 = rhs;
- QCOMPARE(qMove(t1) + t2, expectedResult);
+ QCOMPARE(std::move(t1) + t2, expectedResult);
}
void tst_QByteArrayList::operator_plus_data() const
@@ -287,7 +287,6 @@ void tst_QByteArrayList::indexOf() const
void tst_QByteArrayList::initializerList() const
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
// constructor
QByteArrayList v1 = {QByteArray("hello"),"world",QByteArray("plop")};
QCOMPARE(v1, (QByteArrayList() << "hello" << "world" << "plop"));
@@ -296,9 +295,6 @@ void tst_QByteArrayList::initializerList() const
QByteArrayList v2;
v2 = {QByteArray("hello"),"world",QByteArray("plop")};
QCOMPARE(v2, v1);
-#else
- QSKIP("This test requires C++11 initializer_list support in the compiler.");
-#endif
}
QTEST_APPLESS_MAIN(tst_QByteArrayList)
diff --git a/tests/auto/corelib/tools/qbytearraymatcher/qbytearraymatcher.pro b/tests/auto/corelib/text/qbytearraymatcher/qbytearraymatcher.pro
index 9d4d5964c9..9d4d5964c9 100644
--- a/tests/auto/corelib/tools/qbytearraymatcher/qbytearraymatcher.pro
+++ b/tests/auto/corelib/text/qbytearraymatcher/qbytearraymatcher.pro
diff --git a/tests/auto/corelib/tools/qbytearraymatcher/tst_qbytearraymatcher.cpp b/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp
index 647a3ae379..647a3ae379 100644
--- a/tests/auto/corelib/tools/qbytearraymatcher/tst_qbytearraymatcher.cpp
+++ b/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp
diff --git a/tests/auto/corelib/tools/qbytedatabuffer/.gitignore b/tests/auto/corelib/text/qbytedatabuffer/.gitignore
index 3024a4dba2..3024a4dba2 100644
--- a/tests/auto/corelib/tools/qbytedatabuffer/.gitignore
+++ b/tests/auto/corelib/text/qbytedatabuffer/.gitignore
diff --git a/tests/auto/corelib/tools/qbytedatabuffer/qbytedatabuffer.pro b/tests/auto/corelib/text/qbytedatabuffer/qbytedatabuffer.pro
index e23018f96a..e23018f96a 100644
--- a/tests/auto/corelib/tools/qbytedatabuffer/qbytedatabuffer.pro
+++ b/tests/auto/corelib/text/qbytedatabuffer/qbytedatabuffer.pro
diff --git a/tests/auto/corelib/tools/qbytedatabuffer/tst_qbytedatabuffer.cpp b/tests/auto/corelib/text/qbytedatabuffer/tst_qbytedatabuffer.cpp
index 59f4d153e6..59f4d153e6 100644
--- a/tests/auto/corelib/tools/qbytedatabuffer/tst_qbytedatabuffer.cpp
+++ b/tests/auto/corelib/text/qbytedatabuffer/tst_qbytedatabuffer.cpp
diff --git a/tests/auto/corelib/tools/qchar/.gitignore b/tests/auto/corelib/text/qchar/.gitignore
index 341b3e6c3f..341b3e6c3f 100644
--- a/tests/auto/corelib/tools/qchar/.gitignore
+++ b/tests/auto/corelib/text/qchar/.gitignore
diff --git a/tests/auto/corelib/tools/qchar/data/NormalizationTest.txt b/tests/auto/corelib/text/qchar/data/NormalizationTest.txt
index 0290080998..0290080998 100644
--- a/tests/auto/corelib/tools/qchar/data/NormalizationTest.txt
+++ b/tests/auto/corelib/text/qchar/data/NormalizationTest.txt
diff --git a/tests/auto/corelib/tools/qchar/qchar.pro b/tests/auto/corelib/text/qchar/qchar.pro
index 70c1222988..70c1222988 100644
--- a/tests/auto/corelib/tools/qchar/qchar.pro
+++ b/tests/auto/corelib/text/qchar/qchar.pro
diff --git a/tests/auto/corelib/tools/qchar/testdata.qrc b/tests/auto/corelib/text/qchar/testdata.qrc
index 7b3fb2461c..7b3fb2461c 100644
--- a/tests/auto/corelib/tools/qchar/testdata.qrc
+++ b/tests/auto/corelib/text/qchar/testdata.qrc
diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/text/qchar/tst_qchar.cpp
index cf4f6d21e2..cf4f6d21e2 100644
--- a/tests/auto/corelib/tools/qchar/tst_qchar.cpp
+++ b/tests/auto/corelib/text/qchar/tst_qchar.cpp
diff --git a/tests/auto/corelib/tools/qcollator/qcollator.pro b/tests/auto/corelib/text/qcollator/qcollator.pro
index 2f3995a75f..2f3995a75f 100644
--- a/tests/auto/corelib/tools/qcollator/qcollator.pro
+++ b/tests/auto/corelib/text/qcollator/qcollator.pro
diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp
index 72f88a235d..2ae9c6e159 100644
--- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp
+++ b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp
@@ -47,7 +47,6 @@ private Q_SLOTS:
void state();
};
-#ifdef Q_COMPILER_RVALUE_REFS
static bool dpointer_is_null(QCollator &c)
{
char mem[sizeof c];
@@ -58,11 +57,9 @@ static bool dpointer_is_null(QCollator &c)
return false;
return true;
}
-#endif
void tst_QCollator::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
const QLocale de_AT(QLocale::German, QLocale::Austria);
QCollator c1(de_AT);
@@ -78,9 +75,6 @@ void tst_QCollator::moveSemantics()
c1 = std::move(c2);
QCOMPARE(c1.locale(), de_AT);
QVERIFY(dpointer_is_null(c2));
-#else
- QSKIP("The compiler is not in C++11 mode or does not support move semantics.");
-#endif
}
diff --git a/tests/auto/corelib/tools/qlatin1string/.gitignore b/tests/auto/corelib/text/qlatin1string/.gitignore
index dddf56b2df..dddf56b2df 100644
--- a/tests/auto/corelib/tools/qlatin1string/.gitignore
+++ b/tests/auto/corelib/text/qlatin1string/.gitignore
diff --git a/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro b/tests/auto/corelib/text/qlatin1string/qlatin1string.pro
index 61054b40e4..61054b40e4 100644
--- a/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro
+++ b/tests/auto/corelib/text/qlatin1string/qlatin1string.pro
diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/text/qlatin1string/tst_qlatin1string.cpp
index dcfb0aa042..0427c81b85 100644
--- a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
+++ b/tests/auto/corelib/text/qlatin1string/tst_qlatin1string.cpp
@@ -45,6 +45,7 @@ class tst_QLatin1String : public QObject
private Q_SLOTS:
void at();
+ void arg() const;
void midLeftRight();
void nullString();
void emptyString();
@@ -63,6 +64,47 @@ void tst_QLatin1String::at()
QCOMPARE(l1[l1.size() - 1], QLatin1Char('d'));
}
+void tst_QLatin1String::arg() const
+{
+#define CHECK1(pattern, arg1, expected) \
+ do { \
+ auto p = QLatin1String(pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1)), expected); \
+ QCOMPARE(p.arg(u"" arg1), expected); \
+ QCOMPARE(p.arg(QStringLiteral(arg1)), expected); \
+ QCOMPARE(p.arg(QString(QLatin1String(arg1))), expected); \
+ } while (false) \
+ /*end*/
+#define CHECK2(pattern, arg1, arg2, expected) \
+ do { \
+ auto p = QLatin1String(pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1), QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(u"" arg1, QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(QLatin1String(arg1), u"" arg2), expected); \
+ QCOMPARE(p.arg(u"" arg1, u"" arg2), expected); \
+ } while (false) \
+ /*end*/
+
+ CHECK1("", "World", "");
+ CHECK1("%1", "World", "World");
+ CHECK1("!%1?", "World", "!World?");
+ CHECK1("%1%1", "World", "WorldWorld");
+ CHECK1("%1%2", "World", "World%2");
+ CHECK1("%2%1", "World", "%2World");
+
+ CHECK2("", "Hello", "World", "");
+ CHECK2("%1", "Hello", "World", "Hello");
+ CHECK2("!%1, %2?", "Hello", "World", "!Hello, World?");
+ CHECK2("%1%1", "Hello", "World", "HelloHello");
+ CHECK2("%1%2", "Hello", "World", "HelloWorld");
+ CHECK2("%2%1", "Hello", "World", "WorldHello");
+
+#undef CHECK2
+#undef CHECK1
+
+ QCOMPARE(QLatin1String(" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C ");
+}
+
void tst_QLatin1String::midLeftRight()
{
const QLatin1String l1("Hello World");
diff --git a/tests/auto/corelib/tools/qlocale/.gitignore b/tests/auto/corelib/text/qlocale/.gitignore
index 21ab80a2af..21ab80a2af 100644
--- a/tests/auto/corelib/tools/qlocale/.gitignore
+++ b/tests/auto/corelib/text/qlocale/.gitignore
diff --git a/tests/auto/corelib/tools/qlocale/qlocale.pro b/tests/auto/corelib/text/qlocale/qlocale.pro
index 5161200260..5161200260 100644
--- a/tests/auto/corelib/tools/qlocale/qlocale.pro
+++ b/tests/auto/corelib/text/qlocale/qlocale.pro
diff --git a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.cpp b/tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.cpp
index 1e1bcc8c5f..1e1bcc8c5f 100644
--- a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.cpp
+++ b/tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.cpp
diff --git a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro b/tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.pro
index 3e283c05a4..3e283c05a4 100644
--- a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro
+++ b/tests/auto/corelib/text/qlocale/syslocaleapp/syslocaleapp.pro
diff --git a/tests/auto/corelib/tools/qlocale/test/test.pro b/tests/auto/corelib/text/qlocale/test/test.pro
index f7243e99a7..f7243e99a7 100644
--- a/tests/auto/corelib/tools/qlocale/test/test.pro
+++ b/tests/auto/corelib/text/qlocale/test/test.pro
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
index be2e2a2e08..676c66df3e 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
@@ -423,6 +423,7 @@ void tst_QLocale::defaulted_ctor()
}
QLocale::setDefault(QLocale(QLocale::C));
+ const QString empty;
TEST_CTOR("C", C, AnyCountry)
TEST_CTOR("bla", C, AnyCountry)
@@ -431,7 +432,7 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR("zz...", C, AnyCountry)
TEST_CTOR("", C, AnyCountry)
TEST_CTOR("en/", C, AnyCountry)
- TEST_CTOR(QString::null, C, AnyCountry)
+ TEST_CTOR(empty, C, AnyCountry)
TEST_CTOR("en", English, UnitedStates)
TEST_CTOR("en", English, UnitedStates)
TEST_CTOR("en.", English, UnitedStates)
@@ -1458,8 +1459,8 @@ void tst_QLocale::dayOfWeek()
QCOMPARE(QLocale::c().toString(date, "ddd"), shortName);
QCOMPARE(QLocale::c().toString(date, "dddd"), longName);
- QCOMPARE(QLocale::c().toString(date, QStringViewLiteral("ddd")), shortName);
- QCOMPARE(QLocale::c().toString(date, QStringViewLiteral("dddd")), longName);
+ QCOMPARE(QLocale::c().toString(date, u"ddd"), shortName);
+ QCOMPARE(QLocale::c().toString(date, u"dddd"), longName);
}
void tst_QLocale::formatDate_data()
diff --git a/tests/auto/corelib/tools/qregexp/.gitignore b/tests/auto/corelib/text/qregexp/.gitignore
index e6e629ee2c..e6e629ee2c 100644
--- a/tests/auto/corelib/tools/qregexp/.gitignore
+++ b/tests/auto/corelib/text/qregexp/.gitignore
diff --git a/tests/auto/corelib/tools/qregexp/qregexp.pro b/tests/auto/corelib/text/qregexp/qregexp.pro
index 5f6ff0a71c..5f6ff0a71c 100644
--- a/tests/auto/corelib/tools/qregexp/qregexp.pro
+++ b/tests/auto/corelib/text/qregexp/qregexp.pro
diff --git a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp b/tests/auto/corelib/text/qregexp/tst_qregexp.cpp
index a8111af6c1..a8111af6c1 100644
--- a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp
+++ b/tests/auto/corelib/text/qregexp/tst_qregexp.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/.gitignore b/tests/auto/corelib/text/qregularexpression/.gitignore
index 4650b4454e..4650b4454e 100644
--- a/tests/auto/corelib/tools/qregularexpression/.gitignore
+++ b/tests/auto/corelib/text/qregularexpression/.gitignore
diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/text/qregularexpression/qregularexpression.pro
index ec8189717e..ec8189717e 100644
--- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
+++ b/tests/auto/corelib/text/qregularexpression/qregularexpression.pro
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp
index c02756d76a..c02756d76a 100644
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
+++ b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qstring/.gitignore b/tests/auto/corelib/text/qstring/.gitignore
index c2ea8d0336..c2ea8d0336 100644
--- a/tests/auto/corelib/tools/qstring/.gitignore
+++ b/tests/auto/corelib/text/qstring/.gitignore
diff --git a/tests/auto/corelib/tools/qstring/double_data.h b/tests/auto/corelib/text/qstring/double_data.h
index 0d59ecb5ff..0d59ecb5ff 100644
--- a/tests/auto/corelib/tools/qstring/double_data.h
+++ b/tests/auto/corelib/text/qstring/double_data.h
diff --git a/tests/auto/corelib/tools/qstring/qstring.pro b/tests/auto/corelib/text/qstring/qstring.pro
index ec8a9b5df5..ec8a9b5df5 100644
--- a/tests/auto/corelib/tools/qstring/qstring.pro
+++ b/tests/auto/corelib/text/qstring/qstring.pro
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index e8ed22e427..cce3e601cd 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -482,8 +482,8 @@ private slots:
void indexOf2();
void indexOf3_data();
// void indexOf3();
- void sprintf();
- void sprintfS();
+ void asprintf();
+ void asprintfS();
void fill();
void truncate();
void chop_data();
@@ -521,7 +521,9 @@ private slots:
void stringRef_local8Bit_data();
void stringRef_local8Bit();
void fromLatin1();
+#if QT_DEPRECATED_SINCE(5, 0)
void fromAscii();
+#endif
void fromUcs4();
void toUcs4();
void arg();
@@ -578,7 +580,7 @@ private slots:
#ifdef QT_USE_ICU
void toUpperLower_icu();
#endif
-#if !defined(QT_NO_UNICODE_LITERAL) && defined(Q_COMPILER_LAMBDA)
+#if !defined(QT_NO_UNICODE_LITERAL)
void literals();
#endif
void eightBitLiterals_data();
@@ -612,7 +614,7 @@ QString verifyZeroTermination(const QString &str)
int strSize = str.size();
QChar strTerminator = str.constData()[strSize];
if (QChar('\0') != strTerminator)
- return QString::fromAscii(
+ return QString::fromLatin1(
"*** Result ('%1') not null-terminated: 0x%2 ***").arg(str)
.arg(strTerminator.unicode(), 4, 16, QChar('0'));
@@ -625,11 +627,11 @@ QString verifyZeroTermination(const QString &str)
const_cast<QChar *>(strData)[strSize] = QChar('x');
if (QChar('x') != str.constData()[strSize]) {
- return QString::fromAscii("*** Failed to replace null-terminator in "
+ return QString::fromLatin1("*** Failed to replace null-terminator in "
"result ('%1') ***").arg(str);
}
if (str != strCopy) {
- return QString::fromAscii( "*** Result ('%1') differs from its copy "
+ return QString::fromLatin1( "*** Result ('%1') differs from its copy "
"after null-terminator was replaced ***").arg(str);
}
const_cast<QChar *>(strData)[strSize] = QChar('\0'); // Restore sanity
@@ -1075,9 +1077,8 @@ void tst_QString::isNull()
QString a;
QVERIFY(a.isNull());
- const char *zero = 0;
- a.sprintf( zero );
- QVERIFY(!a.isNull());
+ const char *zero = nullptr;
+ QVERIFY(!QString::asprintf(zero).isNull());
}
QT_WARNING_POP
@@ -1263,75 +1264,66 @@ static inline const void *ptrValue(quintptr v)
return reinterpret_cast<const void *>(v);
}
-void tst_QString::sprintf()
+void tst_QString::asprintf()
{
QString a;
- a.sprintf("COMPARE");
- QCOMPARE(a, QLatin1String("COMPARE"));
- a.sprintf("%%%d",1);
- QCOMPARE(a, QLatin1String("%1"));
- QCOMPARE(a.sprintf("X%dY",2), QLatin1String("X2Y"));
- QCOMPARE(a.sprintf("X%9iY", 50000 ), QLatin1String("X 50000Y"));
- QCOMPARE(a.sprintf("X%-9sY","hello"), QLatin1String("Xhello Y"));
- QCOMPARE(a.sprintf("X%-9iY", 50000 ), QLatin1String("X50000 Y"));
- QCOMPARE(a.sprintf("%lf", 1.23), QLatin1String("1.230000"));
- QCOMPARE(a.sprintf("%lf", 1.23456789), QLatin1String("1.234568"));
- QCOMPARE(a.sprintf("%p", ptrValue(0xbfffd350)), QLatin1String("0xbfffd350"));
- QCOMPARE(a.sprintf("%p", ptrValue(0)), QLatin1String("0x0"));
+ QCOMPARE(QString::asprintf("COMPARE"), QLatin1String("COMPARE"));
+ QCOMPARE(QString::asprintf("%%%d", 1), QLatin1String("%1"));
+ QCOMPARE(QString::asprintf("X%dY",2), QLatin1String("X2Y"));
+ QCOMPARE(QString::asprintf("X%9iY", 50000 ), QLatin1String("X 50000Y"));
+ QCOMPARE(QString::asprintf("X%-9sY","hello"), QLatin1String("Xhello Y"));
+ QCOMPARE(QString::asprintf("X%-9iY", 50000 ), QLatin1String("X50000 Y"));
+ QCOMPARE(QString::asprintf("%lf", 1.23), QLatin1String("1.230000"));
+ QCOMPARE(QString::asprintf("%lf", 1.23456789), QLatin1String("1.234568"));
+ QCOMPARE(QString::asprintf("%p", ptrValue(0xbfffd350)), QLatin1String("0xbfffd350"));
+ QCOMPARE(QString::asprintf("%p", ptrValue(0)), QLatin1String("0x0"));
int i = 6;
long l = -2;
float f = 4.023f;
- QString S1;
- S1.sprintf("%d %ld %f",i,l,f);
- QCOMPARE(S1, QLatin1String("6 -2 4.023000"));
+ QCOMPARE(QString::asprintf("%d %ld %f", i, l, f), QLatin1String("6 -2 4.023000"));
double d = -514.25683;
- S1.sprintf("%f",d);
- QCOMPARE(S1, QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%f", d), QLatin1String("-514.256830"));
}
-void tst_QString::sprintfS()
+void tst_QString::asprintfS()
{
- QString a;
- QCOMPARE(a.sprintf("%.3s", "Hello" ), QLatin1String("Hel"));
- QCOMPARE(a.sprintf("%10.3s", "Hello" ), QLatin1String(" Hel"));
- QCOMPARE(a.sprintf("%.10s", "Hello" ), QLatin1String("Hello"));
- QCOMPARE(a.sprintf("%10.10s", "Hello" ), QLatin1String(" Hello"));
- QCOMPARE(a.sprintf("%-10.10s", "Hello" ), QLatin1String("Hello "));
- QCOMPARE(a.sprintf("%-10.3s", "Hello" ), QLatin1String("Hel "));
- QCOMPARE(a.sprintf("%-5.5s", "Hello" ), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%.3s", "Hello" ), QLatin1String("Hel"));
+ QCOMPARE(QString::asprintf("%10.3s", "Hello" ), QLatin1String(" Hel"));
+ QCOMPARE(QString::asprintf("%.10s", "Hello" ), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%10.10s", "Hello" ), QLatin1String(" Hello"));
+ QCOMPARE(QString::asprintf("%-10.10s", "Hello" ), QLatin1String("Hello "));
+ QCOMPARE(QString::asprintf("%-10.3s", "Hello" ), QLatin1String("Hel "));
+ QCOMPARE(QString::asprintf("%-5.5s", "Hello" ), QLatin1String("Hello"));
// Check utf8 conversion for %s
- QCOMPARE(a.sprintf("%s", "\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205"), QString::fromLatin1("\366\344\374\326\304\334\370\346\345\330\306\305"));
+ QCOMPARE(QString::asprintf("%s", "\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205"), QString::fromLatin1("\366\344\374\326\304\334\370\346\345\330\306\305"));
int n1;
- a.sprintf("%s%n%s", "hello", &n1, "goodbye");
+ QCOMPARE(QString::asprintf("%s%n%s", "hello", &n1, "goodbye"), QString("hellogoodbye"));
QCOMPARE(n1, 5);
- QCOMPARE(a, QString("hellogoodbye"));
qlonglong n2;
- a.sprintf("%s%s%lln%s", "foo", "bar", &n2, "whiz");
+ QCOMPARE(QString::asprintf("%s%s%lln%s", "foo", "bar", &n2, "whiz"), QString("foobarwhiz"));
QCOMPARE((int)n2, 6);
- QCOMPARE(a, QString("foobarwhiz"));
{ // %ls
- QCOMPARE(a.sprintf("%.3ls", qUtf16Printable("Hello")), QLatin1String("Hel"));
- QCOMPARE(a.sprintf("%10.3ls", qUtf16Printable("Hello")), QLatin1String(" Hel"));
- QCOMPARE(a.sprintf("%.10ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
- QCOMPARE(a.sprintf("%10.10ls", qUtf16Printable("Hello")), QLatin1String(" Hello"));
- QCOMPARE(a.sprintf("%-10.10ls", qUtf16Printable("Hello")), QLatin1String("Hello "));
- QCOMPARE(a.sprintf("%-10.3ls", qUtf16Printable("Hello")), QLatin1String("Hel "));
- QCOMPARE(a.sprintf("%-5.5ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%.3ls", qUtf16Printable("Hello")), QLatin1String("Hel"));
+ QCOMPARE(QString::asprintf("%10.3ls", qUtf16Printable("Hello")), QLatin1String(" Hel"));
+ QCOMPARE(QString::asprintf("%.10ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%10.10ls", qUtf16Printable("Hello")), QLatin1String(" Hello"));
+ QCOMPARE(QString::asprintf("%-10.10ls", qUtf16Printable("Hello")), QLatin1String("Hello "));
+ QCOMPARE(QString::asprintf("%-10.3ls", qUtf16Printable("Hello")), QLatin1String("Hel "));
+ QCOMPARE(QString::asprintf("%-5.5ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
// Check utf16 is preserved for %ls
- QCOMPARE(a.sprintf("%ls",
+ QCOMPARE(QString::asprintf("%ls",
qUtf16Printable("\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205")),
QLatin1String("\366\344\374\326\304\334\370\346\345\330\306\305"));
int n;
- a.sprintf("%ls%n%s", qUtf16Printable("hello"), &n, "goodbye");
+ QCOMPARE(QString::asprintf("%ls%n%s", qUtf16Printable("hello"), &n, "goodbye"), QLatin1String("hellogoodbye"));
QCOMPARE(n, 5);
- QCOMPARE(a, QLatin1String("hellogoodbye"));
}
}
@@ -2212,12 +2204,12 @@ void tst_QString::toUpper()
// call rvalue-ref while shared (the original mustn't change)
QString copy = s;
- QCOMPARE(qMove(copy).toUpper(), QString("GROSSSTRASSE"));
+ QCOMPARE(std::move(copy).toUpper(), QString("GROSSSTRASSE"));
QCOMPARE(s, QString::fromUtf8("Gro\xc3\x9fstra\xc3\x9f""e"));
// call rvalue-ref version on detached case
copy.clear();
- QCOMPARE(qMove(s).toUpper(), QString("GROSSSTRASSE"));
+ QCOMPARE(std::move(s).toUpper(), QString("GROSSSTRASSE"));
}
QString lower, upper;
@@ -2427,11 +2419,11 @@ void tst_QString::trimmed()
QCOMPARE(a.trimmed(), QLatin1String("a"));
a="Text";
- QCOMPARE(qMove(a).trimmed(), QLatin1String("Text"));
+ QCOMPARE(std::move(a).trimmed(), QLatin1String("Text"));
a=" ";
- QCOMPARE(qMove(a).trimmed(), QLatin1String(""));
+ QCOMPARE(std::move(a).trimmed(), QLatin1String(""));
a=" a ";
- QCOMPARE(qMove(a).trimmed(), QLatin1String("a"));
+ QCOMPARE(std::move(a).trimmed(), QLatin1String("a"));
}
void tst_QString::simplified_data()
@@ -2486,13 +2478,13 @@ void tst_QString::simplified()
// without detaching:
QString copy1 = full;
- QCOMPARE(qMove(full).simplified(), simple);
+ QCOMPARE(std::move(full).simplified(), simple);
QCOMPARE(full, orig_full);
// force a detach
if (!full.isEmpty())
full[0] = full[0];
- QCOMPARE(qMove(full).simplified(), simple);
+ QCOMPARE(std::move(full).simplified(), simple);
}
void tst_QString::insert_data(bool emptyIsNoop)
@@ -3789,7 +3781,7 @@ void tst_QString::startsWith()
QVERIFY( !a.startsWith("C") );
QVERIFY( !a.startsWith("ABCDEF") );
QVERIFY( a.startsWith("") );
- QVERIFY( a.startsWith(QString::null) );
+ QVERIFY( a.startsWith(QString()) );
QVERIFY( a.startsWith('A') );
QVERIFY( a.startsWith(QLatin1Char('A')) );
QVERIFY( a.startsWith(QChar('A')) );
@@ -3816,7 +3808,7 @@ void tst_QString::startsWith()
QVERIFY( !a.startsWith("c", Qt::CaseInsensitive) );
QVERIFY( !a.startsWith("abcdef", Qt::CaseInsensitive) );
QVERIFY( a.startsWith("", Qt::CaseInsensitive) );
- QVERIFY( a.startsWith(QString::null, Qt::CaseInsensitive) );
+ QVERIFY( a.startsWith(QString(), Qt::CaseInsensitive) );
QVERIFY( a.startsWith('a', Qt::CaseInsensitive) );
QVERIFY( a.startsWith('A', Qt::CaseInsensitive) );
QVERIFY( a.startsWith(QLatin1Char('a'), Qt::CaseInsensitive) );
@@ -3855,7 +3847,7 @@ void tst_QString::startsWith()
a = "";
QVERIFY( a.startsWith("") );
- QVERIFY( a.startsWith(QString::null) );
+ QVERIFY( a.startsWith(QString()) );
QVERIFY( !a.startsWith("ABC") );
QVERIFY( a.startsWith(QLatin1String("")) );
@@ -3868,7 +3860,7 @@ void tst_QString::startsWith()
a = QString();
QVERIFY( !a.startsWith("") );
- QVERIFY( a.startsWith(QString::null) );
+ QVERIFY( a.startsWith(QString()) );
QVERIFY( !a.startsWith("ABC") );
QVERIFY( !a.startsWith(QLatin1String("")) );
@@ -3897,7 +3889,7 @@ void tst_QString::endsWith()
QVERIFY( !a.endsWith("C") );
QVERIFY( !a.endsWith("ABCDEF") );
QVERIFY( a.endsWith("") );
- QVERIFY( a.endsWith(QString::null) );
+ QVERIFY( a.endsWith(QString()) );
QVERIFY( a.endsWith('B') );
QVERIFY( a.endsWith(QLatin1Char('B')) );
QVERIFY( a.endsWith(QChar('B')) );
@@ -3924,7 +3916,7 @@ void tst_QString::endsWith()
QVERIFY( !a.endsWith("c", Qt::CaseInsensitive) );
QVERIFY( !a.endsWith("abcdef", Qt::CaseInsensitive) );
QVERIFY( a.endsWith("", Qt::CaseInsensitive) );
- QVERIFY( a.endsWith(QString::null, Qt::CaseInsensitive) );
+ QVERIFY( a.endsWith(QString(), Qt::CaseInsensitive) );
QVERIFY( a.endsWith('b', Qt::CaseInsensitive) );
QVERIFY( a.endsWith('B', Qt::CaseInsensitive) );
QVERIFY( a.endsWith(QLatin1Char('b'), Qt::CaseInsensitive) );
@@ -3966,7 +3958,7 @@ void tst_QString::endsWith()
a = "";
QVERIFY( a.endsWith("") );
- QVERIFY( a.endsWith(QString::null) );
+ QVERIFY( a.endsWith(QString()) );
QVERIFY( !a.endsWith("ABC") );
QVERIFY( !a.endsWith(QLatin1Char(0)) );
QVERIFY( !a.endsWith(QLatin1Char('x')) );
@@ -3978,7 +3970,7 @@ void tst_QString::endsWith()
a = QString();
QVERIFY( !a.endsWith("") );
- QVERIFY( a.endsWith(QString::null) );
+ QVERIFY( a.endsWith(QString()) );
QVERIFY( !a.endsWith("ABC") );
QVERIFY( !a.endsWith(QLatin1String("")) );
@@ -4294,9 +4286,9 @@ void tst_QString::fromLocal8Bit_data()
//QTest::newRow("null5") << QByteArray() << 5 << QString();
//QTest::newRow("empty-1") << QByteArray("\0abcd", 5) << -1 << QString();
//QTest::newRow("empty0") << QByteArray() << 0 << QString();
- //QTest::newRow("empty5") << QByteArray("\0abcd", 5) << 5 << QString::fromAscii("\0abcd", 5);
- //QTest::newRow("other-1") << QByteArray("ab\0cd", 5) << -1 << QString::fromAscii("ab");
- //QTest::newRow("other5") << QByteArray("ab\0cd", 5) << 5 << QString::fromAscii("ab\0cd", 5);
+ //QTest::newRow("empty5") << QByteArray("\0abcd", 5) << 5 << QString::fromLatin1("\0abcd", 5);
+ //QTest::newRow("other-1") << QByteArray("ab\0cd", 5) << -1 << QString::fromLatin1("ab");
+ //QTest::newRow("other5") << QByteArray("ab\0cd", 5) << 5 << QString::fromLatin1("ab\0cd", 5);
}
void tst_QString::fromLocal8Bit()
@@ -4534,7 +4526,7 @@ void tst_QString::toLatin1Roundtrip()
// try the rvalue version of toLatin1()
QString s = unicodesrc;
- QCOMPARE(qMove(s).toLatin1(), latin1);
+ QCOMPARE(std::move(s).toLatin1(), latin1);
// and verify that the moved-from object can still be used
s = "foo";
@@ -4600,6 +4592,7 @@ void tst_QString::fromLatin1()
QVERIFY(a.size() == 5);
}
+#if QT_DEPRECATED_SINCE(5, 0)
void tst_QString::fromAscii()
{
QString a;
@@ -4620,6 +4613,7 @@ void tst_QString::fromAscii()
a = QString::fromAscii("\0abcd", 5);
QVERIFY(a.size() == 5);
}
+#endif
void tst_QString::fromUcs4()
{
@@ -4769,7 +4763,7 @@ void tst_QString::arg()
QCOMPARE( s4.arg("foo"), QLatin1String("[foo]") );
QCOMPARE( s5.arg(QLatin1String("foo")), QLatin1String("[foo]") );
- QCOMPARE( s6.arg(QStringViewLiteral("foo")), QLatin1String("[foo]") );
+ QCOMPARE( s6.arg(u"foo"), QLatin1String("[foo]") );
QCOMPARE( s7.arg("foo"), QLatin1String("[foo]") );
QCOMPARE( s8.arg("foo"), QLatin1String("[foo %1]") );
QCOMPARE( s8.arg("foo").arg("bar"), QLatin1String("[foo bar]") );
@@ -4831,14 +4825,14 @@ void tst_QString::arg()
QCOMPARE( QString("%1").arg("hello", -10), QLatin1String("hello ") );
QCOMPARE( QString("%1").arg(QLatin1String("hello"), -5), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), -2), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(u"hello", -2), QLatin1String("hello") );
QCOMPARE( QString("%1").arg("hello", 0), QLatin1String("hello") );
QCOMPARE( QString("%1").arg(QLatin1String("hello"), 2), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), 5), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(u"hello", 5), QLatin1String("hello") );
QCOMPARE( QString("%1").arg("hello", 10), QLatin1String(" hello") );
QCOMPARE( QString("%1%1").arg("hello"), QLatin1String("hellohello") );
QCOMPARE( QString("%2%1").arg("hello"), QLatin1String("%2hello") );
- QCOMPARE( QString("%1%1").arg(QString::null), QLatin1String("") );
+ QCOMPARE( QString("%1%1").arg(QString()), QLatin1String("") );
QCOMPARE( QString("%2%1").arg(""), QLatin1String("%2") );
QCOMPARE( QString("%2 %L1").arg(12345.6789).arg(12345.6789),
@@ -4934,9 +4928,7 @@ void tst_QString::doubleOut()
QCOMPARE(QString::number(micro), expect);
QCOMPARE(QString("%1").arg(micro), expect);
{
- QString text;
- text.sprintf("%g", micro);
- QCOMPARE(text, expect);
+ QCOMPARE(QString::asprintf("%g", micro), expect);
}
{
QString text;
@@ -5480,8 +5472,6 @@ void tst_QString::tortureSprintfDouble()
{
const SprintfDoubleData *data = g_sprintf_double_data;
- QString s;
-
for (; data->fmt != 0; ++data) {
double d;
char *buff = (char *)&d;
@@ -5496,7 +5486,7 @@ void tst_QString::tortureSprintfDouble()
for (uint i = 0; i < 8; ++i)
buff[7 - i] = data->bytes[i];
# endif
- s.sprintf(data->fmt, d);
+ const QString s = QString::asprintf(data->fmt, d);
#ifdef QT_NO_FPU // reduced precision when running with hardfloats in qemu
if (d - 0.1 < 1e12)
QSKIP("clib sprintf doesn't fill with 0's on this platform");
@@ -6450,32 +6440,24 @@ void tst_QString::QCharRefDetaching() const
void tst_QString::sprintfZU() const
{
{
- QString string;
size_t s = 6;
- string.sprintf("%zu", s);
- QCOMPARE(string, QString::fromLatin1("6"));
+ QCOMPARE(QString::asprintf("%zu", s), QString::fromLatin1("6"));
}
{
- QString string;
- string.sprintf("%s\n", "foo");
- QCOMPARE(string, QString::fromLatin1("foo\n"));
+ QCOMPARE(QString::asprintf("%s\n", "foo"), QString::fromLatin1("foo\n"));
}
{
/* This code crashed. I don't know how to reduce it further. In other words,
* both %zu and %s needs to be present. */
size_t s = 6;
- QString string;
- string.sprintf("%zu%s", s, "foo");
- QCOMPARE(string, QString::fromLatin1("6foo"));
+ QCOMPARE(QString::asprintf("%zu%s", s, "foo"), QString::fromLatin1("6foo"));
}
{
size_t s = 6;
- QString string;
- string.sprintf("%zu %s\n", s, "foo");
- QCOMPARE(string, QString::fromLatin1("6 foo\n"));
+ QCOMPARE(QString::asprintf("%zu %s\n", s, "foo"), QString::fromLatin1("6 foo\n"));
}
}
@@ -6643,7 +6625,7 @@ void tst_QString::toUpperLower_icu()
}
#endif
-#if !defined(QT_NO_UNICODE_LITERAL) && defined(Q_COMPILER_LAMBDA)
+#if !defined(QT_NO_UNICODE_LITERAL)
// Only tested on c++0x compliant compiler or gcc
void tst_QString::literals()
{
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm b/tests/auto/corelib/text/qstring/tst_qstring_mac.mm
index 60bd3f9b15..60bd3f9b15 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm
+++ b/tests/auto/corelib/text/qstring/tst_qstring_mac.mm
diff --git a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro
index 14dbe779db..14dbe779db 100644
--- a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro
+++ b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/qstring_no_cast_from_bytearray.pro
diff --git a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp
index 47fbeb6069..47fbeb6069 100644
--- a/tests/auto/corelib/tools/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp
+++ b/tests/auto/corelib/text/qstring_no_cast_from_bytearray/tst_qstring_no_cast_from_bytearray.cpp
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/.gitignore b/tests/auto/corelib/text/qstringapisymmetry/.gitignore
index d28de05438..d28de05438 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/.gitignore
+++ b/tests/auto/corelib/text/qstringapisymmetry/.gitignore
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro b/tests/auto/corelib/text/qstringapisymmetry/qstringapisymmetry.pro
index a4e91e38bd..a4e91e38bd 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro
+++ b/tests/auto/corelib/text/qstringapisymmetry/qstringapisymmetry.pro
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
index 82d58becfe..24382a2b61 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -48,6 +49,14 @@ QString toQString(const T &t) { return QString(t); }
QString toQString(const QStringRef &ref) { return ref.toString(); }
QString toQString(QStringView view) { return view.toString(); }
+template <typename Iterable>
+QStringList toQStringList(const Iterable &i) {
+ QStringList result;
+ for (auto &e : i)
+ result.push_back(toQString(e));
+ return result;
+}
+
// FIXME: these are missing at the time of writing, add them, then remove the dummies here:
#define MAKE_RELOP(op, A1, A2) \
static bool operator op (A1 lhs, A2 rhs) \
@@ -293,6 +302,26 @@ private Q_SLOTS:
void endsWith_QLatin1String_QChar() { endsWith_impl<QLatin1String, QChar>(); }
private:
+ void split_data(bool rhsHasVariableLength = true);
+ template <typename Haystack, typename Needle> void split_impl() const;
+
+private Q_SLOTS:
+ // test all combinations of {QString, QStringRef} x {QString, QLatin1String, QChar}:
+ void split_QString_QString_data() { split_data(); }
+ void split_QString_QString() { split_impl<QString, QString>(); }
+ void split_QString_QLatin1String_data() { split_data(); }
+ void split_QString_QLatin1String() { split_impl<QString, QLatin1String>(); }
+ void split_QString_QChar_data() { split_data(false); }
+ void split_QString_QChar() { split_impl<QString, QChar>(); }
+
+ void split_QStringRef_QString_data() { split_data(); }
+ void split_QStringRef_QString() { split_impl<QStringRef, QString>(); }
+ void split_QStringRef_QLatin1String_data() { split_data(); }
+ void split_QStringRef_QLatin1String() { split_impl<QStringRef, QLatin1String>(); }
+ void split_QStringRef_QChar_data() { split_data(false); }
+ void split_QStringRef_QChar() { split_impl<QStringRef, QChar>(); }
+
+private:
void mid_data();
template <typename String> void mid_impl();
@@ -416,6 +445,129 @@ private Q_SLOTS:
void toUcs4_QStringRef() { toUcs4_impl<QStringRef>(); }
void toUcs4_QStringView_data() { toUcs4_data(); }
void toUcs4_QStringView() { toUcs4_impl<QStringView>(); }
+
+private:
+ template <typename Haystack, typename Needle> void indexOf_impl() const;
+ void indexOf_data();
+
+private Q_SLOTS:
+ void indexOf_QString_QString_data() { indexOf_data(); }
+ void indexOf_QString_QString() { indexOf_impl<QString, QString>(); }
+ void indexOf_QString_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QString_QLatin1String() { indexOf_impl<QString, QLatin1String>(); }
+ void indexOf_QString_QStringRef_data() { indexOf_data(); }
+ void indexOf_QString_QStringRef() { indexOf_impl<QString, QStringRef>(); }
+ void indexOf_QString_QStringView_data() { indexOf_data(); }
+ void indexOf_QString_QStringView() { indexOf_impl<QString, QStringView>(); }
+
+ void indexOf_QLatin1String_QString_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QString() { indexOf_impl<QLatin1String, QString>(); }
+ void indexOf_QLatin1String_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QLatin1String() { indexOf_impl<QLatin1String, QLatin1String>(); }
+ void indexOf_QLatin1String_QStringRef_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QStringRef() { indexOf_impl<QLatin1String, QStringRef>(); }
+ void indexOf_QLatin1String_QStringView_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QStringView() { indexOf_impl<QLatin1String, QStringView>(); }
+
+ void indexOf_QStringRef_QString_data() { indexOf_data(); }
+ void indexOf_QStringRef_QString() { indexOf_impl<QStringRef, QString>(); }
+ void indexOf_QStringRef_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QStringRef_QLatin1String() { indexOf_impl<QStringRef, QLatin1String>(); }
+ void indexOf_QStringRef_QStringRef_data() { indexOf_data(); }
+ void indexOf_QStringRef_QStringRef() { indexOf_impl<QStringRef, QStringRef>(); }
+ void indexOf_QStringRef_QStringView_data() { indexOf_data(); }
+ void indexOf_QStringRef_QStringView() { indexOf_impl<QStringRef, QStringView>(); }
+
+ void indexOf_QStringView_QString_data() { indexOf_data(); }
+ void indexOf_QStringView_QString() { indexOf_impl<QStringView, QString>(); }
+ void indexOf_QStringView_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QStringView_QLatin1String() { indexOf_impl<QStringView, QLatin1String>(); }
+ void indexOf_QStringView_QStringRef_data() { indexOf_data(); }
+ void indexOf_QStringView_QStringRef() { indexOf_impl<QStringView, QStringRef>(); }
+ void indexOf_QStringView_QStringView_data() { indexOf_data(); }
+ void indexOf_QStringView_QStringView() { indexOf_impl<QStringView, QStringView>(); }
+
+private:
+ template <typename Haystack, typename Needle> void contains_impl() const;
+ void contains_data();
+
+private Q_SLOTS:
+ void contains_QString_QString_data() { contains_data(); }
+ void contains_QString_QString() { contains_impl<QString, QString>(); }
+ void contains_QString_QLatin1String_data() { contains_data(); }
+ void contains_QString_QLatin1String() { contains_impl<QString, QLatin1String>(); }
+ void contains_QString_QStringRef_data() { contains_data(); }
+ void contains_QString_QStringRef() { contains_impl<QString, QStringRef>(); }
+ void contains_QString_QStringView_data() { contains_data(); }
+ void contains_QString_QStringView() { contains_impl<QString, QStringView>(); }
+
+ void contains_QLatin1String_QString_data() { contains_data(); }
+ void contains_QLatin1String_QString() { contains_impl<QLatin1String, QString>(); }
+ void contains_QLatin1String_QLatin1String_data() { contains_data(); }
+ void contains_QLatin1String_QLatin1String() { contains_impl<QLatin1String, QLatin1String>(); }
+ void contains_QLatin1String_QStringRef_data() { contains_data(); }
+ void contains_QLatin1String_QStringRef() { contains_impl<QLatin1String, QStringRef>(); }
+ void contains_QLatin1String_QStringView_data() { contains_data(); }
+ void contains_QLatin1String_QStringView() { contains_impl<QLatin1String, QStringView>(); }
+
+ void contains_QStringRef_QString_data() { contains_data(); }
+ void contains_QStringRef_QString() { contains_impl<QStringRef, QString>(); }
+ void contains_QStringRef_QLatin1String_data() { contains_data(); }
+ void contains_QStringRef_QLatin1String() { contains_impl<QStringRef, QLatin1String>(); }
+ void contains_QStringRef_QStringRef_data() { contains_data(); }
+ void contains_QStringRef_QStringRef() { contains_impl<QStringRef, QStringRef>(); }
+ void contains_QStringRef_QStringView_data() { contains_data(); }
+ void contains_QStringRef_QStringView() { contains_impl<QStringRef, QStringView>(); }
+
+ void contains_QStringView_QString_data() { contains_data(); }
+ void contains_QStringView_QString() { contains_impl<QStringView, QString>(); }
+ void contains_QStringView_QLatin1String_data() { contains_data(); }
+ void contains_QStringView_QLatin1String() { contains_impl<QStringView, QLatin1String>(); }
+ void contains_QStringView_QStringRef_data() { contains_data(); }
+ void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); }
+ void contains_QStringView_QStringView_data() { contains_data(); }
+ void contains_QStringView_QStringView() { contains_impl<QStringView, QStringView>(); }
+
+private:
+ template <typename Haystack, typename Needle> void lastIndexOf_impl() const;
+ void lastIndexOf_data();
+
+private Q_SLOTS:
+ void lastIndexOf_QString_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QString() { lastIndexOf_impl<QString, QString>(); }
+ void lastIndexOf_QString_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QLatin1String() { lastIndexOf_impl<QString, QLatin1String>(); }
+ void lastIndexOf_QString_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QStringRef() { lastIndexOf_impl<QString, QStringRef>(); }
+ void lastIndexOf_QString_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QStringView() { lastIndexOf_impl<QString, QStringView>(); }
+
+ void lastIndexOf_QLatin1String_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QString() { lastIndexOf_impl<QLatin1String, QString>(); }
+ void lastIndexOf_QLatin1String_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QLatin1String() { lastIndexOf_impl<QLatin1String, QLatin1String>(); }
+ void lastIndexOf_QLatin1String_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); }
+ void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QStringView() { lastIndexOf_impl<QLatin1String, QStringView>(); }
+
+ void lastIndexOf_QStringRef_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QString() { lastIndexOf_impl<QStringRef, QString>(); }
+ void lastIndexOf_QStringRef_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QLatin1String() { lastIndexOf_impl<QStringRef, QLatin1String>(); }
+ void lastIndexOf_QStringRef_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); }
+ void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QStringView() { lastIndexOf_impl<QStringRef, QStringView>(); }
+
+ void lastIndexOf_QStringView_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QString() { lastIndexOf_impl<QStringView, QString>(); }
+ void lastIndexOf_QStringView_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QLatin1String() { lastIndexOf_impl<QStringView, QLatin1String>(); }
+ void lastIndexOf_QStringView_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); }
+ void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QStringView() { lastIndexOf_impl<QStringView, QStringView>(); }
};
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
@@ -540,6 +692,7 @@ void tst_QStringApiSymmetry::compare_impl() const
}
static QString empty = QLatin1String("");
+static QString null;
// the tests below rely on the fact that these objects' names match their contents:
static QString a = QStringLiteral("a");
static QString A = QStringLiteral("A");
@@ -547,6 +700,14 @@ static QString b = QStringLiteral("b");
static QString B = QStringLiteral("B");
static QString c = QStringLiteral("c");
static QString C = QStringLiteral("C");
+static QString d = QStringLiteral("d");
+static QString D = QStringLiteral("D");
+static QString e = QStringLiteral("e");
+static QString E = QStringLiteral("E");
+static QString f = QStringLiteral("f");
+static QString F = QStringLiteral("F");
+static QString g = QStringLiteral("g");
+static QString G = QStringLiteral("G");
static QString ab = QStringLiteral("ab");
static QString aB = QStringLiteral("aB");
static QString Ab = QStringLiteral("Ab");
@@ -738,6 +899,119 @@ void tst_QStringApiSymmetry::endsWith_impl() const
QCOMPARE(haystack.endsWith(needle, Qt::CaseInsensitive), resultCIS);
}
+void tst_QStringApiSymmetry::split_data(bool rhsHasVariableLength)
+{
+ QTest::addColumn<QStringRef>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QStringRef>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<QStringList>("resultCS");
+ QTest::addColumn<QStringList>("resultCIS");
+
+ if (rhsHasVariableLength) {
+ QTest::addRow("null ~= null$") << QStringRef{} << QLatin1String{}
+ << QStringRef{} << QLatin1String{}
+ << QStringList{{}, {}} << QStringList{{}, {}};
+ QTest::addRow("empty ~= null$") << QStringRef{&empty} << QLatin1String("")
+ << QStringRef{} << QLatin1String{}
+ << QStringList{empty, empty} << QStringList{empty, empty};
+ QTest::addRow("a ~= null$") << QStringRef{&a} << QLatin1String{"a"}
+ << QStringRef{} << QLatin1String{}
+ << QStringList{empty, a, empty} << QStringList{empty, a, empty};
+ QTest::addRow("null ~= empty$") << QStringRef{} << QLatin1String{}
+ << QStringRef{&empty} << QLatin1String{""}
+ << QStringList{{}, {}} << QStringList{{}, {}};
+ QTest::addRow("a ~= empty$") << QStringRef{&a} << QLatin1String{"a"}
+ << QStringRef{&empty} << QLatin1String{""}
+ << QStringList{empty, a, empty} << QStringList{empty, a, empty};
+ QTest::addRow("empty ~= empty$") << QStringRef{&empty} << QLatin1String{""}
+ << QStringRef{&empty} << QLatin1String{""}
+ << QStringList{empty, empty} << QStringList{empty, empty};
+ }
+ QTest::addRow("null ~= a$") << QStringRef{} << QLatin1String{}
+ << QStringRef{&a} << QLatin1String{"a"}
+ << QStringList{{}} << QStringList{{}};
+ QTest::addRow("empty ~= a$") << QStringRef{&empty} << QLatin1String{""}
+ << QStringRef{&a} << QLatin1String{"a"}
+ << QStringList{empty} << QStringList{empty};
+
+#define ROW(h, n, cs, cis) \
+ QTest::addRow("%s ~= %s$", #h, #n) << QStringRef(&h) << QLatin1String(#h) \
+ << QStringRef(&n) << QLatin1String(#n) \
+ << QStringList cs << QStringList cis
+ ROW(a, a, ({empty, empty}), ({empty, empty}));
+ ROW(a, A, {a}, ({empty, empty}));
+ ROW(a, b, {a}, {a});
+
+ if (rhsHasVariableLength)
+ ROW(b, ab, {b}, {b});
+
+ ROW(ab, b, ({a, empty}), ({a, empty}));
+ if (rhsHasVariableLength) {
+ ROW(ab, ab, ({empty, empty}), ({empty, empty}));
+ ROW(ab, aB, {ab}, ({empty, empty}));
+ ROW(ab, Ab, {ab}, ({empty, empty}));
+ }
+ ROW(ab, c, {ab}, {ab});
+
+ if (rhsHasVariableLength)
+ ROW(bc, abc, {bc}, {bc});
+
+ ROW(Abc, c, ({Ab, empty}), ({Ab, empty}));
+#if 0
+ if (rhsHasVariableLength) {
+ ROW(Abc, bc, 1, 1);
+ ROW(Abc, bC, 0, 1);
+ ROW(Abc, Bc, 0, 1);
+ ROW(Abc, BC, 0, 1);
+ ROW(aBC, bc, 0, 1);
+ ROW(aBC, bC, 0, 1);
+ ROW(aBC, Bc, 0, 1);
+ ROW(aBC, BC, 1, 1);
+ }
+#endif
+ ROW(ABC, b, {ABC}, ({A, C}));
+ ROW(ABC, a, {ABC}, ({empty, BC}));
+#undef ROW
+}
+
+static QStringList skipped(const QStringList &sl)
+{
+ QStringList result;
+ result.reserve(sl.size());
+ for (const QString &s : sl) {
+ if (!s.isEmpty())
+ result.push_back(s);
+ }
+ return result;
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::split_impl() const
+{
+ QFETCH(const QStringRef, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QStringRef, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const QStringList, resultCS);
+ QFETCH(const QStringList, resultCIS);
+
+ const QStringList skippedResultCS = skipped(resultCS);
+ const QStringList skippedResultCIS = skipped(resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(haystackU16, haystackL1, haystackU8);
+ const auto needle = make<Needle>(needleU16, needleL1, needleU8);
+
+ QCOMPARE(toQStringList(haystack.split(needle)), resultCS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::KeepEmptyParts, Qt::CaseSensitive)), resultCS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::KeepEmptyParts, Qt::CaseInsensitive)), resultCIS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::SkipEmptyParts, Qt::CaseSensitive)), skippedResultCS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::SkipEmptyParts, Qt::CaseInsensitive)), skippedResultCIS);
+}
+
void tst_QStringApiSymmetry::mid_data()
{
QTest::addColumn<QStringRef>("unicode");
@@ -1216,6 +1490,296 @@ void tst_QStringApiSymmetry::toUcs4_impl()
QCOMPARE(unicode.isEmpty(), ucs4.isEmpty());
}
+void tst_QStringApiSymmetry::indexOf_data()
+{
+ QTest::addColumn<QString>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QString>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<qsizetype>("startpos");
+ QTest::addColumn<qsizetype>("resultCS");
+ QTest::addColumn<qsizetype>("resultCIS");
+
+ constexpr qsizetype zeroPos = 0;
+ constexpr qsizetype minus1Pos = -1;
+
+ QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
+ << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
+ << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
+ << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
+ << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
+ << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
+ << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos;
+
+
+#define ROW(h, n, st, cs, cis) \
+ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
+ << n << QLatin1String(#n) \
+ << qsizetype(st) << qsizetype(cs) << qsizetype(cis)
+
+ ROW(abc, a, 0, 0, 0);
+ ROW(abc, A, 0, -1, 0);
+ ROW(abc, a, 1, -1, -1);
+ ROW(abc, A, 1, -1, -1);
+ ROW(abc, b, 0, 1, 1);
+ ROW(abc, B, 0, -1, 1);
+ ROW(abc, b, 1, 1, 1);
+ ROW(abc, B, 1, -1, 1);
+ ROW(abc, B, 2, -1, -1);
+
+ ROW(ABC, A, 0, 0, 0);
+ ROW(ABC, a, 0, -1, 0);
+ ROW(ABC, A, 1, -1, -1);
+ ROW(ABC, a, 1, -1, -1);
+ ROW(ABC, B, 0, 1, 1);
+ ROW(ABC, b, 0, -1, 1);
+ ROW(ABC, B, 1, 1, 1);
+ ROW(ABC, b, 1, -1, 1);
+ ROW(ABC, B, 2, -1, -1);
+
+ ROW(aBc, bc, 0, -1, 1);
+ ROW(aBc, Bc, 0, 1, 1);
+ ROW(aBc, bC, 0, -1, 1);
+ ROW(aBc, BC, 0, -1, 1);
+
+ ROW(AbC, bc, 0, -1, 1);
+ ROW(AbC, Bc, 0, -1, 1);
+ ROW(AbC, bC, 0, 1, 1);
+ ROW(AbC, BC, 0, -1, 1);
+ ROW(AbC, BC, 1, -1, 1);
+ ROW(AbC, BC, 2, -1, -1);
+#undef ROW
+
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::indexOf_impl() const
+{
+ QFETCH(const QString, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QString, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const qsizetype, startpos);
+ QFETCH(const qsizetype, resultCS);
+ QFETCH(const qsizetype, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
+ const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
+
+ using size_type = typename Haystack::size_type;
+
+ QCOMPARE(haystack.indexOf(needle, startpos), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
+
+ if (needle.size() == 1)
+ {
+ QCOMPARE(haystack.indexOf(needle[0], startpos), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
+ }
+}
+
+static QString ABCDEFGHIEfGEFG = QStringLiteral("ABCDEFGHIEfGEFG");
+static QString EFG = QStringLiteral("EFG");
+static QString efg = QStringLiteral("efg");
+static QString asd = QStringLiteral("asd");
+static QString asdf = QStringLiteral("asdf");
+static QString Z = QStringLiteral("Z");
+
+void tst_QStringApiSymmetry::contains_data()
+{
+ QTest::addColumn<QString>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QString>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<bool>("resultCS");
+ QTest::addColumn<bool>("resultCIS");
+
+ QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
+ << null << QLatin1String() << true << true;
+ QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
+ << null << QLatin1String() << true << true;
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << true << true;
+ QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
+ << empty << QLatin1String("") << true << true;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << true << true;;
+ QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
+ << empty << QLatin1String("") << true << true;
+ QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
+ << a << QLatin1String("a") << false << false;
+ QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
+ << a << QLatin1String("a") << false << false;
+
+#define ROW(h, n, cs, cis) \
+ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
+ << n << QLatin1String(#n) \
+ << cs << cis
+
+ ROW(ABCDEFGHIEfGEFG, A, true, true);
+ ROW(ABCDEFGHIEfGEFG, a, false, true);
+ ROW(ABCDEFGHIEfGEFG, Z, false, false);
+ ROW(ABCDEFGHIEfGEFG, EFG, true, true);
+ ROW(ABCDEFGHIEfGEFG, efg, false, true);
+ ROW(ABCDEFGHIEfGEFG, E, true, true);
+ ROW(ABCDEFGHIEfGEFG, e, false, true);
+#undef ROW
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::contains_impl() const
+{
+ QFETCH(const QString, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QString, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const bool, resultCS);
+ QFETCH(const bool, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
+ const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
+
+ QCOMPARE(haystack.contains(needle), resultCS);
+ QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS);
+ QCOMPARE(haystack.contains(needle, Qt::CaseInsensitive), resultCIS);
+
+ if (needle.size() == 1)
+ {
+ QCOMPARE(haystack.contains(needle[0]), resultCS);
+ QCOMPARE(haystack.contains(needle[0], Qt::CaseSensitive), resultCS);
+ QCOMPARE(haystack.contains(needle[0], Qt::CaseInsensitive), resultCIS);
+ }
+}
+
+void tst_QStringApiSymmetry::lastIndexOf_data()
+{
+ QTest::addColumn<QString>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QString>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<qsizetype>("startpos");
+ QTest::addColumn<qsizetype>("resultCS");
+ QTest::addColumn<qsizetype>("resultCIS");
+
+ constexpr qsizetype zeroPos = 0;
+ constexpr qsizetype minus1Pos = -1;
+
+ QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
+ << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
+ << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << minus1Pos << zeroPos << zeroPos;
+ QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
+ << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << minus1Pos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
+ << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
+ << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
+ << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
+
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << qsizetype(1) << qsizetype(1) << qsizetype(1);
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << qsizetype(1) << qsizetype(1) << qsizetype(1);
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << qsizetype(2) << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << qsizetype(2) << minus1Pos << minus1Pos;
+
+#define ROW(h, n, st, cs, cis) \
+ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
+ << n << QLatin1String(#n) \
+ << qsizetype(st) << qsizetype(cs) << qsizetype(cis)
+
+ ROW(asd, asdf, -1, -1, -1);
+
+ ROW(ABCDEFGHIEfGEFG, G, -1, 14, 14);
+ ROW(ABCDEFGHIEfGEFG, g, -1, -1, 14);
+ ROW(ABCDEFGHIEfGEFG, G, -3, 11, 11);
+ ROW(ABCDEFGHIEfGEFG, g, -3, -1, 11);
+ ROW(ABCDEFGHIEfGEFG, G, -5, 6, 6);
+ ROW(ABCDEFGHIEfGEFG, g, -5, -1, 6);
+ ROW(ABCDEFGHIEfGEFG, G, 14, 14, 14);
+ ROW(ABCDEFGHIEfGEFG, g, 14, -1, 14);
+ ROW(ABCDEFGHIEfGEFG, G, 13, 11, 11);
+ ROW(ABCDEFGHIEfGEFG, g, 13, -1, 11);
+ ROW(ABCDEFGHIEfGEFG, G, 15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, g, 15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, B, 14, 1, 1);
+ ROW(ABCDEFGHIEfGEFG, b, 14, -1, 1);
+ ROW(ABCDEFGHIEfGEFG, B, -1, 1, 1);
+ ROW(ABCDEFGHIEfGEFG, b, -1, -1, 1);
+ ROW(ABCDEFGHIEfGEFG, B, 1, 1, 1);
+ ROW(ABCDEFGHIEfGEFG, b, 1, -1, 1);
+ ROW(ABCDEFGHIEfGEFG, B, 0, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, b, 0, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, A, 0, 0, 0);
+ ROW(ABCDEFGHIEfGEFG, a, 0, -1, 0);
+ ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0);
+ ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0);
+
+ ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12);
+ ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12);
+ ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9);
+#undef ROW
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::lastIndexOf_impl() const
+{
+ QFETCH(const QString, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QString, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const qsizetype, startpos);
+ QFETCH(const qsizetype, resultCS);
+ QFETCH(const qsizetype, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
+ const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
+
+ using size_type = typename Haystack::size_type;
+
+ QCOMPARE(haystack.lastIndexOf(needle, startpos), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
+
+ if (needle.size() == 1)
+ {
+ QCOMPARE(haystack.lastIndexOf(needle[0], startpos), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
+ }
+}
+
QTEST_APPLESS_MAIN(tst_QStringApiSymmetry)
#include "tst_qstringapisymmetry.moc"
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder.pro
index d73d541502..d73d541502 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder.pro
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder.pro
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/qstringbuilder1.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/qstringbuilder1.pro
index d9cdad1bf5..d9cdad1bf5 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/qstringbuilder1.pro
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/qstringbuilder1.pro
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp
index ac7f439248..ac7f439248 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp
index 2d320748f2..2d320748f2 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/tst_qstringbuilder1.cpp
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/qstringbuilder2.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/qstringbuilder2.pro
index e134c5d934..e134c5d934 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/qstringbuilder2.pro
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/qstringbuilder2.pro
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp
index 669990c9bc..669990c9bc 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder2/tst_qstringbuilder2.cpp
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/qstringbuilder3.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/qstringbuilder3.pro
index 29607551c3..29607551c3 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/qstringbuilder3.pro
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/qstringbuilder3.pro
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp
index 397e3326bf..397e3326bf 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder3/tst_qstringbuilder3.cpp
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/qstringbuilder4.pro b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/qstringbuilder4.pro
index e55848e4bd..e55848e4bd 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/qstringbuilder4.pro
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/qstringbuilder4.pro
diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp
index 05ce334c82..05ce334c82 100644
--- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder4/tst_qstringbuilder4.cpp
diff --git a/tests/auto/corelib/tools/qstringiterator/qstringiterator.pro b/tests/auto/corelib/text/qstringiterator/qstringiterator.pro
index 3a1678b5f3..3a1678b5f3 100644
--- a/tests/auto/corelib/tools/qstringiterator/qstringiterator.pro
+++ b/tests/auto/corelib/text/qstringiterator/qstringiterator.pro
diff --git a/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp b/tests/auto/corelib/text/qstringiterator/tst_qstringiterator.cpp
index 7d5504c22c..7d5504c22c 100644
--- a/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp
+++ b/tests/auto/corelib/text/qstringiterator/tst_qstringiterator.cpp
diff --git a/tests/auto/corelib/tools/qstringlist/.gitignore b/tests/auto/corelib/text/qstringlist/.gitignore
index 3e0cdc952f..3e0cdc952f 100644
--- a/tests/auto/corelib/tools/qstringlist/.gitignore
+++ b/tests/auto/corelib/text/qstringlist/.gitignore
diff --git a/tests/auto/corelib/tools/qstringlist/qstringlist.pro b/tests/auto/corelib/text/qstringlist/qstringlist.pro
index a87257decb..a87257decb 100644
--- a/tests/auto/corelib/tools/qstringlist/qstringlist.pro
+++ b/tests/auto/corelib/text/qstringlist/qstringlist.pro
diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/text/qstringlist/tst_qstringlist.cpp
index 42bdf62a93..66d4744454 100644
--- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
+++ b/tests/auto/corelib/text/qstringlist/tst_qstringlist.cpp
@@ -30,13 +30,17 @@
#include <qregexp.h>
#include <qregularexpression.h>
#include <qstringlist.h>
+#include <qvector.h>
#include <locale.h>
+#include <algorithm>
+
class tst_QStringList : public QObject
{
Q_OBJECT
private slots:
+ void constructors();
void sort();
void filter();
void replaceInStrings();
@@ -59,13 +63,44 @@ private slots:
void joinChar() const;
void joinChar_data() const;
-#ifdef Q_COMPILER_INITIALIZER_LISTS
void initializeList() const;
-#endif
};
extern const char email[];
+void tst_QStringList::constructors()
+{
+ {
+ QStringList list;
+ QVERIFY(list.isEmpty());
+ QCOMPARE(list.size(), 0);
+ QVERIFY(list == QStringList());
+ }
+ {
+ QString str = "abc";
+ QStringList list(str);
+ QVERIFY(!list.isEmpty());
+ QCOMPARE(list.size(), 1);
+ QCOMPARE(list.at(0), str);
+ }
+ {
+ QStringList list{ "a", "b", "c" };
+ QVERIFY(!list.isEmpty());
+ QCOMPARE(list.size(), 3);
+ QCOMPARE(list.at(0), "a");
+ QCOMPARE(list.at(1), "b");
+ QCOMPARE(list.at(2), "c");
+ }
+ {
+ const QVector<QString> reference{ "a", "b", "c" };
+ QCOMPARE(reference.size(), 3);
+
+ QStringList list(reference.cbegin(), reference.cend());
+ QCOMPARE(list.size(), reference.size());
+ QVERIFY(std::equal(list.cbegin(), list.cend(), reference.cbegin()));
+ }
+}
+
void tst_QStringList::indexOf_regExp()
{
QStringList list;
@@ -224,6 +259,12 @@ void tst_QStringList::filter()
list5 = list5.filter( QRegularExpression("[i]ll") );
list6 << "Bill Gates" << "Bill Clinton";
QCOMPARE( list5, list6 );
+
+ QStringList list7, list8;
+ list7 << "Bill Gates" << "Joe Blow" << "Bill Clinton";
+ list7 = list7.filter( QStringView(QString("Bill")) );
+ list8 << "Bill Gates" << "Bill Clinton";
+ QCOMPARE( list7, list8 );
}
void tst_QStringList::sort()
@@ -281,6 +322,16 @@ void tst_QStringList::replaceInStrings()
list10 << "Bill Clinton" << "Bill Gates";
list9.replaceInStrings( QRegularExpression("^(.*), (.*)$"), "\\2 \\1" );
QCOMPARE( list9, list10 );
+
+ QStringList list11, list12, list13, list14;
+ list11 << "alpha" << "beta" << "gamma" << "epsilon";
+ list12 << "alpha" << "beta" << "gamma" << "epsilon";
+ list13 << "alpha" << "beta" << "gamma" << "epsilon";
+ list11.replaceInStrings( QStringView(QString("a")), QStringView(QString("o")) );
+ list12.replaceInStrings( QStringView(QString("a")), QString("o") );
+ list13.replaceInStrings( QString("a"), QStringView(QString("o")) );
+ list14 << "olpho" << "beto" << "gommo" << "epsilon";
+ QCOMPARE( list11, list12 );
}
void tst_QStringList::contains()
@@ -392,6 +443,7 @@ void tst_QStringList::join() const
QCOMPARE(input.join(separator), expectedResult);
QCOMPARE(input.join(QLatin1String(separator.toLatin1())), expectedResult);
+ QCOMPARE(input.join(QStringView(separator)), expectedResult);
}
void tst_QStringList::join_data() const
@@ -482,8 +534,6 @@ void tst_QStringList::joinEmptiness() const
QVERIFY(string.isNull());
}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-// C++0x support is required
void tst_QStringList::initializeList() const
{
@@ -491,7 +541,6 @@ void tst_QStringList::initializeList() const
QCOMPARE(v1, (QStringList() << "hello" << "world" << "plop"));
QCOMPARE(v1, (QStringList{"hello","world","plop"}));
}
-#endif
QTEST_APPLESS_MAIN(tst_QStringList)
#include "tst_qstringlist.moc"
diff --git a/tests/auto/corelib/tools/qstringmatcher/.gitignore b/tests/auto/corelib/text/qstringmatcher/.gitignore
index 3c7caf8490..3c7caf8490 100644
--- a/tests/auto/corelib/tools/qstringmatcher/.gitignore
+++ b/tests/auto/corelib/text/qstringmatcher/.gitignore
diff --git a/tests/auto/corelib/tools/qstringmatcher/qstringmatcher.pro b/tests/auto/corelib/text/qstringmatcher/qstringmatcher.pro
index e34928776f..e34928776f 100644
--- a/tests/auto/corelib/tools/qstringmatcher/qstringmatcher.pro
+++ b/tests/auto/corelib/text/qstringmatcher/qstringmatcher.pro
diff --git a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp b/tests/auto/corelib/text/qstringmatcher/tst_qstringmatcher.cpp
index 8a55f54449..2d577bb0ab 100644
--- a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp
+++ b/tests/auto/corelib/text/qstringmatcher/tst_qstringmatcher.cpp
@@ -100,6 +100,11 @@ void tst_QStringMatcher::indexIn()
matcher.setPattern(needle);
QCOMPARE(matcher.indexIn(haystack, from), indexIn);
+
+ const auto needleSV = QStringView(needle);
+ QStringMatcher matcherSV(needleSV);
+
+ QCOMPARE(matcherSV.indexIn(QStringView(haystack), from), indexIn);
}
void tst_QStringMatcher::setCaseSensitivity_data()
@@ -128,6 +133,7 @@ void tst_QStringMatcher::setCaseSensitivity()
matcher.setCaseSensitivity(static_cast<Qt::CaseSensitivity> (cs));
QCOMPARE(matcher.indexIn(haystack, from), indexIn);
+ QCOMPARE(matcher.indexIn(QStringView(haystack), from), indexIn);
}
void tst_QStringMatcher::assignOperator()
diff --git a/tests/auto/corelib/tools/qstringref/qstringref.pro b/tests/auto/corelib/text/qstringref/qstringref.pro
index 04f3ba6a92..04f3ba6a92 100644
--- a/tests/auto/corelib/tools/qstringref/qstringref.pro
+++ b/tests/auto/corelib/text/qstringref/qstringref.pro
diff --git a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp b/tests/auto/corelib/text/qstringref/tst_qstringref.cpp
index 581e9152e6..6f01947131 100644
--- a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp
+++ b/tests/auto/corelib/text/qstringref/tst_qstringref.cpp
@@ -596,7 +596,10 @@ void tst_QStringRef::startsWith()
QVERIFY(!ref.startsWith("C"));
QVERIFY(!ref.startsWith("ABCDEF"));
QVERIFY(ref.startsWith(""));
+ QVERIFY(ref.startsWith(QString()));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.startsWith(QString::null));
+#endif
QVERIFY(ref.startsWith('A'));
QVERIFY(ref.startsWith(QLatin1Char('A')));
QVERIFY(ref.startsWith(QChar('A')));
@@ -623,7 +626,10 @@ void tst_QStringRef::startsWith()
QVERIFY(!ref.startsWith("c", Qt::CaseInsensitive));
QVERIFY(!ref.startsWith("abcdef", Qt::CaseInsensitive));
QVERIFY(ref.startsWith("", Qt::CaseInsensitive));
+ QVERIFY(ref.startsWith(QString(), Qt::CaseInsensitive));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.startsWith(QString::null, Qt::CaseInsensitive));
+#endif
QVERIFY(ref.startsWith('a', Qt::CaseInsensitive));
QVERIFY(ref.startsWith('A', Qt::CaseInsensitive));
QVERIFY(ref.startsWith(QLatin1Char('a'), Qt::CaseInsensitive));
@@ -656,7 +662,10 @@ void tst_QStringRef::startsWith()
const QString a = QString::fromLatin1("");
CREATE_REF(a);
QVERIFY(ref.startsWith(""));
+ QVERIFY(ref.startsWith(QString()));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.startsWith(QString::null));
+#endif
QVERIFY(!ref.startsWith("ABC"));
QVERIFY(ref.startsWith(QLatin1String("")));
@@ -670,7 +679,10 @@ void tst_QStringRef::startsWith()
{
const QStringRef ref;
QVERIFY(!ref.startsWith(""));
+ QVERIFY(ref.startsWith(QString()));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.startsWith(QString::null));
+#endif
QVERIFY(!ref.startsWith("ABC"));
QVERIFY(!ref.startsWith(QLatin1String("")));
@@ -693,7 +705,10 @@ void tst_QStringRef::endsWith()
QVERIFY(!ref.endsWith("C"));
QVERIFY(!ref.endsWith("ABCDEF"));
QVERIFY(ref.endsWith(""));
+ QVERIFY(ref.endsWith(QString()));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.endsWith(QString::null));
+#endif
QVERIFY(ref.endsWith('B'));
QVERIFY(ref.endsWith(QLatin1Char('B')));
QVERIFY(ref.endsWith(QChar('B')));
@@ -720,7 +735,10 @@ void tst_QStringRef::endsWith()
QVERIFY(!ref.endsWith("c", Qt::CaseInsensitive));
QVERIFY(!ref.endsWith("abcdef", Qt::CaseInsensitive));
QVERIFY(ref.endsWith("", Qt::CaseInsensitive));
+ QVERIFY(ref.endsWith(QString(), Qt::CaseInsensitive));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.endsWith(QString::null, Qt::CaseInsensitive));
+#endif
QVERIFY(ref.endsWith('b', Qt::CaseInsensitive));
QVERIFY(ref.endsWith('B', Qt::CaseInsensitive));
QVERIFY(ref.endsWith(QLatin1Char('b'), Qt::CaseInsensitive));
@@ -754,7 +772,10 @@ void tst_QStringRef::endsWith()
const QString a = QString::fromLatin1("");
CREATE_REF(a);
QVERIFY(ref.endsWith(""));
+ QVERIFY(ref.endsWith(QString()));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.endsWith(QString::null));
+#endif
QVERIFY(!ref.endsWith("ABC"));
QVERIFY(!ref.endsWith(QLatin1Char(0)));
QVERIFY(!ref.endsWith(QLatin1Char('x')));
@@ -768,7 +789,10 @@ void tst_QStringRef::endsWith()
{
QStringRef ref;
QVERIFY(!ref.endsWith(""));
+ QVERIFY(ref.endsWith(QString()));
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(ref.endsWith(QString::null));
+#endif
QVERIFY(!ref.endsWith("ABC"));
QVERIFY(!ref.endsWith(QLatin1String("")));
diff --git a/tests/auto/corelib/tools/qstringview/.gitignore b/tests/auto/corelib/text/qstringview/.gitignore
index 5f757d448a..5f757d448a 100644
--- a/tests/auto/corelib/tools/qstringview/.gitignore
+++ b/tests/auto/corelib/text/qstringview/.gitignore
diff --git a/tests/auto/corelib/tools/qstringview/qstringview.pro b/tests/auto/corelib/text/qstringview/qstringview.pro
index e0e9973c91..e0e9973c91 100644
--- a/tests/auto/corelib/tools/qstringview/qstringview.pro
+++ b/tests/auto/corelib/text/qstringview/qstringview.pro
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
index e800a0d794..47ce9a6f63 100644
--- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
@@ -134,6 +134,8 @@ private Q_SLOTS:
void literals() const;
void at() const;
+ void arg() const;
+
void fromQString() const;
void fromQStringRef() const;
@@ -249,7 +251,7 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv2.empty());
}
{
- constexpr QStringView sv = QStringViewLiteral("");
+ constexpr QStringView sv = u"";
Q_STATIC_ASSERT(sv.size() == 0);
Q_STATIC_ASSERT(!sv.isNull());
Q_STATIC_ASSERT(sv.empty());
@@ -261,7 +263,7 @@ void tst_QStringView::constExpr() const
Q_STATIC_ASSERT(sv2.empty());
}
{
- constexpr QStringView sv = QStringViewLiteral("Hello");
+ constexpr QStringView sv = u"Hello";
Q_STATIC_ASSERT(sv.size() == 5);
Q_STATIC_ASSERT(!sv.empty());
Q_STATIC_ASSERT(!sv.isEmpty());
@@ -425,6 +427,47 @@ void tst_QStringView::at() const
QCOMPARE(sv.at(4), QChar('o')); QCOMPARE(sv[4], QChar('o'));
}
+void tst_QStringView::arg() const
+{
+#define CHECK1(pattern, arg1, expected) \
+ do { \
+ auto p = QStringView(u"" pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1)), expected); \
+ QCOMPARE(p.arg(u"" arg1), expected); \
+ QCOMPARE(p.arg(QStringLiteral(arg1)), expected); \
+ QCOMPARE(p.arg(QString(QLatin1String(arg1))), expected); \
+ } while (false) \
+ /*end*/
+#define CHECK2(pattern, arg1, arg2, expected) \
+ do { \
+ auto p = QStringView(u"" pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1), QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(u"" arg1, QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(QLatin1String(arg1), u"" arg2), expected); \
+ QCOMPARE(p.arg(u"" arg1, u"" arg2), expected); \
+ } while (false) \
+ /*end*/
+
+ CHECK1("", "World", "");
+ CHECK1("%1", "World", "World");
+ CHECK1("!%1?", "World", "!World?");
+ CHECK1("%1%1", "World", "WorldWorld");
+ CHECK1("%1%2", "World", "World%2");
+ CHECK1("%2%1", "World", "%2World");
+
+ CHECK2("", "Hello", "World", "");
+ CHECK2("%1", "Hello", "World", "Hello");
+ CHECK2("!%1, %2?", "Hello", "World", "!Hello, World?");
+ CHECK2("%1%1", "Hello", "World", "HelloHello");
+ CHECK2("%1%2", "Hello", "World", "HelloWorld");
+ CHECK2("%2%1", "Hello", "World", "WorldHello");
+
+#undef CHECK2
+#undef CHECK1
+
+ QCOMPARE(QStringView(u" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C ");
+}
+
void tst_QStringView::fromQString() const
{
QString null;
@@ -619,9 +662,9 @@ 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");
+ const QStringView aa = u"aa";
+ const QStringView upperAa = u"AA";
+ const QStringView bb = u"bb";
QVERIFY(aa == aa);
QVERIFY(aa != bb);
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/.gitignore b/tests/auto/corelib/text/qtextboundaryfinder/.gitignore
index bd0df58233..bd0df58233 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/.gitignore
+++ b/tests/auto/corelib/text/qtextboundaryfinder/.gitignore
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/GraphemeBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/GraphemeBreakTest.txt
index d7d8f90de0..d7d8f90de0 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/data/GraphemeBreakTest.txt
+++ b/tests/auto/corelib/text/qtextboundaryfinder/data/GraphemeBreakTest.txt
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/LineBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/LineBreakTest.txt
index 6715446aba..6715446aba 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/data/LineBreakTest.txt
+++ b/tests/auto/corelib/text/qtextboundaryfinder/data/LineBreakTest.txt
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/SentenceBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/SentenceBreakTest.txt
index 2985b84cf8..2985b84cf8 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/data/SentenceBreakTest.txt
+++ b/tests/auto/corelib/text/qtextboundaryfinder/data/SentenceBreakTest.txt
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/data/WordBreakTest.txt b/tests/auto/corelib/text/qtextboundaryfinder/data/WordBreakTest.txt
index 63761026ce..63761026ce 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/data/WordBreakTest.txt
+++ b/tests/auto/corelib/text/qtextboundaryfinder/data/WordBreakTest.txt
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro b/tests/auto/corelib/text/qtextboundaryfinder/qtextboundaryfinder.pro
index 3c9f03842d..3c9f03842d 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro
+++ b/tests/auto/corelib/text/qtextboundaryfinder/qtextboundaryfinder.pro
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/testdata.qrc b/tests/auto/corelib/text/qtextboundaryfinder/testdata.qrc
index 0cc4ccaa57..0cc4ccaa57 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/testdata.qrc
+++ b/tests/auto/corelib/text/qtextboundaryfinder/testdata.qrc
diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp b/tests/auto/corelib/text/qtextboundaryfinder/tst_qtextboundaryfinder.cpp
index 5701335b4a..a46011ff6c 100644
--- a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp
+++ b/tests/auto/corelib/text/qtextboundaryfinder/tst_qtextboundaryfinder.cpp
@@ -192,7 +192,7 @@ static void doTestData(const QString &testString, const QList<int> &expectedBrea
// test toPreviousBoundary()
{
QList<int> expectedBreakPositionsRev = expectedBreakPositions;
- std::sort(expectedBreakPositionsRev.begin(), expectedBreakPositionsRev.end(), qGreater<int>());
+ std::sort(expectedBreakPositionsRev.begin(), expectedBreakPositionsRev.end(), std::greater<int>());
QList<int> actualBreakPositions;
boundaryFinder.toEnd();
diff --git a/tests/auto/corelib/text/text.pro b/tests/auto/corelib/text/text.pro
new file mode 100644
index 0000000000..09d58bd74c
--- /dev/null
+++ b/tests/auto/corelib/text/text.pro
@@ -0,0 +1,23 @@
+TEMPLATE = subdirs
+
+SUBDIRS = \
+ qbytearray \
+ qbytearraylist \
+ qbytearraymatcher \
+ qbytedatabuffer \
+ qchar \
+ qcollator \
+ qlatin1string \
+ qlocale \
+ qregexp \
+ qregularexpression \
+ qstring \
+ qstring_no_cast_from_bytearray \
+ qstringapisymmetry \
+ qstringbuilder \
+ qstringiterator \
+ qstringlist \
+ qstringmatcher \
+ qstringref \
+ qstringview \
+ qtextboundaryfinder
diff --git a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
index cc197cabba..bef491d5f0 100644
--- a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
+++ b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
@@ -31,6 +31,7 @@
#include <QAtomicInt>
#include <QCoreApplication>
+#include <QElapsedTimer>
#include <limits.h>
@@ -104,12 +105,12 @@ static void warningFreeHelperTemplate()
assemblyMarker<1>(&i);
// the loads sometimes generate no assembly output
- i.load();
+ i.loadRelaxed();
assemblyMarker<11>(&i);
i.loadAcquire();
assemblyMarker<12>(&i);
- i.store(newValue);
+ i.storeRelaxed(newValue);
assemblyMarker<21>(&i);
i.storeRelease(newValue);
assemblyMarker<22>(&i);
@@ -281,9 +282,9 @@ void tst_QAtomicInt::constructor()
{
QFETCH(int, value);
QAtomicInt atomic1(value);
- QCOMPARE(atomic1.load(), value);
+ QCOMPARE(atomic1.loadRelaxed(), value);
QAtomicInt atomic2 = value;
- QCOMPARE(atomic2.load(), value);
+ QCOMPARE(atomic2.loadRelaxed(), value);
}
void tst_QAtomicInt::copy_constructor_data()
@@ -293,16 +294,16 @@ void tst_QAtomicInt::copy_constructor()
{
QFETCH(int, value);
QAtomicInt atomic1(value);
- QCOMPARE(atomic1.load(), value);
+ QCOMPARE(atomic1.loadRelaxed(), value);
QAtomicInt atomic2(atomic1);
- QCOMPARE(atomic2.load(), value);
+ QCOMPARE(atomic2.loadRelaxed(), value);
QAtomicInt atomic3 = atomic1;
- QCOMPARE(atomic3.load(), value);
+ QCOMPARE(atomic3.loadRelaxed(), value);
QAtomicInt atomic4(atomic2);
- QCOMPARE(atomic4.load(), value);
+ QCOMPARE(atomic4.loadRelaxed(), value);
QAtomicInt atomic5 = atomic2;
- QCOMPARE(atomic5.load(), value);
+ QCOMPARE(atomic5.loadRelaxed(), value);
}
void tst_QAtomicInt::assignment_operator_data()
@@ -326,13 +327,13 @@ void tst_QAtomicInt::assignment_operator()
{
QAtomicInt atomic1 = value;
atomic1 = newval;
- QCOMPARE(atomic1.load(), newval);
+ QCOMPARE(atomic1.loadRelaxed(), newval);
atomic1 = value;
- QCOMPARE(atomic1.load(), value);
+ QCOMPARE(atomic1.loadRelaxed(), value);
QAtomicInt atomic2 = newval;
atomic1 = atomic2;
- QCOMPARE(atomic1.load(), atomic2.load());
+ QCOMPARE(atomic1.loadRelaxed(), atomic2.loadRelaxed());
}
}
@@ -400,7 +401,7 @@ void tst_QAtomicInt::ref()
QFETCH(int, value);
QAtomicInt x = value;
QTEST(x.ref() ? 1 : 0, "result");
- QTEST(x.load(), "expected");
+ QTEST(x.loadRelaxed(), "expected");
}
void tst_QAtomicInt::deref_data()
@@ -419,7 +420,7 @@ void tst_QAtomicInt::deref()
QFETCH(int, value);
QAtomicInt x = value;
QTEST(x.deref() ? 1 : 0, "result");
- QTEST(x.load(), "expected");
+ QTEST(x.loadRelaxed(), "expected");
}
void tst_QAtomicInt::isTestAndSetNative()
@@ -635,25 +636,25 @@ void tst_QAtomicInt::fetchAndStore()
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreRelaxed(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreAcquire(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreRelease(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreOrdered(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
}
@@ -772,28 +773,28 @@ void tst_QAtomicInt::fetchAndAdd()
QAtomicInt atomic = value1;
result = atomic.fetchAndAddRelaxed(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
{
QAtomicInt atomic = value1;
result = atomic.fetchAndAddAcquire(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
{
QAtomicInt atomic = value1;
result = atomic.fetchAndAddRelease(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
{
QAtomicInt atomic = value1;
result = atomic.fetchAndAddOrdered(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
}
@@ -851,14 +852,14 @@ void tst_QAtomicInt::operators()
void tst_QAtomicInt::testAndSet_loop()
{
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
int iterations = 10000000;
QAtomicInt val=0;
for (int i = 0; i < iterations; ++i) {
- int v = val.load();
+ int v = val.loadRelaxed();
QVERIFY(val.testAndSetRelaxed(v, v+1));
if ((i % 1000) == 999) {
if (stopWatch.elapsed() > 60 * 1000) {
@@ -881,7 +882,7 @@ void tst_QAtomicInt::fetchAndAdd_loop()
QAtomicInt val=0;
for (int i = 0; i < iterations; ++i) {
const int prev = val.fetchAndAddRelaxed(1);
- QCOMPARE(prev, val.load() -1);
+ QCOMPARE(prev, val.loadRelaxed() -1);
}
}
@@ -919,7 +920,7 @@ void tst_QAtomicInt::fetchAndAdd_threadedLoop()
t1.wait();
t2.wait();
- QCOMPARE(val.load(), 0);
+ QCOMPARE(val.loadRelaxed(), 0);
}
QTEST_MAIN(tst_QAtomicInt)
diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
index 32e5b8ee56..bfe2a60088 100644
--- a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
+++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
@@ -270,13 +270,13 @@ void tst_QAtomicIntegerXX::constructor()
QFETCH(LargeInt, value);
QAtomicInteger<T> atomic(value);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QAtomicInteger<T> atomic2 = value;
- QCOMPARE(atomic2.load(), T(value));
+ QCOMPARE(atomic2.loadRelaxed(), T(value));
- QVERIFY(atomic.load() >= std::numeric_limits<T>::min());
- QVERIFY(atomic.load() <= std::numeric_limits<T>::max());
+ QVERIFY(atomic.loadRelaxed() >= std::numeric_limits<T>::min());
+ QVERIFY(atomic.loadRelaxed() <= std::numeric_limits<T>::max());
}
void tst_QAtomicIntegerXX::copy()
@@ -285,17 +285,17 @@ void tst_QAtomicIntegerXX::copy()
QAtomicInteger<T> atomic(value);
QAtomicInteger<T> copy(atomic);
- QCOMPARE(copy.load(), atomic.load());
+ QCOMPARE(copy.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy2 = atomic;
- QCOMPARE(copy2.load(), atomic.load());
+ QCOMPARE(copy2.loadRelaxed(), atomic.loadRelaxed());
// move
- QAtomicInteger<T> copy3(qMove(copy));
- QCOMPARE(copy3.load(), atomic.load());
+ QAtomicInteger<T> copy3(std::move(copy));
+ QCOMPARE(copy3.loadRelaxed(), atomic.loadRelaxed());
- QAtomicInteger<T> copy4 = qMove(copy2);
- QCOMPARE(copy4.load(), atomic.load());
+ QAtomicInteger<T> copy4 = std::move(copy2);
+ QCOMPARE(copy4.loadRelaxed(), atomic.loadRelaxed());
}
void tst_QAtomicIntegerXX::assign()
@@ -305,24 +305,24 @@ void tst_QAtomicIntegerXX::assign()
QAtomicInteger<T> atomic(value);
QAtomicInteger<T> copy;
copy = atomic;
- QCOMPARE(copy.load(), atomic.load());
+ QCOMPARE(copy.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy2;
copy2 = atomic; // operator=(const QAtomicInteger &)
- QCOMPARE(copy2.load(), atomic.load());
+ QCOMPARE(copy2.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy2bis;
- copy2bis = atomic.load(); // operator=(T)
- QCOMPARE(copy2bis.load(), atomic.load());
+ copy2bis = atomic.loadRelaxed(); // operator=(T)
+ QCOMPARE(copy2bis.loadRelaxed(), atomic.loadRelaxed());
// move
QAtomicInteger<T> copy3;
- copy3 = qMove(copy);
- QCOMPARE(copy3.load(), atomic.load());
+ copy3 = std::move(copy);
+ QCOMPARE(copy3.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy4;
- copy4 = qMove(copy2);
- QCOMPARE(copy4.load(), atomic.load());
+ copy4 = std::move(copy2);
+ QCOMPARE(copy4.loadRelaxed(), atomic.loadRelaxed());
}
void tst_QAtomicIntegerXX::operatorInteger()
@@ -331,7 +331,7 @@ void tst_QAtomicIntegerXX::operatorInteger()
QAtomicInteger<T> atomic(value);
T val2 = atomic;
- QCOMPARE(val2, atomic.load());
+ QCOMPARE(val2, atomic.loadRelaxed());
QCOMPARE(val2, T(value));
}
@@ -346,7 +346,7 @@ void tst_QAtomicIntegerXX::loadAcquireStoreRelease()
QCOMPARE(atomic.loadAcquire(), T(~value));
atomic.storeRelease(value);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
}
void tst_QAtomicIntegerXX::refDeref()
@@ -364,16 +364,16 @@ void tst_QAtomicIntegerXX::refDeref()
QAtomicInteger<T> atomic(value);
if (!needToPreventOverflow) {
QCOMPARE(atomic.ref(), (nextValue != 0));
- QCOMPARE(atomic.load(), nextValue);
+ QCOMPARE(atomic.loadRelaxed(), nextValue);
QCOMPARE(atomic.deref(), (value != 0));
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.deref(), (prevValue != 0));
- QCOMPARE(atomic.load(), prevValue);
+ QCOMPARE(atomic.loadRelaxed(), prevValue);
QCOMPARE(atomic.ref(), (value != 0));
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(++atomic, nextValue);
@@ -392,7 +392,7 @@ void tst_QAtomicIntegerXX::refDeref()
QCOMPARE(atomic--, T(value));
QCOMPARE(atomic++, prevValue);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
}
void tst_QAtomicIntegerXX::testAndSet()
@@ -402,16 +402,16 @@ void tst_QAtomicIntegerXX::testAndSet()
QAtomicInteger<T> atomic(value);
QVERIFY(atomic.testAndSetRelaxed(value, newValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetRelaxed(value, newValue));
QVERIFY(atomic.testAndSetRelaxed(newValue, value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetAcquire(value, newValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetAcquire(value, newValue));
QVERIFY(atomic.testAndSetAcquire(newValue, value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetRelease(value, newValue));
QCOMPARE(atomic.loadAcquire(), newValue);
@@ -434,18 +434,18 @@ void tst_QAtomicIntegerXX::testAndSet3()
QAtomicInteger<T> atomic(value);
QVERIFY(atomic.testAndSetRelaxed(value, newValue, oldValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetRelaxed(value, newValue, oldValue));
QCOMPARE(oldValue, newValue);
QVERIFY(atomic.testAndSetRelaxed(newValue, value, oldValue));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetAcquire(value, newValue, oldValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetAcquire(value, newValue, oldValue));
QCOMPARE(oldValue, newValue);
QVERIFY(atomic.testAndSetAcquire(newValue, value, oldValue));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetRelease(value, newValue, oldValue));
QCOMPARE(atomic.loadAcquire(), newValue);
@@ -469,14 +469,14 @@ void tst_QAtomicIntegerXX::fetchAndStore()
QAtomicInteger<T> atomic(value);
QCOMPARE(atomic.fetchAndStoreRelaxed(newValue), T(value));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QCOMPARE(atomic.fetchAndStoreRelaxed(value), newValue);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndStoreAcquire(newValue), T(value));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QCOMPARE(atomic.fetchAndStoreAcquire(value), newValue);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndStoreRelease(newValue), T(value));
QCOMPARE(atomic.loadAcquire(), newValue);
@@ -509,29 +509,29 @@ void tst_QAtomicIntegerXX::fetchAndAdd()
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddAcquire(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndAddAcquire(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddAcquire(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndAddAcquire(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddRelease(parcel1), T(value));
@@ -590,29 +590,29 @@ void tst_QAtomicIntegerXX::fetchAndSub()
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubAcquire(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndSubAcquire(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubAcquire(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndSubAcquire(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubRelease(parcel1), T(value));
@@ -662,32 +662,32 @@ void tst_QAtomicIntegerXX::fetchAndOr()
QCOMPARE(atomic.fetchAndOrRelaxed(zero), T(value));
QCOMPARE(atomic.fetchAndOrRelaxed(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrRelaxed(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndOrAcquire(zero), T(value));
QCOMPARE(atomic.fetchAndOrAcquire(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrAcquire(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndOrRelease(zero), T(value));
QCOMPARE(atomic.fetchAndOrRelease(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrRelease(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndOrOrdered(zero), T(value));
QCOMPARE(atomic.fetchAndOrOrdered(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrOrdered(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic |= zero, T(value));
QCOMPARE(atomic |= one, T(value | 1));
QCOMPARE(atomic |= minusOne, minusOne);
@@ -703,37 +703,37 @@ void tst_QAtomicIntegerXX::fetchAndAnd()
T minusOne = T(~0);
QCOMPARE(atomic.fetchAndAndRelaxed(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndRelaxed(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndRelaxed(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndAndAcquire(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndAcquire(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndAcquire(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndAndRelease(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndRelease(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndRelease(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndAndOrdered(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndOrdered(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndOrdered(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic &= minusOne, T(value));
QCOMPARE(atomic &= f, T(value & 0xf));
QCOMPARE(atomic &= zero, zero);
@@ -749,48 +749,48 @@ void tst_QAtomicIntegerXX::fetchAndXor()
T minusOne = T(~0);
QCOMPARE(atomic.fetchAndXorRelaxed(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelaxed(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorRelaxed(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelaxed(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorRelaxed(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorAcquire(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorAcquire(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorAcquire(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorAcquire(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorAcquire(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelease(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelease(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorRelease(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelease(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorRelease(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorOrdered(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorOrdered(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorOrdered(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorOrdered(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorOrdered(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic ^= zero, T(value));
QCOMPARE(atomic ^= pattern, T(value ^ pattern));
diff --git a/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp b/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
index 0200473cae..a699cf6202 100644
--- a/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
+++ b/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
@@ -75,7 +75,7 @@ void tst_QAtomicPointer::warningFreeHelper()
QBasicAtomicPointer<WFHC> p = Q_BASIC_ATOMIC_INITIALIZER(0);
- p.load()->bar();
+ p.loadRelaxed()->bar();
WFHC *expectedValue = 0;
WFHC *newValue = 0;
@@ -119,15 +119,15 @@ void tst_QAtomicPointer::constructor()
{
void *one = this;
QAtomicPointer<void> atomic1 = one;
- QCOMPARE(atomic1.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), one);
void *two = &one;
QAtomicPointer<void> atomic2 = two;
- QCOMPARE(atomic2.load(), two);
+ QCOMPARE(atomic2.loadRelaxed(), two);
void *three = &two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic3.loadRelaxed(), three);
}
void tst_QAtomicPointer::copy_constructor()
@@ -135,20 +135,20 @@ void tst_QAtomicPointer::copy_constructor()
void *one = this;
QAtomicPointer<void> atomic1 = one;
QAtomicPointer<void> atomic1_copy = atomic1;
- QCOMPARE(atomic1_copy.load(), one);
- QCOMPARE(atomic1_copy.load(), atomic1.load());
+ QCOMPARE(atomic1_copy.loadRelaxed(), one);
+ QCOMPARE(atomic1_copy.loadRelaxed(), atomic1.loadRelaxed());
void *two = &one;
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic2_copy = atomic2;
- QCOMPARE(atomic2_copy.load(), two);
- QCOMPARE(atomic2_copy.load(), atomic2.load());
+ QCOMPARE(atomic2_copy.loadRelaxed(), two);
+ QCOMPARE(atomic2_copy.loadRelaxed(), atomic2.loadRelaxed());
void *three = &two;
QAtomicPointer<void> atomic3 = three;
QAtomicPointer<void> atomic3_copy = atomic3;
- QCOMPARE(atomic3_copy.load(), three);
- QCOMPARE(atomic3_copy.load(), atomic3.load());
+ QCOMPARE(atomic3_copy.loadRelaxed(), three);
+ QCOMPARE(atomic3_copy.loadRelaxed(), atomic3.loadRelaxed());
}
void tst_QAtomicPointer::assignment_operator()
@@ -161,17 +161,17 @@ void tst_QAtomicPointer::assignment_operator()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
atomic1 = two;
atomic2 = three;
atomic3 = one;
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
void tst_QAtomicPointer::isTestAndSetNative()
@@ -234,17 +234,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetRelaxed(one, two));
QVERIFY(atomic2.testAndSetRelaxed(two, three));
QVERIFY(atomic3.testAndSetRelaxed(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -252,17 +252,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetAcquire(one, two));
QVERIFY(atomic2.testAndSetAcquire(two, three));
QVERIFY(atomic3.testAndSetAcquire(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -270,17 +270,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetRelease(one, two));
QVERIFY(atomic2.testAndSetRelease(two, three));
QVERIFY(atomic3.testAndSetRelease(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -288,17 +288,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetOrdered(one, two));
QVERIFY(atomic2.testAndSetOrdered(two, three));
QVERIFY(atomic3.testAndSetOrdered(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
}
@@ -362,17 +362,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreRelaxed(two), one);
QCOMPARE(atomic2.fetchAndStoreRelaxed(three), two);
QCOMPARE(atomic3.fetchAndStoreRelaxed(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -380,17 +380,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreAcquire(two), one);
QCOMPARE(atomic2.fetchAndStoreAcquire(three), two);
QCOMPARE(atomic3.fetchAndStoreAcquire(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -398,17 +398,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreRelease(two), one);
QCOMPARE(atomic2.fetchAndStoreRelease(three), two);
QCOMPARE(atomic3.fetchAndStoreRelease(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -416,17 +416,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreOrdered(two), one);
QCOMPARE(atomic2.fetchAndStoreOrdered(three), two);
QCOMPARE(atomic3.fetchAndStoreOrdered(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
}
@@ -530,60 +530,60 @@ void tst_QAtomicPointer::fetchAndAdd()
// cast to void* in order to avoid QCOMPARE to compare string content of the char*
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelaxed(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelaxed(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddRelaxed(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddRelaxed(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddRelaxed(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddRelaxed(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
{
QAtomicPointer<char> pointer1 = pc;
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddAcquire(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddAcquire(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddAcquire(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddAcquire(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddAcquire(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddAcquire(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
{
QAtomicPointer<char> pointer1 = pc;
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelease(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelease(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddRelease(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddRelease(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddRelease(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddRelease(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
{
QAtomicPointer<char> pointer1 = pc;
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddOrdered(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddOrdered(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddOrdered(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddOrdered(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddOrdered(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddOrdered(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
}
@@ -598,34 +598,34 @@ template <typename T> void constAndVolatile_helper()
QAtomicPointer<T> atomic2 = two;
QAtomicPointer<T> atomic3 = three;
- QVERIFY(atomic1.load() == one);
- QVERIFY(atomic2.load() == two);
- QVERIFY(atomic3.load() == three);
+ QVERIFY(atomic1.loadRelaxed() == one);
+ QVERIFY(atomic2.loadRelaxed() == two);
+ QVERIFY(atomic3.loadRelaxed() == three);
QVERIFY(atomic1.fetchAndStoreRelaxed(two) == one);
QVERIFY(atomic2.fetchAndStoreRelaxed(three) == two);
QVERIFY(atomic3.fetchAndStoreRelaxed(one) == three);
- QVERIFY(atomic1.load() == two);
- QVERIFY(atomic2.load() == three);
- QVERIFY(atomic3.load() == one);
+ QVERIFY(atomic1.loadRelaxed() == two);
+ QVERIFY(atomic2.loadRelaxed() == three);
+ QVERIFY(atomic3.loadRelaxed() == one);
}
{
QAtomicPointer<T> atomic1 = one;
QAtomicPointer<T> atomic2 = two;
QAtomicPointer<T> atomic3 = three;
- QVERIFY(atomic1.load() == one);
- QVERIFY(atomic2.load() == two);
- QVERIFY(atomic3.load() == three);
+ QVERIFY(atomic1.loadRelaxed() == one);
+ QVERIFY(atomic2.loadRelaxed() == two);
+ QVERIFY(atomic3.loadRelaxed() == three);
QVERIFY(atomic1.testAndSetRelaxed(one, two));
QVERIFY(atomic2.testAndSetRelaxed(two, three));
QVERIFY(atomic3.testAndSetRelaxed(three, one));
- QVERIFY(atomic1.load() == two);
- QVERIFY(atomic2.load() == three);
- QVERIFY(atomic3.load() == one);
+ QVERIFY(atomic1.loadRelaxed() == two);
+ QVERIFY(atomic2.loadRelaxed() == three);
+ QVERIFY(atomic3.loadRelaxed() == one);
}
}
diff --git a/tests/auto/corelib/thread/qfuture/qfuture.pro b/tests/auto/corelib/thread/qfuture/qfuture.pro
index b1667760d6..1f21130af7 100644
--- a/tests/auto/corelib/thread/qfuture/qfuture.pro
+++ b/tests/auto/corelib/thread/qfuture/qfuture.pro
@@ -3,3 +3,4 @@ TARGET = tst_qfuture
QT = core core-private testlib
SOURCES = tst_qfuture.cpp
DEFINES += QT_STRICT_ITERATORS
+DEFINES -= QT_NO_JAVA_STYLE_ITERATORS
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index b8c82c2ea0..a42454124e 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -49,6 +49,24 @@ struct ResultStoreInt : QtPrivate::ResultStoreBase
~ResultStoreInt() { clear<int>(); }
};
+class LambdaThread : public QThread
+{
+public:
+ LambdaThread(std::function<void ()> fn)
+ :m_fn(fn)
+ {
+
+ }
+
+ void run() override
+ {
+ m_fn();
+ }
+
+private:
+ std::function<void ()> m_fn;
+};
+
class tst_QFuture: public QObject
{
Q_OBJECT
@@ -67,6 +85,7 @@ private slots:
void resultsAsList();
void implicitConversions();
void iterators();
+ void iteratorsThread();
void pause();
void throttling();
void voidConversions();
@@ -1144,6 +1163,54 @@ void tst_QFuture::iterators()
}
}
}
+void tst_QFuture::iteratorsThread()
+{
+ const int expectedResultCount = 10;
+ const int delay = 10;
+ QFutureInterface<int> futureInterface;
+
+ // Create result producer thread. The results are
+ // produced with delays in order to make the consumer
+ // wait.
+ QSemaphore sem;
+ LambdaThread thread = {[=, &futureInterface, &sem](){
+ for (int i = 1; i <= expectedResultCount; i += 2) {
+ int result = i;
+ futureInterface.reportResult(&result);
+ result = i + 1;
+ futureInterface.reportResult(&result);
+ }
+
+ sem.acquire(2);
+ futureInterface.reportFinished();
+ }};
+
+ futureInterface.reportStarted();
+ QFuture<int> future = futureInterface.future();
+
+ // Iterate over results while the thread is producing them.
+ thread.start();
+ int resultCount = 0;
+ int resultSum = 0;
+ for (int result : future) {
+ sem.release();
+ ++resultCount;
+ resultSum += result;
+ }
+ thread.wait();
+
+ QCOMPARE(resultCount, expectedResultCount);
+ QCOMPARE(resultSum, expectedResultCount * (expectedResultCount + 1) / 2);
+
+ // Reverse iterate
+ resultSum = 0;
+ QFutureIterator<int> it(future);
+ it.toBack();
+ while (it.hasPrevious())
+ resultSum += it.previous();
+
+ QCOMPARE(resultSum, expectedResultCount * (expectedResultCount + 1) / 2);
+}
class SignalSlotObject : public QObject
{
diff --git a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
index b2ef516b4e..a322a1c11d 100644
--- a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
+++ b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QCoreApplication>
#include <QDebug>
+#include <QElapsedTimer>
#include <QtTest/QtTest>
#include <QtConcurrent>
@@ -878,7 +879,7 @@ void tst_QFutureWatcher::incrementalFilterResults()
void tst_QFutureWatcher::qfutureSynchronizer()
{
int taskCount = 1000;
- QTime t;
+ QElapsedTimer t;
t.start();
{
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
index 7fb9a861d7..749aa45916 100644
--- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
@@ -69,7 +69,8 @@ private slots:
static const int iterations = 100;
QAtomicInt lockCount(0);
-QMutex normalMutex, recursiveMutex(QMutex::Recursive);
+QMutex normalMutex;
+QRecursiveMutex recursiveMutex;
QSemaphore testsTurn;
QSemaphore threadsTurn;
@@ -993,9 +994,9 @@ public:
QMutex mutex;
QWaitCondition cond;
- QMutex &test_mutex;
+ QRecursiveMutex &test_mutex;
- inline rmutex_Thread(QMutex &m) : test_mutex(m) { }
+ inline rmutex_Thread(QRecursiveMutex &m) : test_mutex(m) { }
void run()
{
@@ -1024,7 +1025,7 @@ void tst_QMutex::lock_unlock_locked_tryLock()
QMutex mutex;
mutex_Thread thread(mutex);
- QMutex rmutex(QMutex::Recursive);
+ QRecursiveMutex rmutex;
rmutex_Thread rthread(rmutex);
for (int i = 0; i < iterations; ++i) {
@@ -1132,7 +1133,7 @@ void tst_QMutex::stressTest()
for (int i = 1; i < threadCount; ++i)
QVERIFY(threads[i].wait(10000));
QCOMPARE(StressTestThread::errorCount, 0);
- qDebug("locked %d times", int(StressTestThread::lockCount.load()));
+ qDebug("locked %d times", int(StressTestThread::lockCount.loadRelaxed()));
}
class TryLockRaceThread : public QThread
@@ -1286,28 +1287,28 @@ public:
quint64 i = 0;
while (t.elapsed() < one_minute) {
i++;
- uint nb = (i * 9 + lockCount.load() * 13) % threadCount;
+ uint nb = (i * 9 + lockCount.loadRelaxed() * 13) % threadCount;
QMutexLocker locker(&mutex[nb]);
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
if (sentinel[nb].fetchAndAddRelaxed(5)) errorCount.ref();
if (!sentinel[nb].testAndSetRelaxed(5, 0)) errorCount.ref();
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
lockCount.ref();
- nb = (nb * 17 + i * 5 + lockCount.load() * 3) % threadCount;
+ nb = (nb * 17 + i * 5 + lockCount.loadRelaxed() * 3) % threadCount;
if (mutex[nb].tryLock()) {
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
if (sentinel[nb].fetchAndAddRelaxed(16)) errorCount.ref();
if (!sentinel[nb].testAndSetRelaxed(16, 0)) errorCount.ref();
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
lockCount.ref();
mutex[nb].unlock();
}
- nb = (nb * 15 + i * 47 + lockCount.load() * 31) % threadCount;
+ nb = (nb * 15 + i * 47 + lockCount.loadRelaxed() * 31) % threadCount;
if (mutex[nb].tryLock(2)) {
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
if (sentinel[nb].fetchAndAddRelaxed(53)) errorCount.ref();
if (!sentinel[nb].testAndSetRelaxed(53, 0)) errorCount.ref();
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
lockCount.ref();
mutex[nb].unlock();
}
@@ -1327,8 +1328,8 @@ void tst_QMutex::moreStress()
QVERIFY(threads[0].wait(one_minute + 10000));
for (int i = 1; i < threadCount; ++i)
QVERIFY(threads[i].wait(10000));
- qDebug("locked %d times", MoreStressTestThread::lockCount.load());
- QCOMPARE(MoreStressTestThread::errorCount.load(), 0);
+ qDebug("locked %d times", MoreStressTestThread::lockCount.loadRelaxed());
+ QCOMPARE(MoreStressTestThread::errorCount.loadRelaxed(), 0);
}
diff --git a/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp b/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp
index 67db5d1458..c83e186ca7 100644
--- a/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp
+++ b/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp
@@ -36,7 +36,7 @@
class tst_QMutexLockerThread : public QThread
{
public:
- QMutex mutex;
+ QRecursiveMutex mutex;
QSemaphore semaphore, testSemaphore;
void waitForTest()
@@ -45,10 +45,6 @@ public:
testSemaphore.acquire();
}
- tst_QMutexLockerThread()
- : mutex(QMutex::Recursive)
- {
- }
};
class tst_QMutexLocker : public QObject
diff --git a/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp b/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
index 8e97229752..47bae585a1 100644
--- a/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
+++ b/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <qcoreapplication.h>
#include <qreadwritelock.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qthread.h>
#include <qwaitcondition.h>
@@ -237,7 +238,7 @@ void tst_QReadWriteLock::tryReadLock()
testsTurn.release();
threadsTurn.acquire();
- QTime timer;
+ QElapsedTimer timer;
timer.start();
QVERIFY(!readWriteLock.tryLockForRead(1000));
QVERIFY(timer.elapsed() >= 1000);
@@ -457,7 +458,7 @@ public:
void run()
{
testRwlock.lockForWrite();
- while(release.load()==false) {
+ while (release.loadRelaxed() == false) {
RWTESTSLEEP
}
testRwlock.unlock();
@@ -477,7 +478,7 @@ public:
void run()
{
testRwlock.lockForRead();
- while(release.load()==false) {
+ while (release.loadRelaxed() == false) {
RWTESTSLEEP
}
testRwlock.unlock();
@@ -500,7 +501,7 @@ public:
int holdTime;
int waitTime;
bool print;
- QTime t;
+ QElapsedTimer t;
inline ReadLockLoopThread(QReadWriteLock &l, int runTime, int holdTime=0, int waitTime=0, bool print=false)
:testRwlock(l)
,runTime(runTime)
@@ -536,7 +537,7 @@ public:
int holdTime;
int waitTime;
bool print;
- QTime t;
+ QElapsedTimer t;
inline WriteLockLoopThread(QReadWriteLock &l, int runTime, int holdTime=0, int waitTime=0, bool print=false)
:testRwlock(l)
,runTime(runTime)
@@ -574,7 +575,7 @@ public:
int runTime;
int waitTime;
int maxval;
- QTime t;
+ QElapsedTimer t;
inline WriteLockCountThread(QReadWriteLock &l, int runTime, int waitTime, int maxval)
:testRwlock(l)
,runTime(runTime)
@@ -615,7 +616,7 @@ public:
QReadWriteLock &testRwlock;
int runTime;
int waitTime;
- QTime t;
+ QElapsedTimer t;
inline ReadLockCountThread(QReadWriteLock &l, int runTime, int waitTime)
:testRwlock(l)
,runTime(runTime)
@@ -676,7 +677,7 @@ void tst_QReadWriteLock::multipleReadersBlockRelease()
{
QReadWriteLock testLock;
- release.store(false);
+ release.storeRelaxed(false);
threadDone=false;
ReadLockReleasableThread rlt1(testLock);
ReadLockReleasableThread rlt2(testLock);
@@ -686,7 +687,7 @@ void tst_QReadWriteLock::multipleReadersBlockRelease()
WriteLockThread wlt(testLock);
wlt.start();
sleep(1);
- release.store(true);
+ release.storeRelaxed(true);
wlt.wait();
rlt1.wait();
rlt2.wait();
@@ -873,7 +874,7 @@ void tst_QReadWriteLock::deleteOnUnlock()
DeleteOnUnlockThread thread2(&lock, &startup, &waitMutex);
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() < 4000) {
lock = new QReadWriteLock();
@@ -899,7 +900,7 @@ void tst_QReadWriteLock::uncontendedLocks()
uint count=0;
int millisecs=1000;
{
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() <millisecs)
{
@@ -908,7 +909,7 @@ void tst_QReadWriteLock::uncontendedLocks()
}
{
QReadWriteLock rwlock;
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() <millisecs)
{
@@ -919,7 +920,7 @@ void tst_QReadWriteLock::uncontendedLocks()
}
{
QReadWriteLock rwlock;
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() <millisecs)
{
diff --git a/tests/auto/corelib/thread/qsemaphore/BLACKLIST b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
index 0786f50417..d7af5c420b 100644
--- a/tests/auto/corelib/thread/qsemaphore/BLACKLIST
+++ b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
@@ -1,3 +1,5 @@
+[tryAcquireWithTimeout]
+osx
[tryAcquireWithTimeout:0.2s]
windows
osx-10.12
diff --git a/tests/auto/corelib/thread/qthread/BLACKLIST b/tests/auto/corelib/thread/qthread/BLACKLIST
index d75249454f..c683154da1 100644
--- a/tests/auto/corelib/thread/qthread/BLACKLIST
+++ b/tests/auto/corelib/thread/qthread/BLACKLIST
@@ -1,2 +1,5 @@
[wait3_slowDestructor]
-windows
+windows-10
+[sleep]
+windows-7sp1
+
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index d73dcc1b6d..7be2f48758 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -29,7 +29,7 @@
#include <QtTest/QtTest>
#include <qcoreapplication.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qthread.h>
#include <qtimer.h>
@@ -110,6 +110,12 @@ private slots:
enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
+template <class Int>
+static QString msgElapsed(Int elapsed)
+{
+ return QString::fromLatin1("elapsed: %1").arg(elapsed);
+}
+
class SignalRecorder : public QObject
{
Q_OBJECT
@@ -121,7 +127,7 @@ public:
{ }
bool wasActivated()
- { return activationCount.load() > 0; }
+ { return activationCount.loadRelaxed() > 0; }
public slots:
void slot();
@@ -244,8 +250,8 @@ public:
QMutexLocker locker(&mutex);
elapsed = 0;
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
switch (sleepType) {
case Second:
sleep(interval);
@@ -257,7 +263,7 @@ public:
usleep(interval);
break;
}
- elapsed = time.elapsed();
+ elapsed = timer.elapsed();
cond.wakeOne();
}
@@ -591,7 +597,7 @@ void tst_QThread::sleep()
thread.interval = 2;
thread.start();
QVERIFY(thread.wait(five_minutes));
- QVERIFY(thread.elapsed >= 2000);
+ QVERIFY2(thread.elapsed >= 2000, qPrintable(msgElapsed(thread.elapsed)));
}
void tst_QThread::msleep()
@@ -601,11 +607,10 @@ void tst_QThread::msleep()
thread.interval = 120;
thread.start();
QVERIFY(thread.wait(five_minutes));
-#if defined (Q_OS_WIN)
- // Since the resolution of QTime is so coarse...
- QVERIFY(thread.elapsed >= 100);
+#if defined (Q_OS_WIN) // May no longer be needed
+ QVERIFY2(thread.elapsed >= 100, qPrintable(msgElapsed(thread.elapsed)));
#else
- QVERIFY(thread.elapsed >= 120);
+ QVERIFY2(thread.elapsed >= 120, qPrintable(msgElapsed(thread.elapsed)));
#endif
}
@@ -616,11 +621,10 @@ void tst_QThread::usleep()
thread.interval = 120000;
thread.start();
QVERIFY(thread.wait(five_minutes));
-#if defined (Q_OS_WIN)
- // Since the resolution of QTime is so coarse...
- QVERIFY(thread.elapsed >= 100);
+#if defined (Q_OS_WIN) // May no longer be needed
+ QVERIFY2(thread.elapsed >= 100, qPrintable(msgElapsed(thread.elapsed)));
#else
- QVERIFY(thread.elapsed >= 120);
+ QVERIFY2(thread.elapsed >= 120, qPrintable(msgElapsed(thread.elapsed)));
#endif
}
@@ -902,7 +906,7 @@ void tst_QThread::adoptMultipleThreads()
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(recorder.activationCount.load(), numThreads);
+ QCOMPARE(recorder.activationCount.loadRelaxed(), numThreads);
}
void tst_QThread::adoptMultipleThreadsOverlap()
@@ -939,7 +943,7 @@ void tst_QThread::adoptMultipleThreadsOverlap()
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(recorder.activationCount.load(), numThreads);
+ QCOMPARE(recorder.activationCount.loadRelaxed(), numThreads);
}
// Disconnects on WinCE
@@ -948,9 +952,9 @@ void tst_QThread::stressTest()
if (EmulationDetector::isRunningArmOnX86())
QSKIP("Qemu uses too much memory for each thread. Test would run out of memory.");
- QTime t;
- t.start();
- while (t.elapsed() < one_minute) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < one_minute) {
Current_Thread t;
t.start();
t.wait(one_minute);
@@ -1067,13 +1071,15 @@ void tst_QThread::wait2()
timer.start();
QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
qint64 elapsed = timer.elapsed(); // On Windows, we sometimes get (WaitTime - 9).
- QVERIFY2(elapsed >= Waiting_Thread::WaitTime - 10, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
+ QVERIFY2(elapsed >= Waiting_Thread::WaitTime - 10,
+ qPrintable(msgElapsed(elapsed)));
timer.start();
thread.cond1.wakeOne();
QVERIFY(thread.wait(/*Waiting_Thread::WaitTime * 1.4*/));
elapsed = timer.elapsed();
- QVERIFY2(elapsed - Waiting_Thread::WaitTime >= -1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
+ QVERIFY2(elapsed - Waiting_Thread::WaitTime >= -1,
+ qPrintable(msgElapsed(elapsed)));
}
@@ -1210,7 +1216,7 @@ class DummyEventDispatcher : public QAbstractEventDispatcher {
public:
DummyEventDispatcher() : QAbstractEventDispatcher() {}
bool processEvents(QEventLoop::ProcessEventsFlags) {
- visited.store(true);
+ visited.storeRelaxed(true);
emit awake();
QCoreApplication::sendPostedEvents();
return false;
@@ -1272,7 +1278,7 @@ void tst_QThread::customEventDispatcher()
QMetaObject::invokeMethod(&obj, "visit", Qt::QueuedConnection);
loop.exec();
// test that the ED has really been used
- QVERIFY(ed->visited.load());
+ QVERIFY(ed->visited.loadRelaxed());
QPointer<DummyEventDispatcher> weak_ed(ed);
QVERIFY(!weak_ed.isNull());
@@ -1330,6 +1336,8 @@ void tst_QThread::quitLock()
QCOMPARE(job->thread(), &thread);
loop.exec();
QVERIFY(exitThreadCalled);
+
+ delete job;
}
void tst_QThread::create()
diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
index d27884197a..3826fa148e 100644
--- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
+++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
@@ -32,7 +32,7 @@
#include "qmutex.h"
-Q_GLOBAL_STATIC_WITH_ARGS(QMutex, onceInitializationMutex, (QMutex::Recursive))
+Q_GLOBAL_STATIC(QRecursiveMutex, onceInitializationMutex)
enum QOnceExtra {
MustRunCode = 0x01,
diff --git a/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
index a9af182ed8..710288af9e 100644
--- a/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
+++ b/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
@@ -56,7 +56,7 @@ class SingletonObject: public QObject
Q_OBJECT
public:
static int runCount;
- SingletonObject() { val.store(42); ++runCount; }
+ SingletonObject() { val.storeRelaxed(42); ++runCount; }
~SingletonObject() { }
QBasicAtomicInt val;
@@ -112,7 +112,7 @@ void tst_QThreadOnce::sameThread()
QCOMPARE(controlVariable, 1);
static QSingleton<SingletonObject> s;
- QTEST((int)s->val.load(), "expectedValue");
+ QTEST((int)s->val.loadRelaxed(), "expectedValue");
s->val.ref();
QCOMPARE(SingletonObject::runCount, 1);
@@ -134,7 +134,7 @@ void tst_QThreadOnce::multipleThreads()
QCOMPARE(controlVariable, 0); // nothing must have set them yet
SingletonObject::runCount = 0;
- IncrementThread::runCount.store(0);
+ IncrementThread::runCount.storeRelaxed(0);
// wait for all of them to be ready
sem2.acquire(NumberOfThreads);
@@ -145,7 +145,7 @@ void tst_QThreadOnce::multipleThreads()
delete parent;
QCOMPARE(controlVariable, 1);
- QCOMPARE((int)IncrementThread::runCount.load(), NumberOfThreads);
+ QCOMPARE((int)IncrementThread::runCount.loadRelaxed(), NumberOfThreads);
QCOMPARE(SingletonObject::runCount, 1);
}
diff --git a/tests/auto/corelib/thread/qthreadpool/BLACKLIST b/tests/auto/corelib/thread/qthreadpool/BLACKLIST
index fc49731687..b8c1f3bf3f 100644
--- a/tests/auto/corelib/thread/qthreadpool/BLACKLIST
+++ b/tests/auto/corelib/thread/qthreadpool/BLACKLIST
@@ -1,3 +1,4 @@
[expiryTimeoutRace]
-osx
-linux
+opensuse-leap
+ubuntu
+rhel
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
index 838431cd5a..60e8d8cba2 100644
--- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
+++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
@@ -27,7 +27,7 @@
**
****************************************************************************/
#include <QtTest/QtTest>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qthreadpool.h>
#include <qstring.h>
#include <qmutex.h>
@@ -92,7 +92,9 @@ private slots:
void priorityStart();
void waitForDone();
void clear();
+#if QT_DEPRECATED_SINCE(5, 9)
void cancel();
+#endif
void tryTake();
void waitForDoneTimeout();
void destroyingWaitsForTasksToFinish();
@@ -220,16 +222,16 @@ class TestTask : public QRunnable
public:
void run()
{
- ran.store(true);
+ ran.storeRelaxed(true);
}
};
void tst_QThreadPool::runTask()
{
QThreadPool manager;
- ran.store(false);
+ ran.storeRelaxed(false);
manager.start(new TestTask());
- QTRY_VERIFY(ran.load());
+ QTRY_VERIFY(ran.loadRelaxed());
}
/*
@@ -237,9 +239,9 @@ void tst_QThreadPool::runTask()
*/
void tst_QThreadPool::singleton()
{
- ran.store(false);
+ ran.storeRelaxed(false);
QThreadPool::globalInstance()->start(new TestTask());
- QTRY_VERIFY(ran.load());
+ QTRY_VERIFY(ran.loadRelaxed());
}
QAtomicInt *value = 0;
@@ -344,7 +346,7 @@ void tst_QThreadPool::expiryTimeout()
// run the task
threadPool.start(&task);
QVERIFY(task.semaphore.tryAcquire(1, 10000));
- QCOMPARE(task.runCount.load(), 1);
+ QCOMPARE(task.runCount.loadRelaxed(), 1);
QVERIFY(!task.thread->wait(100));
// thread should expire
QThread *firstThread = task.thread;
@@ -353,7 +355,7 @@ void tst_QThreadPool::expiryTimeout()
// run task again, thread should be restarted
threadPool.start(&task);
QVERIFY(task.semaphore.tryAcquire(1, 10000));
- QCOMPARE(task.runCount.load(), 2);
+ QCOMPARE(task.runCount.loadRelaxed(), 2);
QVERIFY(!task.thread->wait(100));
// thread should expire again
QVERIFY(task.thread->wait(10000));
@@ -382,7 +384,7 @@ void tst_QThreadPool::expiryTimeoutRace() // QTBUG-3786
QThread::msleep(50); // exactly the same as the expiry timeout
}
QVERIFY(task.semaphore.tryAcquire(numTasks, 10000));
- QCOMPARE(task.runCount.load(), numTasks);
+ QCOMPARE(task.runCount.loadRelaxed(), numTasks);
QVERIFY(threadPool.waitForDone(2000));
}
@@ -685,7 +687,7 @@ void tst_QThreadPool::reserveAndStart() // QTBUG-21051
QCOMPARE(threadpool->activeThreadCount(), 2);
task->waitForStarted.acquire();
task->waitBeforeDone.release();
- QTRY_COMPARE(task->count.load(), 1);
+ QTRY_COMPARE(task->count.loadRelaxed(), 1);
QTRY_COMPARE(threadpool->activeThreadCount(), 1);
// now the thread is waiting, but tryStart() will fail since activeThreadCount() >= maxThreadCount()
@@ -698,7 +700,7 @@ void tst_QThreadPool::reserveAndStart() // QTBUG-21051
QTRY_COMPARE(threadpool->activeThreadCount(), 2);
task->waitForStarted.acquire();
task->waitBeforeDone.release();
- QTRY_COMPARE(task->count.load(), 2);
+ QTRY_COMPARE(task->count.loadRelaxed(), 2);
QTRY_COMPARE(threadpool->activeThreadCount(), 1);
threadpool->releaseThread();
@@ -721,14 +723,14 @@ class CountingRunnable : public QRunnable
void tst_QThreadPool::start()
{
const int runs = 1000;
- count.store(0);
+ count.storeRelaxed(0);
{
QThreadPool threadPool;
for (int i = 0; i< runs; ++i) {
threadPool.start(new CountingRunnable());
}
}
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
}
void tst_QThreadPool::tryStart()
@@ -747,7 +749,7 @@ void tst_QThreadPool::tryStart()
}
};
- count.store(0);
+ count.storeRelaxed(0);
WaitingTask task;
QThreadPool threadPool;
@@ -757,7 +759,7 @@ void tst_QThreadPool::tryStart()
QVERIFY(!threadPool.tryStart(&task));
task.semaphore.release(threadPool.maxThreadCount());
threadPool.waitForDone();
- QCOMPARE(count.load(), threadPool.maxThreadCount());
+ QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount());
}
QMutex mutex;
@@ -775,7 +777,7 @@ void tst_QThreadPool::tryStartPeakThreadCount()
{
QMutexLocker lock(&mutex);
activeThreads.ref();
- peakActiveThreads.store(qMax(peakActiveThreads.load(), activeThreads.load()));
+ peakActiveThreads.storeRelaxed(qMax(peakActiveThreads.loadRelaxed(), activeThreads.loadRelaxed()));
}
QTest::qWait(100);
@@ -793,13 +795,13 @@ void tst_QThreadPool::tryStartPeakThreadCount()
if (threadPool.tryStart(&task) == false)
QTest::qWait(10);
}
- QCOMPARE(peakActiveThreads.load(), QThread::idealThreadCount());
+ QCOMPARE(peakActiveThreads.loadRelaxed(), QThread::idealThreadCount());
for (int i = 0; i < 20; ++i) {
if (threadPool.tryStart(&task) == false)
QTest::qWait(10);
}
- QCOMPARE(peakActiveThreads.load(), QThread::idealThreadCount());
+ QCOMPARE(peakActiveThreads.loadRelaxed(), QThread::idealThreadCount());
}
void tst_QThreadPool::tryStartCount()
@@ -877,27 +879,27 @@ void tst_QThreadPool::priorityStart()
sem.release();
QVERIFY(threadPool.waitForDone());
- QCOMPARE(firstStarted.load(), expected);
+ QCOMPARE(firstStarted.loadRelaxed(), expected);
}
void tst_QThreadPool::waitForDone()
{
- QTime total, pass;
+ QElapsedTimer total, pass;
total.start();
QThreadPool threadPool;
while (total.elapsed() < 10000) {
int runs;
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
pass.restart();
while (pass.elapsed() < 100) {
threadPool.start(new CountingRunnable());
++runs;
}
threadPool.waitForDone();
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
pass.restart();
while (pass.elapsed() < 100) {
threadPool.start(new CountingRunnable());
@@ -905,7 +907,7 @@ void tst_QThreadPool::waitForDone()
runs += 2;
}
threadPool.waitForDone();
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
}
}
@@ -953,16 +955,17 @@ void tst_QThreadPool::clear()
QThreadPool threadPool;
threadPool.setMaxThreadCount(10);
int runs = 2 * threadPool.maxThreadCount();
- count.store(0);
+ count.storeRelaxed(0);
for (int i = 0; i <= runs; i++) {
threadPool.start(new BlockingRunnable(sem));
}
threadPool.clear();
sem.release(threadPool.maxThreadCount());
threadPool.waitForDone();
- QCOMPARE(count.load(), threadPool.maxThreadCount());
+ QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount());
}
+#if QT_DEPRECATED_SINCE(5, 9)
void tst_QThreadPool::cancel()
{
QSemaphore sem(0);
@@ -1008,7 +1011,7 @@ void tst_QThreadPool::cancel()
// and cause an early return:
const QSemaphoreReleaser semReleaser(sem, runs);
- count.store(0);
+ count.storeRelaxed(0);
QAtomicInt dtorCounter = 0;
QAtomicInt runCounter = 0;
for (int i = 0; i < runs; i++) {
@@ -1025,15 +1028,16 @@ void tst_QThreadPool::cancel()
}
runnables[0]->dummy = 0; //valgrind will catch this if cancel() is crazy enough to delete currently running jobs
runnables[runs-1]->dummy = 0;
- QCOMPARE(dtorCounter.load(), runs - threadPool.maxThreadCount() - 1);
+ QCOMPARE(dtorCounter.loadRelaxed(), runs - threadPool.maxThreadCount() - 1);
sem.release(threadPool.maxThreadCount());
threadPool.waitForDone();
- QCOMPARE(runCounter.load(), threadPool.maxThreadCount());
- QCOMPARE(count.load(), threadPool.maxThreadCount());
- QCOMPARE(dtorCounter.load(), runs - 2);
+ QCOMPARE(runCounter.loadRelaxed(), threadPool.maxThreadCount());
+ QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount());
+ QCOMPARE(dtorCounter.loadRelaxed(), runs - 2);
delete runnables[0]; //if the pool deletes them then we'll get double-free crash
delete runnables[runs-1];
}
+#endif
void tst_QThreadPool::tryTake()
{
@@ -1080,7 +1084,7 @@ void tst_QThreadPool::tryTake()
// and cause an early return:
const QSemaphoreReleaser semReleaser(sem, Runs);
- count.store(0);
+ count.storeRelaxed(0);
QAtomicInt dtorCounter = 0;
QAtomicInt runCounter = 0;
for (int i = 0; i < Runs; i++) {
@@ -1102,23 +1106,23 @@ void tst_QThreadPool::tryTake()
}
runnables[0]->dummy = 0; // valgrind will catch this if tryTake() is crazy enough to delete currently running jobs
- QCOMPARE(dtorCounter.load(), int(Runs - MaxThreadCount));
+ QCOMPARE(dtorCounter.loadRelaxed(), int(Runs - MaxThreadCount));
sem.release(MaxThreadCount);
threadPool.waitForDone();
- QCOMPARE(runCounter.load(), int(MaxThreadCount));
- QCOMPARE(count.load(), int(MaxThreadCount));
- QCOMPARE(dtorCounter.load(), int(Runs - 1));
+ QCOMPARE(runCounter.loadRelaxed(), int(MaxThreadCount));
+ QCOMPARE(count.loadRelaxed(), int(MaxThreadCount));
+ QCOMPARE(dtorCounter.loadRelaxed(), int(Runs - 1));
delete runnables[0]; // if the pool deletes them then we'll get double-free crash
}
void tst_QThreadPool::destroyingWaitsForTasksToFinish()
{
- QTime total, pass;
+ QElapsedTimer total, pass;
total.start();
while (total.elapsed() < 10000) {
int runs;
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
{
QThreadPool threadPool;
pass.restart();
@@ -1127,9 +1131,9 @@ void tst_QThreadPool::destroyingWaitsForTasksToFinish()
++runs;
}
}
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
{
QThreadPool threadPool;
pass.restart();
@@ -1139,7 +1143,7 @@ void tst_QThreadPool::destroyingWaitsForTasksToFinish()
runs += 2;
}
}
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
}
}
@@ -1204,7 +1208,7 @@ void tst_QThreadPool::stressTest()
}
};
- QTime total;
+ QElapsedTimer total;
total.start();
while (total.elapsed() < 30000) {
Task t;
@@ -1322,6 +1326,7 @@ void tst_QThreadPool::waitForDoneAfterTake()
QRunnable *runnable = createTask(emptyFunct);
manager.start(runnable);
QVERIFY(manager.tryTake(runnable));
+ delete runnable;
}
// Add another runnable that will not be removed
diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
index ef5d3452d5..3538d90803 100644
--- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
+++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
@@ -359,7 +359,7 @@ void tst_QThreadStorage::leakInDestructor()
QVERIFY(tls.hasLocalData());
}
};
- int c = SPointer::count.load();
+ int c = SPointer::count.loadRelaxed();
QThreadStorage<ThreadStorageLocalDataTester *> tls;
@@ -383,7 +383,7 @@ void tst_QThreadStorage::leakInDestructor()
QVERIFY(t3.wait());
//check all the constructed things have been destructed
- QCOMPARE(int(SPointer::count.load()), c);
+ QCOMPARE(int(SPointer::count.loadRelaxed()), c);
}
class ThreadStorageResetLocalDataTester {
@@ -411,7 +411,7 @@ void tst_QThreadStorage::resetInDestructor()
QVERIFY(ThreadStorageResetLocalDataTesterTls()->hasLocalData());
}
};
- int c = SPointer::count.load();
+ int c = SPointer::count.loadRelaxed();
Thread t1;
Thread t2;
@@ -424,7 +424,7 @@ void tst_QThreadStorage::resetInDestructor()
QVERIFY(t3.wait());
//check all the constructed things have been destructed
- QCOMPARE(int(SPointer::count.load()), c);
+ QCOMPARE(int(SPointer::count.loadRelaxed()), c);
}
@@ -475,7 +475,7 @@ void tst_QThreadStorage::valueBased()
QThreadStorage<QString> tlsString;
QThreadStorage<int> tlsInt;
- int c = SPointer::count.load();
+ int c = SPointer::count.loadRelaxed();
Thread t1(tlsSPointer, tlsString, tlsInt);
Thread t2(tlsSPointer, tlsString, tlsInt);
@@ -495,7 +495,7 @@ void tst_QThreadStorage::valueBased()
QVERIFY(t2.wait());
QVERIFY(t3.wait());
- QCOMPARE(c, int(SPointer::count.load()));
+ QCOMPARE(c, int(SPointer::count.loadRelaxed()));
}
diff --git a/tests/auto/corelib/thread/qwaitcondition/BLACKLIST b/tests/auto/corelib/thread/qwaitcondition/BLACKLIST
deleted file mode 100644
index 3ff336576b..0000000000
--- a/tests/auto/corelib/thread/qwaitcondition/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[wakeOne]
-windows
diff --git a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp
index 126cb6b180..5363231895 100644
--- a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp
+++ b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp
@@ -481,7 +481,7 @@ void tst_QWaitCondition::wakeOne()
}
mutex.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; ++x) {
@@ -502,10 +502,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 1);
- QCOMPARE(count.load(), ThreadCount - (x + 1));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 1));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
@@ -530,7 +530,7 @@ void tst_QWaitCondition::wakeOne()
}
readWriteLock.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; ++x) {
@@ -551,10 +551,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 1);
- QCOMPARE(count.load(), ThreadCount - (x + 1));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 1));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
// wake up threads, two at a time
@@ -585,7 +585,7 @@ void tst_QWaitCondition::wakeOne()
}
mutex.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; x += 2) {
@@ -608,10 +608,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 2);
- QCOMPARE(count.load(), ThreadCount - (x + 2));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 2));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
@@ -636,7 +636,7 @@ void tst_QWaitCondition::wakeOne()
}
readWriteLock.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; x += 2) {
@@ -659,10 +659,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 2);
- QCOMPARE(count.load(), ThreadCount - (x + 2));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 2));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
}
@@ -692,7 +692,7 @@ void tst_QWaitCondition::wakeAll()
}
mutex.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up all threads at once
mutex.lock();
@@ -707,7 +707,7 @@ void tst_QWaitCondition::wakeAll()
}
QCOMPARE(exited, ThreadCount);
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
@@ -728,7 +728,7 @@ void tst_QWaitCondition::wakeAll()
}
readWriteLock.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up all threads at once
readWriteLock.lockForWrite();
@@ -743,7 +743,7 @@ void tst_QWaitCondition::wakeAll()
}
QCOMPARE(exited, ThreadCount);
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
}
diff --git a/tests/auto/corelib/time/qcalendar/qcalendar.pro b/tests/auto/corelib/time/qcalendar/qcalendar.pro
new file mode 100644
index 0000000000..94e8fe8606
--- /dev/null
+++ b/tests/auto/corelib/time/qcalendar/qcalendar.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+TARGET = tst_qcalendar
+QT = core testlib
+SOURCES = \
+ tst_qcalendar.cpp
diff --git a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp
new file mode 100644
index 0000000000..9b41014394
--- /dev/null
+++ b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** 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 <QCalendar>
+Q_DECLARE_METATYPE(QCalendar::System)
+
+class tst_QCalendar : public QObject
+{
+ Q_OBJECT
+private:
+ void checkYear(const QCalendar &cal, int year, bool normal=false);
+
+private slots:
+ void basic_data();
+ void basic();
+ void nameCase();
+ void specific_data();
+ void specific();
+ void daily_data() { basic_data(); }
+ void daily();
+};
+
+// Support for basic():
+void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal)
+{
+ const int moons = cal.monthsInYear(year);
+ // Months are numbered from 1 to moons:
+ QVERIFY(moons > 0);
+ QVERIFY(!cal.isDateValid(year, moons + 1, 1));
+ QVERIFY(!cal.isDateValid(year, 0, 1));
+ QVERIFY(moons <= cal.maximumMonthsInYear());
+
+ const int days = cal.daysInYear(year);
+ QVERIFY(days > 0);
+
+ int sum = 0;
+ const int longest = cal.maximumDaysInMonth();
+ for (int i = moons; i > 0; i--) {
+ const int last = cal.daysInMonth(i, year);
+ sum += last;
+ // Valid month has some days and no more than max:
+ QVERIFY(last > 0);
+ QVERIFY(last <= longest);
+ // Days are numbered from 1 to last:
+ QVERIFY(cal.isDateValid(year, i, 1));
+ QVERIFY(cal.isDateValid(year, i, last));
+ QVERIFY(!cal.isDateValid(year, i, 0));
+ QVERIFY(!cal.isDateValid(year, i, last + 1));
+ if (normal) // Unspecified year gets same daysInMonth():
+ QCOMPARE(cal.daysInMonth(i), last);
+ }
+ // Months add up to the whole year:
+ QCOMPARE(sum, days);
+}
+
+#define CHECKYEAR(cal, year) checkYear(cal, year); \
+ if (QTest::currentTestFailed()) \
+ return
+
+#define NORMALYEAR(cal, year) checkYear(cal, year, true); \
+ if (QTest::currentTestFailed()) \
+ return
+
+void tst_QCalendar::basic_data()
+{
+ QTest::addColumn<QCalendar::System>("system");
+
+ QMetaEnum e = QCalendar::staticMetaObject.enumerator(0);
+ Q_ASSERT(qstrcmp(e.name(), "System") == 0);
+
+ for (int i = 0; i <= int(QCalendar::System::Last); ++i) {
+ // There may be gaps in the enum's numbering; and Last is a duplicate:
+ if (e.value(i) != -1 && qstrcmp(e.key(i), "Last"))
+ QTest::newRow(e.key(i)) << QCalendar::System(e.value(i));
+ }
+}
+
+void tst_QCalendar::basic()
+{
+ QFETCH(QCalendar::System, system);
+ QCalendar cal(system);
+ QVERIFY(cal.isValid());
+ QCOMPARE(QCalendar(cal.name()).isGregorian(), cal.isGregorian());
+ QCOMPARE(QCalendar(cal.name()).name(), cal.name());
+
+ if (cal.hasYearZero()) {
+ CHECKYEAR(cal, 0);
+ } else {
+ QCOMPARE(cal.monthsInYear(0), 0);
+ QCOMPARE(cal.daysInYear(0), 0);
+ QVERIFY(!cal.isDateValid(0, 1, 1));
+ }
+
+ if (cal.isProleptic()) {
+ CHECKYEAR(cal, -1);
+ } else {
+ QCOMPARE(cal.monthsInYear(-1), 0);
+ QCOMPARE(cal.daysInYear(-1), 0);
+ QVERIFY(!cal.isDateValid(-1, 1, 1));
+ }
+
+ // Look for a leap year in the last decade.
+ int year = QDate::currentDate().year(cal);
+ for (int i = 10; i > 0 && !cal.isLeapYear(year); --i)
+ --year;
+ if (cal.isLeapYear(year)) {
+ // ... and a non-leap year within a decade before it.
+ int leap = year--;
+ for (int i = 10; i > 0 && cal.isLeapYear(year); --i)
+ year--;
+ if (!cal.isLeapYear(year))
+ QVERIFY(cal.daysInYear(year) < cal.daysInYear(leap));
+
+ CHECKYEAR(cal, leap);
+ }
+ // Either year is non-leap or we have a decade of leap years together;
+ // expect daysInMonth() to treat year the same as unspecified.
+ NORMALYEAR(cal, year);
+}
+
+void tst_QCalendar::nameCase()
+{
+ QVERIFY(QCalendar::availableCalendars().contains(QStringLiteral("Gregorian")));
+}
+
+void tst_QCalendar::specific_data()
+{
+ QTest::addColumn<QCalendar::System>("system");
+ // Date in that system:
+ QTest::addColumn<int>("sysyear");
+ QTest::addColumn<int>("sysmonth");
+ QTest::addColumn<int>("sysday");
+ // Gregorian equivalent:
+ QTest::addColumn<int>("gregyear");
+ QTest::addColumn<int>("gregmonth");
+ QTest::addColumn<int>("gregday");
+
+#define ADDROW(cal, year, month, day, gy, gm, gd) \
+ QTest::newRow(#cal) << QCalendar::System::cal << year << month << day << gy << gm << gd
+
+ ADDROW(Gregorian, 1970, 1, 1, 1970, 1, 1);
+
+ // One known specific date, for each calendar
+#ifndef QT_BOOTSTRAPPED
+ // Julian 1582-10-4 was followed by Gregorian 1582-10-15
+ ADDROW(Julian, 1582, 10, 4, 1582, 10, 14);
+ // Milankovic matches Gregorian for a few centuries
+ ADDROW(Milankovic, 1923, 3, 20, 1923, 3, 20);
+#endif
+
+#if QT_CONFIG(jalalicalendar)
+ // Jalali year 1355 started on Gregorian 1976-3-21:
+ ADDROW(Jalali, 1355, 1, 1, 1976, 3, 21);
+#endif // jalali
+#if QT_CONFIG(islamiccivilcalendar)
+ // TODO: confirm this is correct
+ ADDROW(IslamicCivil, 1, 1, 1, 622, 7, 19);
+#endif
+
+#undef ADDROW
+}
+
+void tst_QCalendar::specific()
+{
+ QFETCH(QCalendar::System, system);
+ QFETCH(int, sysyear);
+ QFETCH(int, sysmonth);
+ QFETCH(int, sysday);
+ QFETCH(int, gregyear);
+ QFETCH(int, gregmonth);
+ QFETCH(int, gregday);
+
+ const QCalendar cal(system);
+ const QDate date(sysyear, sysmonth, sysday, cal), gregory(gregyear, gregmonth, gregday);
+ QCOMPARE(date, gregory);
+ QCOMPARE(gregory.year(cal), sysyear);
+ QCOMPARE(gregory.month(cal), sysmonth);
+ QCOMPARE(gregory.day(cal), sysday);
+ QCOMPARE(date.year(), gregyear);
+ QCOMPARE(date.month(), gregmonth);
+ QCOMPARE(date.day(), gregday);
+}
+
+void tst_QCalendar::daily()
+{
+ QFETCH(QCalendar::System, system);
+ QCalendar calendar(system);
+ const quint64 startJDN = 0, endJDN = 2488070;
+ // Iterate from -4713-01-01 (Julian calendar) to 2100-01-01
+ for (quint64 expect = startJDN; expect <= endJDN; ++expect)
+ {
+ QDate date = QDate::fromJulianDay(expect);
+ auto parts = calendar.partsFromDate(date);
+ if (!parts.isValid())
+ continue;
+
+ const int year = date.year(calendar);
+ QCOMPARE(year, parts.year);
+ const int month = date.month(calendar);
+ QCOMPARE(month, parts.month);
+ const int day = date.day(calendar);
+ QCOMPARE(day, parts.day);
+ const quint64 actual = QDate(year, month, day, calendar).toJulianDay();
+ QCOMPARE(actual, expect);
+ }
+}
+
+QTEST_APPLESS_MAIN(tst_QCalendar)
+#include "tst_qcalendar.moc"
diff --git a/tests/auto/corelib/tools/qdate/.gitignore b/tests/auto/corelib/time/qdate/.gitignore
index 70945d4a86..70945d4a86 100644
--- a/tests/auto/corelib/tools/qdate/.gitignore
+++ b/tests/auto/corelib/time/qdate/.gitignore
diff --git a/tests/auto/corelib/tools/qdate/qdate.pro b/tests/auto/corelib/time/qdate/qdate.pro
index dd7c6cb888..925c3b4c78 100644
--- a/tests/auto/corelib/tools/qdate/qdate.pro
+++ b/tests/auto/corelib/time/qdate/qdate.pro
@@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qdate
-QT = core testlib
+QT = core-private testlib
SOURCES = tst_qdate.cpp
diff --git a/tests/auto/corelib/tools/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp
index ce1e5730dd..73384c35f4 100644
--- a/tests/auto/corelib/tools/qdate/tst_qdate.cpp
+++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -27,6 +27,7 @@
**
****************************************************************************/
+#include <private/qglobal_p.h> // for the icu feature test
#include <QtTest/QtTest>
#include <qdatetime.h>
#include <qlocale.h>
@@ -54,6 +55,13 @@ private slots:
void weekNumber_invalid();
void weekNumber_data();
void weekNumber();
+#if QT_CONFIG(timezone)
+ void startOfDay_endOfDay_data();
+ void startOfDay_endOfDay();
+#endif
+ void startOfDay_endOfDay_fixed_data();
+ void startOfDay_endOfDay_fixed();
+ void startOfDay_endOfDay_bounds();
void julianDaysLimits();
void addDays_data();
void addDays();
@@ -83,6 +91,7 @@ private slots:
void negativeYear() const;
void printNegativeYear() const;
void roundtripGermanLocale() const;
+#if QT_CONFIG(textdate) && QT_DEPRECATED_SINCE(5, 10)
void shortDayName() const;
void standaloneShortDayName() const;
void longDayName() const;
@@ -91,6 +100,7 @@ private slots:
void standaloneShortMonthName() const;
void longMonthName() const;
void standaloneLongMonthName() const;
+#endif // textdate
void roundtrip() const;
void qdebug() const;
private:
@@ -456,6 +466,164 @@ void tst_QDate::weekNumber_invalid()
QCOMPARE( dt.weekNumber( &yearNumber ), 0 );
}
+#if QT_CONFIG(timezone)
+void tst_QDate::startOfDay_endOfDay_data()
+{
+ QTest::addColumn<QDate>("date"); // Typically a spring-forward.
+ // A zone in which that date's start and end are worth checking:
+ QTest::addColumn<QByteArray>("zoneName");
+ // The start and end times in that zone:
+ QTest::addColumn<QTime>("start");
+ QTest::addColumn<QTime>("end");
+
+ const QTime initial(0, 0), final(23, 59, 59, 999), invalid(QDateTime().time());
+
+ QTest::newRow("epoch")
+ << QDate(1970, 1, 1) << QByteArray("UTC")
+ << initial << final;
+ QTest::newRow("Brazil")
+ << QDate(2008, 10, 19) << QByteArray("America/Sao_Paulo")
+ << QTime(1, 0) << final;
+#if QT_CONFIG(icu) || !defined(Q_OS_WIN) // MS's TZ APIs lack data
+ QTest::newRow("Sofia")
+ << QDate(1994, 3, 27) << QByteArray("Europe/Sofia")
+ << QTime(1, 0) << final;
+#endif
+ QTest::newRow("Kiritimati")
+ << QDate(1994, 12, 31) << QByteArray("Pacific/Kiritimati")
+ << invalid << invalid;
+ QTest::newRow("Samoa")
+ << QDate(2011, 12, 30) << QByteArray("Pacific/Apia")
+ << invalid << invalid;
+ // TODO: find other zones with transitions at/crossing midnight.
+}
+
+void tst_QDate::startOfDay_endOfDay()
+{
+ QFETCH(QDate, date);
+ QFETCH(QByteArray, zoneName);
+ QFETCH(QTime, start);
+ QFETCH(QTime, end);
+ const QTimeZone zone(zoneName);
+ const bool isSystem = QTimeZone::systemTimeZone() == zone;
+ QDateTime front(date.startOfDay(zone)), back(date.endOfDay(zone));
+ if (end.isValid())
+ QCOMPARE(date.addDays(1).startOfDay(zone).addMSecs(-1), back);
+ if (start.isValid())
+ QCOMPARE(date.addDays(-1).endOfDay(zone).addMSecs(1), front);
+ do { // Avoids duplicating these tests for local-time when it *is* zone:
+ if (start.isValid()) {
+ QCOMPARE(front.date(), date);
+ QCOMPARE(front.time(), start);
+ }
+ if (end.isValid()) {
+ QCOMPARE(back.date(), date);
+ QCOMPARE(back.time(), end);
+ }
+ if (front.timeSpec() == Qt::LocalTime)
+ break;
+ front = date.startOfDay(Qt::LocalTime);
+ back = date.endOfDay(Qt::LocalTime);
+ } while (isSystem);
+ if (end.isValid())
+ QCOMPARE(date.addDays(1).startOfDay(Qt::LocalTime).addMSecs(-1), back);
+ if (start.isValid())
+ QCOMPARE(date.addDays(-1).endOfDay(Qt::LocalTime).addMSecs(1), front);
+ if (!isSystem) {
+ // These might fail if system zone coincides with zone; but only if it
+ // did something similarly unusual on the date picked for this test.
+ if (start.isValid()) {
+ QCOMPARE(front.date(), date);
+ QCOMPARE(front.time(), QTime(0, 0));
+ }
+ if (end.isValid()) {
+ QCOMPARE(back.date(), date);
+ QCOMPARE(back.time(), QTime(23, 59, 59, 999));
+ }
+ }
+}
+#endif // timezone
+
+void tst_QDate::startOfDay_endOfDay_fixed_data()
+{
+ const qint64 kilo(1000);
+ using Bounds = std::numeric_limits<qint64>;
+ const QDateTime
+ first(QDateTime::fromMSecsSinceEpoch(Bounds::min() + 1, Qt::UTC)),
+ start32sign(QDateTime::fromMSecsSinceEpoch(-0x80000000L * kilo, Qt::UTC)),
+ end32sign(QDateTime::fromMSecsSinceEpoch(0x80000000L * kilo, Qt::UTC)),
+ end32unsign(QDateTime::fromMSecsSinceEpoch(0x100000000L * kilo, Qt::UTC)),
+ last(QDateTime::fromMSecsSinceEpoch(Bounds::max(), Qt::UTC));
+
+ const struct {
+ const char *name;
+ QDate date;
+ } data[] = {
+ { "epoch", QDate(1970, 1, 1) },
+ { "y2k-leap-day", QDate(2000, 2, 29) },
+ // Just outside the start and end of 32-bit time_t:
+ { "pre-sign32", QDate(start32sign.date().year(), 1, 1) },
+ { "post-sign32", QDate(end32sign.date().year(), 12, 31) },
+ { "post-uint32", QDate(end32unsign.date().year(), 12, 31) },
+ // Just inside the start and end of QDateTime's range:
+ { "first-full", first.date().addDays(1) },
+ { "last-full", last.date().addDays(-1) }
+ };
+
+ QTest::addColumn<QDate>("date");
+ for (const auto &r : data)
+ QTest::newRow(r.name) << r.date;
+}
+
+void tst_QDate::startOfDay_endOfDay_fixed()
+{
+ const QTime early(0, 0), late(23, 59, 59, 999);
+ QFETCH(QDate, date);
+
+ QDateTime start(date.startOfDay(Qt::UTC));
+ QDateTime end(date.endOfDay(Qt::UTC));
+ QCOMPARE(start.date(), date);
+ QCOMPARE(end.date(), date);
+ QCOMPARE(start.time(), early);
+ QCOMPARE(end.time(), late);
+ QCOMPARE(date.addDays(1).startOfDay(Qt::UTC).addMSecs(-1), end);
+ QCOMPARE(date.addDays(-1).endOfDay(Qt::UTC).addMSecs(1), start);
+ for (int offset = -60 * 16; offset <= 60 * 16; offset += 65) {
+ start = date.startOfDay(Qt::OffsetFromUTC, offset);
+ end = date.endOfDay(Qt::OffsetFromUTC, offset);
+ QCOMPARE(start.date(), date);
+ QCOMPARE(end.date(), date);
+ QCOMPARE(start.time(), early);
+ QCOMPARE(end.time(), late);
+ QCOMPARE(date.addDays(1).startOfDay(Qt::OffsetFromUTC, offset).addMSecs(-1), end);
+ QCOMPARE(date.addDays(-1).endOfDay(Qt::OffsetFromUTC, offset).addMSecs(1), start);
+ }
+}
+
+void tst_QDate::startOfDay_endOfDay_bounds()
+{
+ // Check the days in which QDateTime's range starts and ends:
+ using Bounds = std::numeric_limits<qint64>;
+ const QDateTime
+ first(QDateTime::fromMSecsSinceEpoch(Bounds::min(), Qt::UTC)),
+ last(QDateTime::fromMSecsSinceEpoch(Bounds::max(), Qt::UTC)),
+ epoch(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC));
+ // First, check these *are* the start and end of QDateTime's range:
+ QVERIFY(first.isValid());
+ QVERIFY(last.isValid());
+ QVERIFY(first < epoch);
+ QVERIFY(last > epoch);
+ // QDateTime's addMSecs doesn't check against {und,ov}erflow ...
+ QVERIFY(!first.addMSecs(-1).isValid() || first.addMSecs(-1) > first);
+ QVERIFY(!last.addMSecs(1).isValid() || last.addMSecs(1) < last);
+
+ // Now test start/end methods with them:
+ QCOMPARE(first.date().endOfDay(Qt::UTC).time(), QTime(23, 59, 59, 999));
+ QCOMPARE(last.date().startOfDay(Qt::UTC).time(), QTime(0, 0));
+ QVERIFY(!first.date().startOfDay(Qt::UTC).isValid());
+ QVERIFY(!last.date().endOfDay(Qt::UTC).isValid());
+}
+
void tst_QDate::julianDaysLimits()
{
qint64 min = std::numeric_limits<qint64>::min();
@@ -1038,18 +1206,18 @@ void tst_QDate::fromStringFormat_data()
// Undo this (inline the C-locale versions) for ### Qt 6
// Get localized names:
- QString january = QDate::longMonthName(1);
- QString february = QDate::longMonthName(2);
- QString march = QDate::longMonthName(3);
- QString august = QDate::longMonthName(8);
- QString mon = QDate::shortDayName(1);
- QString monday = QDate::longDayName(1);
- QString tuesday = QDate::longDayName(2);
- QString wednesday = QDate::longDayName(3);
- QString thursday = QDate::longDayName(4);
- QString friday = QDate::longDayName(5);
- QString saturday = QDate::longDayName(6);
- QString sunday = QDate::longDayName(7);
+ QString january = QLocale::system().monthName(1, QLocale::LongFormat);
+ QString february = QLocale::system().monthName(2, QLocale::LongFormat);
+ QString march = QLocale::system().monthName(3, QLocale::LongFormat);
+ QString august = QLocale::system().monthName(8, QLocale::LongFormat);
+ QString mon = QLocale::system().dayName(1, QLocale::ShortFormat);
+ QString monday = QLocale::system().dayName(1, QLocale::LongFormat);
+ QString tuesday = QLocale::system().dayName(2, QLocale::LongFormat);
+ QString wednesday = QLocale::system().dayName(3, QLocale::LongFormat);
+ QString thursday = QLocale::system().dayName(4, QLocale::LongFormat);
+ QString friday = QLocale::system().dayName(5, QLocale::LongFormat);
+ QString saturday = QLocale::system().dayName(6, QLocale::LongFormat);
+ QString sunday = QLocale::system().dayName(7, QLocale::LongFormat);
QTest::newRow("data0") << QString("") << QString("") << defDate();
QTest::newRow("data1") << QString(" ") << QString("") << invalidDate();
@@ -1305,6 +1473,10 @@ void tst_QDate::roundtripGermanLocale() const
theDateTime.fromString(theDateTime.toString(Qt::TextDate), Qt::TextDate);
}
+#if QT_CONFIG(textdate) && QT_DEPRECATED_SINCE(5, 10)
+QT_WARNING_PUSH // the methods tested here are all deprecated
+QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
+
void tst_QDate::shortDayName() const
{
QCOMPARE(QDate::shortDayName(0), QString());
@@ -1432,6 +1604,8 @@ void tst_QDate::standaloneLongMonthName() const
QCOMPARE(QDate::longMonthName(i, QDate::StandaloneFormat), locale.standaloneMonthName(i, QLocale::LongFormat));
}
}
+QT_WARNING_POP
+#endif // textdate
void tst_QDate::roundtrip() const
{
diff --git a/tests/auto/corelib/tools/qdatetime/.gitignore b/tests/auto/corelib/time/qdatetime/.gitignore
index 7784f3a3eb..7784f3a3eb 100644
--- a/tests/auto/corelib/tools/qdatetime/.gitignore
+++ b/tests/auto/corelib/time/qdatetime/.gitignore
diff --git a/tests/auto/corelib/tools/qdatetime/qdatetime.pro b/tests/auto/corelib/time/qdatetime/qdatetime.pro
index 742eb47075..742eb47075 100644
--- a/tests/auto/corelib/tools/qdatetime/qdatetime.pro
+++ b/tests/auto/corelib/time/qdatetime/qdatetime.pro
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
index ce7cacf966..ac1b903aa1 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -61,6 +61,10 @@ private slots:
void timeSpec();
void toSecsSinceEpoch_data();
void toSecsSinceEpoch();
+#if QT_DEPRECATED_SINCE(5, 8)
+ void toTime_t_data();
+ void toTime_t();
+#endif
void daylightSavingsTimeChange_data();
void daylightSavingsTimeChange();
void springForward_data();
@@ -147,6 +151,7 @@ private slots:
void systemTimeZoneChange() const;
void invalid() const;
+ void range() const;
void macTypes();
@@ -1005,7 +1010,6 @@ void tst_QDateTime::toString_enumformat()
{
QDateTime dt1(QDate(1995, 5, 20), QTime(12, 34, 56));
-
QString str1 = dt1.toString(Qt::TextDate);
QVERIFY(!str1.isEmpty()); // It's locale dependent everywhere
@@ -1690,6 +1694,34 @@ void tst_QDateTime::toSecsSinceEpoch()
QDateTime datetime = dt( dateTimeStr );
qint64 asSecsSinceEpoch = datetime.toSecsSinceEpoch();
+ QCOMPARE(asSecsSinceEpoch, datetime.toMSecsSinceEpoch() / 1000);
+
+ QDateTime datetime2 = QDateTime::fromSecsSinceEpoch(asSecsSinceEpoch);
+ QCOMPARE(datetime, datetime2);
+}
+
+#if QT_DEPRECATED_SINCE(5, 8)
+void tst_QDateTime::toTime_t_data()
+{
+ QTest::addColumn<QString>("dateTimeStr");
+ QTest::addColumn<bool>("res");
+
+ QTest::newRow( "data1" ) << str( 1800, 1, 1, 12, 0, 0 ) << false;
+ QTest::newRow( "data2" ) << str( 1969, 1, 1, 12, 0, 0 ) << false;
+ QTest::newRow( "data3" ) << str( 2002, 1, 1, 12, 0, 0 ) << true;
+ QTest::newRow( "data4" ) << str( 2002, 6, 1, 12, 0, 0 ) << true;
+ QTest::newRow( "data5" ) << QString("INVALID") << false;
+ QTest::newRow( "data6" ) << str( 2038, 1, 1, 12, 0, 0 ) << true;
+ QTest::newRow( "data7" ) << str( 2063, 4, 5, 12, 0, 0 ) << true; // the day of First Contact
+ QTest::newRow( "data8" ) << str( 2107, 1, 1, 12, 0, 0 )
+ << bool( sizeof(uint) > 32 && sizeof(time_t) > 32 );
+}
+
+void tst_QDateTime::toTime_t()
+{
+ QFETCH( QString, dateTimeStr );
+ QDateTime datetime = dt( dateTimeStr );
+
uint asTime_t = datetime.toTime_t();
QFETCH( bool, res );
if (res) {
@@ -1697,15 +1729,13 @@ void tst_QDateTime::toSecsSinceEpoch()
} else {
QVERIFY( asTime_t == (uint)-1 );
}
- QCOMPARE(asSecsSinceEpoch, datetime.toMSecsSinceEpoch() / 1000);
if ( asTime_t != (uint) -1 ) {
QDateTime datetime2 = QDateTime::fromTime_t( asTime_t );
QCOMPARE(datetime, datetime2);
}
- QDateTime datetime2 = QDateTime::fromSecsSinceEpoch(asSecsSinceEpoch);
- QCOMPARE(datetime, datetime2);
}
+#endif
void tst_QDateTime::daylightSavingsTimeChange_data()
{
@@ -2779,9 +2809,9 @@ void tst_QDateTime::getDate()
int y = -33, m = -44, d = -55;
QDate date;
date.getDate(&y, &m, &d);
- QVERIFY(date.year() == y);
- QVERIFY(date.month() == m);
- QVERIFY(date.day() == d);
+ QCOMPARE(date.year(), y);
+ QCOMPARE(date.month(), m);
+ QCOMPARE(date.day(), d);
date.getDate(0, 0, 0);
}
@@ -2793,9 +2823,9 @@ void tst_QDateTime::getDate()
date.getDate(&y, 0, 0);
date.getDate(0, 0, &d);
- QVERIFY(date.year() == y);
- QVERIFY(date.month() == m);
- QVERIFY(date.day() == d);
+ QCOMPARE(date.year(), y);
+ QCOMPARE(date.month(), m);
+ QCOMPARE(date.day(), d);
}
}
@@ -3476,6 +3506,15 @@ void tst_QDateTime::invalid() const
QCOMPARE(tzDate.timeSpec(), Qt::TimeZone);
}
+void tst_QDateTime::range() const
+{
+ using Bounds = std::numeric_limits<qint64>;
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(Bounds::min() + 1, Qt::UTC).date().year(),
+ int(QDateTime::YearRange::First));
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(Bounds::max() - 1, Qt::UTC).date().year(),
+ int(QDateTime::YearRange::Last));
+}
+
void tst_QDateTime::macTypes()
{
#ifndef Q_OS_MAC
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm b/tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm
index f73c7b9d5d..f73c7b9d5d 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm
diff --git a/tests/auto/corelib/tools/qtime/.gitignore b/tests/auto/corelib/time/qtime/.gitignore
index 26a4c65cc2..26a4c65cc2 100644
--- a/tests/auto/corelib/tools/qtime/.gitignore
+++ b/tests/auto/corelib/time/qtime/.gitignore
diff --git a/tests/auto/corelib/tools/qtime/qtime.pro b/tests/auto/corelib/time/qtime/qtime.pro
index 0973b7a9ef..0973b7a9ef 100644
--- a/tests/auto/corelib/tools/qtime/qtime.pro
+++ b/tests/auto/corelib/time/qtime/qtime.pro
diff --git a/tests/auto/corelib/tools/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp
index 3e5724213e..3403c5bf7f 100644
--- a/tests/auto/corelib/tools/qtime/tst_qtime.cpp
+++ b/tests/auto/corelib/time/qtime/tst_qtime.cpp
@@ -95,8 +95,9 @@ void tst_QTime::addSecs_data()
QTest::newRow("Data0") << QTime(0,0,0) << 200 << QTime(0,3,20);
QTest::newRow("Data1") << QTime(0,0,0) << 20 << QTime(0,0,20);
- QTest::newRow("overflow") << QTime(0,0,0) << (INT_MAX / 1000 + 1)
- << QTime(0,0,0).addSecs((INT_MAX / 1000 + 1) % 86400);
+ QTest::newRow("overflow")
+ << QTime(0,0,0) << (INT_MAX / 1000 + 1)
+ << QTime::fromMSecsSinceStartOfDay(((INT_MAX / 1000 + 1) % 86400) * 1000);
}
void tst_QTime::addSecs()
diff --git a/tests/auto/corelib/tools/qtimezone/BLACKLIST b/tests/auto/corelib/time/qtimezone/BLACKLIST
index 840c3b1181..840c3b1181 100644
--- a/tests/auto/corelib/tools/qtimezone/BLACKLIST
+++ b/tests/auto/corelib/time/qtimezone/BLACKLIST
diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/time/qtimezone/qtimezone.pro
index 5ec8d008e7..5ec8d008e7 100644
--- a/tests/auto/corelib/tools/qtimezone/qtimezone.pro
+++ b/tests/auto/corelib/time/qtimezone/qtimezone.pro
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
index bb6c48a2ed..9904719f7c 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
@@ -480,11 +480,10 @@ void tst_QTimeZone::transitionEachZone_data()
{ 1288488600, -4, 8, 2010 } // 2010-10-31 01:30 UTC; Europe, Russia
};
- QString name;
const auto zones = QTimeZone::availableTimeZoneIds();
for (int k = sizeof(table) / sizeof(table[0]); k-- > 0; ) {
for (const QByteArray &zone : zones) {
- name.sprintf("%s@%d", zone.constData(), table[k].year);
+ const QString name = QString::asprintf("%s@%d", zone.constData(), table[k].year);
QTest::newRow(name.toUtf8().constData())
<< zone
<< table[k].baseSecs
@@ -916,6 +915,14 @@ void tst_QTimeZone::tzTest()
QTzTimeZonePrivate tzp("Europe/Berlin");
QVERIFY(tzp.isValid());
+ // Test POSIX-format value for $TZ:
+ QTzTimeZonePrivate tzposix("MET-1METDST-2,M3.5.0/02:00:00,M10.5.0/03:00:00");
+ QVERIFY(tzposix.isValid());
+
+ QTimeZone tzBrazil("BRT+3"); // parts of Northern Brazil, as a POSIX rule
+ QVERIFY(tzBrazil.isValid());
+ QCOMPARE(tzBrazil.offsetFromUtc(QDateTime(QDate(1111, 11, 11).startOfDay())), -10800);
+
// Test display names by type, either ICU or abbreviation only
QLocale enUS("en_US");
// Only test names in debug mode, names used can vary by ICU version installed
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm b/tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm
index de801e55d0..de801e55d0 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm
diff --git a/tests/auto/corelib/time/time.pro b/tests/auto/corelib/time/time.pro
new file mode 100644
index 0000000000..6f1ee9a8bd
--- /dev/null
+++ b/tests/auto/corelib/time/time.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qcalendar \
+ qdate \
+ qdatetime \
+ qtime \
+ qtimezone
diff --git a/tests/auto/corelib/tools/collections/collections.pro b/tests/auto/corelib/tools/collections/collections.pro
index 5c04515fa0..e0f9f0a0ea 100644
--- a/tests/auto/corelib/tools/collections/collections.pro
+++ b/tests/auto/corelib/tools/collections/collections.pro
@@ -4,4 +4,6 @@ SOURCES += tst_collections.cpp
QT = core testlib
# This test does not work with strict iterators
+DEFINES -= QT_NO_LINKED_LIST
DEFINES -= QT_STRICT_ITERATORS
+DEFINES -= QT_NO_JAVA_STYLE_ITERATORS
diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp
index b40b1f0624..e79a4dba29 100644
--- a/tests/auto/corelib/tools/collections/tst_collections.cpp
+++ b/tests/auto/corelib/tools/collections/tst_collections.cpp
@@ -67,7 +67,6 @@ void foo()
#include <algorithm>
-#include "qalgorithms.h"
#include "qbitarray.h"
#include "qbytearray.h"
#include "qcache.h"
@@ -76,7 +75,7 @@ void foo()
#include "qlist.h"
#include "qmap.h"
#include "qpair.h"
-#include "qregexp.h"
+#include "qregularexpression.h"
#include "qset.h"
#include "qstack.h"
#include "qstring.h"
@@ -105,7 +104,9 @@ private slots:
void map();
void bitArray();
void cache();
+#if QT_CONFIG(regularexpression)
void regexp();
+#endif
void pair();
void sharableQList();
void sharableQLinkedList();
@@ -189,16 +190,6 @@ void tst_Collections::list()
QVERIFY(list.size() == 6);
QVERIFY(list.end() - list.begin() == list.size());
-#if !defined(Q_CC_MSVC) && !defined(Q_CC_SUN)
- QVERIFY(std::binary_search(list.begin(), list.end(), 2) == true);
- QVERIFY(std::binary_search(list.begin(), list.end(), 9) == false);
-#endif
- QVERIFY(qBinaryFind(list.begin(), list.end(), 2) == list.begin() + 1);
- QVERIFY(qLowerBound(list.begin(), list.end(), 2) == list.begin() + 1);
- QVERIFY(qUpperBound(list.begin(), list.end(), 2) == list.begin() + 2);
- QVERIFY(qBinaryFind(list.begin(), list.end(), 9) == list.end());
- QVERIFY(qLowerBound(list.begin(), list.end(), 9) == list.end());
- QVERIFY(qUpperBound(list.begin(), list.end(), 9) == list.end());
{
int sum = 0;
QListIterator<int> i(list);
@@ -580,73 +571,73 @@ void tst_Collections::list()
list1 << 0 << 1 << 2 << 3;
list1.removeFirst();
- list1.swap(0, 0);
+ list1.swapItemsAt(0, 0);
QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
- list1.swap(1, 1);
+ list1.swapItemsAt(1, 1);
QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
- list1.swap(2, 2);
+ list1.swapItemsAt(2, 2);
QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
- list1.swap(0, 1);
+ list1.swapItemsAt(0, 1);
QVERIFY(list1 == QList<int>() << 2 << 1 << 3);
- list1.swap(0, 2);
+ list1.swapItemsAt(0, 2);
QVERIFY(list1 == QList<int>() << 3 << 1 << 2);
- list1.swap(1, 2);
+ list1.swapItemsAt(1, 2);
QVERIFY(list1 == QList<int>() << 3 << 2 << 1);
- list1.swap(1, 2);
+ list1.swapItemsAt(1, 2);
QVERIFY(list1 == QList<int>() << 3 << 1 << 2);
QList<QString> list2;
list2 << "1" << "2" << "3";
- list2.swap(0, 0);
+ list2.swapItemsAt(0, 0);
QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
- list2.swap(1, 1);
+ list2.swapItemsAt(1, 1);
QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
- list2.swap(2, 2);
+ list2.swapItemsAt(2, 2);
QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
- list2.swap(0, 1);
+ list2.swapItemsAt(0, 1);
QVERIFY(list2 == QList<QString>() << "2" << "1" << "3");
- list2.swap(0, 2);
+ list2.swapItemsAt(0, 2);
QVERIFY(list2 == QList<QString>() << "3" << "1" << "2");
- list2.swap(1, 2);
+ list2.swapItemsAt(1, 2);
QVERIFY(list2 == QList<QString>() << "3" << "2" << "1");
- list2.swap(1, 2);
+ list2.swapItemsAt(1, 2);
QVERIFY(list2 == QList<QString>() << "3" << "1" << "2");
QList<double> list3;
list3 << 1.0 << 2.0 << 3.0;
- list3.swap(0, 0);
+ list3.swapItemsAt(0, 0);
QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
- list3.swap(1, 1);
+ list3.swapItemsAt(1, 1);
QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
- list3.swap(2, 2);
+ list3.swapItemsAt(2, 2);
QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
- list3.swap(0, 1);
+ list3.swapItemsAt(0, 1);
QVERIFY(list3 == QList<double>() << 2.0 << 1.0 << 3.0);
- list3.swap(0, 2);
+ list3.swapItemsAt(0, 2);
QVERIFY(list3 == QList<double>() << 3.0 << 1.0 << 2.0);
- list3.swap(1, 2);
+ list3.swapItemsAt(1, 2);
QVERIFY(list3 == QList<double>() << 3.0 << 2.0 << 1.0);
- list3.swap(1, 2);
+ list3.swapItemsAt(1, 2);
QVERIFY(list3 == QList<double>() << 3.0 << 1.0 << 2.0);
}
@@ -994,16 +985,8 @@ void tst_Collections::vector()
v.append(2);
QVERIFY(*v.begin() == 2);
v.prepend(1);
-
- v << 3 << 4 << 5 << 6;
- QVERIFY(std::binary_search(v.begin(), v.end(), 2) == true);
- QVERIFY(std::binary_search(v.begin(), v.end(), 9) == false);
- QVERIFY(qBinaryFind(v.begin(), v.end(), 2) == v.begin() + 1);
- QVERIFY(qLowerBound(v.begin(), v.end(), 2) == v.begin() + 1);
- QVERIFY(qUpperBound(v.begin(), v.end(), 2) == v.begin() + 2);
- QVERIFY(qBinaryFind(v.begin(), v.end(), 9) == v.end());
- QVERIFY(qLowerBound(v.begin(), v.end(), 9) == v.end());
- QVERIFY(qUpperBound(v.begin(), v.end(), 9) == v.end());
+ QVERIFY(*v.begin() == 1);
+ QVERIFY(*(v.begin() + 1) == 2);
v.clear();
v << 1 << 2 << 3;
@@ -1368,7 +1351,7 @@ void tst_Collections::hash()
{
typedef QHash<QString, QString> Hash;
Hash hash;
- QString key;
+ QString key = QLatin1String(" ");
for (int i = 0; i < 10; ++i) {
key[0] = i + '0';
for (int j = 0; j < 10; ++j) {
@@ -2011,13 +1994,17 @@ void tst_Collections::qstring()
QString nonNull = "";
QVERIFY(null.left(10).isNull());
QVERIFY(null.mid(0).isNull());
+ QVERIFY(null.isNull());
+ QVERIFY(!nonNull.isNull());
+#if QT_DEPRECATED_SINCE(5, 9)
QVERIFY(null == QString::null);
QVERIFY(QString::null == null);
QVERIFY(nonNull != QString::null);
QVERIFY(QString::null != nonNull);
QVERIFY(null == nonNull);
QVERIFY(QString::null == QString::null);
+#endif
QString fill = "123";
fill.fill('a');
@@ -2285,13 +2272,15 @@ void tst_Collections::cache()
}
+#if QT_CONFIG(regularexpression)
void tst_Collections::regexp()
{
- QRegExp rx("^\\d\\d?$");
- QVERIFY(rx.indexIn("123") == -1);
- QVERIFY(rx.indexIn("-6") == -1);
- QVERIFY(rx.indexIn("6") == 0) ;
+ QRegularExpression rx("^\\d\\d?$");
+ QVERIFY(!rx.match("123").hasMatch());
+ QVERIFY(!rx.match("-6").hasMatch());
+ QVERIFY(rx.match("6").hasMatch()) ;
}
+#endif
void tst_Collections::pair()
{
@@ -2425,7 +2414,7 @@ void testContainer()
c1 = newInstance<Container>();
QVERIFY(c1.size() == 4);
QVERIFY(c1 == newInstance<Container>());
- Container c2 = qMove(c1);
+ Container c2 = std::move(c1);
QVERIFY(c2.size() == 4);
QVERIFY(c2 == newInstance<Container>());
}
@@ -2531,14 +2520,18 @@ void tst_Collections::conversions()
QCOMPARE(list2.size(), 4);
QVERIFY(list2 == (QList<QString>() << STUFF));
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QSet<QString> set1 = list1.toSet();
+#else
+ QSet<QString> set1(list1.begin(), list1.end());
+#endif
QCOMPARE(set1.size(), 3);
QVERIFY(set1.contains("A"));
QVERIFY(set1.contains("B"));
QVERIFY(set1.contains("C"));
QVERIFY(!set1.contains("D"));
- QList<QString> list3 = set1.toList();
+ QList<QString> list3 = set1.values();
QCOMPARE(list3.size(), 3);
QVERIFY(list3.contains("A"));
QVERIFY(list3.contains("B"));
@@ -2546,9 +2539,11 @@ void tst_Collections::conversions()
QVERIFY(!list3.contains("D"));
QVERIFY(QList<int>().toVector().isEmpty());
- QVERIFY(QList<int>().toSet().isEmpty());
QVERIFY(QVector<int>().toList().isEmpty());
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ QVERIFY(QList<int>().toSet().isEmpty());
QVERIFY(QSet<int>().toList().isEmpty());
+#endif
}
{
@@ -2563,14 +2558,22 @@ void tst_Collections::conversions()
QCOMPARE(list2.size(), 4);
QVERIFY(list2 == (QList<QString>() << STUFF));
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QSet<QString> set1 = QSet<QString>::fromList(list1);
+#else
+ QSet<QString> set1(list1.begin(), list1.end());
+#endif
QCOMPARE(set1.size(), 3);
QVERIFY(set1.contains("A"));
QVERIFY(set1.contains("B"));
QVERIFY(set1.contains("C"));
QVERIFY(!set1.contains("D"));
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QList<QString> list3 = QList<QString>::fromSet(set1);
+#else
+ QList<QString> list3 = set1.values();
+#endif
QCOMPARE(list3.size(), 3);
QVERIFY(list3.contains("A"));
QVERIFY(list3.contains("B"));
@@ -2578,9 +2581,11 @@ void tst_Collections::conversions()
QVERIFY(!list3.contains("D"));
QVERIFY(QVector<int>::fromList(QList<int>()).isEmpty());
- QVERIFY(QSet<int>::fromList(QList<int>()).isEmpty());
QVERIFY(QList<int>::fromVector(QVector<int>()).isEmpty());
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ QVERIFY(QSet<int>::fromList(QList<int>()).isEmpty());
QVERIFY(QList<int>::fromSet(QSet<int>()).isEmpty());
+#endif
}
#undef STUFF
}
@@ -2776,15 +2781,21 @@ void tst_Collections::vector_stl()
for (int i = 0; i < elements.count(); ++i)
vector << elements.at(i);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
std::vector<QString> stdVector = vector.toStdVector();
-
+#else
+ std::vector<QString> stdVector(vector.begin(), vector.end());
+#endif
QCOMPARE(int(stdVector.size()), elements.size());
std::vector<QString>::const_iterator it = stdVector.begin();
for (uint j = 0; j < stdVector.size() && it != stdVector.end(); ++j, ++it)
QCOMPARE(*it, vector[j]);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QCOMPARE(QVector<QString>::fromStdVector(stdVector), vector);
+#endif
+ QCOMPARE(QVector<QString>(stdVector.begin(), stdVector.end()), vector);
}
void tst_Collections::linkedlist_stl_data()
@@ -2830,7 +2841,11 @@ void tst_Collections::list_stl()
for (int i = 0; i < elements.count(); ++i)
list << elements.at(i);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
std::list<QString> stdList = list.toStdList();
+#else
+ std::list<QString> stdList(list.begin(), list.end());
+#endif
QCOMPARE(int(stdList.size()), elements.size());
@@ -2838,7 +2853,10 @@ void tst_Collections::list_stl()
for (uint j = 0; j < stdList.size() && it != stdList.end(); ++j, ++it)
QCOMPARE(*it, list[j]);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QCOMPARE(QList<QString>::fromStdList(stdList), list);
+#endif
+ QCOMPARE(QList<QString>(stdList.begin(), stdList.end()), list);
}
template <typename T>
diff --git a/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro b/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro
index 30dc8026ef..e46d51761e 100644
--- a/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro
+++ b/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro
@@ -5,3 +5,4 @@ QT = core testlib
# This test does not work with strict iterators
DEFINES -= QT_STRICT_ITERATORS
+DEFINES -= QT_NO_LINKED_LIST
diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
index 3b8111f1a3..4b085d387d 100644
--- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
+++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
@@ -34,13 +34,446 @@
#include "qstring.h"
#include "qvarlengtharray.h"
#include "qvector.h"
+#include "qhash.h"
+#include "qdebug.h"
+#include <algorithm>
+#include <functional>
#include <vector> // for reference
+#include <list>
+#include <set>
+#include <map>
+
+// MSVC has these containers from the Standard Library, but it lacks
+// a __has_include mechanism (that we need to use for other stdlibs).
+// For the sake of increasing our test coverage, work around the issue.
+
+#ifdef Q_CC_MSVC
+#define COMPILER_HAS_STDLIB_INCLUDE(x) 1
+#else
+#define COMPILER_HAS_STDLIB_INCLUDE(x) QT_HAS_INCLUDE(x)
+#endif
+
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+#include <forward_list>
+#endif
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+#include <unordered_set>
+#endif
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+#include <unordered_map>
+#endif
+
+struct Movable
+{
+ explicit Movable(int i = 0) Q_DECL_NOTHROW
+ : i(i)
+ {
+ ++instanceCount;
+ }
+
+ Movable(const Movable &m)
+ : i(m.i)
+ {
+ ++instanceCount;
+ }
+
+ ~Movable()
+ {
+ --instanceCount;
+ }
+
+ int i;
+ static int instanceCount;
+};
+
+int Movable::instanceCount = 0;
+bool operator==(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i == rhs.i; }
+bool operator!=(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i != rhs.i; }
+bool operator<(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i < rhs.i; }
+
+uint qHash(Movable m, uint seed = 0) Q_DECL_NOTHROW { return qHash(m.i, seed); }
+QDebug &operator<<(QDebug &d, Movable m)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "Movable(" << m.i << ")";
+}
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+
+struct Complex
+{
+ explicit Complex(int i = 0) Q_DECL_NOTHROW
+ : i(i)
+ {
+ ++instanceCount;
+ }
+
+ Complex(const Complex &c)
+ : i(c.i)
+ {
+ ++instanceCount;
+ }
+
+ ~Complex()
+ {
+ --instanceCount;
+ }
+
+ int i;
+ static int instanceCount;
+};
+
+int Complex::instanceCount = 0;
+bool operator==(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i == rhs.i; }
+bool operator!=(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i != rhs.i; }
+bool operator<(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i < rhs.i; }
+
+uint qHash(Complex c, uint seed = 0) Q_DECL_NOTHROW { return qHash(c.i, seed); }
+QDebug &operator<<(QDebug &d, Complex c)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "Complex(" << c.i << ")";
+}
+
+
+struct DuplicateStrategyTestType
+{
+ explicit DuplicateStrategyTestType(int i = 0) Q_DECL_NOTHROW
+ : i(i),
+ j(++counter)
+ {
+ }
+
+ int i;
+ int j;
+
+ static int counter;
+};
+
+int DuplicateStrategyTestType::counter = 0;
+
+// only look at the i member, not j. j allows us to identify which instance
+// gets inserted in containers that don't allow for duplicates
+bool operator==(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i == rhs.i;
+}
+
+bool operator!=(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i != rhs.i;
+}
+
+bool operator<(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i < rhs.i;
+}
+
+uint qHash(DuplicateStrategyTestType c, uint seed = 0) Q_DECL_NOTHROW
+{
+ return qHash(c.i, seed);
+}
+
+bool reallyEqual(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i == rhs.i && lhs.j == rhs.j;
+}
+
+QDebug &operator<<(QDebug &d, DuplicateStrategyTestType c)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "DuplicateStrategyTestType(" << c.i << "," << c.j << ")";
+}
+
+
+namespace std {
+template<>
+struct hash<Movable>
+{
+ std::size_t operator()(Movable m) const Q_DECL_NOTHROW
+ {
+ return hash<int>()(m.i);
+ }
+};
+
+template<>
+struct hash<Complex>
+{
+ std::size_t operator()(Complex m) const Q_DECL_NOTHROW
+ {
+ return hash<int>()(m.i);
+ }
+};
+
+template<>
+struct hash<DuplicateStrategyTestType>
+{
+ std::size_t operator()(DuplicateStrategyTestType m) const Q_DECL_NOTHROW
+ {
+ return hash<int>()(m.i);
+ }
+};
+}
+
+// work around the fact that QVarLengthArray has a non-type
+// template parameter, and that breaks non_associative_container_duplicates_strategy
+template<typename T>
+class VarLengthArray : public QVarLengthArray<T>
+{
+public:
+#ifdef Q_COMPILER_INHERITING_CONSTRUCTORS
+ using QVarLengthArray<T>::QVarLengthArray;
+#else
+ template<typename InputIterator>
+ VarLengthArray(InputIterator first, InputIterator last)
+ : QVarLengthArray<T>(first, last)
+ {
+ }
+
+ VarLengthArray(std::initializer_list<T> args)
+ : QVarLengthArray<T>(args)
+ {
+ }
+#endif
+};
class tst_ContainerApiSymmetry : public QObject
{
Q_OBJECT
+ int m_movableInstanceCount;
+ int m_complexInstanceCount;
+
+private Q_SLOTS:
+ void init();
+ void cleanup();
+
+private:
+ template <typename Container>
+ void ranged_ctor_non_associative_impl() const;
+
+ template<template<typename ... T> class Container>
+ void non_associative_container_duplicates_strategy() const;
+
+ template <typename Container>
+ void ranged_ctor_associative_impl() const;
+
+private Q_SLOTS:
+ // non associative
+ void ranged_ctor_std_vector_int() { ranged_ctor_non_associative_impl<std::vector<int>>(); }
+ void ranged_ctor_std_vector_char() { ranged_ctor_non_associative_impl<std::vector<char>>(); }
+ void ranged_ctor_std_vector_QChar() { ranged_ctor_non_associative_impl<std::vector<QChar>>(); }
+ void ranged_ctor_std_vector_Movable() { ranged_ctor_non_associative_impl<std::vector<Movable>>(); }
+ void ranged_ctor_std_vector_Complex() { ranged_ctor_non_associative_impl<std::vector<Complex>>(); }
+ void ranged_ctor_std_vector_duplicates_strategy() { non_associative_container_duplicates_strategy<std::vector>(); }
+
+ void ranged_ctor_QVector_int() { ranged_ctor_non_associative_impl<QVector<int>>(); }
+ void ranged_ctor_QVector_char() { ranged_ctor_non_associative_impl<QVector<char>>(); }
+ void ranged_ctor_QVector_QChar() { ranged_ctor_non_associative_impl<QVector<QChar>>(); }
+ void ranged_ctor_QVector_Movable() { ranged_ctor_non_associative_impl<QVector<Movable>>(); }
+ void ranged_ctor_QVector_Complex() { ranged_ctor_non_associative_impl<QVector<Complex>>(); }
+ void ranged_ctor_QVector_duplicates_strategy() { non_associative_container_duplicates_strategy<QVector>(); }
+
+ void ranged_ctor_QVarLengthArray_int() { ranged_ctor_non_associative_impl<QVarLengthArray<int>>(); }
+ void ranged_ctor_QVarLengthArray_Movable() { ranged_ctor_non_associative_impl<QVarLengthArray<Movable>>(); }
+ void ranged_ctor_QVarLengthArray_Complex() { ranged_ctor_non_associative_impl<QVarLengthArray<Complex>>(); }
+ void ranged_ctor_QVarLengthArray_duplicates_strategy() { non_associative_container_duplicates_strategy<VarLengthArray>(); } // note the VarLengthArray passed
+
+ void ranged_ctor_QList_int() { ranged_ctor_non_associative_impl<QList<int>>(); }
+ void ranged_ctor_QList_Movable() { ranged_ctor_non_associative_impl<QList<Movable>>(); }
+ void ranged_ctor_QList_Complex() { ranged_ctor_non_associative_impl<QList<Complex>>(); }
+ void ranged_ctor_QList_duplicates_strategy() { non_associative_container_duplicates_strategy<QList>(); }
+
+ void ranged_ctor_std_list_int() { ranged_ctor_non_associative_impl<std::list<int>>(); }
+ void ranged_ctor_std_list_Movable() { ranged_ctor_non_associative_impl<std::list<Movable>>(); }
+ void ranged_ctor_std_list_Complex() { ranged_ctor_non_associative_impl<std::list<Complex>>(); }
+ void ranged_ctor_std_list_duplicates_strategy() { non_associative_container_duplicates_strategy<std::list>(); }
+
+ void ranged_ctor_std_forward_list_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ ranged_ctor_non_associative_impl<std::forward_list<int>>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_forward_list_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ ranged_ctor_non_associative_impl<std::forward_list<Movable>>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_forward_list_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ ranged_ctor_non_associative_impl<std::forward_list<Complex>>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_forward_list_duplicates_strategy() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ non_associative_container_duplicates_strategy<std::forward_list>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QLinkedList_int() { ranged_ctor_non_associative_impl<QLinkedList<int>>(); }
+ void ranged_ctor_QLinkedList_Movable() { ranged_ctor_non_associative_impl<QLinkedList<Movable>>(); }
+ void ranged_ctor_QLinkedList_Complex() { ranged_ctor_non_associative_impl<QLinkedList<Complex>>(); }
+ void ranged_ctor_QLinkedList_duplicates_strategy() { non_associative_container_duplicates_strategy<QLinkedList>(); }
+
+ void ranged_ctor_std_set_int() { ranged_ctor_non_associative_impl<std::set<int>>(); }
+ void ranged_ctor_std_set_Movable() { ranged_ctor_non_associative_impl<std::set<Movable>>(); }
+ void ranged_ctor_std_set_Complex() { ranged_ctor_non_associative_impl<std::set<Complex>>(); }
+ void ranged_ctor_std_set_duplicates_strategy() { non_associative_container_duplicates_strategy<std::set>(); }
+
+ void ranged_ctor_std_multiset_int() { ranged_ctor_non_associative_impl<std::multiset<int>>(); }
+ void ranged_ctor_std_multiset_Movable() { ranged_ctor_non_associative_impl<std::multiset<Movable>>(); }
+ void ranged_ctor_std_multiset_Complex() { ranged_ctor_non_associative_impl<std::multiset<Complex>>(); }
+ void ranged_ctor_std_multiset_duplicates_strategy() { non_associative_container_duplicates_strategy<std::multiset>(); }
+
+ void ranged_ctor_std_unordered_set_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_set<int>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_set_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_set<Movable>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_set_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_set<Complex>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_set_duplicates_strategy() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ non_associative_container_duplicates_strategy<std::unordered_set>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+
+ void ranged_ctor_std_unordered_multiset_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_multiset<int>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_multiset_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_multiset<Movable>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_multiset_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_multiset<Complex>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_multiset_duplicates_strategy() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ non_associative_container_duplicates_strategy<std::unordered_multiset>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QSet_int() { ranged_ctor_non_associative_impl<QSet<int>>(); }
+ void ranged_ctor_QSet_Movable() { ranged_ctor_non_associative_impl<QSet<Movable>>(); }
+ void ranged_ctor_QSet_Complex() { ranged_ctor_non_associative_impl<QSet<Complex>>(); }
+ void ranged_ctor_QSet_duplicates_strategy() { non_associative_container_duplicates_strategy<QSet>(); }
+
+ // associative
+ void ranged_ctor_std_map_int() { ranged_ctor_associative_impl<std::map<int, int>>(); }
+ void ranged_ctor_std_map_Movable() { ranged_ctor_associative_impl<std::map<Movable, int>>(); }
+ void ranged_ctor_std_map_Complex() { ranged_ctor_associative_impl<std::map<Complex, int>>(); }
+
+ void ranged_ctor_std_multimap_int() { ranged_ctor_associative_impl<std::multimap<int, int>>(); }
+ void ranged_ctor_std_multimap_Movable() { ranged_ctor_associative_impl<std::multimap<Movable, int>>(); }
+ void ranged_ctor_std_multimap_Complex() { ranged_ctor_associative_impl<std::multimap<Complex, int>>(); }
+
+ void ranged_ctor_unordered_map_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_map<int, int>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_map_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_map<Movable, Movable>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_map_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_map<Complex, Complex>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QHash_int() { ranged_ctor_associative_impl<QHash<int, int>>(); }
+ void ranged_ctor_QHash_Movable() { ranged_ctor_associative_impl<QHash<Movable, int>>(); }
+ void ranged_ctor_QHash_Complex() { ranged_ctor_associative_impl<QHash<Complex, int>>(); }
+
+ void ranged_ctor_unordered_multimap_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_multimap<int, int>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_multimap_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_multimap<Movable, Movable>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_multimap_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_multimap<Complex, Complex>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QMultiHash_int() { ranged_ctor_associative_impl<QMultiHash<int, int>>(); }
+ void ranged_ctor_QMultiHash_Movable() { ranged_ctor_associative_impl<QMultiHash<Movable, int>>(); }
+ void ranged_ctor_QMultiHash_Complex() { ranged_ctor_associative_impl<QMultiHash<Complex, int>>(); }
+
private:
template <typename Container>
void front_back_impl() const;
@@ -58,6 +491,296 @@ private Q_SLOTS:
void front_back_QByteArray() { front_back_impl<QByteArray>(); }
};
+void tst_ContainerApiSymmetry::init()
+{
+ m_movableInstanceCount = Movable::instanceCount;
+ m_complexInstanceCount = Complex::instanceCount;
+}
+
+void tst_ContainerApiSymmetry::cleanup()
+{
+ // very simple leak check
+ QCOMPARE(Movable::instanceCount, m_movableInstanceCount);
+ QCOMPARE(Complex::instanceCount, m_complexInstanceCount);
+}
+
+template <typename Container>
+Container createContainerReference()
+{
+ using V = typename Container::value_type;
+
+ return {V(0), V(1), V(2), V(0)};
+}
+
+template <typename Container>
+void tst_ContainerApiSymmetry::ranged_ctor_non_associative_impl() const
+{
+ using V = typename Container::value_type;
+
+ // the double V(0) is deliberate
+ const auto reference = createContainerReference<Container>();
+
+ // plain array
+ const V values1[] = { V(0), V(1), V(2), V(0) };
+
+ const Container c1(values1, values1 + sizeof(values1)/sizeof(values1[0]));
+
+ // from QList
+ QList<V> l2;
+ l2 << V(0) << V(1) << V(2) << V(0);
+
+ const Container c2a(l2.begin(), l2.end());
+ const Container c2b(l2.cbegin(), l2.cend());
+
+ // from std::list
+ std::list<V> l3;
+ l3.push_back(V(0));
+ l3.push_back(V(1));
+ l3.push_back(V(2));
+ l3.push_back(V(0));
+ const Container c3a(l3.begin(), l3.end());
+
+ // from const std::list
+ const std::list<V> l3c = l3;
+ const Container c3b(l3c.begin(), l3c.end());
+
+ // from itself
+ const Container c4(reference.begin(), reference.end());
+
+ QCOMPARE(c1, reference);
+ QCOMPARE(c2a, reference);
+ QCOMPARE(c2b, reference);
+ QCOMPARE(c3a, reference);
+ QCOMPARE(c3b, reference);
+ QCOMPARE(c4, reference);
+}
+
+
+// type traits for detecting whether a non-associative container
+// accepts duplicated values, and if it doesn't, whether construction/insertion
+// prefer the new values (overwriting) or the old values (rejecting)
+
+struct ContainerAcceptsDuplicateValues {};
+struct ContainerOverwritesDuplicateValues {};
+struct ContainerRejectsDuplicateValues {};
+
+template<typename Container>
+struct ContainerDuplicatedValuesStrategy {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::vector<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QVector<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QVarLengthArray<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<VarLengthArray<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QList<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::list<T...>> : ContainerAcceptsDuplicateValues {};
+
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::forward_list<T...>> : ContainerAcceptsDuplicateValues {};
+#endif
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QLinkedList<T...>> : ContainerAcceptsDuplicateValues {};
+
+// assuming https://cplusplus.github.io/LWG/lwg-active.html#2844 resolution
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::set<T...>> : ContainerRejectsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::multiset<T...>> : ContainerAcceptsDuplicateValues {};
+
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+// assuming https://cplusplus.github.io/LWG/lwg-active.html#2844 resolution
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::unordered_set<T...>> : ContainerRejectsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::unordered_multiset<T...>> : ContainerAcceptsDuplicateValues {};
+#endif
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QSet<T...>> : ContainerRejectsDuplicateValues {};
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, ContainerAcceptsDuplicateValues)
+{
+ // do a deep check for equality, not ordering
+ QVERIFY(std::distance(reference.begin(), reference.end()) == std::distance(c.begin(), c.end()));
+ QVERIFY(std::is_permutation(reference.begin(), reference.end(), c.begin(), &reallyEqual));
+}
+
+enum class IterationOnReference
+{
+ ForwardIteration,
+ ReverseIteration
+};
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl_no_duplicates(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, IterationOnReference ior)
+{
+ std::vector<DuplicateStrategyTestType> valuesAlreadySeen;
+
+ // iterate on reference forward or backwards, depending on ior. this will give
+ // us the expected semantics when checking for duplicated values into c
+ auto it = [&reference, ior]() {
+ switch (ior) {
+ case IterationOnReference::ForwardIteration: return reference.begin();
+ case IterationOnReference::ReverseIteration: return reference.end() - 1;
+ };
+ return std::initializer_list<DuplicateStrategyTestType>::const_iterator();
+ }();
+
+ const auto &end = [&reference, ior]() {
+ switch (ior) {
+ case IterationOnReference::ForwardIteration: return reference.end();
+ case IterationOnReference::ReverseIteration: return reference.begin() - 1;
+ };
+ return std::initializer_list<DuplicateStrategyTestType>::const_iterator();
+ }();
+
+ while (it != end) {
+ const auto &value = *it;
+
+ // check that there is indeed the same value in the container (using operator==)
+ const auto &valueInContainerIterator = std::find(c.begin(), c.end(), value);
+ QVERIFY(valueInContainerIterator != c.end());
+ QVERIFY(value == *valueInContainerIterator);
+
+ // if the value is a duplicate, we don't expect to find it in the container
+ // (when doing a deep comparison). otherwise it should be there
+
+ const auto &valuesAlreadySeenIterator = std::find(valuesAlreadySeen.cbegin(), valuesAlreadySeen.cend(), value);
+ const bool valueIsDuplicated = (valuesAlreadySeenIterator != valuesAlreadySeen.cend());
+
+ const auto &reallyEqualCheck = [&value](const DuplicateStrategyTestType &v) { return reallyEqual(value, v); };
+ QCOMPARE(std::find_if(c.begin(), c.end(), reallyEqualCheck) == c.end(), valueIsDuplicated);
+
+ valuesAlreadySeen.push_back(value);
+
+ switch (ior) {
+ case IterationOnReference::ForwardIteration:
+ ++it;
+ break;
+ case IterationOnReference::ReverseIteration:
+ --it;
+ break;
+ };
+ }
+
+}
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, ContainerRejectsDuplicateValues)
+{
+ non_associative_container_check_duplicates_impl_no_duplicates(reference, c, IterationOnReference::ForwardIteration);
+}
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, ContainerOverwritesDuplicateValues)
+{
+ non_associative_container_check_duplicates_impl_no_duplicates(reference, c, IterationOnReference::ReverseIteration);
+}
+
+template<typename Container>
+void non_associative_container_check_duplicates(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c)
+{
+ non_associative_container_check_duplicates_impl(reference, c, ContainerDuplicatedValuesStrategy<Container>());
+}
+
+template<template<class ... T> class Container>
+void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() const
+{
+ // first and last are "duplicates" -- they compare equal for operator==,
+ // but they differ when using reallyEqual
+ const std::initializer_list<DuplicateStrategyTestType> reference{ DuplicateStrategyTestType{0},
+ DuplicateStrategyTestType{1},
+ DuplicateStrategyTestType{2},
+ DuplicateStrategyTestType{0} };
+ Container<DuplicateStrategyTestType> c1{reference};
+ non_associative_container_check_duplicates(reference, c1);
+
+ Container<DuplicateStrategyTestType> c2{reference.begin(), reference.end()};
+ non_associative_container_check_duplicates(reference, c2);
+}
+
+template <typename Container>
+void tst_ContainerApiSymmetry::ranged_ctor_associative_impl() const
+{
+ using K = typename Container::key_type;
+ using V = typename Container::mapped_type;
+
+ // The double K(0) is deliberate. The order of the elements matters:
+ // * for unique-key STL containers, the first one should be the one inserted (cf. LWG 2844)
+ // * for unique-key Qt containers, the last one should be the one inserted
+ // * for multi-key sorted containers, the order of insertion of identical keys is also the
+ // iteration order (which establishes the equality of the containers)
+ // (although nothing of this is being tested here, that deserves its own testing)
+ const Container reference{
+ { K(0), V(1000) },
+ { K(1), V(1001) },
+ { K(2), V(1002) },
+ { K(0), V(1003) }
+ };
+
+ // Note that using anything not convertible to std::pair doesn't work for
+ // std containers. Their ranged construction is defined in terms of
+ // insert(value_type), which for std associative containers is
+ // std::pair<const K, T>.
+
+ // plain array
+ const std::pair<K, V> values1[] = {
+ std::make_pair(K(0), V(1000)),
+ std::make_pair(K(1), V(1001)),
+ std::make_pair(K(2), V(1002)),
+ std::make_pair(K(0), V(1003))
+ };
+
+ const Container c1(values1, values1 + sizeof(values1)/sizeof(values1[0]));
+
+ // from QList
+ QList<std::pair<K, V>> l2;
+ l2 << std::make_pair(K(0), V(1000))
+ << std::make_pair(K(1), V(1001))
+ << std::make_pair(K(2), V(1002))
+ << std::make_pair(K(0), V(1003));
+
+ const Container c2a(l2.begin(), l2.end());
+ const Container c2b(l2.cbegin(), l2.cend());
+
+ // from std::list
+ std::list<std::pair<K, V>> l3;
+ l3.push_back(std::make_pair(K(0), V(1000)));
+ l3.push_back(std::make_pair(K(1), V(1001)));
+ l3.push_back(std::make_pair(K(2), V(1002)));
+ l3.push_back(std::make_pair(K(0), V(1003)));
+ const Container c3a(l3.begin(), l3.end());
+
+ // from const std::list
+ const std::list<std::pair<K, V>> l3c = l3;
+ const Container c3b(l3c.begin(), l3c.end());
+
+ // from itself
+ const Container c4(reference.begin(), reference.end());
+
+ QCOMPARE(c1, reference);
+ QCOMPARE(c2a, reference);
+ QCOMPARE(c2b, reference);
+ QCOMPARE(c3a, reference);
+ QCOMPARE(c3b, reference);
+ QCOMPARE(c4, reference);
+}
+
template <typename Container>
Container make(int size)
{
diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
index 72299402f0..18432e51a6 100644
--- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
+++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
@@ -48,6 +48,11 @@ class tst_QAlgorithms : public QObject
{
Q_OBJECT
private slots:
+ void swap();
+ void swap2();
+ void convenienceAPI();
+
+#if QT_DEPRECATED_SINCE(5, 2)
void test_qLowerBound_data();
void test_qLowerBound();
void test_qUpperBound_data();
@@ -55,19 +60,23 @@ private slots:
void test_qBinaryFind_data();
void test_qBinaryFind();
void qBinaryFindOneEntry();
- void swap();
- void swap2();
void sortEmptyList();
void sortedList();
void sortAPItest();
void stableSortTest();
void stableSortCorrectnessTest_data();
void stableSortCorrectnessTest();
- void convenienceAPI();
+ void convenienceAPI_deprecated();
void qCountIterators() const;
void qCountContainer() const;
void binaryFindOnLargeContainer() const;
+#if Q_TEST_PERFORMANCE
+ void performance();
+#endif
+
+#endif // QT_DEPRECATED_SINCE(5, 2)
+
void popCount08_data() { popCount_data_impl(sizeof(quint8 )); }
void popCount16_data() { popCount_data_impl(sizeof(quint16)); }
void popCount32_data() { popCount_data_impl(sizeof(quint32)); }
@@ -96,9 +105,6 @@ private slots:
void countLeading64() { countLeading_impl<quint64>(); }
private:
-#if Q_TEST_PERFORMANCE
- void performance();
-#endif
void popCount_data_impl(size_t sizeof_T_Int);
template <typename T_Int>
void popCount_impl();
@@ -112,6 +118,8 @@ private:
void countLeading_impl();
};
+#if QT_DEPRECATED_SINCE(5, 2)
+
class TestInt
{
public:
@@ -172,7 +180,7 @@ ResultSet testRun(ContainerType &container, Algorithm &algorithm, int millisecs)
{
TestInt::lessThanRefCount = 0;
int count = 0;
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() < millisecs) {
++count;
@@ -208,7 +216,7 @@ void printHeader(QStringList &headers)
for (int h = 0; h < headers.count(); ++h) {
cout << setw(20) << setiosflags(ios_base::left) << headers.at(h).toLatin1().constData();
}
- cout << endl;
+ cout << Qt::endl;
}
template <typename ContainerType>
@@ -220,7 +228,7 @@ void print(ContainerType testContainer)
cout << value << " ";
}
- cout << endl;
+ cout << Qt::endl;
}
template <typename Algorithm, typename DataType>
@@ -252,11 +260,13 @@ void testAlgorithm(Algorithm algorithm, QStringList &dataSetTypes)
lessThan << setiosflags(ios_base::left) << setw(10) << result.lessThanRefCount / result.numSorts;
cout << numSorts.str() << lessThan.str();
}
- cout << endl;
+ cout << Qt::endl;
}
}
#endif
+#endif // QT_DEPRECATED_SINCE(5, 2)
+
void tst_QAlgorithms::swap()
{
{
@@ -391,6 +401,17 @@ void tst_QAlgorithms::swap2()
}
}
+void tst_QAlgorithms::convenienceAPI()
+{
+ // Compile-test for QAlgorithm convenience functions.
+
+ QList<int *> pointerList;
+ qDeleteAll(pointerList);
+ qDeleteAll(pointerList.begin(), pointerList.end());
+}
+
+#if QT_DEPRECATED_SINCE(5, 2)
+
void tst_QAlgorithms::sortEmptyList()
{
// Only test if it crashes
@@ -676,7 +697,7 @@ void tst_QAlgorithms::stableSortCorrectnessTest()
QVERIFY(isSorted(sorted));
}
-void tst_QAlgorithms::convenienceAPI()
+void tst_QAlgorithms::convenienceAPI_deprecated()
{
// Compile-test for QAlgorithm convenience functions.
QList<int> list, list2;
@@ -716,10 +737,6 @@ void tst_QAlgorithms::convenienceAPI()
qBinaryFind(list, 1);
qBinaryFind(list.begin(), list.end(), 1);
qBinaryFind(list.begin(), list.end(), 1, qLess<int>());
-
- QList<int *> pointerList;
- qDeleteAll(pointerList);
- qDeleteAll(pointerList.begin(), pointerList.end());
}
template <typename DataType>
@@ -765,21 +782,21 @@ public:
#if Q_TEST_PERFORMANCE
void tst_QAlgorithms::performance()
{
- cout << endl << "Quick sort" << endl;
+ cout << Qt::endl << "Quick sort" << Qt::endl;
testAlgorithm<QuickSortHelper<TestInt>, TestInt>(QuickSortHelper<TestInt>(), dataSetTypes);
- cout << endl << "stable sort" << endl;
+ cout << Qt::endl << "stable sort" << Qt::endl;
testAlgorithm<StableSortHelper<TestInt>, TestInt>(StableSortHelper<TestInt>(), dataSetTypes);
- cout << endl << "std::sort" << endl;
+ cout << Qt::endl << "std::sort" << Qt::endl;
testAlgorithm<StlSortHelper<TestInt>, TestInt>(StlSortHelper<TestInt>(), dataSetTypes);
- cout << endl << "std::stable_sort" << endl;
+ cout << Qt::endl << "std::stable_sort" << Qt::endl;
testAlgorithm<StlStableSortHelper<TestInt>, TestInt>(StlStableSortHelper<TestInt>(), dataSetTypes);
/*
- cout << endl << "Sorting lists of ints" << endl;
- cout << endl << "Quick sort" << endl;
+ cout << Qt::endl << "Sorting lists of ints" << Qt::endl;
+ cout << Qt::endl << "Quick sort" << Qt::endl;
testAlgorithm<QuickSortHelper<int>, int>(QuickSortHelper<int>(), dataSetTypes);
- cout << endl << "std::sort" << endl;
+ cout << Qt::endl << "std::sort" << Qt::endl;
testAlgorithm<StlSortHelper<int>, int>(StlSortHelper<int>(), dataSetTypes);
- cout << endl << "std::stable_sort" << endl;
+ cout << Qt::endl << "std::stable_sort" << Qt::endl;
testAlgorithm<StlStableSortHelper<int>, int>(StlStableSortHelper<int>(), dataSetTypes);
*/
}
@@ -1041,6 +1058,8 @@ void tst_QAlgorithms::binaryFindOnLargeContainer() const
QCOMPARE(foundIt.pos(), 1073987655);
}
+#endif // QT_DEPRECATED_SINCE(5, 2)
+
// alternative implementation of qPopulationCount for comparison:
static Q_DECL_CONSTEXPR const uint bitsSetInNibble[] = {
0, 1, 1, 2, 1, 2, 2, 3,
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
index a00c962510..25e2f21d03 100644
--- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -78,12 +78,8 @@ private slots:
void fromRawData_data();
void fromRawData();
void literals();
-#if defined(Q_COMPILER_VARIADIC_MACROS) && defined(Q_COMPILER_LAMBDA)
void variadicLiterals();
-#endif
-#ifdef Q_COMPILER_RVALUE_REFS
void rValueReferences();
-#endif
void grow();
};
@@ -95,7 +91,7 @@ void tst_QArrayData::referenceCounting()
// Reference counting initialized to 1 (owned)
QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(1) }, 0, 0, 0, 0 };
- QCOMPARE(array.ref.atomic.load(), 1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 1);
QVERIFY(!array.ref.isStatic());
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
@@ -103,19 +99,19 @@ void tst_QArrayData::referenceCounting()
#endif
QVERIFY(array.ref.ref());
- QCOMPARE(array.ref.atomic.load(), 2);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 2);
QVERIFY(array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 1);
QVERIFY(array.ref.ref());
- QCOMPARE(array.ref.atomic.load(), 2);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 2);
QVERIFY(array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 1);
QVERIFY(!array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
// Now would be a good time to free/release allocated data
}
@@ -125,17 +121,17 @@ void tst_QArrayData::referenceCounting()
// Reference counting initialized to 0 (non-sharable)
QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 };
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
QVERIFY(!array.ref.isStatic());
QVERIFY(!array.ref.isSharable());
QVERIFY(!array.ref.ref());
// Reference counting fails, data should be copied
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
QVERIFY(!array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
// Free/release data
}
@@ -145,7 +141,7 @@ void tst_QArrayData::referenceCounting()
// Reference counting initialized to -1 (static read-only data)
QArrayData array = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
- QCOMPARE(array.ref.atomic.load(), -1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), -1);
QVERIFY(array.ref.isStatic());
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
@@ -153,10 +149,10 @@ void tst_QArrayData::referenceCounting()
#endif
QVERIFY(array.ref.ref());
- QCOMPARE(array.ref.atomic.load(), -1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), -1);
QVERIFY(array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), -1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), -1);
}
}
@@ -172,8 +168,8 @@ void tst_QArrayData::sharedNullEmpty()
QVERIFY(empty->ref.isStatic());
QVERIFY(empty->ref.isShared());
- QCOMPARE(null->ref.atomic.load(), -1);
- QCOMPARE(empty->ref.atomic.load(), -1);
+ QCOMPARE(null->ref.atomic.loadRelaxed(), -1);
+ QCOMPARE(empty->ref.atomic.loadRelaxed(), -1);
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QVERIFY(null->ref.isSharable());
@@ -183,14 +179,14 @@ void tst_QArrayData::sharedNullEmpty()
QVERIFY(null->ref.ref());
QVERIFY(empty->ref.ref());
- QCOMPARE(null->ref.atomic.load(), -1);
- QCOMPARE(empty->ref.atomic.load(), -1);
+ QCOMPARE(null->ref.atomic.loadRelaxed(), -1);
+ QCOMPARE(empty->ref.atomic.loadRelaxed(), -1);
QVERIFY(null->ref.deref());
QVERIFY(empty->ref.deref());
- QCOMPARE(null->ref.atomic.load(), -1);
- QCOMPARE(empty->ref.atomic.load(), -1);
+ QCOMPARE(null->ref.atomic.loadRelaxed(), -1);
+ QCOMPARE(empty->ref.atomic.loadRelaxed(), -1);
QVERIFY(null != empty);
@@ -1618,9 +1614,7 @@ void tst_QArrayData::literals()
QCOMPARE(v.size(), size_t(11));
// v.capacity() is unspecified, for now
-#if defined(Q_COMPILER_VARIADIC_MACROS) && defined(Q_COMPILER_LAMBDA)
QVERIFY(v.isStatic());
-#endif
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QVERIFY(v.isSharable());
@@ -1631,9 +1625,20 @@ void tst_QArrayData::literals()
QCOMPARE(const_(v)[i], char('A' + i));
QCOMPARE(const_(v)[10], char('\0'));
}
+
+ {
+ struct LiteralType {
+ int value;
+ Q_DECL_CONSTEXPR LiteralType(int v = 0) : value(v) {}
+ };
+
+ QArrayDataPointer<LiteralType> d = Q_ARRAY_LITERAL(LiteralType, LiteralType(0), LiteralType(1), LiteralType(2));
+ QCOMPARE(d->size, 3);
+ for (int i = 0; i < 3; ++i)
+ QCOMPARE(d->data()[i].value, i);
+ }
}
-#if defined(Q_COMPILER_VARIADIC_MACROS) && defined(Q_COMPILER_LAMBDA)
// Variadic Q_ARRAY_LITERAL need to be available in the current configuration.
void tst_QArrayData::variadicLiterals()
{
@@ -1682,9 +1687,7 @@ void tst_QArrayData::variadicLiterals()
QCOMPARE(const_(v)[i], i);
}
}
-#endif
-#ifdef Q_COMPILER_RVALUE_REFS
// std::remove_reference is in C++11, but requires library support
template <class T> struct RemoveReference { typedef T Type; };
template <class T> struct RemoveReference<T &> { typedef T Type; };
@@ -1767,7 +1770,6 @@ void tst_QArrayData::rValueReferences()
QCOMPARE(v3.size(), size_t(1));
QCOMPARE(v3.front(), 42);
}
-#endif
void tst_QArrayData::grow()
{
diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
index b9bcecd607..513c811788 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
@@ -74,10 +74,12 @@ int main(int argc, char *argv[])
hiddenOption.setDescription(QStringLiteral("THIS SHOULD NEVER APPEAR"));
hiddenOption.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(hiddenOption);
+#if QT_DEPRECATED_SINCE(5, 8)
QCommandLineOption hiddenOption2(QStringList() << QStringLiteral("hidden2"));
hiddenOption2.setDescription(QStringLiteral("NEITHER SHOULD THIS"));
hiddenOption2.setHidden(true);
parser.addOption(hiddenOption2);
+#endif
// This program supports different options depending on the "command" (first argument).
// Call parse() to find out the positional arguments.
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index 7980f1f8f4..1e87c76d2f 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -44,6 +44,7 @@ private slots:
// In-process tests
void testInvalidOptions();
+ void testDuplicateOption();
void testPositionalArguments();
void testBooleanOption_data();
void testBooleanOption();
@@ -75,6 +76,8 @@ private slots:
void testHelpOption();
void testQuoteEscaping();
void testUnknownOption();
+ void testHelpAll_data();
+ void testHelpAll();
};
static char *empty_argv[] = { 0 };
@@ -104,6 +107,15 @@ void tst_QCommandLineParser::testInvalidOptions()
QVERIFY(!parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information."))));
}
+void tst_QCommandLineParser::testDuplicateOption()
+{
+ QCoreApplication app(empty_argc, empty_argv);
+ QCommandLineParser parser;
+ QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("h"), QStringLiteral("Hostname."), QStringLiteral("hostname"))));
+ QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: already having an option named \"h\"");
+ parser.addHelpOption();
+}
+
void tst_QCommandLineParser::testPositionalArguments()
{
QCoreApplication app(empty_argc, empty_argv);
@@ -489,7 +501,7 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes()
void tst_QCommandLineParser::testCpp11StyleInitialization()
{
-#if defined(Q_COMPILER_INITIALIZER_LISTS) && defined(Q_COMPILER_UNIFORM_INIT)
+#if defined(Q_COMPILER_UNIFORM_INIT)
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
@@ -532,7 +544,8 @@ void tst_QCommandLineParser::testVersionOption()
static const char expectedOptionsHelp[] =
"Options:\n"
- " -h, --help Displays this help.\n"
+ " -h, --help Displays help on commandline options.\n"
+ " --help-all Displays help including Qt specific options.\n"
" -v, --version Displays version information.\n"
" --load <url> Load file from URL.\n"
" -o, --output <file> Set output file.\n"
@@ -566,8 +579,8 @@ void tst_QCommandLineParser::testHelpOption_data()
" parsingMode The parsing mode to test.\n"
" command The command to execute.\n");
#ifdef Q_OS_WIN
- expectedOutput.replace(" -h, --help Displays this help.\n",
- " -?, -h, --help Displays this help.\n");
+ expectedOutput.replace(" -h, --help Displays help on commandline options.\n",
+ " -?, -h, --help Displays help on commandline options.\n");
expectedOutput.replace("testhelper/", "testhelper\\");
#endif
@@ -615,8 +628,8 @@ void tst_QCommandLineParser::testHelpOption()
"Arguments:\n"
" resize Resize the object to a new size.\n";
#ifdef Q_OS_WIN
- expectedResizeHelp.replace(" -h, --help Displays this help.\n",
- " -?, -h, --help Displays this help.\n");
+ expectedResizeHelp.replace(" -h, --help Displays help on commandline options.\n",
+ " -?, -h, --help Displays help on commandline options.\n");
expectedResizeHelp.replace("testhelper/", "testhelper\\");
#endif
QCOMPARE(output, QString(expectedResizeHelp));
@@ -670,6 +683,60 @@ void tst_QCommandLineParser::testUnknownOption()
#endif // QT_CONFIG(process)
}
+void tst_QCommandLineParser::testHelpAll_data()
+{
+ QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
+ QTest::addColumn<QString>("expectedHelpOutput");
+
+ QString expectedOutput = QString::fromLatin1(
+ "Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n"
+ "Test helper\n"
+ "\n")
+ + QString::fromLatin1(expectedOptionsHelp) +
+ QString::fromLatin1(
+ " --qmljsdebugger <value> Activates the QML/JS debugger with a specified\n"
+ " port. The value must be of format\n"
+ " port:1234[,block]. \"block\" makes the application\n"
+ " wait for a connection.\n"
+ "\n"
+ "Arguments:\n"
+ " parsingMode The parsing mode to test.\n"
+ " command The command to execute.\n");
+#ifdef Q_OS_WIN
+ expectedOutput.replace(" -h, --help Displays help on commandline options.\n",
+ " -?, -h, --help Displays help on commandline options.\n");
+ expectedOutput.replace("testhelper/", "testhelper\\");
+#endif
+
+ QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << expectedOutput;
+ QTest::newRow("long") << QCommandLineParser::ParseAsLongOptions << expectedOutput;
+}
+
+void tst_QCommandLineParser::testHelpAll()
+{
+#if !QT_CONFIG(process)
+ QSKIP("This test requires QProcess support");
+#else
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+ QSKIP("Deploying executable applications to file system on Android not supported.");
+#endif
+
+ QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
+ QFETCH(QString, expectedHelpOutput);
+ QCoreApplication app(empty_argc, empty_argv);
+ QProcess process;
+ process.start("testhelper/qcommandlineparser_test_helper", QStringList() << QString::number(parsingMode) << "--help-all");
+ QVERIFY(process.waitForFinished(5000));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QString output = process.readAll();
+#ifdef Q_OS_WIN
+ output.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
+#endif
+ QCOMPARE(output.split('\n'), expectedHelpOutput.split('\n')); // easier to debug than the next line, on failure
+ QCOMPARE(output, expectedHelpOutput);
+#endif // QT_CONFIG(process)
+}
+
QTEST_APPLESS_MAIN(tst_QCommandLineParser)
#include "tst_qcommandlineparser.moc"
diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
index 31a5f93822..f305d63d46 100644
--- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
+++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
@@ -68,7 +68,7 @@ void tst_QContiguousCache::assignment()
// copy:
cc1 = cc2;
// move:
- cc1 = qMove(cc2);
+ cc1 = std::move(cc2);
}
void tst_QContiguousCache::empty()
@@ -244,7 +244,7 @@ public:
return *this;
}
- int refCount() const { return d->ref.load(); }
+ int refCount() const { return d->ref.loadRelaxed(); }
private:
RefCountingClassData *d;
};
diff --git a/tests/auto/corelib/tools/qdatetime/BLACKLIST b/tests/auto/corelib/tools/qdatetime/BLACKLIST
deleted file mode 100644
index 3a42ee066b..0000000000
--- a/tests/auto/corelib/tools/qdatetime/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[timeZoneAbbreviation]
-osx
diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
index 0196dd2d23..3af6132695 100644
--- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
+++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
@@ -30,9 +30,7 @@
#include <qeasingcurve.h>
-#ifdef Q_COMPILER_RVALUE_REFS // cpp11() slot
-# include <utility> // for std::move()
-#endif
+#include <utility> // for std::move()
class tst_QEasingCurve : public QObject
{
@@ -55,6 +53,8 @@ private slots:
void testCbrtFloat();
void cpp11();
void quadraticEquation();
+ void streamInOut_data();
+ void streamInOut();
};
void tst_QEasingCurve::type()
@@ -792,7 +792,6 @@ void tst_QEasingCurve::testCbrtFloat()
void tst_QEasingCurve::cpp11()
{
-#ifdef Q_COMPILER_RVALUE_REFS
{
QEasingCurve ec( QEasingCurve::InOutBack );
QEasingCurve copy = std::move(ec); // move ctor
@@ -807,7 +806,6 @@ void tst_QEasingCurve::cpp11()
QCOMPARE( copy.type(), QEasingCurve::InOutBack );
QCOMPARE( ec.type(), type );
}
-#endif
}
void tst_QEasingCurve::quadraticEquation() {
@@ -879,5 +877,36 @@ void tst_QEasingCurve::quadraticEquation() {
}
}
+void tst_QEasingCurve::streamInOut_data()
+{
+ QTest::addColumn<int>("version");
+ QTest::addColumn<bool>("equality");
+
+ QTest::newRow("5.11") << int(QDataStream::Qt_5_11) << false;
+ QTest::newRow("5.13") << int(QDataStream::Qt_5_13) << true;
+}
+
+void tst_QEasingCurve::streamInOut()
+{
+ QFETCH(int, version);
+ QFETCH(bool, equality);
+
+ QEasingCurve orig;
+ orig.addCubicBezierSegment(QPointF(0.43, 0.0025), QPointF(0.38, 0.51), QPointF(0.57, 0.99));
+
+ QEasingCurve copy;
+
+ QByteArray data;
+ QDataStream dsw(&data,QIODevice::WriteOnly);
+ QDataStream dsr(&data,QIODevice::ReadOnly);
+
+ dsw.setVersion(version);
+ dsr.setVersion(version);
+ dsw << orig;
+ dsr >> copy;
+
+ QCOMPARE(copy == orig, equality);
+}
+
QTEST_MAIN(tst_QEasingCurve)
#include "tst_qeasingcurve.moc"
diff --git a/tests/auto/corelib/tools/qhash/qhash.pro b/tests/auto/corelib/tools/qhash/qhash.pro
index 79ffd4e9d1..e96c0d1bf1 100644
--- a/tests/auto/corelib/tools/qhash/qhash.pro
+++ b/tests/auto/corelib/tools/qhash/qhash.pro
@@ -2,3 +2,5 @@ CONFIG += testcase
TARGET = tst_qhash
QT = core testlib
SOURCES = $$PWD/tst_qhash.cpp
+
+DEFINES -= QT_NO_JAVA_STYLE_ITERATORS
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 0015efacfa..f0aaad98bd 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -273,7 +273,7 @@ void tst_QHash::insert1()
{
typedef QHash<QString, QString> Hash;
Hash hash;
- QString key;
+ QString key = QLatin1String(" ");
for (int i = 0; i < 10; ++i) {
key[0] = i + '0';
for (int j = 0; j < 10; ++j) {
@@ -1480,7 +1480,6 @@ void tst_QHash::twoArguments_qHash()
void tst_QHash::initializerList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QHash<int, QString> hash = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}};
QCOMPARE(hash.count(), 2);
QCOMPARE(hash[1], QString("hello"));
@@ -1507,9 +1506,6 @@ void tst_QHash::initializerList()
QMultiHash<int, float> emptyPairs2{{}, {}};
QVERIFY(!emptyPairs2.isEmpty());
-#else
- QSKIP("Compiler doesn't support initializer lists");
-#endif
}
void tst_QHash::eraseValidIteratorOnSharedHash()
diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
index 124e3cdf00..f76f3aa0c6 100644
--- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
+++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
@@ -34,6 +34,8 @@
#include <sstream>
#include <algorithm>
+#include <unordered_set>
+
class tst_QHashFunctions : public QObject
{
Q_OBJECT
@@ -59,6 +61,8 @@ private Q_SLOTS:
void range();
void rangeCommutative();
+ void stdHash();
+
void setGlobalQHashSeed();
};
@@ -281,6 +285,38 @@ void tst_QHashFunctions::rangeCommutative()
(void)qHashRangeCommutative(hashables, hashables + numHashables, seed);
}
+void tst_QHashFunctions::stdHash()
+{
+ {
+ std::unordered_set<QString> s = {QStringLiteral("Hello"), QStringLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QStringLiteral("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QStringView> s = {QStringLiteral("Hello"), QStringLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QStringLiteral("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QLatin1String> s = {QLatin1String("Hello"), QLatin1String("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QLatin1String("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QByteArray> s = {QByteArrayLiteral("Hello"), QByteArrayLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QByteArray("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+}
+
void tst_QHashFunctions::setGlobalQHashSeed()
{
// Setter works as advertised
diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp
index ae65d8f697..31aa5b4e0c 100644
--- a/tests/auto/corelib/tools/qline/tst_qline.cpp
+++ b/tests/auto/corelib/tools/qline/tst_qline.cpp
@@ -53,8 +53,10 @@ private slots:
void testNormalVector();
void testNormalVector_data();
+#if QT_DEPRECATED_SINCE(5, 14)
void testAngle();
void testAngle_data();
+#endif
void testAngle2();
void testAngle2_data();
@@ -205,7 +207,10 @@ void tst_QLine::testIntersection()
QPointF ip;
- QLineF::IntersectType itype = a.intersect(b, &ip);
+ QLineF::IntersectionType itype = a.intersects(b, &ip);
+#if QT_DEPRECATED_SINCE(5, 14)
+ QCOMPARE(a.intersect(b, &ip), itype);
+#endif
QCOMPARE(int(itype), type);
if (type != QLineF::NoIntersection) {
@@ -378,6 +383,7 @@ void tst_QLine::testNormalVector()
QCOMPARE(n.dy(), qreal(nvy));
}
+#if QT_DEPRECATED_SINCE(5, 14)
void tst_QLine::testAngle_data()
{
QTest::addColumn<double>("xa1");
@@ -426,6 +432,7 @@ void tst_QLine::testAngle()
double resultAngle = a.angle(b);
QCOMPARE(qRound(resultAngle), qRound(angle));
}
+#endif
void tst_QLine::testAngle2_data()
{
diff --git a/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro b/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro
index 80630f78ad..c53d553d6d 100644
--- a/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro
+++ b/tests/auto/corelib/tools/qlinkedlist/qlinkedlist.pro
@@ -1,4 +1,7 @@
CONFIG += testcase
TARGET = tst_qlinkedlist
QT = core testlib
+qtConfig(c++14): CONFIG += c++14
+qtConfig(c++1z): CONFIG += c++1z
SOURCES = tst_qlinkedlist.cpp
+DEFINES -= QT_NO_LINKED_LIST
diff --git a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp
index f17d6695f0..df42b5dea9 100644
--- a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp
+++ b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp
@@ -187,6 +187,7 @@ private slots:
void countInt() const;
void countMovable() const;
void countComplex() const;
+ void cpp17ctad() const;
void emptyInt() const;
void emptyMovable() const;
void emptyComplex() const;
@@ -594,6 +595,33 @@ void tst_QLinkedList::countComplex() const
QCOMPARE(liveCount, Complex::getLiveCount());
}
+void tst_QLinkedList::cpp17ctad() const
+{
+#ifdef __cpp_deduction_guides
+#define QVERIFY_IS_LIST_OF(obj, Type) \
+ QVERIFY2((std::is_same<decltype(obj), QLinkedList<Type>>::value), \
+ QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
+#define CHECK(Type, One, Two, Three) \
+ do { \
+ const Type v[] = {One, Two, Three}; \
+ QLinkedList v1 = {One, Two, Three}; \
+ QVERIFY_IS_LIST_OF(v1, Type); \
+ QLinkedList v2(v1.begin(), v1.end()); \
+ QVERIFY_IS_LIST_OF(v2, Type); \
+ QLinkedList v3(std::begin(v), std::end(v)); \
+ QVERIFY_IS_LIST_OF(v3, Type); \
+ } while (false) \
+ /*end*/
+ CHECK(int, 1, 2, 3);
+ CHECK(double, 1.0, 2.0, 3.0);
+ CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
+#undef QVERIFY_IS_LIST_OF
+#undef CHECK
+#else
+ QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
+#endif
+}
+
template<typename T>
void tst_QLinkedList::empty() const
{
@@ -1005,7 +1033,6 @@ void tst_QLinkedList::testSTLIteratorsComplex() const
void tst_QLinkedList::initializeList() const
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QLinkedList<int> v1 { 2, 3, 4 };
QCOMPARE(v1, QLinkedList<int>() << 2 << 3 << 4);
QCOMPARE(v1, (QLinkedList<int> { 2, 3, 4}));
@@ -1014,7 +1041,6 @@ void tst_QLinkedList::initializeList() const
QLinkedList<QLinkedList<int>> v3;
v3 << v1 << (QLinkedList<int>() << 1) << QLinkedList<int>() << v1;
QCOMPARE(v3, v2);
-#endif
}
diff --git a/tests/auto/corelib/tools/qlist/qlist.pro b/tests/auto/corelib/tools/qlist/qlist.pro
index 47f0140abb..118c607880 100644
--- a/tests/auto/corelib/tools/qlist/qlist.pro
+++ b/tests/auto/corelib/tools/qlist/qlist.pro
@@ -1,4 +1,6 @@
CONFIG += testcase
TARGET = tst_qlist
QT = core testlib
+qtConfig(c++14): CONFIG += c++14
+qtConfig(c++1z): CONFIG += c++1z
SOURCES = $$PWD/tst_qlist.cpp
diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
index b3f8130d27..cc9a3a16d1 100644
--- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp
+++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
@@ -310,6 +310,7 @@ private slots:
void lastComplex() const;
void constFirst() const;
void constLast() const;
+ void cpp17ctad() const;
void beginOptimal() const;
void beginMovable() const;
void beginComplex() const;
@@ -364,12 +365,14 @@ private slots:
void takeLastOptimal() const;
void takeLastMovable() const;
void takeLastComplex() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void toSetOptimal() const;
void toSetMovable() const;
void toSetComplex() const;
void toStdListOptimal() const;
void toStdListMovable() const;
void toStdListComplex() const;
+#endif
void toVectorOptimal() const;
void toVectorMovable() const;
void toVectorComplex() const;
@@ -426,8 +429,10 @@ private:
template<typename T> void takeAt() const;
template<typename T> void takeFirst() const;
template<typename T> void takeLast() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template<typename T> void toSet() const;
template<typename T> void toStdList() const;
+#endif
template<typename T> void toVector() const;
template<typename T> void value() const;
@@ -860,6 +865,33 @@ void tst_QList::constLast() const
QVERIFY(listCopy.isSharedWith(list));
}
+void tst_QList::cpp17ctad() const
+{
+#ifdef __cpp_deduction_guides
+#define QVERIFY_IS_LIST_OF(obj, Type) \
+ QVERIFY2((std::is_same<decltype(obj), QList<Type>>::value), \
+ QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
+#define CHECK(Type, One, Two, Three) \
+ do { \
+ const Type v[] = {One, Two, Three}; \
+ QList v1 = {One, Two, Three}; \
+ QVERIFY_IS_LIST_OF(v1, Type); \
+ QList v2(v1.begin(), v1.end()); \
+ QVERIFY_IS_LIST_OF(v2, Type); \
+ QList v3(std::begin(v), std::end(v)); \
+ QVERIFY_IS_LIST_OF(v3, Type); \
+ } while (false) \
+ /*end*/
+ CHECK(int, 1, 2, 3);
+ CHECK(double, 1.0, 2.0, 3.0);
+ CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
+#undef QVERIFY_IS_LIST_OF
+#undef CHECK
+#else
+ QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
+#endif
+}
+
template<typename T>
void tst_QList::last() const
{
@@ -1457,11 +1489,11 @@ void tst_QList::swap() const
list << T_FOO << T_BAR << T_BAZ;
// swap
- list.swap(0, 2);
+ list.swapItemsAt(0, 2);
QCOMPARE(list, QList<T>() << T_BAZ << T_BAR << T_FOO);
// swap again
- list.swap(1, 2);
+ list.swapItemsAt(1, 2);
QCOMPARE(list, QList<T>() << T_BAZ << T_FOO << T_BAR);
QList<T> list2;
@@ -1595,6 +1627,7 @@ void tst_QList::takeLastComplex() const
QCOMPARE(liveCount, Complex::getLiveCount());
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template<typename T>
void tst_QList::toSet() const
{
@@ -1669,6 +1702,7 @@ void tst_QList::toStdListComplex() const
toStdList<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
+#endif
template<typename T>
void tst_QList::toVector() const
@@ -1871,7 +1905,6 @@ void tst_QList::testSTLIteratorsComplex() const
void tst_QList::initializeList() const
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QList<int> v1{2,3,4};
QCOMPARE(v1, QList<int>() << 2 << 3 << 4);
QCOMPARE(v1, (QList<int>{2,3,4}));
@@ -1880,7 +1913,6 @@ void tst_QList::initializeList() const
QList<QList<int>> v3;
v3 << v1 << (QList<int>() << 1) << QList<int>() << v1;
QCOMPARE(v3, v2);
-#endif
}
template<typename T>
diff --git a/tests/auto/corelib/tools/qlocale/BLACKLIST b/tests/auto/corelib/tools/qlocale/BLACKLIST
deleted file mode 100644
index 3eac7c10ed..0000000000
--- a/tests/auto/corelib/tools/qlocale/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[formatTimeZone]
-osx
diff --git a/tests/auto/corelib/tools/qmap/qmap.pro b/tests/auto/corelib/tools/qmap/qmap.pro
index 27820a76c8..2cc772720d 100644
--- a/tests/auto/corelib/tools/qmap/qmap.pro
+++ b/tests/auto/corelib/tools/qmap/qmap.pro
@@ -2,3 +2,5 @@ CONFIG += testcase
TARGET = tst_qmap
QT = core testlib
SOURCES = $$PWD/tst_qmap.cpp
+
+DEFINES -= QT_NO_JAVA_STYLE_ITERATORS
diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
index b39444e76f..d66fd28779 100644
--- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp
+++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
@@ -1319,7 +1319,6 @@ void tst_QMap::checkMostLeftNode()
void tst_QMap::initializerList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QMap<int, QString> map = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}};
QCOMPARE(map.count(), 2);
QCOMPARE(map[1], QString("hello"));
@@ -1346,9 +1345,6 @@ void tst_QMap::initializerList()
QMultiMap<float, float> emptyPairs2{{}, {}};
QVERIFY(!emptyPairs2.isEmpty());
-#else
- QSKIP("Compiler doesn't support initializer lists");
-#endif
}
void tst_QMap::testInsertWithHint()
diff --git a/tests/auto/corelib/tools/qpair/qpair.pro b/tests/auto/corelib/tools/qpair/qpair.pro
index 659be887d3..d684a24a57 100644
--- a/tests/auto/corelib/tools/qpair/qpair.pro
+++ b/tests/auto/corelib/tools/qpair/qpair.pro
@@ -2,3 +2,6 @@ CONFIG += testcase
TARGET = tst_qpair
QT = core testlib
SOURCES = tst_qpair.cpp
+
+# Force C++17 if available (needed due to Q_COMPILER_DEDUCTION_GUIDES)
+contains(QT_CONFIG, c++1z): CONFIG += c++1z
diff --git a/tests/auto/corelib/tools/qpair/tst_qpair.cpp b/tests/auto/corelib/tools/qpair/tst_qpair.cpp
index dedc353e67..3c972329bc 100644
--- a/tests/auto/corelib/tools/qpair/tst_qpair.cpp
+++ b/tests/auto/corelib/tools/qpair/tst_qpair.cpp
@@ -39,6 +39,7 @@ private Q_SLOTS:
void testConstexpr();
void testConversions();
void taskQTBUG_48780_pairContainingCArray();
+ void testDeducationRules();
};
class C { C() {} char _[4]; };
@@ -202,5 +203,30 @@ void tst_QPair::taskQTBUG_48780_pairContainingCArray()
Q_UNUSED(pair);
}
+void tst_QPair::testDeducationRules()
+{
+#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
+ QPair p1{1, 2};
+ static_assert(std::is_same<decltype(p1)::first_type, decltype(1)>::value);
+ static_assert(std::is_same<decltype(p1)::second_type, decltype(2)>::value);
+ QCOMPARE(p1.first, 1);
+ QCOMPARE(p1.second, 2);
+
+ QPair p2{QString("string"), 2};
+ static_assert(std::is_same<decltype(p2)::first_type, QString>::value);
+ static_assert(std::is_same<decltype(p2)::second_type, decltype(2)>::value);
+ QCOMPARE(p2.first, "string");
+ QCOMPARE(p2.second, 2);
+
+ QPair p3(p2);
+ static_assert(std::is_same<decltype(p3)::first_type, decltype(p2)::first_type>::value);
+ static_assert(std::is_same<decltype(p3)::second_type, decltype(p2)::second_type>::value);
+ QCOMPARE(p3.first, "string");
+ QCOMPARE(p3.second, 2);
+#else
+ QSKIP("Unsupported");
+#endif
+}
+
QTEST_APPLESS_MAIN(tst_QPair)
#include "tst_qpair.moc"
diff --git a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp
index 8e184f3ef3..f25492d2db 100644
--- a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp
+++ b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp
@@ -42,6 +42,8 @@ private slots:
void getSet_data();
void getSet();
+ void transposed();
+
void rx();
void ry();
@@ -126,6 +128,11 @@ void tst_QPoint::getSet()
QCOMPARE(point.y(), i);
}
+void tst_QPoint::transposed()
+{
+ QCOMPARE(QPoint(1, 2).transposed(), QPoint(2, 1));
+}
+
void tst_QPoint::rx()
{
const QPoint originalPoint(-1, 0);
diff --git a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp
index d4ccdf7ba6..e78a8e3082 100644
--- a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp
+++ b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp
@@ -46,6 +46,8 @@ private slots:
void getSet_data();
void getSet();
+ void transposed();
+
void rx();
void ry();
@@ -154,6 +156,11 @@ void tst_QPointF::getSet()
QCOMPARE(point.y(), r);
}
+void tst_QPointF::transposed()
+{
+ QCOMPARE(QPointF(1, 2).transposed(), QPointF(2, 1));
+}
+
void tst_QPointF::rx()
{
const QPointF originalPoint(-1, 0);
diff --git a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
index b943b04e23..ea94cc2999 100644
--- a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
+++ b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
@@ -327,7 +327,7 @@ struct RefCounted
~RefCounted()
{
- QVERIFY( ref.load() == 0 );
+ QVERIFY( ref.loadRelaxed() == 0 );
instanceCount.deref();
}
@@ -369,13 +369,13 @@ void scopedPointerComparisonTest(const A1 &a1, const A2 &a2, const B &b)
void tst_QScopedPointer::comparison()
{
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
{
RefCounted *a = new RefCounted;
RefCounted *b = new RefCounted;
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
QScopedPointer<RefCounted> pa1(a);
QScopedPointer<RefCounted> pa2(a);
@@ -387,16 +387,16 @@ void tst_QScopedPointer::comparison()
pa2.take();
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
}
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
{
RefCounted *a = new RefCounted[42];
RefCounted *b = new RefCounted[43];
- QCOMPARE( RefCounted::instanceCount.load(), 85 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 85 );
QScopedArrayPointer<RefCounted> pa1(a);
QScopedArrayPointer<RefCounted> pa2(a);
@@ -406,10 +406,10 @@ void tst_QScopedPointer::comparison()
pa2.take();
- QCOMPARE( RefCounted::instanceCount.load(), 85 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 85 );
}
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
{
// QScopedSharedPointer is an internal helper class -- it is unsupported!
@@ -417,42 +417,42 @@ void tst_QScopedPointer::comparison()
RefCounted *a = new RefCounted;
RefCounted *b = new RefCounted;
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
QSharedDataPointer<RefCounted> pa1(a);
QSharedDataPointer<RefCounted> pa2(a);
QSharedDataPointer<RefCounted> pb(b);
- QCOMPARE( a->ref.load(), 2 );
- QCOMPARE( b->ref.load(), 1 );
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( a->ref.loadRelaxed(), 2 );
+ QCOMPARE( b->ref.loadRelaxed(), 1 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
scopedPointerComparisonTest(pa1, pa2, pb);
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
}
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
}
void tst_QScopedPointer::array()
{
- int instCount = RefCounted::instanceCount.load();
+ int instCount = RefCounted::instanceCount.loadRelaxed();
{
QScopedArrayPointer<RefCounted> array;
array.reset(new RefCounted[42]);
- QCOMPARE(instCount + 42, RefCounted::instanceCount.load());
+ QCOMPARE(instCount + 42, RefCounted::instanceCount.loadRelaxed());
}
- QCOMPARE(instCount, RefCounted::instanceCount.load());
+ QCOMPARE(instCount, RefCounted::instanceCount.loadRelaxed());
{
QScopedArrayPointer<RefCounted> array(new RefCounted[42]);
- QCOMPARE(instCount + 42, RefCounted::instanceCount.load());
+ QCOMPARE(instCount + 42, RefCounted::instanceCount.loadRelaxed());
array.reset(new RefCounted[28]);
- QCOMPARE(instCount + 28, RefCounted::instanceCount.load());
+ QCOMPARE(instCount + 28, RefCounted::instanceCount.loadRelaxed());
array.reset(0);
- QCOMPARE(instCount, RefCounted::instanceCount.load());
+ QCOMPARE(instCount, RefCounted::instanceCount.loadRelaxed());
}
- QCOMPARE(instCount, RefCounted::instanceCount.load());
+ QCOMPARE(instCount, RefCounted::instanceCount.loadRelaxed());
}
diff --git a/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp b/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp
index 656dd6a6e3..9b607db608 100644
--- a/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp
+++ b/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp
@@ -46,6 +46,7 @@ private Q_SLOTS:
void rollbackToPreviousCommit();
void exceptions();
void earlyExitScope();
+ void moveOnly();
private:
void earlyExitScope_helper(int exitpoint, int &member);
};
@@ -190,5 +191,17 @@ void tst_QScopedValueRollback::earlyExitScope_helper(int exitpoint, int& member)
r.commit();
}
+void tst_QScopedValueRollback::moveOnly()
+{
+ std::unique_ptr<int> uniquePtr;
+ std::unique_ptr<int> newVal(new int(5));
+ QVERIFY(!uniquePtr);
+ {
+ QScopedValueRollback<std::unique_ptr<int>> r(uniquePtr, std::move(newVal));
+ QVERIFY(uniquePtr);
+ }
+ QVERIFY(!uniquePtr);
+}
+
QTEST_MAIN(tst_QScopedValueRollback)
#include "tst_qscopedvaluerollback.moc"
diff --git a/tests/auto/corelib/tools/qset/qset.pro b/tests/auto/corelib/tools/qset/qset.pro
index 10ae3307d1..3ae4bc4805 100644
--- a/tests/auto/corelib/tools/qset/qset.pro
+++ b/tests/auto/corelib/tools/qset/qset.pro
@@ -1,4 +1,8 @@
CONFIG += testcase
TARGET = tst_qset
QT = core testlib
+qtConfig(c++14): CONFIG += c++14
+qtConfig(c++1z): CONFIG += c++1z
SOURCES = tst_qset.cpp
+
+DEFINES -= QT_NO_JAVA_STYLE_ITERATORS
diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp
index 0b60350380..8a545712a2 100644
--- a/tests/auto/corelib/tools/qset/tst_qset.cpp
+++ b/tests/auto/corelib/tools/qset/tst_qset.cpp
@@ -54,6 +54,7 @@ private slots:
void detach();
void isDetached();
void clear();
+ void cpp17ctad();
void remove();
void contains();
void containsSet();
@@ -325,6 +326,33 @@ void tst_QSet::clear()
QVERIFY(set2.size() == 0);
}
+void tst_QSet::cpp17ctad()
+{
+#ifdef __cpp_deduction_guides
+#define QVERIFY_IS_SET_OF(obj, Type) \
+ QVERIFY2((std::is_same<decltype(obj), QSet<Type>>::value), \
+ QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
+#define CHECK(Type, One, Two, Three) \
+ do { \
+ const Type v[] = {One, Two, Three}; \
+ QSet v1 = {One, Two, Three}; \
+ QVERIFY_IS_SET_OF(v1, Type); \
+ QSet v2(v1.begin(), v1.end()); \
+ QVERIFY_IS_SET_OF(v2, Type); \
+ QSet v3(std::begin(v), std::end(v)); \
+ QVERIFY_IS_SET_OF(v3, Type); \
+ } while (false) \
+ /*end*/
+ CHECK(int, 1, 2, 3);
+ CHECK(double, 1.0, 2.0, 3.0);
+ CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
+#undef QVERIFY_IS_SET_OF
+#undef CHECK
+#else
+ QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
+#endif
+}
+
void tst_QSet::remove()
{
QSet<QString> set1;
@@ -955,7 +983,6 @@ void tst_QSet::makeSureTheComfortFunctionsCompile()
void tst_QSet::initializerList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QSet<int> set = {1, 1, 2, 3, 4, 5};
QCOMPARE(set.count(), 5);
QVERIFY(set.contains(1));
@@ -976,9 +1003,6 @@ void tst_QSet::initializerList()
QSet<int> set3{{}, {}, {}};
QVERIFY(!set3.isEmpty());
-#else
- QSKIP("Compiler doesn't support initializer lists");
-#endif
}
void tst_QSet::qhash()
@@ -1011,15 +1035,7 @@ void tst_QSet::qhash()
// check that sets of sets work:
//
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QSet<QSet<int> > intSetSet = { { 0, 1, 2 }, { 0, 1 }, { 1, 2 } };
-#else
- QSet<QSet<int> > intSetSet;
- QSet<int> intSet01, intSet12;
- intSet01 << 0 << 1;
- intSet12 << 1 << 2;
- intSetSet << intSet01 << intSet12 << (intSet01|intSet12);
-#endif
QCOMPARE(intSetSet.size(), 3);
}
}
diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
index e97848fb1c..f3c647515a 100644
--- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
@@ -75,10 +75,13 @@ private slots:
void functionCallDownCast();
void upCast();
void qobjectWeakManagement();
+#if QT_DEPRECATED_SINCE(5, 0)
void noSharedPointerFromWeakQObject();
void sharedPointerFromQObjectWithWeak();
+#endif
void weakQObjectFromSharedPointer();
void objectCast();
+ void objectCastStdSharedPtr();
void differentPointers();
void virtualBaseDifferentPointers();
#ifndef QTEST_NO_RTTI
@@ -90,9 +93,7 @@ private slots:
#endif
void constCorrectness();
void customDeleter();
-#ifdef Q_COMPILER_LAMBDA
void lambdaCustomDeleter();
-#endif
void creating();
void creatingCvQualified();
void creatingVariadic();
@@ -227,7 +228,6 @@ struct NoDefaultConstructorConstRef2
NoDefaultConstructorConstRef2(const QByteArray &ba, int i = 42) : str(QString::fromLatin1(ba)), i(i) {}
};
-#ifdef Q_COMPILER_RVALUE_REFS
struct NoDefaultConstructorRRef1
{
int &i;
@@ -239,7 +239,6 @@ struct NoDefaultConstructorRRef2
std::unique_ptr<int> i;
NoDefaultConstructorRRef2(std::unique_ptr<int> &&i) : i(std::move(i)) {}
};
-#endif
void tst_QSharedPointer::basics_data()
{
@@ -297,8 +296,8 @@ void tst_QSharedPointer::basics()
QVERIFY(! (ptr == otherData));
QVERIFY(! (otherData == ptr));
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
{
// create another object:
@@ -310,8 +309,8 @@ void tst_QSharedPointer::basics()
// otherData is deleted here
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
{
// create a copy:
@@ -328,8 +327,8 @@ void tst_QSharedPointer::basics()
QCOMPARE(copy.get(), aData);
QVERIFY(copy == aData);
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
{
// create a weak reference:
@@ -361,8 +360,8 @@ void tst_QSharedPointer::basics()
QCOMPARE(strong.data(), aData);
QCOMPARE(strong.get(), aData);
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
// aData is deleted here
}
@@ -508,7 +507,6 @@ void tst_QSharedPointer::swap()
void tst_QSharedPointer::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QSharedPointer<int> p1, p2(new int(42)), control = p2;
QVERIFY(p1 != control);
QVERIFY(p1.isNull());
@@ -561,9 +559,6 @@ void tst_QSharedPointer::moveSemantics()
QVERIFY(w1.isNull());
QVERIFY(w2.isNull());
QVERIFY(w3.isNull());
-#else
- QSKIP("This test requires C++11 rvalue/move semantics support in the compiler.");
-#endif
}
void tst_QSharedPointer::useOfForwardDeclared()
@@ -580,10 +575,10 @@ void tst_QSharedPointer::useOfForwardDeclared()
// move assignment:
QSharedPointer<ForwardDeclared> sp4;
- sp4 = qMove(sp);
+ sp4 = std::move(sp);
// and move constuction:
- QSharedPointer<ForwardDeclared> sp5 = qMove(sp2);
+ QSharedPointer<ForwardDeclared> sp5 = std::move(sp2);
// swapping:
sp4.swap(sp3);
@@ -850,15 +845,15 @@ void tst_QSharedPointer::upCast()
QVERIFY(baseptr == derivedptr);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr);
QVERIFY(baseptr == derivedptr);
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -866,16 +861,16 @@ void tst_QSharedPointer::upCast()
QVERIFY(baseptr == derivedptr);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>();
QVERIFY(baseptr == derivedptr);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
class OtherObject: public QObject
@@ -889,6 +884,78 @@ void tst_QSharedPointer::qobjectWeakManagement()
QWeakPointer<QObject> weak;
weak = QWeakPointer<QObject>();
QVERIFY(weak.isNull());
+ QVERIFY(weak.toStrongRef().isNull());
+ }
+
+ {
+ QObject *obj = new QObject;
+ QSharedPointer<QObject> shared(obj);
+ QWeakPointer<QObject> weak(shared);
+ QVERIFY(!weak.isNull());
+ QVERIFY(weak.toStrongRef() == obj);
+
+ // now delete
+ shared.reset();
+ QVERIFY(weak.isNull());
+ }
+ safetyCheck();
+
+ {
+ // same, bit with operator=
+ QObject *obj = new QObject;
+ QSharedPointer<QObject> shared(obj);
+ QWeakPointer<QObject> weak;
+ weak = shared;
+ QVERIFY(!weak.isNull());
+ QVERIFY(weak.toStrongRef() == obj);
+
+ // now delete
+ shared.reset();
+ QVERIFY(weak.isNull());
+ }
+ safetyCheck();
+
+ {
+ // with two QWeakPointers
+ QObject *obj = new QObject;
+ QSharedPointer<QObject> shared(obj);
+ QWeakPointer<QObject> weak(shared);
+
+ {
+ QWeakPointer<QObject> weak2(shared);
+ QVERIFY(!weak2.isNull());
+ QVERIFY(weak == weak2);
+ }
+ QVERIFY(!weak.isNull());
+
+ shared.reset();
+ QVERIFY(weak.isNull());
+ }
+ safetyCheck();
+
+ {
+ // same, but delete the pointer while two QWeakPointers exist
+ QObject *obj = new QObject;
+ QSharedPointer<QObject> shared(obj);
+ QWeakPointer<QObject> weak(shared);
+
+ {
+ QWeakPointer<QObject> weak2(shared);
+ QVERIFY(!weak2.isNull());
+
+ shared.reset();
+ QVERIFY(weak.isNull());
+ QVERIFY(weak2.isNull());
+ }
+ QVERIFY(weak.isNull());
+ }
+ safetyCheck();
+
+#if QT_DEPRECATED_SINCE(5, 0)
+ {
+ QWeakPointer<QObject> weak;
+ weak = QWeakPointer<QObject>();
+ QVERIFY(weak.isNull());
QVERIFY(!weak.data());
}
@@ -979,8 +1046,10 @@ void tst_QSharedPointer::qobjectWeakManagement()
QVERIFY(weak.isNull());
}
safetyCheck();
+#endif
}
+#if QT_DEPRECATED_SINCE(5, 0)
void tst_QSharedPointer::noSharedPointerFromWeakQObject()
{
// you're not allowed to create a QSharedPointer from an unmanaged QObject
@@ -1014,18 +1083,32 @@ void tst_QSharedPointer::sharedPointerFromQObjectWithWeak()
}
QVERIFY(weak.isNull());
}
+#endif
void tst_QSharedPointer::weakQObjectFromSharedPointer()
{
- // this is the inverse of the above: you're allowed to create a QWeakPointer
- // from a managed QObject
- QSharedPointer<QObject> shared(new QObject);
- QWeakPointer<QObject> weak = shared.data();
- QVERIFY(!weak.isNull());
+#if QT_DEPRECATED_SINCE(5, 0)
+ {
+ // this is the inverse of the above: you're allowed to create a QWeakPointer
+ // from a managed QObject
+ QSharedPointer<QObject> shared(new QObject);
+ QWeakPointer<QObject> weak = shared.data();
+ QVERIFY(!weak.isNull());
- // delete:
- shared.clear();
- QVERIFY(weak.isNull());
+ // delete:
+ shared.clear();
+ QVERIFY(weak.isNull());
+ }
+#endif
+ {
+ QSharedPointer<QObject> shared(new QObject);
+ QWeakPointer<QObject> weak = shared;
+ QVERIFY(!weak.isNull());
+
+ // delete:
+ shared.clear();
+ QVERIFY(weak.isNull());
+ }
}
void tst_QSharedPointer::objectCast()
@@ -1122,6 +1205,60 @@ void tst_QSharedPointer::objectCast()
safetyCheck();
}
+
+void tst_QSharedPointer::objectCastStdSharedPtr()
+{
+ {
+ OtherObject *data = new OtherObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform successful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
+ QVERIFY(ptr.get());
+ QVERIFY(ptr.get() == data);
+
+ QVERIFY(baseptr.get() == data);
+ }
+
+ {
+ OtherObject *data = new OtherObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform successful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
+ QVERIFY(ptr.get());
+ QVERIFY(ptr.get() == data);
+
+ QVERIFY(!baseptr.get());
+ }
+
+ {
+ QObject *data = new QObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform unsuccessful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
+ QVERIFY(!ptr.get());
+
+ QVERIFY(baseptr.get() == data);
+ }
+
+ {
+ QObject *data = new QObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform unsuccessful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
+ QVERIFY(!ptr.get());
+
+ QVERIFY(baseptr.get() == data);
+ }
+}
+
void tst_QSharedPointer::differentPointers()
{
{
@@ -1250,8 +1387,8 @@ void tst_QSharedPointer::dynamicCast()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -1260,8 +1397,8 @@ void tst_QSharedPointer::dynamicCast()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
@@ -1269,8 +1406,8 @@ void tst_QSharedPointer::dynamicCast()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
void tst_QSharedPointer::dynamicCastDifferentPointers()
@@ -1285,8 +1422,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -1295,8 +1432,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DiffPtrDerivedData> derivedptr = baseptr.dynamicCast<DiffPtrDerivedData>();
@@ -1304,8 +1441,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
Stuffing *nakedptr = dynamic_cast<Stuffing *>(baseptr.data());
@@ -1330,8 +1467,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -1340,8 +1477,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<VirtualDerived> derivedptr = baseptr.dynamicCast<VirtualDerived>();
@@ -1349,8 +1486,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
void tst_QSharedPointer::dynamicCastFailure()
@@ -1362,15 +1499,15 @@ void tst_QSharedPointer::dynamicCastFailure()
QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
QVERIFY(derivedptr.isNull());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
QVERIFY(derivedptr.isNull());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
void tst_QSharedPointer::dynamicCastFailureNoLeak()
@@ -1677,7 +1814,6 @@ void tst_QSharedPointer::customDeleter()
safetyCheck();
}
-#ifdef Q_COMPILER_LAMBDA
// The compiler needs to be in C++11 mode and to support lambdas
void tst_QSharedPointer::lambdaCustomDeleter()
{
@@ -1705,7 +1841,6 @@ void tst_QSharedPointer::lambdaCustomDeleter()
}
safetyCheck();
}
-#endif
void customQObjectDeleterFn(QObject *obj)
{
@@ -1741,8 +1876,8 @@ void tst_QSharedPointer::creating()
QCOMPARE(Data::destructorCounter, 1);
// valgrind will complain here if something happened to the pointer
- QVERIFY(d->weakref.load() == 1);
- QVERIFY(d->strongref.load() == 0);
+ QVERIFY(d->weakref.loadRelaxed() == 1);
+ QVERIFY(d->strongref.loadRelaxed() == 0);
}
safetyCheck();
@@ -1977,7 +2112,7 @@ void tst_QSharedPointer::threadStressTest()
for (int r = 0; r < 5; ++r) {
QVector<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0);
QSharedPointer<ThreadData> base = QSharedPointer<ThreadData>(new ThreadData(&counter));
- counter.store(0);
+ counter.storeRelaxed(0);
// set the pointers
for (int i = 0; i < strongThreadCount; ++i) {
@@ -2011,8 +2146,8 @@ void tst_QSharedPointer::threadStressTest()
// verify that the count is the right range
int minValue = strongThreadCount;
int maxValue = strongThreadCount + weakThreadCount;
- QVERIFY(counter.load() >= minValue);
- QVERIFY(counter.load() <= maxValue);
+ QVERIFY(counter.loadRelaxed() >= minValue);
+ QVERIFY(counter.loadRelaxed() <= maxValue);
}
}
@@ -2245,11 +2380,9 @@ void tst_QSharedPointer::invalidConstructs_data()
<< &QTest::QExternalTest::tryCompileFail
<< "struct IncompatibleCustomDeleter { void operator()(int *); };\n"
"QSharedPointer<Data> ptr(new Data, IncompatibleCustomDeleter());\n";
-#ifdef Q_COMPILER_LAMBDA
QTest::newRow("incompatible-custom-lambda-deleter")
<< &QTest::QExternalTest::tryCompileFail
<< "QSharedPointer<Data> ptr(new Data, [](int *) {});\n";
-#endif
}
void tst_QSharedPointer::invalidConstructs()
@@ -2333,6 +2466,7 @@ void tst_QSharedPointer::qvariantCast()
// Intentionally does not compile.
// QSharedPointer<int> sop = qSharedPointerFromVariant<int>(v);
+#if QT_DEPRECATED_SINCE(5, 0)
v = QVariant::fromValue(sp.toWeakRef());
{
@@ -2376,6 +2510,7 @@ void tst_QSharedPointer::qvariantCast()
QWeakPointer<QThread> other = qWeakPointerFromVariant<QThread>(v);
QVERIFY(!other);
}
+#endif
}
class SomeClass : public QEnableSharedFromThis<SomeClass>
diff --git a/tests/auto/corelib/tools/qsize/tst_qsize.cpp b/tests/auto/corelib/tools/qsize/tst_qsize.cpp
index 385ff18ce5..6824bad9c8 100644
--- a/tests/auto/corelib/tools/qsize/tst_qsize.cpp
+++ b/tests/auto/corelib/tools/qsize/tst_qsize.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <qsize.h>
+Q_DECLARE_METATYPE(QMargins)
class tst_QSize : public QObject
{
@@ -43,6 +44,9 @@ private slots:
void boundedTo_data();
void boundedTo();
+ void grownOrShrunkBy_data();
+ void grownOrShrunkBy();
+
void transpose_data();
void transpose();
};
@@ -186,6 +190,46 @@ void tst_QSize::boundedTo()
QCOMPARE( input1.boundedTo(input2), expected);
}
+void tst_QSize::grownOrShrunkBy_data()
+{
+ QTest::addColumn<QSize>("input");
+ QTest::addColumn<QMargins>("margins");
+ QTest::addColumn<QSize>("grown");
+ QTest::addColumn<QSize>("shrunk");
+
+ auto row = [](QSize i, QMargins m, QSize g, QSize s) {
+ QTest::addRow("{%d,%d}/{%d,%d,%d,%d}", i.width(), i.height(),
+ m.left(), m.top(), m.right(), m.bottom())
+ << i << m << g << s;
+ };
+
+ const QSize zero = {0, 0};
+ const QSize some = {100, 200};
+ const QMargins zeroMargins = {};
+ const QMargins negative = {-1, -2, -3, -4};
+ const QMargins positive = { 1, 2, 3, 4};
+
+ row(zero, zeroMargins, zero, zero);
+ row(zero, negative, {-4, -6}, { 4, 6});
+ row(zero, positive, { 4, 6}, {-4, -6});
+ row(some, zeroMargins, some, some);
+ row(some, negative, { 96, 194}, {104, 206});
+ row(some, positive, {104, 206}, { 96, 194});
+}
+
+void tst_QSize::grownOrShrunkBy()
+{
+ QFETCH(const QSize, input);
+ QFETCH(const QMargins, margins);
+ QFETCH(const QSize, grown);
+ QFETCH(const QSize, shrunk);
+
+ QCOMPARE(input.grownBy(margins), grown);
+ QCOMPARE(input.shrunkBy(margins), shrunk);
+ QCOMPARE(grown.shrunkBy(margins), input);
+ QCOMPARE(shrunk.grownBy(margins), input);
+}
+
void tst_QSize::transpose_data()
{
QTest::addColumn<QSize>("input1");
diff --git a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp
index 42801d63a9..bbffa74a62 100644
--- a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp
+++ b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <qsize.h>
+Q_DECLARE_METATYPE(QMarginsF)
class tst_QSizeF : public QObject
{
@@ -45,6 +46,9 @@ private slots:
void boundedTo_data();
void boundedTo();
+ void grownOrShrunkBy_data();
+ void grownOrShrunkBy();
+
void transpose_data();
void transpose();
};
@@ -152,6 +156,46 @@ void tst_QSizeF::boundedTo() {
QCOMPARE( input1.boundedTo(input2), expected);
}
+void tst_QSizeF::grownOrShrunkBy_data()
+{
+ QTest::addColumn<QSizeF>("input");
+ QTest::addColumn<QMarginsF>("margins");
+ QTest::addColumn<QSizeF>("grown");
+ QTest::addColumn<QSizeF>("shrunk");
+
+ auto row = [](QSizeF i, QMarginsF m, QSizeF g, QSizeF s) {
+ QTest::addRow("{%g,%g}/{%g,%g,%g,%g}", i.width(), i.height(),
+ m.left(), m.top(), m.right(), m.bottom())
+ << i << m << g << s;
+ };
+
+ const QSizeF zero = {0, 0};
+ const QSizeF some = {100, 200};
+ const QMarginsF zeroMargins = {};
+ const QMarginsF negative = {-1, -2, -3, -4};
+ const QMarginsF positive = { 1, 2, 3, 4};
+
+ row(zero, zeroMargins, zero, zero);
+ row(zero, negative, {-4, -6}, { 4, 6});
+ row(zero, positive, { 4, 6}, {-4, -6});
+ row(some, zeroMargins, some, some);
+ row(some, negative, { 96, 194}, {104, 206});
+ row(some, positive, {104, 206}, { 96, 194});
+}
+
+void tst_QSizeF::grownOrShrunkBy()
+{
+ QFETCH(const QSizeF, input);
+ QFETCH(const QMarginsF, margins);
+ QFETCH(const QSizeF, grown);
+ QFETCH(const QSizeF, shrunk);
+
+ QCOMPARE(input.grownBy(margins), grown);
+ QCOMPARE(input.shrunkBy(margins), shrunk);
+ QCOMPARE(grown.shrunkBy(margins), input);
+ QCOMPARE(shrunk.grownBy(margins), input);
+}
+
void tst_QSizeF::transpose_data() {
QTest::addColumn<QSizeF>("input1");
QTest::addColumn<QSizeF>("expected");
diff --git a/tests/auto/corelib/tools/qtimeline/BLACKLIST b/tests/auto/corelib/tools/qtimeline/BLACKLIST
index 5611969b4d..9794b0059f 100644
--- a/tests/auto/corelib/tools/qtimeline/BLACKLIST
+++ b/tests/auto/corelib/tools/qtimeline/BLACKLIST
@@ -1,9 +1,7 @@
[interpolation]
-windows
-osx-10.12
-osx-10.13
-[duration]
-windows
+windows-10 msvc-2015
+osx
[frameRate]
osx-10.12
osx-10.13
+
diff --git a/tests/auto/corelib/tools/qvarlengtharray/qvarlengtharray.pro b/tests/auto/corelib/tools/qvarlengtharray/qvarlengtharray.pro
index 108fb33db5..14b2bc213b 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/qvarlengtharray.pro
+++ b/tests/auto/corelib/tools/qvarlengtharray/qvarlengtharray.pro
@@ -1,4 +1,6 @@
CONFIG += testcase
TARGET = tst_qvarlengtharray
QT = core testlib
+qtConfig(c++14): CONFIG += c++14
+qtConfig(c++1z): CONFIG += c++1z
SOURCES = tst_qvarlengtharray.cpp
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index 5737db760c..a1d0100f96 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -44,6 +44,7 @@ private slots:
void realloc();
void reverseIterators();
void count();
+ void cpp17ctad();
void first();
void last();
void squeeze();
@@ -57,27 +58,28 @@ private slots:
void initializeListComplex();
void insertMove();
void nonCopyable();
+ void implicitDefaultCtor();
private:
template<typename T>
void initializeList();
};
-int fooCtor = 0;
-int fooDtor = 0;
-
-struct Foo
+struct Tracker
{
- int *p;
-
- Foo() { p = new int; ++fooCtor; }
- Foo(const Foo &/*other*/) { p = new int; ++fooCtor; }
+ static int count;
+ Tracker() { ++count; }
+ Tracker(const Tracker &) { ++count; }
+ Tracker(Tracker &&) { ++count; }
- void operator=(const Foo & /* other */) { }
+ Tracker &operator=(const Tracker &) = default;
+ Tracker &operator=(Tracker &&) = default;
- ~Foo() { delete p; ++fooDtor; }
+ ~Tracker() { --count; }
};
+int Tracker::count = 0;
+
void tst_QVarLengthArray::append()
{
QVarLengthArray<QString, 2> v;
@@ -129,6 +131,23 @@ void tst_QVarLengthArray::removeLast()
v.removeLast();
QCOMPARE(v.size(), 2);
}
+
+ {
+ Tracker t;
+ QCOMPARE(Tracker::count, 1);
+ QVarLengthArray<Tracker, 2> v;
+ v.append(t);
+ v.append({});
+ QCOMPARE(Tracker::count, 3);
+ v.removeLast();
+ QCOMPARE(Tracker::count, 2);
+ v.append(t);
+ v.append({});
+ QCOMPARE(Tracker::count, 4);
+ v.removeLast();
+ QCOMPARE(Tracker::count, 3);
+ }
+ QCOMPARE(Tracker::count, 0);
}
void tst_QVarLengthArray::oldTests()
@@ -699,6 +718,34 @@ void tst_QVarLengthArray::count()
}
}
+void tst_QVarLengthArray::cpp17ctad()
+{
+#ifdef __cpp_deduction_guides
+#define QVERIFY_IS_VLA_OF(obj, Type) \
+ QVERIFY2((std::is_same<decltype(obj), QVarLengthArray<Type>>::value), \
+ QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
+#define CHECK(Type, One, Two, Three) \
+ do { \
+ const Type v[] = {One, Two, Three}; \
+ QVarLengthArray v1 = {One, Two, Three}; \
+ QVERIFY_IS_VLA_OF(v1, Type); \
+ QVarLengthArray v2(v1.begin(), v1.end()); \
+ QVERIFY_IS_VLA_OF(v2, Type); \
+ QVarLengthArray v3(std::begin(v), std::end(v)); \
+ QVERIFY_IS_VLA_OF(v3, Type); \
+ } while (false) \
+ /*end*/
+ CHECK(int, 1, 2, 3);
+ CHECK(double, 1.0, 2.0, 3.0);
+ CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
+#undef QVERIFY_IS_VLA_OF
+#undef CHECK
+#else
+ QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
+#endif
+
+}
+
void tst_QVarLengthArray::first()
{
// append some items, make sure it stays sane
@@ -908,7 +955,6 @@ void tst_QVarLengthArray::initializeListComplex()
template<typename T>
void tst_QVarLengthArray::initializeList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
T val1(110);
T val2(105);
T val3(101);
@@ -945,9 +991,6 @@ void tst_QVarLengthArray::initializeList()
v6 = {}; // assign empty
QCOMPARE(v6.size(), 0);
-#else
- QSKIP("This tests requires a compiler that supports initializer lists.");
-#endif
}
void tst_QVarLengthArray::insertMove()
@@ -1082,5 +1125,11 @@ void tst_QVarLengthArray::nonCopyable()
QVERIFY(ptr6 == vec.at(5).get());
}
+void tst_QVarLengthArray::implicitDefaultCtor()
+{
+ QVarLengthArray<int> def = {};
+ QCOMPARE(def.size(), 0);
+}
+
QTEST_APPLESS_MAIN(tst_QVarLengthArray)
#include "tst_qvarlengtharray.moc"
diff --git a/tests/auto/corelib/tools/qvector/qvector.pro b/tests/auto/corelib/tools/qvector/qvector.pro
index b9a4ae747b..689d9b87a2 100644
--- a/tests/auto/corelib/tools/qvector/qvector.pro
+++ b/tests/auto/corelib/tools/qvector/qvector.pro
@@ -1,5 +1,7 @@
CONFIG += testcase
qtConfig(c++11): CONFIG += c++11
+qtConfig(c++14): CONFIG += c++14
+qtConfig(c++1z): CONFIG += c++1z
TARGET = tst_qvector
QT = core testlib
SOURCES = $$PWD/tst_qvector.cpp
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index 383318979d..08d5a8cd50 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -206,6 +206,9 @@ private slots:
void assignmentInt() const;
void assignmentMovable() const;
void assignmentCustom() const;
+ void assignFromInitializerListInt() const;
+ void assignFromInitializerListMovable() const;
+ void assignFromInitializerListCustom() const;
void addInt() const;
void addMovable() const;
void addCustom() const;
@@ -227,6 +230,7 @@ private slots:
void countInt() const;
void countMovable() const;
void countCustom() const;
+ void cpp17ctad() const;
void data() const;
void emptyInt() const;
void emptyMovable() const;
@@ -255,7 +259,6 @@ private slots:
void fromListInt() const;
void fromListMovable() const;
void fromListCustom() const;
- void fromStdVector() const;
void indexOf() const;
void insertInt() const;
void insertMovable() const;
@@ -294,7 +297,10 @@ private slots:
void swapMovable() const;
void swapCustom() const;
void toList() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ void fromStdVector() const;
void toStdVector() const;
+#endif
void value() const;
void testOperators() const;
@@ -327,10 +333,13 @@ private slots:
void insertMove() const;
+ void swapItemsAt() const;
+
private:
template<typename T> void copyConstructor() const;
template<typename T> void add() const;
template<typename T> void append() const;
+ template<typename T> void assignFromInitializerList() const;
template<typename T> void capacity() const;
template<typename T> void clear() const;
template<typename T> void count() const;
@@ -544,6 +553,40 @@ void tst_QVector::assignmentCustom() const
}
template<typename T>
+void tst_QVector::assignFromInitializerList() const
+{
+ T val1(SimpleValue<T>::at(1));
+ T val2(SimpleValue<T>::at(2));
+ T val3(SimpleValue<T>::at(3));
+
+ QVector<T> v1 = {val1, val2, val3};
+ QCOMPARE(v1, QVector<T>() << val1 << val2 << val3);
+ QCOMPARE(v1, (QVector<T> {val1, val2, val3}));
+
+ v1 = {};
+ QCOMPARE(v1.size(), 0);
+}
+
+void tst_QVector::assignFromInitializerListInt() const
+{
+ assignFromInitializerList<int>();
+}
+
+void tst_QVector::assignFromInitializerListMovable() const
+{
+ const int instancesCount = Movable::counter.loadAcquire();
+ assignFromInitializerList<Movable>();
+ QCOMPARE(instancesCount, Movable::counter.loadAcquire());
+}
+
+void tst_QVector::assignFromInitializerListCustom() const
+{
+ const int instancesCount = Custom::counter.loadAcquire();
+ assignFromInitializerList<Custom>();
+ QCOMPARE(instancesCount, Custom::counter.loadAcquire());
+}
+
+template<typename T>
void tst_QVector::add() const
{
{
@@ -668,7 +711,6 @@ void tst_QVector::appendCustom() const
void tst_QVector::appendRvalue() const
{
-#ifdef Q_COMPILER_RVALUE_REFS
QVector<QString> v;
v.append("hello");
QString world = "world";
@@ -676,9 +718,6 @@ void tst_QVector::appendRvalue() const
QVERIFY(world.isEmpty());
QCOMPARE(v.front(), QString("hello"));
QCOMPARE(v.back(), QString("world"));
-#else
- QSKIP("This test requires that C++11 move semantics support is enabled in the compiler");
-#endif
}
void tst_QVector::at() const
@@ -876,6 +915,33 @@ void tst_QVector::countCustom() const
QCOMPARE(instancesCount, Custom::counter.loadAcquire());
}
+void tst_QVector::cpp17ctad() const
+{
+#ifdef __cpp_deduction_guides
+#define QVERIFY_IS_VECTOR_OF(obj, Type) \
+ QVERIFY2((std::is_same<decltype(obj), QVector<Type>>::value), \
+ QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
+#define CHECK(Type, One, Two, Three) \
+ do { \
+ const Type v[] = {One, Two, Three}; \
+ QVector v1 = {One, Two, Three}; \
+ QVERIFY_IS_VECTOR_OF(v1, Type); \
+ QVector v2(v1.begin(), v1.end()); \
+ QVERIFY_IS_VECTOR_OF(v2, Type); \
+ QVector v3(std::begin(v), std::end(v)); \
+ QVERIFY_IS_VECTOR_OF(v3, Type); \
+ } while (false) \
+ /*end*/
+ CHECK(int, 1, 2, 3);
+ CHECK(double, 1.0, 2.0, 3.0);
+ CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
+#undef QVERIFY_IS_VECTOR_OF
+#undef CHECK
+#else
+ QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
+#endif
+}
+
void tst_QVector::data() const
{
QVector<int> myvec;
@@ -1403,6 +1469,7 @@ void tst_QVector::fromListCustom() const
QCOMPARE(instancesCount, Custom::counter.loadAcquire());
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void tst_QVector::fromStdVector() const
{
// stl = :(
@@ -1416,6 +1483,7 @@ void tst_QVector::fromStdVector() const
// test it converts ok
QCOMPARE(myvec, QVector<QString>() << "aaa" << "bbb" << "ninjas" << "pirates");
}
+#endif
void tst_QVector::indexOf() const
{
@@ -2308,6 +2376,7 @@ void tst_QVector::toList() const
QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void tst_QVector::toStdVector() const
{
QVector<QString> myvec;
@@ -2320,6 +2389,7 @@ void tst_QVector::toStdVector() const
QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
}
+#endif
void tst_QVector::value() const
{
@@ -2526,7 +2596,6 @@ void tst_QVector::reallocAfterCopy()
template<typename T>
void tst_QVector::initializeList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
T val1(SimpleValue<T>::at(1));
T val2(SimpleValue<T>::at(2));
T val3(SimpleValue<T>::at(3));
@@ -2543,7 +2612,6 @@ void tst_QVector::initializeList()
QVector<T> v4({});
QCOMPARE(v4.size(), 0);
-#endif
}
void tst_QVector::initializeListInt()
@@ -2853,7 +2921,7 @@ void tst_QVector::detachThreadSafety() const
struct : QThread {
void run() override
{
- QVector<T> copy(*detachThreadSafetyData<T>()->load());
+ QVector<T> copy(*detachThreadSafetyData<T>()->loadRelaxed());
QVERIFY(!copy.isDetached());
detachThreadSafetyLock.release();
detachThreadSafetyLock.acquire(100);
@@ -2963,5 +3031,22 @@ void tst_QVector::insertMove() const
QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
}
+void tst_QVector::swapItemsAt() const
+{
+ QVector<int> v;
+ v << 0 << 1 << 2 << 3;
+
+ v.swapItemsAt(0, 2);
+ QCOMPARE(v.at(0), 2);
+ QCOMPARE(v.at(2), 0);
+
+ auto copy = v;
+ copy.swapItemsAt(0, 2);
+ QCOMPARE(v.at(0), 2);
+ QCOMPARE(v.at(2), 0);
+ QCOMPARE(copy.at(0), 0);
+ QCOMPARE(copy.at(2), 2);
+}
+
QTEST_MAIN(tst_QVector)
#include "tst_qvector.moc"
diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
index 05579dce6e..7c4d1071ce 100644
--- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
+++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
@@ -260,12 +260,10 @@ void tst_QVersionNumber::constructorExplicit()
QCOMPARE(v5.segments(), v6.segments());
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QVersionNumber v7(4, 5, 6);
QVersionNumber v8 = {4, 5, 6};
QCOMPARE(v7.segments(), v8.segments());
-#endif
}
void tst_QVersionNumber::constructorCopy_data()
@@ -436,7 +434,7 @@ void tst_QVersionNumber::normalized()
QFETCH(QVersionNumber, expected);
QCOMPARE(version.normalized(), expected);
- QCOMPARE(qMove(version).normalized(), expected);
+ QCOMPARE(std::move(version).normalized(), expected);
}
void tst_QVersionNumber::isNormalized_data()
@@ -586,30 +584,28 @@ void tst_QVersionNumber::serialize()
void tst_QVersionNumber::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
// QVersionNumber(QVersionNumber &&)
{
QVersionNumber v1(1, 2, 3);
- QVersionNumber v2 = qMove(v1);
+ QVersionNumber v2 = std::move(v1);
QCOMPARE(v2, QVersionNumber(1, 2, 3));
}
// QVersionNumber &operator=(QVersionNumber &&)
{
QVersionNumber v1(1, 2, 3);
QVersionNumber v2;
- v2 = qMove(v1);
+ v2 = std::move(v1);
QCOMPARE(v2, QVersionNumber(1, 2, 3));
}
// QVersionNumber(QVector<int> &&)
{
QVector<int> segments = QVector<int>() << 1 << 2 << 3;
QVersionNumber v1(segments);
- QVersionNumber v2(qMove(segments));
+ QVersionNumber v2(std::move(segments));
QVERIFY(!v1.isNull());
QVERIFY(!v2.isNull());
QCOMPARE(v1, v2);
}
-#endif
#ifdef Q_COMPILER_REF_QUALIFIERS
// normalized()
{
@@ -620,7 +616,7 @@ void tst_QVersionNumber::moveSemantics()
QVERIFY(!v.isNull());
QVERIFY(!nv.isNull());
QVERIFY(nv.isNormalized());
- nv = qMove(v).normalized();
+ nv = std::move(v).normalized();
QVERIFY(!nv.isNull());
QVERIFY(nv.isNormalized());
}
@@ -632,13 +628,10 @@ void tst_QVersionNumber::moveSemantics()
segments = v.segments();
QVERIFY(!v.isNull());
QVERIFY(!segments.empty());
- segments = qMove(v).segments();
+ segments = std::move(v).segments();
QVERIFY(!segments.empty());
}
#endif
-#if !defined(Q_COMPILER_RVALUE_REFS) && !defined(Q_COMPILER_REF_QUALIFIERS)
- QSKIP("This test requires C++11 move semantics support in the compiler.");
-#endif
}
void tst_QVersionNumber::qtVersion()
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index 2a975e67d1..49b2a1f075 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -6,30 +6,20 @@ SUBDIRS=\
qarraydata \
qarraydata_strictiterators \
qbitarray \
- qbytearray \
- qbytearraylist \
- qbytearraymatcher \
- qbytedatabuffer \
qcache \
- qchar \
- qcollator \
qcommandlineparser \
qcontiguouscache \
qcryptographichash \
- qdate \
- qdatetime \
qeasingcurve \
qexplicitlyshareddatapointer \
qfreelist \
qhash \
qhash_strictiterators \
qhashfunctions \
- qlatin1string \
qline \
qlinkedlist \
qlist \
qlist_strictiterators \
- qlocale \
qmakearray \
qmap \
qmap_strictiterators \
@@ -41,28 +31,15 @@ SUBDIRS=\
qpointf \
qqueue \
qrect \
- qregexp \
- qregularexpression \
qringbuffer \
qscopedpointer \
qscopedvaluerollback \
+ qscopeguard \
qset \
qsharedpointer \
qsize \
qsizef \
qstl \
- qstring \
- qstring_no_cast_from_bytearray \
- qstringapisymmetry \
- qstringbuilder \
- qstringiterator \
- qstringlist \
- qstringmatcher \
- qstringref \
- qstringview \
- qtextboundaryfinder \
- qtime \
- qtimezone \
qtimeline \
qvarlengtharray \
qvector \
diff --git a/tests/auto/dbus/qdbusabstractadaptor/qdbusabstractadaptor/BLACKLIST b/tests/auto/dbus/qdbusabstractadaptor/qdbusabstractadaptor/BLACKLIST
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/dbus/qdbusabstractadaptor/qdbusabstractadaptor/BLACKLIST
diff --git a/tests/auto/dbus/qdbusconnection_spyhook/BLACKLIST b/tests/auto/dbus/qdbusconnection_spyhook/BLACKLIST
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/dbus/qdbusconnection_spyhook/BLACKLIST
diff --git a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
index 018b7c2a35..b4690268c8 100644
--- a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
+++ b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
@@ -197,8 +197,8 @@ tst_QDBusThreading::tst_QDBusThreading()
void tst_QDBusThreading::joinThreads()
{
- threadJoin.acquire(threadJoinCount.load());
- threadJoinCount.store(0);
+ threadJoin.acquire(threadJoinCount.loadRelaxed());
+ threadJoinCount.storeRelaxed(0);
}
bool tst_QDBusThreading::waitForSignal(QObject *obj, const char *signal, int delay)
diff --git a/tests/auto/gui/gui.pro b/tests/auto/gui/gui.pro
index e0c8123f26..c90fc48251 100644
--- a/tests/auto/gui/gui.pro
+++ b/tests/auto/gui/gui.pro
@@ -13,6 +13,7 @@ SUBDIRS = \
text \
util \
itemmodels \
+ rhi
!qtConfig(opengl)|winrt: SUBDIRS -= qopengl qopenglconfig
diff --git a/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp b/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp
index 2dbb078ae0..fe12175081 100644
--- a/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp
+++ b/tests/auto/gui/image/qicoimageformat/tst_qicoimageformat.cpp
@@ -164,7 +164,7 @@ void tst_QIcoImageFormat::imageCount_data()
QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 2;
QTest::newRow("16px16c, 32px32c, 32px256c 1") << "valid/WORLD.ico" << 3;
QTest::newRow("16px16c, 32px32c, 32px256c 2") << "valid/WORLDH.ico" << 3;
- QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1;
QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 9;
QTest::newRow("PNG compression") << "valid/Qt.ico" << 4;
QTest::newRow("CUR file") << "valid/yellow.cur" << 1;
@@ -177,7 +177,6 @@ void tst_QIcoImageFormat::imageCount()
QImageReader reader(m_IconPath + QLatin1Char('/') + fileName);
QCOMPARE(reader.imageCount(), count);
-
}
void tst_QIcoImageFormat::jumpToNextImage_data()
@@ -218,7 +217,7 @@ void tst_QIcoImageFormat::loopCount_data()
QTest::addColumn<int>("count");
QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 0;
- QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
+ QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1;
}
void tst_QIcoImageFormat::loopCount()
@@ -228,6 +227,7 @@ void tst_QIcoImageFormat::loopCount()
QImageReader reader(m_IconPath + QLatin1Char('/') + fileName);
QCOMPARE(reader.loopCount(), count);
+ QCOMPARE(reader.canRead(), count < 0 ? false : true);
}
void tst_QIcoImageFormat::nextImageDelay_data()
@@ -256,7 +256,7 @@ void tst_QIcoImageFormat::nextImageDelay()
QImageReader reader(m_IconPath + QLatin1Char('/') + fileName);
if (count == -1) {
- QCOMPARE(reader.nextImageDelay(), 0);
+ QCOMPARE(reader.nextImageDelay(), -1);
} else {
int i;
for (i = 0; i < count; i++) {
diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro
index b40866892e..0593cfbc23 100644
--- a/tests/auto/gui/image/qimage/qimage.pro
+++ b/tests/auto/gui/image/qimage/qimage.pro
@@ -7,7 +7,7 @@ qtConfig(c++11): CONFIG += c++11
android:!android-embedded: RESOURCES += qimage.qrc
-win32:!winrt: LIBS += -lgdi32 -luser32
+win32:!winrt: QMAKE_USE += user32 gdi32
darwin: LIBS += -framework CoreGraphics
TESTDATA += images/*
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 4d41b5e873..b84aa52465 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -303,6 +303,8 @@ static QLatin1String formatToString(QImage::Format format)
return QLatin1String("RGBA64pm");
case QImage::Format_Grayscale16:
return QLatin1String("Grayscale16");
+ case QImage::Format_BGR888:
+ return QLatin1String("BGR888");
default:
break;
};
@@ -844,6 +846,13 @@ void tst_QImage::convertToFormat_data()
QTest::newRow("blue rgb32 -> rgb888") << int(QImage::Format_RGB32) << 0xff0000ff
<< int(QImage::Format_RGB888) << 0xff0000ff;
+ QTest::newRow("red rgb32 -> bgr888") << int(QImage::Format_RGB32) << 0xffff0000
+ << int(QImage::Format_BGR888) << 0xffff0000;
+ QTest::newRow("green rgb32 -> bgr888") << int(QImage::Format_RGB32) << 0xff00ff00
+ << int(QImage::Format_BGR888) << 0xff00ff00;
+ QTest::newRow("blue rgb32 -> bgr888") << int(QImage::Format_RGB32) << 0xff0000ff
+ << int(QImage::Format_BGR888) << 0xff0000ff;
+
QTest::newRow("red rgb16 -> rgb888") << int(QImage::Format_RGB16) << 0xffff0000
<< int(QImage::Format_RGB888) << 0xffff0000;
QTest::newRow("green rgb16 -> rgb888") << int(QImage::Format_RGB16) << 0xff00ff00
@@ -858,6 +867,13 @@ void tst_QImage::convertToFormat_data()
QTest::newRow("blue rgb888 -> argb32") << int(QImage::Format_RGB888) << 0xff0000ff
<< int(QImage::Format_ARGB32) << 0xff0000ff;
+ QTest::newRow("red bgr888 -> argb32") << int(QImage::Format_RGB888) << 0xffff0000
+ << int(QImage::Format_ARGB32) << 0xffff0000;
+ QTest::newRow("green bgr888 -> argb32") << int(QImage::Format_RGB888) << 0xff00ff00
+ << int(QImage::Format_ARGB32) << 0xff00ff00;
+ QTest::newRow("blue bgr888 -> argb32") << int(QImage::Format_RGB888) << 0xff0000ff
+ << int(QImage::Format_ARGB32) << 0xff0000ff;
+
QTest::newRow("red rgb888 -> rgbx8888") << int(QImage::Format_RGB888) << 0xffff0000
<< int(QImage::Format_RGBX8888) << 0xffff0000;
QTest::newRow("green rgb888 -> rgbx8888") << int(QImage::Format_RGB888) << 0xff00ff00
@@ -1338,6 +1354,12 @@ void tst_QImage::setPixel_data()
<< 0xff00ff00 << 0x00ff00u;
QTest::newRow("RGB888 blue") << int(QImage::Format_RGB888)
<< 0xff0000ff << 0x0000ffu;
+ QTest::newRow("BGR888 red") << int(QImage::Format_BGR888)
+ << 0xffff0000 << 0x0000ffu;
+ QTest::newRow("BGR888 green") << int(QImage::Format_BGR888)
+ << 0xff00ff00 << 0x00ff00u;
+ QTest::newRow("BGR888 blue") << int(QImage::Format_BGR888)
+ << 0xff0000ff << 0xff0000u;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
QTest::newRow("RGBA8888 red") << int(QImage::Format_RGBA8888)
<< 0xffff0000u << 0xff0000ffu;
@@ -1425,6 +1447,7 @@ void tst_QImage::setPixel()
case int(QImage::Format_ARGB8565_Premultiplied):
case int(QImage::Format_ARGB8555_Premultiplied):
case int(QImage::Format_RGB888):
+ case int(QImage::Format_BGR888):
{
for (int y = 0; y < h; ++y) {
const quint24 *row = (const quint24*)(img.scanLine(y));
@@ -1852,7 +1875,9 @@ void tst_QImage::smoothScale4_data()
QTest::addColumn<QImage::Format>("format");
QTest::newRow("RGB32") << QImage::Format_RGB32;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("RGBx64") << QImage::Format_RGBX64;
+#endif
}
void tst_QImage::smoothScale4()
@@ -2443,6 +2468,7 @@ void tst_QImage::mirrored_data()
QTest::newRow("Format_RGB555, vertical") << QImage::Format_RGB555 << true << false << 16 << 16;
QTest::newRow("Format_ARGB8555_Premultiplied, vertical") << QImage::Format_ARGB8555_Premultiplied << true << false << 16 << 16;
QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false << 16 << 16;
+ QTest::newRow("Format_BGR888, vertical") << QImage::Format_BGR888 << true << false << 16 << 16;
QTest::newRow("Format_RGB444, vertical") << QImage::Format_RGB444 << true << false << 16 << 16;
QTest::newRow("Format_RGBX8888, vertical") << QImage::Format_RGBX8888 << true << false << 16 << 16;
QTest::newRow("Format_RGBA8888_Premultiplied, vertical") << QImage::Format_RGBA8888_Premultiplied << true << false << 16 << 16;
@@ -3403,7 +3429,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("rgb32 -> rgb666 (dithering)") << rgb32 << QImage::Format_RGB666 << int(Qt::PreferDither | Qt::OrderedDither) << 129;
// Test we get the same results for opaque input in the ARGBPM implementation.
- rgb32 = qMove(rgb32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ rgb32 = std::move(rgb32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
QTest::newRow("argb32pm -> argb4444pm (no dither)") << rgb32 << QImage::Format_ARGB4444_Premultiplied << 0 << 16;
QTest::newRow("argb32pm -> rgb444 (dithering)") << rgb32 << QImage::Format_RGB444 << int(Qt::PreferDither | Qt::OrderedDither) << 33;
QTest::newRow("argb32pm -> argb4444pm (dithering)") << rgb32 << QImage::Format_ARGB4444_Premultiplied << int(Qt::PreferDither | Qt::OrderedDither) << 33;
@@ -3412,6 +3438,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("argb32pm -> argb6666pm (no dither)") << rgb32 << QImage::Format_ARGB6666_Premultiplied << 0 << 64;
QTest::newRow("argb32pm -> argb6666pm (dithering)") << rgb32 << QImage::Format_ARGB6666_Premultiplied << int(Qt::PreferDither | Qt::OrderedDither) << 129;
+#if QT_CONFIG(raster_64bit)
QImage rgb30(1024, 16, QImage::Format_RGB30);
QLinearGradient gradient30(QRectF(rgb30.rect()).topLeft(), QRectF(rgb30.rect()).topRight());
gradient30.setColorAt(0.0, QColor(0, 0, 0));
@@ -3424,6 +3451,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("rgb30 -> rgb32 (dithering)") << rgb30 << QImage::Format_RGB32 << int(Qt::PreferDither | Qt::OrderedDither) << 513;
QTest::newRow("rgb30 -> rgb888 (no dither)") << rgb30 << QImage::Format_RGB888 << 0 << 256;
QTest::newRow("rgb30 -> rgb888 (dithering)") << rgb30 << QImage::Format_RGB888 << int(Qt::PreferDither | Qt::OrderedDither) << 513;
+#endif
}
void tst_QImage::ditherGradient()
diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
index d17a171728..22d96e76f9 100644
--- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
@@ -30,6 +30,7 @@
#include <QtTest/QtTest>
#include <QBuffer>
+#include <QColorSpace>
#include <QDebug>
#include <QImage>
#include <QImageReader>
@@ -158,6 +159,9 @@ private slots:
void saveFormat_data();
void saveFormat();
+ void saveColorSpace_data();
+ void saveColorSpace();
+
void readText_data();
void readText();
@@ -1859,6 +1863,7 @@ void tst_QImageReader::saveFormat_data()
QTest::newRow("Format_RGB555") << QImage::Format_RGB555;
QTest::newRow("Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
+ QTest::newRow("Format_BGR888") << QImage::Format_BGR888;
QTest::newRow("Format_RGB444") << QImage::Format_RGB444;
QTest::newRow("Format_ARGB4444_Premultiplied") << QImage::Format_ARGB4444_Premultiplied;
QTest::newRow("Format_RGBA64") << QImage::Format_RGBA64;
@@ -1883,6 +1888,40 @@ void tst_QImageReader::saveFormat()
QCOMPARE(stored, converted);
}
+void tst_QImageReader::saveColorSpace_data()
+{
+ QTest::addColumn<QColorSpace::NamedColorSpace>("namedColorSpace");
+
+ QTest::newRow("sRGB") << QColorSpace::SRgb;
+ QTest::newRow("sRGB(linear)") << QColorSpace::SRgbLinear;
+ QTest::newRow("AdobeRGB") << QColorSpace::AdobeRgb;
+ QTest::newRow("DisplayP3") << QColorSpace::DisplayP3;
+ QTest::newRow("ProPhotoRgb") << QColorSpace::ProPhotoRgb;
+}
+
+void tst_QImageReader::saveColorSpace()
+{
+ QFETCH(QColorSpace::NamedColorSpace, namedColorSpace);
+
+ QImage orig(":/images/kollada.png");
+
+ orig.setColorSpace(namedColorSpace);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QVERIFY(orig.save(&buf, "png"));
+ buf.close();
+ QImage stored = QImage::fromData(buf.buffer(), "png");
+
+ QCOMPARE(stored, orig);
+ QCOMPARE(stored.colorSpace(), orig.colorSpace());
+
+ buf.open(QIODevice::WriteOnly);
+ QVERIFY(orig.save(&buf, "jpeg"));
+ buf.close();
+ stored = QImage::fromData(buf.buffer(), "jpeg");
+
+ QCOMPARE(stored.colorSpace(), orig.colorSpace());
+}
void tst_QImageReader::readText_data()
{
diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro
index e6a020af1a..c9219dad1d 100644
--- a/tests/auto/gui/image/qpixmap/qpixmap.pro
+++ b/tests/auto/gui/image/qpixmap/qpixmap.pro
@@ -5,7 +5,7 @@ QT += core-private gui-private testlib
qtHaveModule(widgets): QT += widgets widgets-private
SOURCES += tst_qpixmap.cpp
-win32:!winrt:LIBS += -lgdi32 -luser32
+win32:!winrt: QMAKE_USE += user32 gdi32
RESOURCES += qpixmap.qrc
TESTDATA += convertFromImage/* convertFromToHICON/* loadFromData/* images/*
diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
index 4d31d80246..ba5df809f2 100644
--- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
@@ -267,10 +267,6 @@ void tst_QPixmap::fromImage()
image.fill(0x7f7f7f7f);
const QPixmap pixmap = QPixmap::fromImage(image);
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- if (pixmap.handle()->classId() == QPlatformPixmap::X11Class && !pixmap.x11PictureHandle())
- QSKIP("Requires XRender support");
-#endif
const QImage result = pixmap.toImage();
image = image.convertToFormat(result.format());
QCOMPARE(result, image);
@@ -491,11 +487,6 @@ void tst_QPixmap::fill()
else
pm = QPixmap(400, 400);
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- if (!bitmap && pm.handle()->classId() == QPlatformPixmap::X11Class && !pm.x11PictureHandle())
- QSKIP("Requires XRender support");
-#endif
-
pm.fill(color);
if (syscolor && !bitmap && pm.depth() < 24) {
QSKIP("Test does not work on displays without true color");
@@ -521,10 +512,6 @@ void tst_QPixmap::fill()
void tst_QPixmap::fill_transparent()
{
QPixmap pixmap(10, 10);
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- if (pixmap.handle()->classId() == QPlatformPixmap::X11Class && !pixmap.x11PictureHandle())
- QSKIP("Requires XRender support");
-#endif
pixmap.fill(Qt::transparent);
QVERIFY(pixmap.hasAlphaChannel());
}
diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
index 158530428d..3158883ef5 100644
--- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
+++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
@@ -104,18 +104,28 @@ void tst_QPixmapCache::cacheLimit()
void tst_QPixmapCache::setCacheLimit()
{
+ QPixmap res;
QPixmap *p1 = new QPixmap(2, 3);
QPixmapCache::insert("P1", *p1);
+#if QT_DEPRECATED_SINCE(5, 13)
QVERIFY(QPixmapCache::find("P1") != 0);
+#endif
+ QVERIFY(QPixmapCache::find("P1", &res));
delete p1;
QPixmapCache::setCacheLimit(0);
+#if QT_DEPRECATED_SINCE(5, 13)
QVERIFY(!QPixmapCache::find("P1"));
+#endif
+ QVERIFY(!QPixmapCache::find("P1", &res));
p1 = new QPixmap(2, 3);
QPixmapCache::setCacheLimit(1000);
QPixmapCache::insert("P1", *p1);
+#if QT_DEPRECATED_SINCE(5, 13)
QVERIFY(QPixmapCache::find("P1") != 0);
+#endif
+ QVERIFY(QPixmapCache::find("P1", &res));
delete p1;
@@ -200,6 +210,7 @@ void tst_QPixmapCache::find()
QVERIFY(QPixmapCache::insert("P1", p1));
QPixmap p2;
+#if QT_DEPRECATED_SINCE(5, 13)
QVERIFY(QPixmapCache::find("P1", p2));
QCOMPARE(p2.width(), 10);
QCOMPARE(p2.height(), 10);
@@ -209,6 +220,12 @@ void tst_QPixmapCache::find()
QPixmap *p3 = QPixmapCache::find("P1");
QVERIFY(p3);
QCOMPARE(p1, *p3);
+#endif
+
+ QVERIFY(QPixmapCache::find("P1", &p2));
+ QCOMPARE(p2.width(), 10);
+ QCOMPARE(p2.height(), 10);
+ QCOMPARE(p1, p2);
//The int part of the API
QPixmapCache::Key key = QPixmapCache::insert(p1);
@@ -261,6 +278,7 @@ void tst_QPixmapCache::insert()
}
int num = 0;
+#if QT_DEPRECATED_SINCE(5, 13)
for (int k = 0; k < numberOfKeys; ++k) {
if (QPixmapCache::find(QString::number(k)))
++num;
@@ -268,6 +286,16 @@ void tst_QPixmapCache::insert()
if (QPixmapCache::find("0"))
++num;
+ num = 0;
+#endif
+ QPixmap res;
+ for (int k = 0; k < numberOfKeys; ++k) {
+ if (QPixmapCache::find(QString::number(k), &res))
+ ++num;
+ }
+
+ if (QPixmapCache::find("0", &res))
+ ++num;
QVERIFY(num <= estimatedNum);
QPixmap p3;
@@ -340,17 +368,17 @@ void tst_QPixmapCache::remove()
p1.fill(Qt::yellow);
QPixmap p2;
- QVERIFY(QPixmapCache::find("red", p2));
+ QVERIFY(QPixmapCache::find("red", &p2));
QVERIFY(p1.toImage() != p2.toImage());
QVERIFY(p1.toImage() == p1.toImage()); // sanity check
QPixmapCache::remove("red");
- QVERIFY(!QPixmapCache::find("red"));
+ QVERIFY(!QPixmapCache::find("red", &p2));
QPixmapCache::remove("red");
- QVERIFY(!QPixmapCache::find("red"));
+ QVERIFY(!QPixmapCache::find("red", &p2));
QPixmapCache::remove("green");
- QVERIFY(!QPixmapCache::find("green"));
+ QVERIFY(!QPixmapCache::find("green", &p2));
//The int part of the API
QPixmapCache::clear();
@@ -392,7 +420,7 @@ void tst_QPixmapCache::remove()
key = QPixmapCache::insert(p1);
QPixmapCache::remove(key);
QVERIFY(QPixmapCache::find(key, &p1) == 0);
- QVERIFY(QPixmapCache::find("red") != 0);
+ QVERIFY(QPixmapCache::find("red", &p1) != 0);
}
void tst_QPixmapCache::clear()
@@ -408,14 +436,14 @@ void tst_QPixmapCache::clear()
const int numberOfKeys = estimatedNum + 1000;
for (int i = 0; i < numberOfKeys; ++i)
- QVERIFY(QPixmapCache::find("x" + QString::number(i)) == 0);
+ QVERIFY(!QPixmapCache::find("x" + QString::number(i), &p1));
for (int j = 0; j < numberOfKeys; ++j)
QPixmapCache::insert(QString::number(j), p1);
int num = 0;
for (int k = 0; k < numberOfKeys; ++k) {
- if (QPixmapCache::find(QString::number(k), p1))
+ if (QPixmapCache::find(QString::number(k), &p1))
++num;
}
QVERIFY(num > 0);
@@ -423,7 +451,7 @@ void tst_QPixmapCache::clear()
QPixmapCache::clear();
for (int k = 0; k < numberOfKeys; ++k)
- QVERIFY(!QPixmapCache::find(QString::number(k)));
+ QVERIFY(!QPixmapCache::find(QString::number(k), &p1));
//The int part of the API
QPixmap p2(10, 10);
diff --git a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
index 2deb84fa5f..b6921fc0bb 100644
--- a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
@@ -311,12 +311,14 @@ void tst_QStandardItem::getSetFlags()
item.setCheckable(true);
QCOMPARE(item.checkState(), Qt::Checked);
+#if QT_DEPRECATED_SINCE(5, 6)
// deprecated API
item.setTristate(true);
QVERIFY(item.isTristate());
QVERIFY(item.flags() & Qt::ItemIsTristate);
item.setTristate(false);
QVERIFY(!(item.flags() & Qt::ItemIsTristate));
+#endif
}
void tst_QStandardItem::getSetRowAndColumnCount()
diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
index 550f70890e..bc8bc38da6 100644
--- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
@@ -734,7 +734,7 @@ void tst_QStandardItemModel::data()
currentRoles.clear();
// bad args
m_model->setData(QModelIndex(), "bla", Qt::DisplayRole);
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
QIcon icon;
for (int r=0; r < m_model->rowCount(); ++r) {
@@ -742,9 +742,9 @@ void tst_QStandardItemModel::data()
m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
QCOMPARE(currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole);
- QCOMPARE(currentRoles, {Qt::ToolTipRole});
+ QCOMPARE(currentRoles, QVector<int>{Qt::ToolTipRole});
m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole);
- QCOMPARE(currentRoles, {Qt::DecorationRole});
+ QCOMPARE(currentRoles, QVector<int>{Qt::DecorationRole});
}
}
@@ -761,7 +761,7 @@ void tst_QStandardItemModel::clearItemData()
{
currentRoles.clear();
QVERIFY(!m_model->clearItemData(QModelIndex()));
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
const QModelIndex idx = m_model->index(0, 0);
const QMap<int, QVariant> oldData = m_model->itemData(idx);
m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole);
@@ -773,7 +773,7 @@ void tst_QStandardItemModel::clearItemData()
QCOMPARE(idx.data(Qt::ToolTipRole), QVariant());
QCOMPARE(idx.data(Qt::DisplayRole), QVariant());
QCOMPARE(idx.data(Qt::EditRole), QVariant());
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
m_model->setItemData(idx, oldData);
currentRoles.clear();
}
diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
index 7e98704aea..293a6a8581 100644
--- a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
+++ b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
@@ -5,4 +5,4 @@ QT += core-private network gui-private testlib
SOURCES += tst_noqteventloop.cpp
-qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32
+qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp
index 4fca9a07fc..3d1876f00f 100644
--- a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp
+++ b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp
@@ -36,6 +36,7 @@
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qtcpsocket.h>
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qtimer.h>
#include <QtCore/qt_windows.h>
@@ -49,7 +50,7 @@ class tst_NoQtEventLoop : public QObject
private slots:
void consumeMouseEvents();
void consumeSocketEvents();
-
+ void deliverEventsInLivelock();
};
class Window : public QRasterWindow
@@ -258,8 +259,8 @@ void tst_NoQtEventLoop::consumeMouseEvents()
::SetWindowPos(mainWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- Window *childWindow = new Window;
- childWindow->setParent(QWindow::fromWinId((WId)mainWnd));
+ QWindow *mainWindow = QWindow::fromWinId(reinterpret_cast<WId>(mainWnd));
+ Window *childWindow = new Window(mainWindow);
childWindow->setGeometry(margin, topVerticalMargin,
width - 2 * margin, height - margin - topVerticalMargin);
childWindow->show();
@@ -276,6 +277,7 @@ void tst_NoQtEventLoop::consumeMouseEvents()
if (g_exit)
break;
}
+ delete mainWindow;
QCOMPARE(testThread->passed(), true);
@@ -311,6 +313,34 @@ void tst_NoQtEventLoop::consumeSocketEvents()
QVERIFY(server.hasPendingConnections());
}
+void tst_NoQtEventLoop::deliverEventsInLivelock()
+{
+ int argc = 1;
+ char *argv[] = { const_cast<char *>("test"), 0 };
+ QGuiApplication app(argc, argv);
+
+ QTimer livelockTimer;
+ livelockTimer.start(0);
+ QTimer::singleShot(100, Qt::CoarseTimer, &livelockTimer, &QTimer::stop);
+
+ QElapsedTimer elapsedTimer;
+ elapsedTimer.start();
+
+ // Exec own message loop
+ MSG msg;
+ forever {
+ if (elapsedTimer.hasExpired(3000) || !livelockTimer.isActive())
+ break;
+
+ if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+ }
+
+ QVERIFY(!livelockTimer.isActive());
+}
+
#include <tst_noqteventloop.moc>
QTEST_APPLESS_MAIN(tst_NoQtEventLoop)
diff --git a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp
index 68852f5a3f..d67b17fd43 100644
--- a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp
+++ b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp
@@ -68,10 +68,17 @@ void tst_QDrag::getSetCheck()
QCOMPARE((QMimeData *)0, obj1.mimeData());
// delete var1; // No delete, since QDrag takes ownership
- Qt::DropAction result = obj1.start();
+ Qt::DropAction result = obj1.exec();
+ QCOMPARE(result, Qt::IgnoreAction);
+ result = obj1.exec(Qt::MoveAction | Qt::LinkAction);
+ QCOMPARE(result, Qt::IgnoreAction);
+
+#if QT_DEPRECATED_SINCE(5, 13)
+ result = obj1.start();
QCOMPARE(result, Qt::IgnoreAction);
result = obj1.start(Qt::MoveAction | Qt::LinkAction);
QCOMPARE(result, Qt::IgnoreAction);
+#endif
}
QTEST_MAIN(tst_QDrag)
diff --git a/tests/auto/gui/kernel/qguiapplication/BLACKLIST b/tests/auto/gui/kernel/qguiapplication/BLACKLIST
index 9a670237b7..e6ffe78ae3 100644
--- a/tests/auto/gui/kernel/qguiapplication/BLACKLIST
+++ b/tests/auto/gui/kernel/qguiapplication/BLACKLIST
@@ -1,4 +1,3 @@
[focusObject]
-opensuse
-opensuse-leap
-ubuntu
+ubuntu-16.04
+opensuse-42.3
diff --git a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
index 895c2a0307..34b75a8397 100644
--- a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
+++ b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
@@ -6,6 +6,7 @@ INCLUDEPATH += $$CORE_TEST_PATH
TARGET = tst_qguiapplication
QT += gui-private
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050E00
SOURCES += tst_qguiapplication.cpp
RESOURCES = tst_qguiapplication.qrc
diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
index a304981cd1..5ee25677bf 100644
--- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
+++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
@@ -184,7 +184,7 @@ void tst_QGuiApplication::windowIcon()
class DummyWindow : public QWindow
{
public:
- DummyWindow() : m_focusObject(0) {}
+ DummyWindow() : m_focusObject(nullptr) {}
virtual QObject *focusObject() const
{
@@ -204,7 +204,7 @@ public:
void tst_QGuiApplication::focusObject()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported.");
@@ -271,15 +271,15 @@ void tst_QGuiApplication::focusObject()
void tst_QGuiApplication::allWindows()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
QWindow *window1 = new QWindow;
QWindow *window2 = new QWindow(window1);
QVERIFY(app.allWindows().contains(window1));
QVERIFY(app.allWindows().contains(window2));
QCOMPARE(app.allWindows().count(), 2);
delete window1;
- window1 = 0;
- window2 = 0;
+ window1 = nullptr;
+ window2 = nullptr;
QVERIFY(!app.allWindows().contains(window2));
QVERIFY(!app.allWindows().contains(window1));
QCOMPARE(app.allWindows().count(), 0);
@@ -288,15 +288,15 @@ void tst_QGuiApplication::allWindows()
void tst_QGuiApplication::topLevelWindows()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
QWindow *window1 = new QWindow;
QWindow *window2 = new QWindow(window1);
QVERIFY(app.topLevelWindows().contains(window1));
QVERIFY(!app.topLevelWindows().contains(window2));
QCOMPARE(app.topLevelWindows().count(), 1);
delete window1;
- window1 = 0;
- window2 = 0;
+ window1 = nullptr;
+ window2 = nullptr;
QVERIFY(!app.topLevelWindows().contains(window2));
QVERIFY(!app.topLevelWindows().contains(window1));
QCOMPARE(app.topLevelWindows().count(), 0);
@@ -306,7 +306,7 @@ class ShowCloseShowWindow : public QWindow
{
Q_OBJECT
public:
- ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
+ ShowCloseShowWindow(bool showAgain, QWindow *parent = nullptr)
: QWindow(parent), showAgain(showAgain)
{
QTimer::singleShot(0, this, SLOT(doClose()));
@@ -331,7 +331,7 @@ private:
void tst_QGuiApplication::abortQuitOnShow()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QScopedPointer<QWindow> window1(new ShowCloseShowWindow(false));
@@ -366,7 +366,7 @@ protected:
}
public:
- FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
+ FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(nullptr), windowDuringFocusOut(nullptr) {}
QWindow *windowDuringFocusAboutToChange;
QWindow *windowDuringFocusOut;
@@ -378,7 +378,7 @@ void tst_QGuiApplication::changeFocusWindow()
QSKIP("WinRt does not support multiple native windows.");
#endif
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported.");
@@ -430,7 +430,7 @@ void tst_QGuiApplication::changeFocusWindow()
void tst_QGuiApplication::keyboardModifiers()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QScopedPointer<QWindow> window(new QWindow);
@@ -564,7 +564,7 @@ public:
int leaves;
int enters;
- inline explicit BlockableWindow(QWindow *parent = 0)
+ inline explicit BlockableWindow(QWindow *parent = nullptr)
: QWindow(parent), blocked(false), leaves(0), enters(0) {}
bool event(QEvent *e)
@@ -601,7 +601,7 @@ void tst_QGuiApplication::modalWindow()
QSKIP("WinRt does not support multiple native windows.");
#endif
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
int x = screenGeometry.left() + spacing;
@@ -654,7 +654,7 @@ void tst_QGuiApplication::modalWindow()
window2->show();
QVERIFY(QTest::qWaitForWindowExposed(window1.data()));
QVERIFY(QTest::qWaitForWindowExposed(window2.data()));
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(childWindow1->blocked, 0);
QCOMPARE(window2->blocked, 0);
@@ -698,7 +698,7 @@ void tst_QGuiApplication::modalWindow()
// everything is unblocked when applicationModalWindow1 is hidden
applicationModalWindow1->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(childWindow1->blocked, 0); // QTBUG-32242, blocked status needs to be set on children as well.
QCOMPARE(window2->blocked, 0);
@@ -750,7 +750,7 @@ void tst_QGuiApplication::modalWindow()
// hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
windowModalWindow2->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(window2->blocked, 0);
QCOMPARE(windowModalWindow1->blocked, 0);
@@ -815,7 +815,7 @@ void tst_QGuiApplication::modalWindow()
// hide windowModalWindow1, everything is unblocked
windowModalWindow1->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(window2->blocked, 0);
QCOMPARE(windowModalWindow1->blocked, 0);
@@ -829,7 +829,7 @@ void tst_QGuiApplication::modalWindow()
void tst_QGuiApplication::quitOnLastWindowClosed()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QTimer timer;
@@ -869,7 +869,7 @@ void tst_QGuiApplication::quitOnLastWindowClosed()
void tst_QGuiApplication::quitOnLastWindowClosedMulti()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QTimer timer;
@@ -909,7 +909,7 @@ void tst_QGuiApplication::quitOnLastWindowClosedMulti()
void tst_QGuiApplication::dontQuitOnLastWindowClosed()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
app.setQuitOnLastWindowClosed(false);
QTimer timer;
@@ -959,7 +959,7 @@ public:
{
if (key == "testplugin")
return new TestPlugin;
- return 0;
+ return nullptr;
}
};
@@ -989,9 +989,13 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User));
QCOMPARE(testReceiver.customEvents, 0);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata);
+#else
QStaticPlugin testPluginInfo;
testPluginInfo.instance = qt_plugin_instance;
testPluginInfo.rawMetaData = qt_plugin_query_metadata;
+#endif
qRegisterStaticPluginFunction(testPluginInfo);
int argc = 3;
char *argv[] = { const_cast<char*>(QTest::currentAppName()), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") };
@@ -1065,7 +1069,7 @@ void tst_QGuiApplication::testSetPaletteAttribute()
QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette));
QPalette palette;
- palette.setColor(QPalette::Foreground, Qt::red);
+ palette.setColor(QPalette::WindowText, Qt::red);
QGuiApplication::setPalette(palette);
QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette));
@@ -1122,7 +1126,7 @@ void tst_QGuiApplication::settableStyleHints()
int argc = 0;
QScopedPointer<QGuiApplication> app;
if (appInstance)
- app.reset(new QGuiApplication(argc, 0));
+ app.reset(new QGuiApplication(argc, nullptr));
const int keyboardInputInterval = 555;
QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval);
diff --git a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
index b1590a5ccf..d2c51922a8 100644
--- a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
+++ b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
@@ -1,5 +1,3 @@
-[sendPostedEvents]
-windows
[registerTimer]
-windows
winrt
+
diff --git a/tests/auto/gui/kernel/qguieventloop/BLACKLIST b/tests/auto/gui/kernel/qguieventloop/BLACKLIST
deleted file mode 100644
index 03acb2f5b0..0000000000
--- a/tests/auto/gui/kernel/qguieventloop/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[testQuitLock]
-osx-10.12
diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
index b2572188b9..3ce65a6785 100644
--- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
+++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
@@ -191,7 +191,7 @@ template<> struct TestValueFactory<QMetaType::QTextLength> {
static QTextLength *create() { return new QTextLength(QTextLength::PercentageLength, 50); }
};
template<> struct TestValueFactory<QMetaType::QTextFormat> {
- static QTextFormat *create() { return new QTextFormat(QTextFormat::TableFormat); }
+ static QTextFormat *create() { return new QTextFormat(QTextFormat::FrameFormat); }
};
template<> struct TestValueFactory<QMetaType::QMatrix> {
static QMatrix *create() { return new QMatrix(10, 20, 30, 40, 50, 60); }
diff --git a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
index bad021c3b0..87a47bd93b 100644
--- a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
+++ b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
@@ -121,7 +121,7 @@ static QByteArray modifiersTestRowName(const QString &keySequence)
if (uc > 32 && uc < 128)
str << '"' << c << '"';
else
- str << "U+" << hex << uc << dec;
+ str << "U+" << Qt::hex << uc << Qt::dec;
if (i < size - 1)
str << ',';
}
@@ -155,7 +155,7 @@ void tst_QKeyEvent::modifiers_data()
modifierCombinations.append(modifierCombination);
}
- qSort(modifierCombinations.begin(), modifierCombinations.end(), orderByModifier);
+ std::sort(modifierCombinations.begin(), modifierCombinations.end(), orderByModifier);
QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
foreach (const QVector<int> combination, modifierCombinations) {
diff --git a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
index f8b6bf064a..874468c954 100644
--- a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
+++ b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
@@ -86,7 +86,7 @@ static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntrie
static QChar macSymbolForQtKey(int key)
{
- const MacSpecialKey *i = qBinaryFind(entries, MacSpecialKeyEntriesEnd, key);
+ const MacSpecialKey *i = std::lower_bound(entries, MacSpecialKeyEntriesEnd, key);
if (i == MacSpecialKeyEntriesEnd)
return QChar();
return QChar(i->macSymbol);
diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
index 7f29b1c24e..6ce6422f48 100644
--- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
+++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
@@ -141,21 +141,20 @@ void tst_QPalette::copySemantics()
void tst_QPalette::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QPalette src(Qt::red), dst;
const QPalette control = src;
QVERIFY(src != dst);
QCOMPARE(src, control);
QVERIFY(!dst.isCopyOf(src));
QVERIFY(!dst.isCopyOf(control));
- dst = qMove(src); // move assignment
+ dst = std::move(src); // move assignment
QVERIFY(!dst.isCopyOf(src)); // isCopyOf() works on moved-from palettes, too
QVERIFY(dst.isCopyOf(control));
QCOMPARE(dst, control);
src = control; // check moved-from 'src' can still be assigned to (doesn't crash)
QVERIFY(src.isCopyOf(dst));
QVERIFY(src.isCopyOf(control));
- QPalette dst2(qMove(src)); // move construction
+ QPalette dst2(std::move(src)); // move construction
QVERIFY(!src.isCopyOf(dst));
QVERIFY(!src.isCopyOf(dst2));
QVERIFY(!src.isCopyOf(control));
@@ -163,9 +162,6 @@ void tst_QPalette::moveSemantics()
QVERIFY(dst2.isCopyOf(dst));
QVERIFY(dst2.isCopyOf(control));
// check moved-from 'src' can still be destroyed (doesn't crash)
-#else
- QSKIP("Compiler doesn't support C++11 move semantics");
-#endif
}
void tst_QPalette::setBrush()
diff --git a/tests/auto/gui/kernel/qtouchevent/BLACKLIST b/tests/auto/gui/kernel/qtouchevent/BLACKLIST
index 8e78d7e41f..dcda77bce7 100644
--- a/tests/auto/gui/kernel/qtouchevent/BLACKLIST
+++ b/tests/auto/gui/kernel/qtouchevent/BLACKLIST
@@ -1,6 +1,2 @@
-[basicRawEventTranslation]
-linux
[multiPointRawEventTranslationOnTouchScreen]
-linux
-[multiPointRawEventTranslationOnTouchPad]
-linux
+ubuntu-16.04
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST
index 1820499a53..27463adf99 100644
--- a/tests/auto/gui/kernel/qwindow/BLACKLIST
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -1,3 +1,5 @@
+[positioning]
+opensuse-leap
[positioning:default]
linux
osx-10.12 ci
@@ -5,39 +7,19 @@ winrt
[positioning:fake]
osx-10.12 ci
[modalWithChildWindow]
-ubuntu-16.04
# QTBUG-66851
-opensuse
-opensuse-leap
# QTBUG-69160
-android
+opensuse-leap
[setVisible]
# QTBUG-69154
android
[modalWindowEnterEventOnHide_QTBUG35109]
-ubuntu-16.04
-osx ci
+osx
[spuriousMouseMove]
-windows ci
# QTBUG-69162
-android
-[modalDialogClosingOneOfTwoModal]
-osx
-[modalWindowModallity]
-osx
-# QTBUG-69163
-android
-[visibility]
-osx-10.12 ci
-
+windows-10
[testInputEvents]
rhel-7.4
-[isActive]
-# QTBUG-67768
-ubuntu
-# QTBUG-69157
-android
-
[exposeEventOnShrink_QTBUG54040]
# QTBUG-69155
android
diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro
index 844b3e8507..e7931ca773 100644
--- a/tests/auto/gui/kernel/qwindow/qwindow.pro
+++ b/tests/auto/gui/kernel/qwindow/qwindow.pro
@@ -5,4 +5,4 @@ QT += core-private gui-private testlib
SOURCES += tst_qwindow.cpp
-qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32
+qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
index 96d983c8f7..e19f76d830 100644
--- a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
+++ b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
@@ -2861,8 +2861,10 @@ void tst_QMatrixNxN::convertGeneric()
QMatrix4x4 m4(m1);
QVERIFY(isSame(m4, unique4x4));
+#if QT_DEPRECATED_SINCE(5, 0)
QMatrix4x4 m5 = qGenericMatrixToMatrix4x4(m1);
QVERIFY(isSame(m5, unique4x4));
+#endif
static float const conv4x4[12] = {
1.0f, 2.0f, 3.0f, 4.0f,
@@ -2874,8 +2876,10 @@ void tst_QMatrixNxN::convertGeneric()
QMatrix4x3 m10 = m9.toGenericMatrix<4, 3>();
QVERIFY(isSame(m10, conv4x4));
+#if QT_DEPRECATED_SINCE(5, 0)
QMatrix4x3 m11 = qGenericMatrixFromMatrix4x4<4, 3>(m9);
QVERIFY(isSame(m11, conv4x4));
+#endif
}
// Copy of "flagBits" in qmatrix4x4.h.
diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
index 097dd111d3..8041fb5439 100644
--- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
+++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
@@ -778,7 +778,10 @@ void tst_QQuaternion::conjugate()
QQuaternion v1(w1, x1, y1, z1);
QQuaternion v2(w1, -x1, -y1, -z1);
+#if QT_DEPRECATED_SINCE(5, 5)
QCOMPARE(v1.conjugate(), v2);
+#endif
+ QCOMPARE(v1.conjugated(), v2);
}
// Test quaternion creation from an axis and an angle.
diff --git a/tests/auto/gui/painting/painting.pro b/tests/auto/gui/painting/painting.pro
index 831fffab30..26e84c1b15 100644
--- a/tests/auto/gui/painting/painting.pro
+++ b/tests/auto/gui/painting/painting.pro
@@ -3,6 +3,7 @@ SUBDIRS=\
qpainterpath \
qpainterpathstroker \
qcolor \
+ qcolorspace \
qbrush \
qregion \
qpagelayout \
diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
index ce6ce15767..f35d4f330b 100644
--- a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
+++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
@@ -338,9 +338,9 @@ void tst_QBrush::gradientPresets()
QCOMPARE(lg->finalStop(), QPointF(1, 0));
QCOMPARE(lg->stops().size(), 3);
- QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1Literal("#ff9a9e"))));
- QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1Literal("#fad0c4"))));
- QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1Literal("#fad0c4"))));
+ QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1String("#ff9a9e"))));
+ QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1String("#fad0c4"))));
+ QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1String("#fad0c4"))));
QGradient invalidPreset(QGradient::Preset(-1));
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 17289e0b85..07c820dc86 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -33,7 +33,7 @@
#include <qcolor.h>
#include <qdebug.h>
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
#include <qrgba64.h>
@@ -64,12 +64,17 @@ private slots:
void globalColors_data();
void globalColors();
+#if defined(Q_COMPILER_CONSTEXPR) & defined(Q_COMPILER_UNIFORM_INIT)
+ void colorConstants_data();
+ void colorConstants();
+#endif
void setRed();
void setGreen();
void setBlue();
void setRgb();
+ void setRgbF();
void setRgba();
void setHsv();
void setCmyk();
@@ -93,8 +98,8 @@ private slots:
void convertTo();
- void light();
- void dark();
+ void lighter();
+ void darker();
void specConstructor_data();
void specConstructor();
@@ -110,10 +115,6 @@ private slots:
void qcolorprofile_data();
void qcolorprofile();
-
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- void setallowX11ColorNames();
-#endif
};
// Testing get/set functions
@@ -187,28 +188,28 @@ void tst_QColor::getSetCheck()
// void QColor::setRedF(qreal)
obj1.setRedF(0.0);
QCOMPARE(obj1.redF(), qreal(0.0));
- obj1.setRedF(-0.2);
- QCOMPARE(obj1.redF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setRedF(1.1);
- QCOMPARE(obj1.redF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setRedF(-0.25);
+ QCOMPARE(obj1.redF(), qreal(-0.25));
+ obj1.setRedF(1.25);
+ QCOMPARE(obj1.redF(), qreal(1.25));
// qreal QColor::greenF()
// void QColor::setGreenF(qreal)
obj1.setGreenF(0.0);
QCOMPARE(obj1.greenF(), qreal(0.0));
- obj1.setGreenF(-0.2);
- QCOMPARE(obj1.greenF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setGreenF(1.1);
- QCOMPARE(obj1.greenF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setGreenF(-0.25);
+ QCOMPARE(obj1.greenF(), qreal(-0.25));
+ obj1.setGreenF(1.5);
+ QCOMPARE(obj1.greenF(), qreal(1.5));
// qreal QColor::blueF()
// void QColor::setBlueF(qreal)
obj1.setBlueF(0.0);
QCOMPARE(obj1.blueF(), qreal(0.0));
- obj1.setBlueF(-0.2);
- QCOMPARE(obj1.blueF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setBlueF(1.1);
- QCOMPARE(obj1.blueF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setBlueF(-0.5);
+ QCOMPARE(obj1.blueF(), qreal(-0.5));
+ obj1.setBlueF(2.0);
+ QCOMPARE(obj1.blueF(), qreal(2.0));
// QRgb QColor::rgba()
// void QColor::setRgba(QRgb)
@@ -367,6 +368,191 @@ void tst_QColor::globalColors()
QCOMPARE(color.rgba(), argb);
}
+#if defined(Q_COMPILER_CONSTEXPR) & defined(Q_COMPILER_UNIFORM_INIT)
+void tst_QColor::colorConstants_data()
+{
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<QRgb>("argb");
+
+ QTest::newRow("invalid") << QColor() << 0xff000000;
+ QTest::newRow("global color color0") << QColorConstants::Color0 << 0xff000000u;
+ QTest::newRow("global color color1") << QColorConstants::Color1 << 0xffffffffu;
+ QTest::newRow("global color black") << QColorConstants::Black << 0xff000000u;
+ QTest::newRow("global color white") << QColorConstants::White << 0xffffffffu;
+ QTest::newRow("global color darkGray") << QColorConstants::DarkGray << 0xff808080u;
+ QTest::newRow("global color gray") << QColorConstants::Gray << 0xffa0a0a4u;
+ QTest::newRow("global color lightGray") << QColorConstants::LightGray << 0xffc0c0c0u;
+ QTest::newRow("global color red") << QColorConstants::Red << 0xffff0000u;
+ QTest::newRow("global color green") << QColorConstants::Green << 0xff00ff00u;
+ QTest::newRow("global color blue") << QColorConstants::Blue << 0xff0000ffu;
+ QTest::newRow("global color cyan") << QColorConstants::Cyan << 0xff00ffffu;
+ QTest::newRow("global color magenta") << QColorConstants::Magenta << 0xffff00ffu;
+ QTest::newRow("global color yellow") << QColorConstants::Yellow << 0xffffff00u;
+ QTest::newRow("global color darkRed") << QColorConstants::DarkRed << 0xff800000u;
+ QTest::newRow("global color darkGreen") << QColorConstants::DarkGreen << 0xff008000u;
+ QTest::newRow("global color darkBlue") << QColorConstants::DarkBlue << 0xff000080u;
+ QTest::newRow("global color darkCyan") << QColorConstants::DarkCyan << 0xff008080u;
+ QTest::newRow("global color darkMagenta") << QColorConstants::DarkMagenta << 0xff800080u;
+ QTest::newRow("global color darkYellow") << QColorConstants::DarkYellow << 0xff808000u;
+ QTest::newRow("global color transparent") << QColorConstants::Transparent << 0x00000000u;
+
+ QTest::newRow("SVG aliceblue") << QColorConstants::Svg::aliceblue << 0xfff0f8ffu;
+ QTest::newRow("SVG antiquewhite") << QColorConstants::Svg::antiquewhite << 0xfffaebd7u;
+ QTest::newRow("SVG aqua") << QColorConstants::Svg::aqua << 0xff00ffffu;
+ QTest::newRow("SVG aquamarine") << QColorConstants::Svg::aquamarine << 0xff7fffd4u;
+ QTest::newRow("SVG azure") << QColorConstants::Svg::azure << 0xfff0ffffu;
+ QTest::newRow("SVG beige") << QColorConstants::Svg::beige << 0xfff5f5dcu;
+ QTest::newRow("SVG bisque") << QColorConstants::Svg::bisque << 0xffffe4c4u;
+ QTest::newRow("SVG black") << QColorConstants::Svg::black << 0xff000000u;
+ QTest::newRow("SVG blanchedalmond") << QColorConstants::Svg::blanchedalmond << 0xffffebcdu;
+ QTest::newRow("SVG blue") << QColorConstants::Svg::blue << 0xff0000ffu;
+ QTest::newRow("SVG blueviolet") << QColorConstants::Svg::blueviolet << 0xff8a2be2u;
+ QTest::newRow("SVG brown") << QColorConstants::Svg::brown << 0xffa52a2au;
+ QTest::newRow("SVG burlywood") << QColorConstants::Svg::burlywood << 0xffdeb887u;
+ QTest::newRow("SVG cadetblue") << QColorConstants::Svg::cadetblue << 0xff5f9ea0u;
+ QTest::newRow("SVG chartreuse") << QColorConstants::Svg::chartreuse << 0xff7fff00u;
+ QTest::newRow("SVG chocolate") << QColorConstants::Svg::chocolate << 0xffd2691eu;
+ QTest::newRow("SVG coral") << QColorConstants::Svg::coral << 0xffff7f50u;
+ QTest::newRow("SVG cornflowerblue") << QColorConstants::Svg::cornflowerblue << 0xff6495edu;
+ QTest::newRow("SVG cornsilk") << QColorConstants::Svg::cornsilk << 0xfffff8dcu;
+ QTest::newRow("SVG crimson") << QColorConstants::Svg::crimson << 0xffdc143cu;
+ QTest::newRow("SVG cyan") << QColorConstants::Svg::cyan << 0xff00ffffu;
+ QTest::newRow("SVG darkblue") << QColorConstants::Svg::darkblue << 0xff00008bu;
+ QTest::newRow("SVG darkcyan") << QColorConstants::Svg::darkcyan << 0xff008b8bu;
+ QTest::newRow("SVG darkgoldenrod") << QColorConstants::Svg::darkgoldenrod << 0xffb8860bu;
+ QTest::newRow("SVG darkgray") << QColorConstants::Svg::darkgray << 0xffa9a9a9u;
+ QTest::newRow("SVG darkgreen") << QColorConstants::Svg::darkgreen << 0xff006400u;
+ QTest::newRow("SVG darkgrey") << QColorConstants::Svg::darkgrey << 0xffa9a9a9u;
+ QTest::newRow("SVG darkkhaki") << QColorConstants::Svg::darkkhaki << 0xffbdb76bu;
+ QTest::newRow("SVG darkmagenta") << QColorConstants::Svg::darkmagenta << 0xff8b008bu;
+ QTest::newRow("SVG darkolivegreen") << QColorConstants::Svg::darkolivegreen << 0xff556b2fu;
+ QTest::newRow("SVG darkorange") << QColorConstants::Svg::darkorange << 0xffff8c00u;
+ QTest::newRow("SVG darkorchid") << QColorConstants::Svg::darkorchid << 0xff9932ccu;
+ QTest::newRow("SVG darkred") << QColorConstants::Svg::darkred << 0xff8b0000u;
+ QTest::newRow("SVG darksalmon") << QColorConstants::Svg::darksalmon << 0xffe9967au;
+ QTest::newRow("SVG darkseagreen") << QColorConstants::Svg::darkseagreen << 0xff8fbc8fu;
+ QTest::newRow("SVG darkslateblue") << QColorConstants::Svg::darkslateblue << 0xff483d8bu;
+ QTest::newRow("SVG darkslategray") << QColorConstants::Svg::darkslategray << 0xff2f4f4fu;
+ QTest::newRow("SVG darkslategrey") << QColorConstants::Svg::darkslategrey << 0xff2f4f4fu;
+ QTest::newRow("SVG darkturquoise") << QColorConstants::Svg::darkturquoise << 0xff00ced1u;
+ QTest::newRow("SVG darkviolet") << QColorConstants::Svg::darkviolet << 0xff9400d3u;
+ QTest::newRow("SVG deeppink") << QColorConstants::Svg::deeppink << 0xffff1493u;
+ QTest::newRow("SVG deepskyblue") << QColorConstants::Svg::deepskyblue << 0xff00bfffu;
+ QTest::newRow("SVG dimgray") << QColorConstants::Svg::dimgray << 0xff696969u;
+ QTest::newRow("SVG dimgrey") << QColorConstants::Svg::dimgrey << 0xff696969u;
+ QTest::newRow("SVG dodgerblue") << QColorConstants::Svg::dodgerblue << 0xff1e90ffu;
+ QTest::newRow("SVG firebrick") << QColorConstants::Svg::firebrick << 0xffb22222u;
+ QTest::newRow("SVG floralwhite") << QColorConstants::Svg::floralwhite << 0xfffffaf0u;
+ QTest::newRow("SVG forestgreen") << QColorConstants::Svg::forestgreen << 0xff228b22u;
+ QTest::newRow("SVG fuchsia") << QColorConstants::Svg::fuchsia << 0xffff00ffu;
+ QTest::newRow("SVG gainsboro") << QColorConstants::Svg::gainsboro << 0xffdcdcdcu;
+ QTest::newRow("SVG ghostwhite") << QColorConstants::Svg::ghostwhite << 0xfff8f8ffu;
+ QTest::newRow("SVG gold") << QColorConstants::Svg::gold << 0xffffd700u;
+ QTest::newRow("SVG goldenrod") << QColorConstants::Svg::goldenrod << 0xffdaa520u;
+ QTest::newRow("SVG gray") << QColorConstants::Svg::gray << 0xff808080u;
+ QTest::newRow("SVG green") << QColorConstants::Svg::green << 0xff008000u;
+ QTest::newRow("SVG greenyellow") << QColorConstants::Svg::greenyellow << 0xffadff2fu;
+ QTest::newRow("SVG grey") << QColorConstants::Svg::grey << 0xff808080u;
+ QTest::newRow("SVG honeydew") << QColorConstants::Svg::honeydew << 0xfff0fff0u;
+ QTest::newRow("SVG hotpink") << QColorConstants::Svg::hotpink << 0xffff69b4u;
+ QTest::newRow("SVG indianred") << QColorConstants::Svg::indianred << 0xffcd5c5cu;
+ QTest::newRow("SVG indigo") << QColorConstants::Svg::indigo << 0xff4b0082u;
+ QTest::newRow("SVG ivory") << QColorConstants::Svg::ivory << 0xfffffff0u;
+ QTest::newRow("SVG khaki") << QColorConstants::Svg::khaki << 0xfff0e68cu;
+ QTest::newRow("SVG lavender") << QColorConstants::Svg::lavender << 0xffe6e6fau;
+ QTest::newRow("SVG lavenderblush") << QColorConstants::Svg::lavenderblush << 0xfffff0f5u;
+ QTest::newRow("SVG lawngreen") << QColorConstants::Svg::lawngreen << 0xff7cfc00u;
+ QTest::newRow("SVG lemonchiffon") << QColorConstants::Svg::lemonchiffon << 0xfffffacdu;
+ QTest::newRow("SVG lightblue") << QColorConstants::Svg::lightblue << 0xffadd8e6u;
+ QTest::newRow("SVG lightcoral") << QColorConstants::Svg::lightcoral << 0xfff08080u;
+ QTest::newRow("SVG lightcyan") << QColorConstants::Svg::lightcyan << 0xffe0ffffu;
+ QTest::newRow("SVG lightgoldenrodyellow") << QColorConstants::Svg::lightgoldenrodyellow << 0xfffafad2u;
+ QTest::newRow("SVG lightgray") << QColorConstants::Svg::lightgray << 0xffd3d3d3u;
+ QTest::newRow("SVG lightgreen") << QColorConstants::Svg::lightgreen << 0xff90ee90u;
+ QTest::newRow("SVG lightgrey") << QColorConstants::Svg::lightgrey << 0xffd3d3d3u;
+ QTest::newRow("SVG lightpink") << QColorConstants::Svg::lightpink << 0xffffb6c1u;
+ QTest::newRow("SVG lightsalmon") << QColorConstants::Svg::lightsalmon << 0xffffa07au;
+ QTest::newRow("SVG lightseagreen") << QColorConstants::Svg::lightseagreen << 0xff20b2aau;
+ QTest::newRow("SVG lightskyblue") << QColorConstants::Svg::lightskyblue << 0xff87cefau;
+ QTest::newRow("SVG lightslategray") << QColorConstants::Svg::lightslategray << 0xff778899u;
+ QTest::newRow("SVG lightslategrey") << QColorConstants::Svg::lightslategrey << 0xff778899u;
+ QTest::newRow("SVG lightsteelblue") << QColorConstants::Svg::lightsteelblue << 0xffb0c4deu;
+ QTest::newRow("SVG lightyellow") << QColorConstants::Svg::lightyellow << 0xffffffe0u;
+ QTest::newRow("SVG lime") << QColorConstants::Svg::lime << 0xff00ff00u;
+ QTest::newRow("SVG limegreen") << QColorConstants::Svg::limegreen << 0xff32cd32u;
+ QTest::newRow("SVG linen") << QColorConstants::Svg::linen << 0xfffaf0e6u;
+ QTest::newRow("SVG magenta") << QColorConstants::Svg::magenta << 0xffff00ffu;
+ QTest::newRow("SVG maroon") << QColorConstants::Svg::maroon << 0xff800000u;
+ QTest::newRow("SVG mediumaquamarine") << QColorConstants::Svg::mediumaquamarine << 0xff66cdaau;
+ QTest::newRow("SVG mediumblue") << QColorConstants::Svg::mediumblue << 0xff0000cdu;
+ QTest::newRow("SVG mediumorchid") << QColorConstants::Svg::mediumorchid << 0xffba55d3u;
+ QTest::newRow("SVG mediumpurple") << QColorConstants::Svg::mediumpurple << 0xff9370dbu;
+ QTest::newRow("SVG mediumseagreen") << QColorConstants::Svg::mediumseagreen << 0xff3cb371u;
+ QTest::newRow("SVG mediumslateblue") << QColorConstants::Svg::mediumslateblue << 0xff7b68eeu;
+ QTest::newRow("SVG mediumspringgreen") << QColorConstants::Svg::mediumspringgreen << 0xff00fa9au;
+ QTest::newRow("SVG mediumturquoise") << QColorConstants::Svg::mediumturquoise << 0xff48d1ccu;
+ QTest::newRow("SVG mediumvioletred") << QColorConstants::Svg::mediumvioletred << 0xffc71585u;
+ QTest::newRow("SVG midnightblue") << QColorConstants::Svg::midnightblue << 0xff191970u;
+ QTest::newRow("SVG mintcream") << QColorConstants::Svg::mintcream << 0xfff5fffau;
+ QTest::newRow("SVG mistyrose") << QColorConstants::Svg::mistyrose << 0xffffe4e1u;
+ QTest::newRow("SVG moccasin") << QColorConstants::Svg::moccasin << 0xffffe4b5u;
+ QTest::newRow("SVG navajowhite") << QColorConstants::Svg::navajowhite << 0xffffdeadu;
+ QTest::newRow("SVG navy") << QColorConstants::Svg::navy << 0xff000080u;
+ QTest::newRow("SVG oldlace") << QColorConstants::Svg::oldlace << 0xfffdf5e6u;
+ QTest::newRow("SVG olive") << QColorConstants::Svg::olive << 0xff808000u;
+ QTest::newRow("SVG olivedrab") << QColorConstants::Svg::olivedrab << 0xff6b8e23u;
+ QTest::newRow("SVG orange") << QColorConstants::Svg::orange << 0xffffa500u;
+ QTest::newRow("SVG orangered") << QColorConstants::Svg::orangered << 0xffff4500u;
+ QTest::newRow("SVG orchid") << QColorConstants::Svg::orchid << 0xffda70d6u;
+ QTest::newRow("SVG palegoldenrod") << QColorConstants::Svg::palegoldenrod << 0xffeee8aau;
+ QTest::newRow("SVG palegreen") << QColorConstants::Svg::palegreen << 0xff98fb98u;
+ QTest::newRow("SVG paleturquoise") << QColorConstants::Svg::paleturquoise << 0xffafeeeeu;
+ QTest::newRow("SVG palevioletred") << QColorConstants::Svg::palevioletred << 0xffdb7093u;
+ QTest::newRow("SVG papayawhip") << QColorConstants::Svg::papayawhip << 0xffffefd5u;
+ QTest::newRow("SVG peachpuff") << QColorConstants::Svg::peachpuff << 0xffffdab9u;
+ QTest::newRow("SVG peru") << QColorConstants::Svg::peru << 0xffcd853fu;
+ QTest::newRow("SVG pink") << QColorConstants::Svg::pink << 0xffffc0cbu;
+ QTest::newRow("SVG plum") << QColorConstants::Svg::plum << 0xffdda0ddu;
+ QTest::newRow("SVG powderblue") << QColorConstants::Svg::powderblue << 0xffb0e0e6u;
+ QTest::newRow("SVG purple") << QColorConstants::Svg::purple << 0xff800080u;
+ QTest::newRow("SVG red") << QColorConstants::Svg::red << 0xffff0000u;
+ QTest::newRow("SVG rosybrown") << QColorConstants::Svg::rosybrown << 0xffbc8f8fu;
+ QTest::newRow("SVG royalblue") << QColorConstants::Svg::royalblue << 0xff4169e1u;
+ QTest::newRow("SVG saddlebrown") << QColorConstants::Svg::saddlebrown << 0xff8b4513u;
+ QTest::newRow("SVG salmon") << QColorConstants::Svg::salmon << 0xfffa8072u;
+ QTest::newRow("SVG sandybrown") << QColorConstants::Svg::sandybrown << 0xfff4a460u;
+ QTest::newRow("SVG seagreen") << QColorConstants::Svg::seagreen << 0xff2e8b57u;
+ QTest::newRow("SVG seashell") << QColorConstants::Svg::seashell << 0xfffff5eeu;
+ QTest::newRow("SVG sienna") << QColorConstants::Svg::sienna << 0xffa0522du;
+ QTest::newRow("SVG silver") << QColorConstants::Svg::silver << 0xffc0c0c0u;
+ QTest::newRow("SVG skyblue") << QColorConstants::Svg::skyblue << 0xff87ceebu;
+ QTest::newRow("SVG slateblue") << QColorConstants::Svg::slateblue << 0xff6a5acdu;
+ QTest::newRow("SVG slategray") << QColorConstants::Svg::slategray << 0xff708090u;
+ QTest::newRow("SVG slategrey") << QColorConstants::Svg::slategrey << 0xff708090u;
+ QTest::newRow("SVG snow") << QColorConstants::Svg::snow << 0xfffffafau;
+ QTest::newRow("SVG springgreen") << QColorConstants::Svg::springgreen << 0xff00ff7fu;
+ QTest::newRow("SVG steelblue") << QColorConstants::Svg::steelblue << 0xff4682b4u;
+ QTest::newRow("SVG tan") << QColorConstants::Svg::tan << 0xffd2b48cu;
+ QTest::newRow("SVG teal") << QColorConstants::Svg::teal << 0xff008080u;
+ QTest::newRow("SVG thistle") << QColorConstants::Svg::thistle << 0xffd8bfd8u;
+ QTest::newRow("SVG tomato") << QColorConstants::Svg::tomato << 0xffff6347u;
+ QTest::newRow("SVG turquoise") << QColorConstants::Svg::turquoise << 0xff40e0d0u;
+ QTest::newRow("SVG violet") << QColorConstants::Svg::violet << 0xffee82eeu;
+ QTest::newRow("SVG wheat") << QColorConstants::Svg::wheat << 0xfff5deb3u;
+ QTest::newRow("SVG white") << QColorConstants::Svg::white << 0xffffffffu;
+ QTest::newRow("SVG whitesmoke") << QColorConstants::Svg::whitesmoke << 0xfff5f5f5u;
+ QTest::newRow("SVG yellow") << QColorConstants::Svg::yellow << 0xffffff00u;
+ QTest::newRow("SVG yellowgreen") << QColorConstants::Svg::yellowgreen << 0xff9acd32u;
+}
+
+void tst_QColor::colorConstants()
+{
+ QFETCH(QColor, color);
+ QFETCH(QRgb, argb);
+ QCOMPARE(color.rgba(), argb);
+}
+#endif // defined(Q_COMPILER_CONSTEXPR) & defined(Q_COMPILER_UNIFORM_INIT)
+
/*
CSS color names = SVG 1.0 color names + transparent (rgba(0,0,0,0))
*/
@@ -677,30 +863,81 @@ void tst_QColor::setRgb()
{
QColor color;
- for (int A = 0; A <= USHRT_MAX; ++A) {
- {
- // 0-255
- int a = A >> 8;
- QRgb rgb = qRgba(0, 0, 0, a);
+ for (int a = 0; a <= 255; ++a) {
+ QRgb rgb = qRgba(0, 0, 0, a);
- color.setRgb(0, 0, 0, a);
- QCOMPARE(color.alpha(), a);
- QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+ color.setRgb(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
- color.setRgb(rgb);
- QCOMPARE(color.alpha(), 255);
- QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+ color.setRgb(rgb);
+ QCOMPARE(color.alpha(), 255);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
- int r, g, b, a2;
- color.setRgb(0, 0, 0, a);
- color.getRgb(&r, &g, &b, &a2);
- QCOMPARE(a2, a);
+ int r, g, b, a2;
+ color.setRgb(0, 0, 0, a);
+ color.getRgb(&r, &g, &b, &a2);
+ QCOMPARE(a2, a);
- QColor c(0, 0, 0);
- c.setAlpha(a);
- QCOMPARE(c.alpha(), a);
- }
+ QColor c(0, 0, 0);
+ c.setAlpha(a);
+ QCOMPARE(c.alpha(), a);
+ }
+
+ for (int r = 0; r <= 255; ++r) {
+ QRgb rgb = qRgb(r, 0, 0);
+ color.setRgb(r, 0, 0);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r2, g, b, a;
+ color.getRgb(&r2, &g, &b, &a);
+ QCOMPARE(r2, r);
+ }
+
+ for (int g = 0; g <= 255; ++g) {
+ QRgb rgb = qRgb(0, g, 0);
+
+ color.setRgb(0, g, 0);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g2, b, a;
+ color.getRgb(&r, &g2, &b, &a);
+ QCOMPARE(g2, g);
+ }
+
+ for (int b = 0; b <= 255; ++b) {
+ QRgb rgb = qRgb(0, 0, b);
+
+ color.setRgb(0, 0, b);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g, b2, a;
+ color.getRgb(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+}
+
+void tst_QColor::setRgbF()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
{
// 0.0-1.0
qreal a = A / qreal(USHRT_MAX);
@@ -720,24 +957,6 @@ void tst_QColor::setRgb()
for (int R = 0; R <= USHRT_MAX; ++R) {
{
- // 0-255
- int r = R >> 8;
- QRgb rgb = qRgb(r, 0, 0);
-
- color.setRgb(r, 0, 0);
- QCOMPARE(color.red(), r);
- QCOMPARE(color.rgb(), rgb);
-
- color.setRgb(rgb);
- QCOMPARE(color.red(), r);
- QCOMPARE(color.rgb(), rgb);
-
- int r2, g, b, a;
- color.getRgb(&r2, &g, &b, &a);
- QCOMPARE(r2, r);
- }
-
- {
// 0.0-1.0
qreal r = R / qreal(USHRT_MAX);
color.setRgbF(r, 0.0, 0.0);
@@ -751,24 +970,6 @@ void tst_QColor::setRgb()
for (int G = 0; G <= USHRT_MAX; ++G) {
{
- // 0-255
- int g = G >> 8;
- QRgb rgb = qRgb(0, g, 0);
-
- color.setRgb(0, g, 0);
- QCOMPARE(color.green(), g);
- QCOMPARE(color.rgb(), rgb);
-
- color.setRgb(rgb);
- QCOMPARE(color.green(), g);
- QCOMPARE(color.rgb(), rgb);
-
- int r, g2, b, a;
- color.getRgb(&r, &g2, &b, &a);
- QCOMPARE(g2, g);
- }
-
- {
// 0.0-1.0
qreal g = G / qreal(USHRT_MAX);
color.setRgbF(0.0, g, 0.0);
@@ -782,32 +983,53 @@ void tst_QColor::setRgb()
for (int B = 0; B <= USHRT_MAX; ++B) {
{
- // 0-255
- int b = B >> 8;
- QRgb rgb = qRgb(0, 0, b);
+ // 0.0-1.0
+ qreal b = B / qreal(USHRT_MAX);
+ color.setRgbF(0.0, 0.0, b);
+ QCOMPARE(color.blueF(), b);
- color.setRgb(0, 0, b);
- QCOMPARE(color.blue(), b);
- QCOMPARE(color.rgb(), rgb);
+ qreal r, g, b2, a;
+ color.getRgbF(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+ }
- color.setRgb(rgb);
- QCOMPARE(color.blue(), b);
- QCOMPARE(color.rgb(), rgb);
+ for (int R = -128; R <= 512; ++R) {
+ {
+ // extended RGB
+ qreal r = R / qreal(256);
+ color.setRgbF(r, 0.0, 0.0);
+ QCOMPARE(qfloat16(color.redF()), qfloat16(r));
- int r, g, b2, a;
- color.getRgb(&r, &g, &b2, &a);
- QCOMPARE(b2, b);
+ qreal r2, g, b, a;
+ color.getRgbF(&r2, &g, &b, &a);
+ QCOMPARE(qfloat16(r2), qfloat16(r));
}
+ }
+ for (int G = -128; G <= 512; ++G) {
{
- // 0.0-1.0
- qreal b = B / qreal(USHRT_MAX);
+ // extended RGB
+ qreal g = G / qreal(256);
+ color.setRgbF(0.0, g, 0.0);
+ QCOMPARE(qfloat16(color.greenF()), qfloat16(g));
+
+ qreal r, g2, b, a;
+ color.getRgbF(&r, &g2, &b, &a);
+ QCOMPARE(qfloat16(g2), qfloat16(g));
+ }
+ }
+
+ for (int B = -128; B <= 512; ++B) {
+ {
+ // extended RGB
+ qreal b = B / qreal(256);
color.setRgbF(0.0, 0.0, b);
- QCOMPARE(color.blueF(), b);
+ QCOMPARE(qfloat16(color.blueF()), qfloat16(b));
qreal r, g, b2, a;
color.getRgbF(&r, &g, &b2, &a);
- QCOMPARE(b2, b);
+ QCOMPARE(qfloat16(b2), qfloat16(b));
}
}
}
@@ -1382,17 +1604,17 @@ void tst_QColor::convertTo()
QCOMPARE(invalid.spec(), QColor::Invalid);
}
-void tst_QColor::light()
+void tst_QColor::lighter()
{
QColor gray(Qt::gray);
- QColor lighter = gray.light();
+ QColor lighter = gray.lighter();
QVERIFY(lighter.value() > gray.value());
}
-void tst_QColor::dark()
+void tst_QColor::darker()
{
QColor gray(Qt::gray);
- QColor darker = gray.dark();
+ QColor darker = gray.darker();
QVERIFY(darker.value() < gray.value());
}
@@ -1423,62 +1645,6 @@ void tst_QColor::achromaticHslHue()
QCOMPARE(hsl.hslHue(), -1);
}
-#if 0 // Used to be included in Qt4 for Q_WS_X11
-void tst_QColor::setallowX11ColorNames()
-{
- RGBData x11RgbTbl[] = {
- // a few standard X11 color names
- { "DodgerBlue1", qRgb(30, 144, 255) },
- { "DodgerBlue2", qRgb(28, 134, 238) },
- { "DodgerBlue3", qRgb(24, 116, 205) },
- { "DodgerBlue4", qRgb(16, 78, 139) },
- { "SteelBlue1", qRgb(99, 184, 255) },
- { "SteelBlue2", qRgb(92, 172, 238) },
- { "SteelBlue3", qRgb(79, 148, 205) },
- { "SteelBlue4", qRgb(54, 100, 139) },
- { "DeepSkyBlue1", qRgb(0, 191, 255) },
- { "DeepSkyBlue2", qRgb(0, 178, 238) },
- { "DeepSkyBlue3", qRgb(0, 154, 205) },
- { "DeepSkyBlue4", qRgb(0, 104, 139) },
- { "SkyBlue1", qRgb(135, 206, 255) },
- { "SkyBlue2", qRgb(126, 192, 238) },
- { "SkyBlue3", qRgb(108, 166, 205) },
- { "SkyBlue4", qRgb(74, 112, 139) }
- };
- static const int x11RgbTblSize = sizeof(x11RgbTbl) / sizeof(RGBData);
-
- // X11 color names should not work by default
- QVERIFY(!QColor::allowX11ColorNames());
- for (int i = 0; i < x11RgbTblSize; ++i) {
- QString colorName = QLatin1String(x11RgbTbl[i].name);
- QColor color;
- color.setNamedColor(colorName);
- QVERIFY(!color.isValid());
- }
-
- // enable X11 color names
- QColor::setAllowX11ColorNames(true);
- QVERIFY(QColor::allowX11ColorNames());
- for (int i = 0; i < x11RgbTblSize; ++i) {
- QString colorName = QLatin1String(x11RgbTbl[i].name);
- QColor color;
- color.setNamedColor(colorName);
- QColor expected(x11RgbTbl[i].value);
- QCOMPARE(color, expected);
- }
-
- // should be able to turn off X11 color names
- QColor::setAllowX11ColorNames(false);
- QVERIFY(!QColor::allowX11ColorNames());
- for (int i = 0; i < x11RgbTblSize; ++i) {
- QString colorName = QLatin1String(x11RgbTbl[i].name);
- QColor color;
- color.setNamedColor(colorName);
- QVERIFY(!color.isValid());
- }
-}
-#endif
-
void tst_QColor::premultiply()
{
// Tests that qPremultiply(qUnpremultiply(x)) returns x.
@@ -1632,14 +1798,13 @@ void tst_QColor::qcolorprofile_data()
QTest::newRow("gamma=1.7") << qreal(1.7) << 2;
QTest::newRow("gamma=2.0") << qreal(2.0) << 8;
QTest::newRow("gamma=2.31") << qreal(2.31) << 33;
- QTest::newRow("SRgb") << qreal(0.0) << 7;
}
void tst_QColor::qcolorprofile()
{
QFETCH(qreal, gammaC);
QFETCH(int, tolerance);
- QColorProfile *cp = (gammaC == 0) ? QColorProfile::fromSRgb(): QColorProfile::fromGamma(gammaC);
+ QColorTrcLut *cp = QColorTrcLut::fromGamma(gammaC);
// Test we are accurate for most values after converting through gamma-correction.
int error = 0;
diff --git a/tests/auto/gui/painting/qcolorspace/qcolorspace.pro b/tests/auto/gui/painting/qcolorspace/qcolorspace.pro
new file mode 100644
index 0000000000..14bd699bf7
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/qcolorspace.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+QT += testlib gui-private core-private
+
+TARGET = tst_qcolorspace
+SOURCES += tst_qcolorspace.cpp
+
+RESOURCES += $$files(resources/*)
+
+TESTDATA += resources/*
diff --git a/tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.icc b/tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.icc
new file mode 100644
index 0000000000..b3f860714c
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/HP_ZR30w.icc
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg b/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg
new file mode 100644
index 0000000000..481d35ca8e
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc b/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc
new file mode 100644
index 0000000000..49afbfef10
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
new file mode 100644
index 0000000000..531e14d25b
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
@@ -0,0 +1,448 @@
+/****************************************************************************
+**
+** 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 <qcolorspace.h>
+#include <qimage.h>
+#include <qimagereader.h>
+
+#include <private/qcolorspace_p.h>
+
+Q_DECLARE_METATYPE(QColorSpace::NamedColorSpace)
+Q_DECLARE_METATYPE(QColorSpace::Primaries)
+Q_DECLARE_METATYPE(QColorSpace::TransferFunction)
+
+class tst_QColorSpace : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QColorSpace();
+
+private slots:
+ void movable();
+ void namedColorSpaces_data();
+ void namedColorSpaces();
+
+ void toIccProfile_data();
+ void toIccProfile();
+
+ void fromIccProfile_data();
+ void fromIccProfile();
+
+ void imageConversion_data();
+ void imageConversion();
+
+ void loadImage();
+
+ void primaries();
+ void primariesXyz();
+
+#ifdef QT_BUILD_INTERNAL
+ void primaries2_data();
+ void primaries2();
+#endif
+
+ void invalidPrimaries();
+
+ void changeTransferFunction();
+ void changePrimaries();
+};
+
+tst_QColorSpace::tst_QColorSpace()
+{ }
+
+
+void tst_QColorSpace::movable()
+{
+ QColorSpace cs1 = QColorSpace::SRgb;
+ QColorSpace cs2 = QColorSpace::SRgbLinear;
+ QVERIFY(cs1.isValid());
+ QVERIFY(cs2.isValid());
+ QCOMPARE(cs1, QColorSpace::SRgb);
+
+ cs2 = std::move(cs1);
+ QVERIFY(!cs1.isValid());
+ QVERIFY(cs2.isValid());
+ QCOMPARE(cs2, QColorSpace::SRgb);
+ QVERIFY(cs1 != QColorSpace::SRgb);
+ QCOMPARE(cs1, QColorSpace());
+
+ QColorSpace cs3(std::move(cs2));
+ QVERIFY(!cs2.isValid());
+ QVERIFY(cs3.isValid());
+ QCOMPARE(cs3, QColorSpace::SRgb);
+ QCOMPARE(cs2, QColorSpace());
+}
+
+void tst_QColorSpace::namedColorSpaces_data()
+{
+ QTest::addColumn<QColorSpace::NamedColorSpace>("namedColorSpace");
+ QTest::addColumn<QColorSpace::Primaries>("primariesId");
+ QTest::addColumn<QColorSpace::TransferFunction>("transferFunctionId");
+
+ QTest::newRow("sRGB") << QColorSpace::SRgb
+ << QColorSpace::Primaries::SRgb
+ << QColorSpace::TransferFunction::SRgb;
+ QTest::newRow("sRGB Linear") << QColorSpace::SRgbLinear
+ << QColorSpace::Primaries::SRgb
+ << QColorSpace::TransferFunction::Linear;
+ QTest::newRow("Adobe RGB") << QColorSpace::AdobeRgb
+ << QColorSpace::Primaries::AdobeRgb
+ << QColorSpace::TransferFunction::Gamma;
+ QTest::newRow("Display-P3") << QColorSpace::DisplayP3
+ << QColorSpace::Primaries::DciP3D65
+ << QColorSpace::TransferFunction::SRgb;
+ QTest::newRow("ProPhoto RGB") << QColorSpace::ProPhotoRgb
+ << QColorSpace::Primaries::ProPhotoRgb
+ << QColorSpace::TransferFunction::ProPhotoRgb;
+}
+
+void tst_QColorSpace::namedColorSpaces()
+{
+ QFETCH(QColorSpace::NamedColorSpace, namedColorSpace);
+ QFETCH(QColorSpace::Primaries, primariesId);
+ QFETCH(QColorSpace::TransferFunction, transferFunctionId);
+
+ QColorSpace colorSpace = namedColorSpace;
+
+ QVERIFY(colorSpace.isValid());
+
+ QCOMPARE(colorSpace, namedColorSpace);
+ QCOMPARE(colorSpace.primaries(), primariesId);
+ QCOMPARE(colorSpace.transferFunction(), transferFunctionId);
+}
+
+
+void tst_QColorSpace::toIccProfile_data()
+{
+ namedColorSpaces_data();
+}
+
+void tst_QColorSpace::toIccProfile()
+{
+ QFETCH(QColorSpace::NamedColorSpace, namedColorSpace);
+ QFETCH(QColorSpace::Primaries, primariesId);
+ QFETCH(QColorSpace::TransferFunction, transferFunctionId);
+
+ Q_UNUSED(primariesId);
+ Q_UNUSED(transferFunctionId);
+
+ QColorSpace colorSpace = namedColorSpace;
+ QByteArray iccProfile = colorSpace.iccProfile();
+ QVERIFY(!iccProfile.isEmpty());
+
+ QColorSpace colorSpace2 = QColorSpace::fromIccProfile(iccProfile);
+ QVERIFY(colorSpace2.isValid());
+
+ QCOMPARE(colorSpace2, colorSpace);
+
+ QByteArray iccProfile2 = colorSpace2.iccProfile();
+ QVERIFY(!iccProfile2.isEmpty());
+
+ QCOMPARE(iccProfile2, iccProfile);
+}
+
+void tst_QColorSpace::fromIccProfile_data()
+{
+ QTest::addColumn<QString>("testProfile");
+ QTest::addColumn<QColorSpace::NamedColorSpace>("namedColorSpace");
+ QTest::addColumn<QColorSpace::TransferFunction>("transferFunction");
+ QTest::addColumn<QString>("description");
+
+ QString prefix = QFINDTESTDATA("resources/");
+ // Read the official sRGB ICCv2 profile:
+ QTest::newRow("sRGB2014 (ICCv2)") << prefix + "sRGB2014.icc" << QColorSpace::SRgb
+ << QColorSpace::TransferFunction::SRgb << QString("sRGB2014");
+ // My monitor's profile:
+ QTest::newRow("HP ZR30w (ICCv4)") << prefix + "HP_ZR30w.icc" << QColorSpace::NamedColorSpace(0)
+ << QColorSpace::TransferFunction::Gamma << QString("HP Z30i");
+}
+
+void tst_QColorSpace::fromIccProfile()
+{
+ QFETCH(QString, testProfile);
+ QFETCH(QColorSpace::NamedColorSpace, namedColorSpace);
+ QFETCH(QColorSpace::TransferFunction, transferFunction);
+ QFETCH(QString, description);
+
+ QFile file(testProfile);
+ file.open(QIODevice::ReadOnly);
+ QByteArray iccProfile = file.readAll();
+ QColorSpace fileColorSpace = QColorSpace::fromIccProfile(iccProfile);
+ QVERIFY(fileColorSpace.isValid());
+
+ if (namedColorSpace)
+ QCOMPARE(fileColorSpace, namedColorSpace);
+
+ QCOMPARE(fileColorSpace.transferFunction(), transferFunction);
+ QCOMPARE(QColorSpacePrivate::get(fileColorSpace)->description, description);
+}
+
+void tst_QColorSpace::imageConversion_data()
+{
+ QTest::addColumn<QColorSpace::NamedColorSpace>("fromColorSpace");
+ QTest::addColumn<QColorSpace::NamedColorSpace>("toColorSpace");
+ QTest::addColumn<int>("tolerance");
+
+ QTest::newRow("sRGB -> Display-P3") << QColorSpace::SRgb << QColorSpace::DisplayP3 << 0;
+ QTest::newRow("sRGB -> Adobe RGB") << QColorSpace::SRgb << QColorSpace::AdobeRgb << 2;
+ QTest::newRow("Display-P3 -> sRGB") << QColorSpace::DisplayP3 << QColorSpace::SRgb << 0;
+ QTest::newRow("Adobe RGB -> sRGB") << QColorSpace::AdobeRgb << QColorSpace::SRgb << 2;
+ QTest::newRow("Display-P3 -> Adobe RGB") << QColorSpace::DisplayP3 << QColorSpace::AdobeRgb << 2;
+ QTest::newRow("sRGB -> sRGB Linear") << QColorSpace::SRgb << QColorSpace::SRgbLinear << 0;
+}
+
+void tst_QColorSpace::imageConversion()
+{
+ QFETCH(QColorSpace::NamedColorSpace, fromColorSpace);
+ QFETCH(QColorSpace::NamedColorSpace, toColorSpace);
+ QFETCH(int, tolerance);
+
+ QImage testImage(256, 1, QImage::Format_RGB32);
+
+ for (int i = 0; i < 256; ++i)
+ testImage.setPixel(i, 0, qRgb(i, i, i));
+
+ testImage.setColorSpace(fromColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace));
+
+ testImage.convertToColorSpace(toColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(toColorSpace));
+
+ int lastRed = 0;
+ int lastGreen = 0;
+ int lastBlue = 0;
+ for (int i = 0; i < 256; ++i) {
+ QRgb p = testImage.pixel(i, 0);
+ QVERIFY(qRed(p) >= lastRed);
+ QVERIFY(qGreen(p) >= lastGreen);
+ QVERIFY(qBlue(p) >= lastBlue);
+ lastRed = qRed(p);
+ lastGreen = qGreen(p);
+ lastBlue = qBlue(p);
+ }
+
+ lastRed = 0;
+ lastGreen = 0;
+ lastBlue = 0;
+ testImage.convertToColorSpace(fromColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace));
+ for (int i = 0; i < 256; ++i) {
+ QRgb p = testImage.pixel(i, 0);
+ QVERIFY(qAbs(qRed(p) - qGreen(p)) <= tolerance);
+ QVERIFY(qAbs(qRed(p) - qBlue(p)) <= tolerance);
+ QVERIFY((lastRed - qRed(p)) <= (tolerance / 2));
+ QVERIFY((lastGreen - qGreen(p)) <= (tolerance / 2));
+ QVERIFY((lastBlue - qBlue(p)) <= (tolerance / 2));
+ lastRed = qRed(p);
+ lastGreen = qGreen(p);
+ lastBlue = qBlue(p);
+ }
+}
+
+
+void tst_QColorSpace::loadImage()
+{
+ QString prefix = QFINDTESTDATA("resources/");
+ QImageReader reader(prefix + "ProPhoto.jpg");
+ QImage image = reader.read();
+
+ QVERIFY(!image.isNull());
+ QVERIFY(image.colorSpace().isValid());
+ QCOMPARE(image.colorSpace(), QColorSpace::ProPhotoRgb);
+ QVERIFY(!image.colorSpace().iccProfile().isEmpty());
+
+ QColorSpace defaultProPhotoRgb = QColorSpace::ProPhotoRgb;
+ QVERIFY(!defaultProPhotoRgb.iccProfile().isEmpty());
+
+ // Test the iccProfile getter returns the ICC profile from the image
+ // which since we didn't write it, isn't identical to our defaults.
+ QVERIFY(defaultProPhotoRgb.iccProfile() != image.colorSpace().iccProfile());
+
+ QColorTransform transform = image.colorSpace().transformationToColorSpace(QColorSpace::SRgb);
+ qreal maxRed = 0;
+ qreal maxBlue = 0;
+ qreal maxRed2 = 0;
+ qreal maxBlue2 = 0;
+ for (int y = 0; y < image.height(); ++y) {
+ for (int x = 0; x < image.width(); ++x) {
+ QColor p = image.pixelColor(x, y);
+ maxRed = std::max(maxRed, p.redF());
+ maxBlue = std::max(maxBlue, p.blueF());
+ p = transform.map(p);
+ maxRed2 = std::max(maxRed2, p.redF());
+ maxBlue2 = std::max(maxBlue2, p.blueF());
+
+ }
+ }
+ // ProPhotoRgb can be a lot more red and blue than SRgb can, so it will have lower values.
+ QVERIFY(maxRed2 > maxRed);
+ QVERIFY(maxBlue2 > maxBlue);
+}
+
+void tst_QColorSpace::primaries()
+{
+ QColor black = QColor::fromRgbF(0.0, 0.0, 0.0);
+ QColor white = QColor::fromRgbF(1.0, 1.0, 1.0);
+ QColor red = QColor::fromRgbF(1.0, 0.0, 0.0);
+ QColor green = QColor::fromRgbF(0.0, 1.0, 0.0);
+ QColor blue = QColor::fromRgbF(0.0, 0.0, 1.0);
+
+ QColorTransform toAdobeRgb = QColorSpace(QColorSpace::SRgb).transformationToColorSpace(QColorSpace::AdobeRgb);
+
+ QColor tblack = toAdobeRgb.map(black);
+ QColor twhite = toAdobeRgb.map(white);
+ QColor tred = toAdobeRgb.map(red);
+ QColor tgreen = toAdobeRgb.map(green);
+ QColor tblue = toAdobeRgb.map(blue);
+
+ // Black is black
+ QCOMPARE(tblack, black);
+
+ // This white hasn't changed
+ QCOMPARE(twhite, white);
+
+ // Adobe's red and blue gamut corners are the same as sRGB's
+ // So, a color in the red corner, will stay in the red corner
+ // the same for blue, but not for green.
+ QVERIFY(tred.greenF() < 0.001);
+ QVERIFY(tred.blueF() < 0.001);
+ QVERIFY(tblue.redF() < 0.001);
+ QVERIFY(tblue.greenF() < 0.001);
+ QVERIFY(tgreen.redF() > 0.2);
+ QVERIFY(tgreen.blueF() > 0.2);
+}
+
+void tst_QColorSpace::primariesXyz()
+{
+ QColorSpace sRgb = QColorSpace::SRgb;
+ QColorSpace adobeRgb = QColorSpace::AdobeRgb;
+ QColorSpace displayP3 = QColorSpace::DisplayP3;
+ QColorSpace proPhotoRgb = QColorSpace::ProPhotoRgb;
+
+ // Check if our calculated matrices, match the precalculated ones.
+ QCOMPARE(QColorSpacePrivate::get(sRgb)->toXyz, QColorMatrix::toXyzFromSRgb());
+ QCOMPARE(QColorSpacePrivate::get(adobeRgb)->toXyz, QColorMatrix::toXyzFromAdobeRgb());
+ QCOMPARE(QColorSpacePrivate::get(displayP3)->toXyz, QColorMatrix::toXyzFromDciP3D65());
+ QCOMPARE(QColorSpacePrivate::get(proPhotoRgb)->toXyz, QColorMatrix::toXyzFromProPhotoRgb());
+}
+
+#ifdef QT_BUILD_INTERNAL
+void tst_QColorSpace::primaries2_data()
+{
+ QTest::addColumn<QColorSpace::Primaries>("primariesId");
+
+ QTest::newRow("sRGB") << QColorSpace::Primaries::SRgb;
+ QTest::newRow("DCI-P3 (D65)") << QColorSpace::Primaries::DciP3D65;
+ QTest::newRow("Adobe RGB (1998)") << QColorSpace::Primaries::AdobeRgb;
+ QTest::newRow("ProPhoto RGB") << QColorSpace::Primaries::ProPhotoRgb;
+}
+
+void tst_QColorSpace::primaries2()
+{
+ QFETCH(QColorSpace::Primaries, primariesId);
+ QColorSpacePrimaries primaries(primariesId);
+
+ QColorSpace original(primariesId, QColorSpace::TransferFunction::Linear);
+ QColorSpace custom1(primaries.whitePoint, primaries.redPoint,
+ primaries.greenPoint, primaries.bluePoint, QColorSpace::TransferFunction::Linear);
+ QCOMPARE(original, custom1);
+
+ // A custom color swizzled color-space:
+ QColorSpace custom2(primaries.whitePoint, primaries.bluePoint,
+ primaries.greenPoint, primaries.redPoint, QColorSpace::TransferFunction::Linear);
+
+ QVERIFY(custom1 != custom2);
+ QColor color1(255, 127, 63);
+ QColor color2 = custom1.transformationToColorSpace(custom2).map(color1);
+ QCOMPARE(color2.red(), color1.blue());
+ QCOMPARE(color2.green(), color1.green());
+ QCOMPARE(color2.blue(), color1.red());
+ QCOMPARE(color2.alpha(), color1.alpha());
+ QColor color3 = custom2.transformationToColorSpace(custom1).map(color2);
+ QCOMPARE(color3.red(), color1.red());
+ QCOMPARE(color3.green(), color1.green());
+ QCOMPARE(color3.blue(), color1.blue());
+ QCOMPARE(color3.alpha(), color1.alpha());
+}
+#endif
+
+void tst_QColorSpace::invalidPrimaries()
+{
+ QColorSpace custom(QPointF(), QPointF(), QPointF(), QPointF(), QColorSpace::TransferFunction::Linear);
+ QVERIFY(!custom.isValid());
+}
+
+void tst_QColorSpace::changeTransferFunction()
+{
+ QColorSpace sRgb = QColorSpace::SRgb;
+
+ QColorSpace sRgbLinear = sRgb.withTransferFunction(QColorSpace::TransferFunction::Linear);
+ QCOMPARE(sRgbLinear.transferFunction(), QColorSpace::TransferFunction::Linear);
+ QCOMPARE(sRgbLinear.gamma(), 1.0f);
+ QCOMPARE(sRgbLinear.primaries(), QColorSpace::Primaries::SRgb);
+ QCOMPARE(sRgbLinear, QColorSpace::SRgbLinear);
+ QCOMPARE(sRgbLinear, QColorSpace(QColorSpace::SRgbLinear));
+ QVERIFY(sRgbLinear != sRgb);
+ QCOMPARE(sRgbLinear.withTransferFunction(QColorSpace::TransferFunction::SRgb), sRgb);
+
+ QColorSpace aRgb = QColorSpace::AdobeRgb;
+ aRgb.setTransferFunction(QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(aRgb.transferFunction(), QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(aRgb.primaries(), QColorSpace::Primaries::AdobeRgb);
+ QVERIFY(aRgb != QColorSpace(QColorSpace::AdobeRgb));
+ QVERIFY(aRgb != sRgb);
+ QCOMPARE(aRgb.withTransferFunction(QColorSpace::TransferFunction::Gamma, 2.2f),
+ QColorSpace(QColorSpace::AdobeRgb));
+ QVERIFY(aRgb != QColorSpace(QColorSpace::AdobeRgb));
+ aRgb.setTransferFunction(QColorSpace::TransferFunction::Gamma, 2.2f);
+ QVERIFY(aRgb == QColorSpace(QColorSpace::AdobeRgb));
+
+ QColorSpace undefined;
+ QCOMPARE(undefined.withTransferFunction(QColorSpace::TransferFunction::Linear), undefined);
+ undefined.setTransferFunction(QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(undefined, QColorSpace());
+}
+
+void tst_QColorSpace::changePrimaries()
+{
+ QColorSpace cs = QColorSpace::SRgb;
+ cs.setPrimaries(QColorSpace::Primaries::DciP3D65);
+ QVERIFY(cs.isValid());
+ QCOMPARE(cs, QColorSpace(QColorSpace::DisplayP3));
+ cs.setTransferFunction(QColorSpace::TransferFunction::Linear);
+ cs.setPrimaries(QPointF(0.3127, 0.3290), QPointF(0.640, 0.330),
+ QPointF(0.3000, 0.6000), QPointF(0.150, 0.060));
+ QCOMPARE(cs, QColorSpace(QColorSpace::SRgbLinear));
+}
+
+QTEST_MAIN(tst_QColorSpace)
+#include "tst_qcolorspace.moc"
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index bc0baed15c..d2a4dfc3e9 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -123,14 +123,18 @@ private slots:
void drawPath2();
void drawPath3();
+#if QT_DEPRECATED_SINCE(5, 13)
void drawRoundRect_data() { fillData(); }
void drawRoundRect();
+#endif
+ void drawRoundedRect_data() { fillData(); }
+ void drawRoundedRect();
void qimageFormats_data();
void qimageFormats();
void textOnTransparentImage();
-#ifndef QT_NO_WIDGETS
+#if !defined(QT_NO_WIDGETS) && QT_DEPRECATED_SINCE(5, 13)
void initFrom();
#endif
@@ -185,10 +189,12 @@ private slots:
void gradientPixelFormat_data();
void gradientPixelFormat();
+#if QT_CONFIG(raster_64bit)
void linearGradientRgb30_data();
void linearGradientRgb30();
void radialGradientRgb30_data();
void radialGradientRgb30();
+#endif
void fpe_pixmapTransform();
void fpe_zeroLengthLines();
@@ -368,10 +374,10 @@ void tst_QPainter::getSetCheck()
// bool QPainter::matrixEnabled()
// void QPainter::setMatrixEnabled(bool)
- obj1.setMatrixEnabled(false);
- QCOMPARE(false, obj1.matrixEnabled());
- obj1.setMatrixEnabled(true);
- QCOMPARE(true, obj1.matrixEnabled());
+ obj1.setWorldMatrixEnabled(false);
+ QCOMPARE(false, obj1.worldMatrixEnabled());
+ obj1.setWorldMatrixEnabled(true);
+ QCOMPARE(true, obj1.worldMatrixEnabled());
// bool QPainter::viewTransformEnabled()
// void QPainter::setViewTransformEnabled(bool)
@@ -455,11 +461,6 @@ void tst_QPainter::drawPixmap_comp()
destPm.fill(c1);
srcPm.fill(c2);
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- if (!destPm.x11PictureHandle())
- QSKIP("Requires XRender support");
-#endif
-
QPainter p(&destPm);
p.drawPixmap(0, 0, srcPm);
p.end();
@@ -677,12 +678,14 @@ static QRect getPaintedSize(const QPixmap &pm, const QColor &background)
}
#ifndef QT_NO_WIDGETS
+
+#if QT_DEPRECATED_SINCE(5, 13)
void tst_QPainter::initFrom()
{
QWidget *widget = new QWidget();
QPalette pal = widget->palette();
- pal.setColor(QPalette::Foreground, QColor(255, 0, 0));
- pal.setBrush(QPalette::Background, QColor(0, 255, 0));
+ pal.setColor(QPalette::WindowText, QColor(255, 0, 0));
+ pal.setBrush(QPalette::Window, QColor(0, 255, 0));
widget->setPalette(pal);
widget->show();
@@ -696,11 +699,12 @@ void tst_QPainter::initFrom()
p.initFrom(widget);
QCOMPARE(p.font(), font);
- QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground));
- QCOMPARE(p.background(), pal.background());
+ QCOMPARE(p.pen().color(), pal.color(QPalette::WindowText));
+ QCOMPARE(p.background(), pal.window());
delete widget;
}
+#endif
void tst_QPainter::drawBorderPixmap()
{
@@ -1544,6 +1548,7 @@ void tst_QPainter::drawClippedEllipse()
}
+#if QT_DEPRECATED_SINCE(5, 13)
void tst_QPainter::drawRoundRect()
{
QFETCH(QRect, rect);
@@ -1578,6 +1583,42 @@ void tst_QPainter::drawRoundRect()
QCOMPARE(painted.height(), rect.height() + increment);
}
}
+#endif
+
+void tst_QPainter::drawRoundedRect()
+{
+ QFETCH(QRect, rect);
+ QFETCH(bool, usePen);
+
+#ifdef Q_OS_DARWIN
+ if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen") ||
+ QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen"))
+ QSKIP("The Mac paint engine is off-by-one on certain rect sizes");
+#endif
+ QPixmap pixmap(rect.x() + rect.width() + 10,
+ rect.y() + rect.height() + 10);
+ {
+ pixmap.fill(Qt::white);
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Qt4CompatiblePainting);
+ p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
+ p.setBrush(Qt::black);
+ p.drawRoundedRect(rect, 25, 25, Qt::RelativeSize);
+ p.end();
+
+ int increment = usePen ? 1 : 0;
+
+ const QRect painted = getPaintedSize(pixmap, Qt::white);
+ QCOMPARE(painted.width(), rect.width() + increment);
+ QCOMPARE(painted.height(), rect.height() + increment);
+ }
+}
void tst_QPainter::qimageFormats_data()
{
@@ -1591,6 +1632,7 @@ void tst_QPainter::qimageFormats_data()
QTest::newRow("Qimage::Format_RGB555") << QImage::Format_RGB555;
QTest::newRow("Qimage::Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
QTest::newRow("Qimage::Format_RGB888") << QImage::Format_RGB888;
+ QTest::newRow("Qimage::Format_BGR888") << QImage::Format_BGR888;
QTest::newRow("Qimage::Format_A2RGB30_Premultiplied") << QImage::Format_A2RGB30_Premultiplied;
QTest::newRow("Qimage::Format_RGB30") << QImage::Format_RGB30;
}
@@ -1660,9 +1702,13 @@ void tst_QPainter::combinedMatrix()
p.translate(0.5, 0.5);
+ QTransform ct = p.combinedTransform();
+#if QT_DEPRECATED_SINCE(5, 13)
QMatrix cm = p.combinedMatrix();
+ QCOMPARE(cm, ct.toAffine());
+#endif
- QPointF pt = QPointF(0, 0) * cm;
+ QPointF pt = QPointF(0, 0) * ct.toAffine();
QCOMPARE(pt.x(), 48.0);
QCOMPARE(pt.y(), 16.0);
@@ -1977,7 +2023,7 @@ void tst_QPainter::clippedFillPath_data()
<< pen2;
path = QPainterPath();
- path.addRoundRect(QRect(15, 15, 50, 50), 20);
+ path.addRoundedRect(QRect(15, 15, 50, 50), 20, Qt::RelativeSize);
QTest::newRow("round rect 0") << QSize(100, 100) << path
<< QRect(15, 15, 49, 49)
<< QBrush(Qt::NoBrush)
@@ -3195,7 +3241,7 @@ void tst_QPainter::largeImagePainting()
p.translate(4, 0);
}
- p.resetMatrix();
+ p.resetTransform();
for (int i = 4; i < img.height(); i += 4) {
p.translate(0, 4);
@@ -3946,6 +3992,7 @@ void tst_QPainter::gradientInterpolation()
}
}
+#if QT_CONFIG(raster_64bit)
void tst_QPainter::linearGradientRgb30_data()
{
QTest::addColumn<QColor>("stop0");
@@ -4004,6 +4051,7 @@ void tst_QPainter::radialGradientRgb30()
QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb()));
}
}
+#endif
void tst_QPainter::drawPolygon()
{
@@ -4084,14 +4132,18 @@ void tst_QPainter::inactivePainter()
p.setClipRegion(region);
p.setClipping(true);
+#if QT_DEPRECATED_SINCE(5, 13)
p.combinedMatrix();
+#endif
p.combinedTransform();
p.compositionMode();
p.setCompositionMode(QPainter::CompositionMode_Plus);
p.device();
+#if QT_DEPRECATED_SINCE(5, 13)
p.deviceMatrix();
+#endif
p.deviceTransform();
p.font();
@@ -4115,7 +4167,9 @@ void tst_QPainter::inactivePainter()
p.setRenderHint(QPainter::Antialiasing, true);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
+#if QT_DEPRECATED_SINCE(5, 13)
p.resetMatrix();
+#endif
p.resetTransform();
p.rotate(1);
p.scale(2, 2);
@@ -4131,8 +4185,10 @@ void tst_QPainter::inactivePainter()
p.window();
p.setWindow(QRect(10, 10, 620, 460));
+#if QT_DEPRECATED_SINCE(5, 13)
p.worldMatrix();
p.setWorldMatrix(QMatrix().translate(43, 21), true);
+#endif
p.setWorldMatrixEnabled(true);
p.transform();
@@ -4884,14 +4940,18 @@ void tst_QPainter::blendARGBonRGB_data()
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM over RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_SourceOver << qRgba(85, 0, 0, 85) << 85;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 120) << 85;
+#endif
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(85, 0, 0, 85) << 85;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(180, 0, 0, 180) << 170;
+#endif
QTest::newRow("ARGB source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
diff --git a/tests/auto/gui/painting/qpathclipper/paths.cpp b/tests/auto/gui/painting/qpathclipper/paths.cpp
index 077527e1a0..1328befd1b 100644
--- a/tests/auto/gui/painting/qpathclipper/paths.cpp
+++ b/tests/auto/gui/painting/qpathclipper/paths.cpp
@@ -578,7 +578,7 @@ QPainterPath Paths::node()
m_rect.setHeight(100);
QPainterPath shape;
- shape.addRoundRect(m_rect, 25);
+ shape.addRoundedRect(m_rect, 25, Qt::RelativeSize);
const int conWidth = 10;
const int xOffset = 7;
diff --git a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
index c1a8f7f0de..9e9b0db366 100644
--- a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
+++ b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
@@ -154,12 +154,7 @@ void tst_QPdfWriter::testPageMetrics()
if (setMargins) {
// Setup the given margins
- QPdfWriter::Margins margins;
- margins.left = leftMMf;
- margins.right = rightMMf;
- margins.top = topMMf;
- margins.bottom = bottomMMf;
- writer.setMargins(margins);
+ writer.setPageMargins({leftMMf, topMMf, rightMMf, bottomMMf}, QPageLayout::Millimeter);
QCOMPARE(writer.margins().left, leftMMf);
QCOMPARE(writer.margins().right, rightMMf);
QCOMPARE(writer.margins().top, topMMf);
@@ -169,7 +164,7 @@ void tst_QPdfWriter::testPageMetrics()
// Set the given size, in Portrait mode
if (pageSize < 0) {
- writer.setPageSizeMM(sizeMMf);
+ writer.setPageSize(QPageSize(sizeMMf, QPageSize::Millimeter));
QCOMPARE(writer.pageSize(), QPdfWriter::Custom);
QCOMPARE(writer.pageLayout().pageSize().id(), QPageSize::Custom);
} else {
@@ -221,7 +216,7 @@ void tst_QPdfWriter::testPageMetrics()
// Now while in Landscape mode, set the size again, results should be the same
if (pageSize < 0) {
- writer.setPageSizeMM(sizeMMf);
+ writer.setPageSize(QPageSize(sizeMMf, QPageSize::Millimeter));
QCOMPARE(writer.pageSize(), QPdfWriter::Custom);
QCOMPARE(writer.pageLayout().pageSize().id(), QPageSize::Custom);
} else {
@@ -255,7 +250,7 @@ void tst_QPdfWriter::qtbug59443()
QTemporaryFile file;
QVERIFY2(file.open(), qPrintable(file.errorString()));
QPdfWriter writer(file.fileName());
- writer.setPageSize(QPdfWriter::A4);
+ writer.setPageSize(QPageSize(QPageSize::A4));
QTextDocument doc;
doc.documentLayout()->setPaintDevice(&writer);
diff --git a/tests/auto/gui/painting/qpen/tst_qpen.cpp b/tests/auto/gui/painting/qpen/tst_qpen.cpp
index ef65d653ce..295ae27d17 100644
--- a/tests/auto/gui/painting/qpen/tst_qpen.cpp
+++ b/tests/auto/gui/painting/qpen/tst_qpen.cpp
@@ -95,7 +95,7 @@ void tst_QPen::move()
QPen p1(Qt::black);
// check that moving does the right thing:
- QPen p2 = qMove(p1); // could be move or copy construction, so don't check p1's state
+ QPen p2 = std::move(p1); // could be move or copy construction, so don't check p1's state
QCOMPARE(p2.color(), QColor(Qt::black));
// this, executed ehre, would crash:
@@ -110,7 +110,7 @@ void tst_QPen::move()
QCOMPARE(p1.color(), QColor(Qt::yellow));
// check that moved-from QPens p2, p3 can still be safely destroyed:
- QPen p5 = qMove(p2);
+ QPen p5 = std::move(p2);
// intentionally no more statements beyond this point
}
@@ -120,7 +120,7 @@ void tst_QPen::move_assign()
QPen p1(Qt::black), p2(Qt::white);
// check that moving does the right thing:
- p2 = qMove(p1); // could be move or copy assignment, so don't check p1's state
+ p2 = std::move(p1); // could be move or copy assignment, so don't check p1's state
QCOMPARE(p2.color(), QColor(Qt::black));
// check that move-assigned-from QPen p1 can still be used, albeit
@@ -137,7 +137,7 @@ void tst_QPen::move_assign()
// check that moved-from QPens p2, p3 can still be safely destroyed:
QPen p5;
- p5 = qMove(p2);
+ p5 = std::move(p2);
// intentionally no more statements beyond this point
}
diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp
index 24c4583819..d1ea7706b9 100644
--- a/tests/auto/gui/painting/qregion/tst_qregion.cpp
+++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp
@@ -33,9 +33,6 @@
#include <qbitmap.h>
#include <qpainter.h>
#include <qpolygon.h>
-#if 0 // Used to be included in Qt4 for Q_WS_X11
-#include <private/qt_x11_p.h>
-#endif
class tst_QRegion : public QObject
{
@@ -79,9 +76,6 @@ private slots:
void isEmpty_data();
void isEmpty();
-#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && defined(QT_BUILD_INTERNAL)
- void clipRectangles();
-#endif
void regionFromPath();
void scaleRegions_data();
@@ -910,24 +904,6 @@ void tst_QRegion::isEmpty()
#endif
}
-#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && defined(QT_BUILD_INTERNAL)
-void tst_QRegion::clipRectangles()
-{
- QRegion region(30, 30, 30, 30);
- int num = 0;
- qt_getClipRects(region, num);
- QCOMPARE(num, 1);
-
- region += QRegion(10, 10, 10, 10);
- XRectangle *rects2 = static_cast<XRectangle *>(qt_getClipRects(region, num));
- QCOMPARE(num, 2);
-
- // Here's the important part (Y-sorted):
- QCOMPARE(int(rects2[0].y), 10);
- QCOMPARE(int(rects2[1].y), 30);
-}
-#endif
-
void tst_QRegion::regionFromPath()
{
{
diff --git a/tests/auto/gui/qopengl/BLACKLIST b/tests/auto/gui/qopengl/BLACKLIST
index a036106c57..10e0520bd9 100644
--- a/tests/auto/gui/qopengl/BLACKLIST
+++ b/tests/auto/gui/qopengl/BLACKLIST
@@ -1,10 +1,2 @@
-[fboRendering]
-windows
-[QTBUG15621_triangulatingStrokerDivZero]
-windows
-[imageFormatPainting]
-windows
-[openGLPaintDevice]
-windows
[wglContextWrap]
windows
diff --git a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
index f8dfdbd3b0..b82b277781 100644
--- a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
+++ b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
@@ -200,7 +200,7 @@ static void dumpGlConfiguration(QOpenGLContext &context, QTextStream &str)
<< "\nShading language : " << reinterpret_cast<const char *>(functions.glGetString(GL_SHADING_LANGUAGE_VERSION))
<< "\nFormat : " << context.format();
- QList<QByteArray> extensionList = context.extensions().toList();
+ QList<QByteArray> extensionList = context.extensions().values();
std::sort(extensionList.begin(), extensionList.end());
const int extensionCount = extensionList.size();
str << "\n\nFound " << extensionCount << " extensions:\n";
@@ -233,9 +233,9 @@ void tst_QOpenGlConfig::testGlConfiguration()
static inline QByteArray msgSetMismatch(const QSet<QString> &expected,
const QSet<QString> &actual)
{
- const QString result = QStringList(expected.toList()).join(QLatin1Char(','))
+ const QString result = QStringList(expected.values()).join(QLatin1Char(','))
+ QLatin1String(" != ")
- + QStringList(actual.toList()).join(QLatin1Char(','));
+ + QStringList(actual.values()).join(QLatin1Char(','));
return result.toLatin1();
}
diff --git a/tests/auto/gui/rhi/qrhi/data/texture.frag b/tests/auto/gui/rhi/qrhi/data/texture.frag
new file mode 100644
index 0000000000..e6021fe905
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/texture.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ fragColor = texture(tex, v_texcoord);
+}
diff --git a/tests/auto/gui/rhi/qrhi/data/texture.vert b/tests/auto/gui/rhi/qrhi/data/texture.vert
new file mode 100644
index 0000000000..de486cb772
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/texture.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = texcoord;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/auto/gui/rhi/qrhi/qrhi.pro b/tests/auto/gui/rhi/qrhi/qrhi.pro
new file mode 100644
index 0000000000..58000ed514
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/qrhi.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qrhi
+CONFIG += testcase
+
+QT += testlib gui-private
+
+SOURCES += tst_qrhi.cpp
+
+RESOURCES += qrhi.qrc
diff --git a/tests/auto/gui/rhi/qrhi/qrhi.qrc b/tests/auto/gui/rhi/qrhi/qrhi.qrc
new file mode 100644
index 0000000000..f161d8aad6
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/qrhi.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
new file mode 100644
index 0000000000..897613d525
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QThread>
+#include <QFile>
+#include <QOffscreenSurface>
+#include <QtGui/private/qrhi_p.h>
+#include <QtGui/private/qrhinull_p.h>
+
+#if QT_CONFIG(opengl)
+# include <QtGui/private/qrhigles2_p.h>
+# define TST_GL
+#endif
+
+#if QT_CONFIG(vulkan)
+# include <QVulkanInstance>
+# include <QtGui/private/qrhivulkan_p.h>
+# define TST_VK
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+# define TST_D3D11
+#endif
+
+#ifdef Q_OS_DARWIN
+# include <QtGui/private/qrhimetal_p.h>
+# define TST_MTL
+#endif
+
+Q_DECLARE_METATYPE(QRhi::Implementation)
+Q_DECLARE_METATYPE(QRhiInitParams *)
+
+class tst_QRhi : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void create_data();
+ void create();
+
+private:
+ struct {
+ QRhiNullInitParams null;
+#ifdef TST_GL
+ QRhiGles2InitParams gl;
+#endif
+#ifdef TST_VK
+ QRhiVulkanInitParams vk;
+#endif
+#ifdef TST_D3D11
+ QRhiD3D11InitParams d3d;
+#endif
+#ifdef TST_MTL
+ QRhiMetalInitParams mtl;
+#endif
+ } initParams;
+
+#ifdef TST_VK
+ QVulkanInstance vulkanInstance;
+#endif
+ QOffscreenSurface *fallbackSurface = nullptr;
+};
+
+void tst_QRhi::initTestCase()
+{
+#ifdef TST_GL
+ fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ initParams.gl.fallbackSurface = fallbackSurface;
+#endif
+
+#ifdef TST_VK
+ vulkanInstance.create();
+ initParams.vk.inst = &vulkanInstance;
+#endif
+}
+
+void tst_QRhi::cleanupTestCase()
+{
+#ifdef TST_VK
+ vulkanInstance.destroy();
+#endif
+
+ delete fallbackSurface;
+}
+
+void tst_QRhi::create_data()
+{
+ QTest::addColumn<QRhi::Implementation>("impl");
+ QTest::addColumn<QRhiInitParams *>("initParams");
+
+ QTest::newRow("Null") << QRhi::Null << static_cast<QRhiInitParams *>(&initParams.null);
+#ifdef TST_GL
+ QTest::newRow("OpenGL") << QRhi::OpenGLES2 << static_cast<QRhiInitParams *>(&initParams.gl);
+#endif
+#ifdef TST_VK
+ if (vulkanInstance.isValid())
+ QTest::newRow("Vulkan") << QRhi::Vulkan << static_cast<QRhiInitParams *>(&initParams.vk);
+#endif
+#ifdef TST_D3D11
+ QTest::newRow("Direct3D 11") << QRhi::D3D11 << static_cast<QRhiInitParams *>(&initParams.d3d);
+#endif
+#ifdef TST_MTL
+ QTest::newRow("Metal") << QRhi::Metal << static_cast<QRhiInitParams *>(&initParams.mtl);
+#endif
+}
+
+static int aligned(int v, int a)
+{
+ return (v + a - 1) & ~(a - 1);
+}
+
+void tst_QRhi::create()
+{
+ // Merely attempting to create a QRhi should survive, with an error when
+ // not supported. (of course, there is always a chance we encounter a crash
+ // due to some random graphics stack...)
+
+ QFETCH(QRhi::Implementation, impl);
+ QFETCH(QRhiInitParams *, initParams);
+
+ QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
+
+ if (rhi) {
+ QCOMPARE(rhi->backend(), impl);
+ QCOMPARE(rhi->thread(), QThread::currentThread());
+
+ int cleanupOk = 0;
+ QRhi *rhiPtr = rhi.data();
+ auto cleanupFunc = [rhiPtr, &cleanupOk](QRhi *dyingRhi) {
+ if (rhiPtr == dyingRhi)
+ cleanupOk += 1;
+ };
+ rhi->addCleanupCallback(cleanupFunc);
+ rhi->runCleanup();
+ QCOMPARE(cleanupOk, 1);
+ cleanupOk = 0;
+ rhi->addCleanupCallback(cleanupFunc);
+
+ QRhiResourceUpdateBatch *resUpd = rhi->nextResourceUpdateBatch();
+ QVERIFY(resUpd);
+ resUpd->release();
+
+ QVERIFY(!rhi->supportedSampleCounts().isEmpty());
+ QVERIFY(rhi->supportedSampleCounts().contains(1));
+
+ QVERIFY(rhi->ubufAlignment() > 0);
+ QCOMPARE(rhi->ubufAligned(123), aligned(123, rhi->ubufAlignment()));
+
+ QCOMPARE(rhi->mipLevelsForSize(QSize(512, 300)), 10);
+ QCOMPARE(rhi->sizeForMipLevel(0, QSize(512, 300)), QSize(512, 300));
+ QCOMPARE(rhi->sizeForMipLevel(1, QSize(512, 300)), QSize(256, 150));
+ QCOMPARE(rhi->sizeForMipLevel(2, QSize(512, 300)), QSize(128, 75));
+ QCOMPARE(rhi->sizeForMipLevel(9, QSize(512, 300)), QSize(1, 1));
+
+ const bool fbUp = rhi->isYUpInFramebuffer();
+ const bool ndcUp = rhi->isYUpInNDC();
+ const bool d0to1 = rhi->isClipDepthZeroToOne();
+ const QMatrix4x4 corrMat = rhi->clipSpaceCorrMatrix();
+ if (impl == QRhi::OpenGLES2) {
+ QVERIFY(fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(!d0to1);
+ QVERIFY(corrMat.isIdentity());
+ } else if (impl == QRhi::Vulkan) {
+ QVERIFY(!fbUp);
+ QVERIFY(!ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ } else if (impl == QRhi::D3D11) {
+ QVERIFY(!fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ } else if (impl == QRhi::Metal) {
+ QVERIFY(!fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ }
+
+ const int texMin = rhi->resourceLimit(QRhi::TextureSizeMin);
+ const int texMax = rhi->resourceLimit(QRhi::TextureSizeMax);
+ const int maxAtt = rhi->resourceLimit(QRhi::MaxColorAttachments);
+ QVERIFY(texMin >= 1);
+ QVERIFY(texMax >= texMin);
+ QVERIFY(maxAtt >= 1);
+
+ QVERIFY(rhi->nativeHandles());
+ QVERIFY(rhi->profiler());
+
+ const QRhi::Feature features[] = {
+ QRhi::MultisampleTexture,
+ QRhi::MultisampleRenderBuffer,
+ QRhi::DebugMarkers,
+ QRhi::Timestamps,
+ QRhi::Instancing,
+ QRhi::CustomInstanceStepRate,
+ QRhi::PrimitiveRestart,
+ QRhi::NonDynamicUniformBuffers,
+ QRhi::NonFourAlignedEffectiveIndexBufferOffset,
+ QRhi::NPOTTextureRepeat,
+ QRhi::RedOrAlpha8IsRed,
+ QRhi::ElementIndexUint
+ };
+ for (size_t i = 0; i <sizeof(features) / sizeof(QRhi::Feature); ++i)
+ rhi->isFeatureSupported(features[i]);
+
+ QVERIFY(rhi->isTextureFormatSupported(QRhiTexture::RGBA8));
+
+ rhi.reset();
+ QCOMPARE(cleanupOk, 1);
+ }
+}
+
+#include <tst_qrhi.moc>
+QTEST_MAIN(tst_QRhi)
diff --git a/tests/auto/gui/rhi/qshader/data/color.vert b/tests/auto/gui/rhi/qshader/data/color.vert
new file mode 100644
index 0000000000..c92f71b9e1
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/auto/gui/rhi/qshader/data/color.vert.qsb b/tests/auto/gui/rhi/qshader/data/color.vert.qsb
new file mode 100644
index 0000000000..7d02d823d2
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb b/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb
new file mode 100644
index 0000000000..c82ba7e8e7
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qshader/qshader.pro b/tests/auto/gui/rhi/qshader/qshader.pro
new file mode 100644
index 0000000000..5d9ef8304d
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/qshader.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qshader
+CONFIG += testcase
+
+QT += testlib gui-private
+
+SOURCES += tst_qshader.cpp
+
+RESOURCES += qshader.qrc
diff --git a/tests/auto/gui/rhi/qshader/qshader.qrc b/tests/auto/gui/rhi/qshader/qshader.qrc
new file mode 100644
index 0000000000..f161d8aad6
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/qshader.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
new file mode 100644
index 0000000000..21f0cc7895
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QFile>
+#include <QtGui/private/qshaderdescription_p_p.h>
+#include <QtGui/private/qshader_p_p.h>
+
+class tst_QShader : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void simpleCompileCheckResults();
+ void genVariants();
+ void shaderDescImplicitSharing();
+ void bakedShaderImplicitSharing();
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void tst_QShader::simpleCompileCheckResults()
+{
+ QShader s = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 1);
+
+ const QShaderCode shader = s.shader(QShaderKey(QShader::SpirvShader,
+ QShaderVersion(100)));
+ QVERIFY(!shader.shader().isEmpty());
+ QCOMPARE(shader.entryPoint(), QByteArrayLiteral("main"));
+
+ const QShaderDescription desc = s.description();
+ QVERIFY(desc.isValid());
+ QCOMPARE(desc.inputVariables().count(), 2);
+ for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) {
+ switch (v.location) {
+ case 0:
+ QCOMPARE(v.name, QLatin1String("position"));
+ QCOMPARE(v.type, QShaderDescription::Vec4);
+ break;
+ case 1:
+ QCOMPARE(v.name, QLatin1String("color"));
+ QCOMPARE(v.type, QShaderDescription::Vec3);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+ QCOMPARE(desc.outputVariables().count(), 1);
+ for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) {
+ switch (v.location) {
+ case 0:
+ QCOMPARE(v.name, QLatin1String("v_color"));
+ QCOMPARE(v.type, QShaderDescription::Vec3);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+ QCOMPARE(desc.uniformBlocks().count(), 1);
+ const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first();
+ QCOMPARE(blk.blockName, QLatin1String("buf"));
+ QCOMPARE(blk.structName, QLatin1String("ubuf"));
+ QCOMPARE(blk.size, 68);
+ QCOMPARE(blk.binding, 0);
+ QCOMPARE(blk.descriptorSet, 0);
+ QCOMPARE(blk.members.count(), 2);
+ for (int i = 0; i < blk.members.count(); ++i) {
+ const QShaderDescription::BlockVariable v = blk.members[i];
+ switch (i) {
+ case 0:
+ QCOMPARE(v.offset, 0);
+ QCOMPARE(v.size, 64);
+ QCOMPARE(v.name, QLatin1String("mvp"));
+ QCOMPARE(v.type, QShaderDescription::Mat4);
+ QCOMPARE(v.matrixStride, 16);
+ break;
+ case 1:
+ QCOMPARE(v.offset, 64);
+ QCOMPARE(v.size, 4);
+ QCOMPARE(v.name, QLatin1String("opacity"));
+ QCOMPARE(v.type, QShaderDescription::Float);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+}
+
+void tst_QShader::genVariants()
+{
+ QShader s = getShader(QLatin1String(":/data/color.vert.qsb"));
+ // spirv, glsl 100, glsl 330, glsl 120, hlsl 50, msl 12
+ // + batchable variants
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 2 * 6);
+
+ int batchableVariantCount = 0;
+ int batchableGlslVariantCount = 0;
+ for (const QShaderKey &key : s.availableShaders()) {
+ if (key.sourceVariant() == QShader::BatchableVertexShader) {
+ ++batchableVariantCount;
+ if (key.source() == QShader::GlslShader) {
+ ++batchableGlslVariantCount;
+ const QByteArray src = s.shader(key).shader();
+ QVERIFY(src.contains(QByteArrayLiteral("_qt_order * ")));
+ }
+ }
+ }
+ QCOMPARE(batchableVariantCount, 6);
+ QCOMPARE(batchableGlslVariantCount, 3);
+}
+
+void tst_QShader::shaderDescImplicitSharing()
+{
+ QShader s = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 1);
+ QVERIFY(s.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+
+ QShaderDescription d0 = s.description();
+ QVERIFY(d0.isValid());
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+
+ QShaderDescription d1 = d0;
+ QVERIFY(QShaderDescriptionPrivate::get(&d0) == QShaderDescriptionPrivate::get(&d1));
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+
+ d1.detach();
+ QVERIFY(QShaderDescriptionPrivate::get(&d0) != QShaderDescriptionPrivate::get(&d1));
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+}
+
+void tst_QShader::bakedShaderImplicitSharing()
+{
+ QShader s0 = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s0.isValid());
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+
+ {
+ QShader s1 = s0;
+ QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s0.stage(), s1.stage());
+ QCOMPARE(s0, s1);
+
+ s1.detach();
+ QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s0.stage(), s1.stage());
+ QCOMPARE(s0, s1);
+ }
+
+ {
+ QShader s1 = s0;
+ QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
+ QCOMPARE(s0.stage(), s1.stage());
+
+ s1.setStage(QShader::FragmentStage); // call a setter to trigger a detach
+ QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QShaderDescription d0 = s0.description();
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QShaderDescription d1 = s1.description();
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+ QVERIFY(s0 != s1);
+ }
+}
+
+#include <tst_qshader.moc>
+QTEST_MAIN(tst_QShader)
diff --git a/tests/auto/gui/rhi/rhi.pro b/tests/auto/gui/rhi/rhi.pro
new file mode 100644
index 0000000000..cc548b7b8a
--- /dev/null
+++ b/tests/auto/gui/rhi/rhi.pro
@@ -0,0 +1,4 @@
+TEMPLATE=subdirs
+SUBDIRS= \
+ qshader \
+ qrhi
diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
index 7dbeb13aa7..7764a716ca 100644
--- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
+++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
@@ -78,6 +78,8 @@ private slots:
void extractBorder();
void noTextDecoration();
void quotedAndUnquotedIdentifiers();
+ void whitespaceValues_data();
+ void whitespaceValues();
};
void tst_QCssParser::scanner_data()
@@ -1746,6 +1748,33 @@ void tst_QCssParser::quotedAndUnquotedIdentifiers()
QCOMPARE(decls.at(1).d->values.first().toString(), QLatin1String("bold"));
}
+void tst_QCssParser::whitespaceValues_data()
+{
+ QTest::addColumn<QString>("value");
+
+ QTest::newRow("normal") << "normal";
+ QTest::newRow("inherit") << "inherit";
+ QTest::newRow("nowrap") << "nowrap";
+ QTest::newRow("pre") << "pre";
+ QTest::newRow("pre-wrap") << "pre-wrap";
+ QTest::newRow("pre-line") << "pre-line";
+}
+
+void tst_QCssParser::whitespaceValues()
+{
+ QFETCH(QString, value);
+ QCss::Parser parser(QString("foo { white-space: %1 }").arg(value));
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+ QCOMPARE(rule.declarations.size(), 1);
+
+ QCOMPARE(rule.declarations.at(0).d->property, QLatin1String("white-space"));
+ QCOMPARE(rule.declarations.at(0).d->values.first().toString(), value);
+}
+
QTEST_MAIN(tst_QCssParser)
#include "tst_qcssparser.moc"
diff --git a/tests/auto/gui/text/qfont/BLACKLIST b/tests/auto/gui/text/qfont/BLACKLIST
deleted file mode 100644
index 42cb8408f4..0000000000
--- a/tests/auto/gui/text/qfont/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[defaultFamily]
-b2qt
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
index 9acf877790..96f3b1c1d7 100644
--- a/tests/auto/gui/text/qfont/tst_qfont.cpp
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -58,7 +58,9 @@ private slots:
void insertAndRemoveSubstitutions();
void serialize_data();
void serialize();
+#if QT_DEPRECATED_SINCE(5, 13)
void lastResortFont();
+#endif
void styleName();
void defaultFamily_data();
void defaultFamily();
@@ -484,6 +486,7 @@ void tst_QFont::serialize()
}
}
+#if QT_DEPRECATED_SINCE(5, 13)
// QFont::lastResortFont() may abort with qFatal() on QWS/QPA
// if absolutely no font is found. Just as ducumented for QFont::lastResortFont().
// This happens on our CI machines which run QWS autotests.
@@ -494,6 +497,7 @@ void tst_QFont::lastResortFont()
QFont font;
QVERIFY(!font.lastResortFont().isEmpty());
}
+#endif
void tst_QFont::styleName()
{
@@ -609,37 +613,37 @@ void tst_QFont::sharing()
QFont f;
f.setStyleHint(QFont::Serif);
f.exactMatch(); // loads engine
- QCOMPARE(QFontPrivate::get(f)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f)->ref.loadRelaxed(), 1);
QVERIFY(QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
QFont f2(f);
QCOMPARE(QFontPrivate::get(f2), QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 2);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
f2.setKerning(!f.kerning());
QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 1);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 2 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 2 + refs_by_cache);
f2 = f;
QCOMPARE(QFontPrivate::get(f2), QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 2);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
if (f.pointSize() > 0)
f2.setPointSize(f.pointSize() * 2 / 3);
else
f2.setPixelSize(f.pixelSize() * 2 / 3);
QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 1);
QVERIFY(!QFontPrivate::get(f2)->engineData);
QVERIFY(QFontPrivate::get(f2)->engineData != QFontPrivate::get(f)->engineData);
}
diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
index 785cc3fef2..3d3211c7a2 100644
--- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
+++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
@@ -217,7 +217,7 @@ void tst_QFontCache::clear()
#ifdef QT_BUILD_INTERNAL
QList<QFontEngine *> leakedEngines = QFontEngine_stopCollectingEngines();
-for (int i = 0; i < leakedEngines.size(); ++i) qWarning() << i << leakedEngines.at(i) << leakedEngines.at(i)->ref.load();
+for (int i = 0; i < leakedEngines.size(); ++i) qWarning() << i << leakedEngines.at(i) << leakedEngines.at(i)->ref.loadRelaxed();
// and we are not leaking!
QCOMPARE(leakedEngines.size(), 0);
#endif
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 064e37f73c..2b69801b59 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -211,8 +211,8 @@ void tst_QFontDatabase::widthTwoTimes()
f.setPixelSize(pixelSize);
QFontMetrics fm(f);
- int w1 = fm.charWidth(text, 0);
- int w2 = fm.charWidth(text, 0);
+ int w1 = fm.horizontalAdvance(text, 0);
+ int w2 = fm.horizontalAdvance(text, 0);
QCOMPARE(w1, w2);
}
diff --git a/tests/auto/gui/text/qglyphrun/BLACKLIST b/tests/auto/gui/text/qglyphrun/BLACKLIST
index d8dbdabb4b..57f32c683d 100644
--- a/tests/auto/gui/text/qglyphrun/BLACKLIST
+++ b/tests/auto/gui/text/qglyphrun/BLACKLIST
@@ -1,4 +1,3 @@
[mixedScripts]
ubuntu-18.04
b2qt
-windows
diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
index d00dc251d8..b091edb64d 100644
--- a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
+++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
@@ -681,7 +681,7 @@ static bool checkPixels(const QImage &image,
if (pixel != expectedRgb1 && pixel != expectedRgb2) {
QString message;
QDebug(&message) << "Color mismatch in image" << image
- << "at" << x << ',' << y << ':' << showbase << hex << pixel
+ << "at" << x << ',' << y << ':' << Qt::showbase << Qt::hex << pixel
<< "(expected: " << expectedRgb1 << ',' << expectedRgb2 << ')';
*errorMessage = message.toLocal8Bit();
return false;
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 58810f73c1..52e56feb5a 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -50,6 +50,7 @@
#include <QDomDocument>
#include "common.h"
+// #define DEBUG_WRITE_OUTPUT
QT_FORWARD_DECLARE_CLASS(QTextDocument)
@@ -196,6 +197,7 @@ private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
static QString cssFontSizeString(const QFont &font);
+ void writeActualAndExpected(const char* testTag, const QString &actual, const QString &expected);
QTextDocument *doc;
QTextCursor cursor;
@@ -224,6 +226,27 @@ QString tst_QTextDocument::cssFontSizeString(const QFont &font)
: QString::number(font.pixelSize()) + QStringLiteral("px");
}
+void tst_QTextDocument::writeActualAndExpected(const char *testTag, const QString &actual, const QString &expected)
+{
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out(QDir::temp().absoluteFilePath(QLatin1String(testTag) + QLatin1String("-actual.html")));
+ out.open(QFile::WriteOnly);
+ out.write(actual.toUtf8());
+ out.close();
+ } {
+ QFile out(QDir::temp().absoluteFilePath(QLatin1String(testTag) + QLatin1String("-expected.html")));
+ out.open(QFile::WriteOnly);
+ out.write(expected.toUtf8());
+ out.close();
+ }
+#else
+ Q_UNUSED(testTag)
+ Q_UNUSED(actual)
+ Q_UNUSED(expected)
+#endif
+}
+
// Testing get/set functions
void tst_QTextDocument::getSetCheck()
{
@@ -1765,6 +1788,8 @@ void tst_QTextDocument::toHtml()
QString output = doc->toHtml();
+ writeActualAndExpected(QTest::currentDataTag(), output, expectedOutput);
+
QCOMPARE(output, expectedOutput);
QDomDocument document;
@@ -1962,6 +1987,8 @@ void tst_QTextDocument::toHtmlRootFrameProperties()
expectedOutput.replace("DEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"");
expectedOutput.append(htmlTail);
+ writeActualAndExpected(QTest::currentTestFunction(), doc.toHtml(), expectedOutput);
+
QCOMPARE(doc.toHtml(), expectedOutput);
}
@@ -2734,6 +2761,8 @@ void tst_QTextDocument::backgroundImage_checkExpectedHtml(const QTextDocument &d
.arg(defaultFont.weight() * 8)
.arg((defaultFont.italic() ? "italic" : "normal"));
+ writeActualAndExpected(QTest::currentTestFunction(), doc.toHtml(), expectedHtml);
+
QCOMPARE(doc.toHtml(), expectedHtml);
}
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index fe0b6dae49..b6917f1208 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -34,6 +34,7 @@
#include <qtextdocumentfragment.h>
#include <qtexttable.h>
#include <qtextlist.h>
+#include <qregularexpression.h>
#include <qdebug.h>
#include <private/qtextdocument_p.h>
@@ -180,6 +181,11 @@ private slots:
void html_tableCellBackground();
void css_bodyBackground();
void css_tableCellBackground();
+ void css_tableCellBorder();
+ void css_tableCellBorderShorthand();
+ void css_tableCellAllBordersShorthand();
+ void css_tableCellOverrideOneBorder();
+ void css_tableBorderCollapse();
void css_fontWeight();
void css_float();
void css_textIndent();
@@ -944,7 +950,7 @@ void tst_QTextDocumentFragment::namedAnchorFragments3()
QCOMPARE(it.fragment().text(), QString::fromLatin1("T"));
QVERIFY(it.fragment().charFormat().isAnchor());
- QCOMPARE(it.fragment().charFormat().anchorName(), QString("target"));
+ QCOMPARE(it.fragment().charFormat().anchorNames().constFirst(), QLatin1String("target"));
QStringList targets; targets << "target" << "target2";
QCOMPARE(it.fragment().charFormat().anchorNames(), targets);
@@ -1271,11 +1277,11 @@ void tst_QTextDocumentFragment::html_whitespace_data()
QTest::newRow("2") << QString("<span> </span><span>nowhitespacehereplease</span>")
<< QString::fromLatin1("nowhitespacehereplease");
- QTest::newRow("3") << QString("<span style=\"white-space: pre;\"> white space here </span>")
- << QString::fromLatin1(" white space here ");
+ QTest::newRow("3") << QString("<span style=\"white-space: pre;\"> white space \n\n here </span>")
+ << QString::fromLatin1(" white space \n\n here ");
- QTest::newRow("4") << QString("<span style=\"white-space: pre-wrap;\"> white space here </span>")
- << QString::fromLatin1(" white space here ");
+ QTest::newRow("4") << QString("<span style=\"white-space: pre-wrap;\"> white space \n\n here </span>")
+ << QString::fromLatin1(" white space \n\n here ");
QTest::newRow("5") << QString("<a href=\"One.html\">One</a> <a href=\"Two.html\">Two</a> <b>Three</b>\n"
"<b>Four</b>")
@@ -1290,6 +1296,12 @@ void tst_QTextDocumentFragment::html_whitespace_data()
QTest::newRow("8") << QString("<table><tr><td><i>Blah</i></td></tr></table> <i>Blub</i>")
<< QString("\nBlah\nBlub");
+ QTest::newRow("9") << QString("<span style=\"white-space: nowrap;\"> white space \n\n here </span>")
+ << QString::fromLatin1("white space here ");
+
+ QTest::newRow("10") << QString("<span style=\"white-space: pre-line;\"> white space \n\n here </span>")
+ << QString::fromLatin1("white space\n\nhere ");
+
QTest::newRow("task116492") << QString("<p>a<font=\"Times\"> b </font>c</p>")
<< QString("a b c");
@@ -1746,6 +1758,135 @@ void tst_QTextDocumentFragment::css_tableCellBackground()
QCOMPARE(cell.format().background().style(), Qt::TexturePattern);
}
+void tst_QTextDocumentFragment::css_tableCellBorder()
+{
+ const char html[] = "<body><table><tr><td style=\"border-width:8px;border-color:green;border-style:groove;border-left-style:dashed;border-left-color:red;border-left-width:4px\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(4));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("red")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(8));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Groove);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(8));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Groove);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(8));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Groove);
+}
+
+void tst_QTextDocumentFragment::css_tableCellBorderShorthand()
+{
+ const char html[] = "<body><table><tr><td style=\"border-left:1px solid green;border-right:2px dashed red;border-bottom:3px dotted yellow;border-top:4px dot-dash blue\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(1));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Solid);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(2));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("red")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(3));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("yellow")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Dotted);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(4));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("blue")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_DotDash);
+}
+
+void tst_QTextDocumentFragment::css_tableCellAllBordersShorthand()
+{
+ const char html[] = "<body><table><tr><td style=\"border:2px dashed green\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(2));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(2));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(2));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(2));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+}
+
+void tst_QTextDocumentFragment::css_tableCellOverrideOneBorder()
+{
+ const char html[] = "<body><table><tr><td style=\"border:2px dashed green;border-left:4px solid red\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(4));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("red")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Solid);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(2));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(2));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(2));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+}
+
+void tst_QTextDocumentFragment::css_tableBorderCollapse()
+{
+ const char html[] = "<body><table style=\"border-collapse:collapse\"><tr><td>Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QCOMPARE(table->format().borderCollapse(), true);
+}
+
void tst_QTextDocumentFragment::css_cellPaddings()
{
const char html[] = "<body><table><tr><td style=\"padding-left:1\">Foo</td>"
@@ -1925,7 +2066,7 @@ void tst_QTextDocumentFragment::html_nobr()
QString text = doc->begin().begin().fragment().text();
QString expectedText = input;
- expectedText.replace(QRegExp("\\s+"), QString(QChar::Nbsp));
+ expectedText.replace(QRegularExpression("\\s+"), QString(QChar::Nbsp));
QCOMPARE(text, expectedText);
}
diff --git a/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST b/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST
index b13b2497d3..5c81e74aa0 100644
--- a/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST
+++ b/tests/auto/gui/text/qtextdocumentlayout/BLACKLIST
@@ -1,2 +1,4 @@
[imageAtRightAlignedTab]
-linux
+rhel-6.6
+rhel-7.4
+rhel-7.6
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index f0a32c2ed4..a474acd790 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -138,6 +138,7 @@ private slots:
void noModificationOfInputString();
void superscriptCrash_qtbug53911();
void showLineAndParagraphSeparatorsCrash();
+ void koreanWordWrap();
void tooManyDirectionalCharctersCrash_qtbug77819();
private:
@@ -2228,7 +2229,6 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
for (int j = 0; j < 4; ++j) {
QTextLayout* newTextLayout = new QTextLayout();
newTextLayout->setText(layoutText);
- QList<QTextLayout::FormatRange> formatRanges;
QTextLayout::FormatRange formatRange;
formatRange.format.setFont(QFont());
@@ -2257,8 +2257,7 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
formatRange.start = 0;
formatRange.length = layoutText.size();
- formatRanges << formatRange;
- newTextLayout->setAdditionalFormats(formatRanges);
+ newTextLayout->setFormats({formatRange});
textLayouts.push_front(newTextLayout);
}
@@ -2289,10 +2288,7 @@ void tst_QTextLayout::nbspWithFormat()
formatRange.length = 1;
formatRange.format.setFontUnderline(true);
- QList<QTextLayout::FormatRange> overrides;
- overrides.append(formatRange);
-
- layout.setAdditionalFormats(overrides);
+ layout.setFormats({formatRange});
layout.beginLayout();
forever {
@@ -2310,6 +2306,31 @@ void tst_QTextLayout::nbspWithFormat()
QCOMPARE(layout.lineAt(1).textLength(), s2.length() + 1 + s3.length());
}
+void tst_QTextLayout::koreanWordWrap()
+{
+ QString s = QString::fromUtf8("안녕하세요 여러분!");
+ QTextLayout layout;
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WordWrap);
+ option.setFlags(QTextOption::Flag(QTextOption::IncludeTrailingSpaces));
+ layout.setTextOption(option);
+ layout.setText(s);
+
+ QFontMetrics metrics(layout.font());
+
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ line.setLineWidth(metrics.horizontalAdvance(s) * 0.8);
+ }
+ layout.endLayout();
+ QCOMPARE(layout.lineCount(), 2);
+ QCOMPARE(layout.lineAt(0).textLength(), 6);
+ QCOMPARE(layout.lineAt(1).textLength(), 4);
+}
+
void tst_QTextLayout::tooManyDirectionalCharctersCrash_qtbug77819()
{
QString data;
diff --git a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
index d623ce4044..93e40e7f23 100644
--- a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
+++ b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
@@ -314,7 +314,7 @@ void tst_QTextList::partialRemoval()
selection.deleteChar(); // deletes the second list
QVERIFY(!secondList);
- QVERIFY(!firstList->isEmpty());
+ QVERIFY(firstList->count() > 0);
doc->undo();
}
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md
new file mode 100644
index 0000000000..99eb633d17
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md
@@ -0,0 +1,28 @@
+# heading
+- bullet 1
+ continuation line 1, indented via tab
+- bullet 2
+ continuation line 2, indented via 4 spaces
+- bullet 3
+
+ continuation paragraph 3, indented via tab
+
+ - bullet 3.1
+
+ continuation paragraph 3.1, indented via 4 spaces
+
+ - bullet 3.2
+ continuation line, indented via 2 tabs
+- bullet 4
+
+ continuation paragraph 4, indented via 4 spaces
+ and continuing onto another line too
+
+- bullet 5
+
+ continuation paragraph 5, indented via 2 spaces and continuing onto another
+ line too
+
+- bullet 6
+
+plain old paragraph at the end
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md
new file mode 100644
index 0000000000..7a0d5388ad
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md
@@ -0,0 +1,17 @@
+Heading
+-------
+***
+stars
+- bullet
+ ** not a bullet or a rule, just two stars
+- [ ] unchecked
+
+ --- indented too far, so not a rule
+* * *
+stars with tabs between
+***
+stars with whitespace after
+---
+hyphens with whitespace after
+_____
+underscores with whitespace after
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
new file mode 100644
index 0000000000..7b7fb61244
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qtextmarkdownimporter
+QT += core-private gui-private testlib
+SOURCES += tst_qtextmarkdownimporter.cpp
+TESTDATA += \
+ data/thematicBreaks.md \
+ data/headingBulletsContinuations.md \
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
new file mode 100644
index 0000000000..8f51a7a474
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#include <private/qtextmarkdownimporter_p.h>
+
+// #define DEBUG_WRITE_HTML
+
+Q_LOGGING_CATEGORY(lcTests, "qt.text.tests")
+
+static const QChar LineBreak = QChar(0x2028);
+static const QChar Tab = QLatin1Char('\t');
+static const QChar Space = QLatin1Char(' ');
+static const QChar Period = QLatin1Char('.');
+
+class tst_QTextMarkdownImporter : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void headingBulletsContinuations();
+ void thematicBreaks();
+};
+
+void tst_QTextMarkdownImporter::headingBulletsContinuations()
+{
+ const QStringList expectedBlocks = QStringList() <<
+ "" << // we could do without this blank line before the heading, but currently it happens
+ "heading" <<
+ "bullet 1 continuation line 1, indented via tab" <<
+ "bullet 2 continuation line 2, indented via 4 spaces" <<
+ "bullet 3" <<
+ "continuation paragraph 3, indented via tab" <<
+ "bullet 3.1" <<
+ "continuation paragraph 3.1, indented via 4 spaces" <<
+ "bullet 3.2 continuation line, indented via 2 tabs" <<
+ "bullet 4" <<
+ "continuation paragraph 4, indented via 4 spaces and continuing onto another line too" <<
+ "bullet 5" <<
+ // indenting by only 2 spaces is perhaps non-standard but currently is OK
+ "continuation paragraph 5, indented via 2 spaces and continuing onto another line too" <<
+ "bullet 6" <<
+ "plain old paragraph at the end";
+
+ QFile f(QFINDTESTDATA("data/headingBulletsContinuations.md"));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString md = QString::fromUtf8(f.readAll());
+ f.close();
+
+ QTextDocument doc;
+ QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md);
+ QTextFrame::iterator iterator = doc.rootFrame()->begin();
+ QTextFrame *currentFrame = iterator.currentFrame();
+ QStringList::const_iterator expectedIt = expectedBlocks.constBegin();
+ int i = 0;
+ while (!iterator.atEnd()) {
+ // There are no child frames
+ QCOMPARE(iterator.currentFrame(), currentFrame);
+ // Check whether we got the right child block
+ QTextBlock block = iterator.currentBlock();
+ QCOMPARE(block.text().contains(LineBreak), false);
+ QCOMPARE(block.text().contains(Tab), false);
+ QVERIFY(!block.text().startsWith(Space));
+ int expectedIndentation = 0;
+ if (block.text().contains(QLatin1String("continuation paragraph")))
+ expectedIndentation = (block.text().contains(Period) ? 2 : 1);
+ qCDebug(lcTests) << i << "child block" << block.text() << "indentation" << block.blockFormat().indent();
+ QVERIFY(expectedIt != expectedBlocks.constEnd());
+ QCOMPARE(block.text(), *expectedIt);
+ if (i > 2)
+ QCOMPARE(block.blockFormat().indent(), expectedIndentation);
+ ++iterator;
+ ++expectedIt;
+ ++i;
+ }
+ QCOMPARE(expectedIt, expectedBlocks.constEnd());
+
+#ifdef DEBUG_WRITE_HTML
+ {
+ QFile out("/tmp/headingBulletsContinuations.html");
+ out.open(QFile::WriteOnly);
+ out.write(doc.toHtml().toLatin1());
+ out.close();
+ }
+#endif
+}
+
+void tst_QTextMarkdownImporter::thematicBreaks()
+{
+ int horizontalRuleCount = 0;
+ int textLinesCount = 0;
+
+ QFile f(QFINDTESTDATA("data/thematicBreaks.md"));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString md = QString::fromUtf8(f.readAll());
+ f.close();
+
+ QTextDocument doc;
+ QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md);
+ QTextFrame::iterator iterator = doc.rootFrame()->begin();
+ QTextFrame *currentFrame = iterator.currentFrame();
+ int i = 0;
+ while (!iterator.atEnd()) {
+ // There are no child frames
+ QCOMPARE(iterator.currentFrame(), currentFrame);
+ // Check whether the block is text or a horizontal rule
+ QTextBlock block = iterator.currentBlock();
+ if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth))
+ ++horizontalRuleCount;
+ else if (!block.text().isEmpty())
+ ++textLinesCount;
+ qCDebug(lcTests) << i << (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) ? QLatin1String("- - -") : block.text());
+ ++iterator;
+ ++i;
+ }
+ QCOMPARE(horizontalRuleCount, 5);
+ QCOMPARE(textLinesCount, 9);
+
+#ifdef DEBUG_WRITE_HTML
+ {
+ QFile out("/tmp/thematicBreaks.html");
+ out.open(QFile::WriteOnly);
+ out.write(doc.toHtml().toLatin1());
+ out.close();
+ }
+#endif
+}
+
+QTEST_MAIN(tst_QTextMarkdownImporter)
+#include "tst_qtextmarkdownimporter.moc"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST
new file mode 100644
index 0000000000..0ce46130ce
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST
@@ -0,0 +1,2 @@
+[rewriteDocument]
+winrt
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
new file mode 100644
index 0000000000..6336d0219f
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
@@ -0,0 +1,62 @@
+In 1958, Mahatma Gandhi was quoted as follows:
+
+> The Earth provides enough to satisfy every man's need but not for every man's
+> greed.
+
+In [The CommonMark Specification](https://spec.commonmark.org/0.29/) John
+MacFarlane writes:
+
+> What distinguishes Markdown from many other lightweight markup syntaxes,
+> which are often easier to write, is its readability. As Gruber writes:
+
+> > The overriding design goal for Markdown's formatting syntax is to make it
+> > as readable as possible. The idea is that a Markdown-formatted document should
+> > be publishable as-is, as plain text, without looking like it's been marked up
+> > with tags or formatting instructions. (
+> > [http://daringfireball.net/projects/markdown/](http://daringfireball.net/projects/markdown/)
+> > )
+
+> The point can be illustrated by comparing a sample of AsciiDoc with an
+> equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc
+> manual:
+
+> ``` AsciiDoc
+> 1. List item one.
+> +
+> List item one continued with a second paragraph followed by an
+> Indented block.
+> +
+> .................
+> $ ls *.sh
+> $ mv *.sh ~/tmp
+> .................
+> +
+> List item continued with a third paragraph.
+>
+> 2. List item two continued with an open block.
+> ...
+> ```
+The quotation includes an embedded quotation and a code quotation and ends with
+an ellipsis due to being incomplete.
+
+Now let's have an indented code block:
+
+ #include <stdio.h>
+
+ int main(void)
+ {
+ printf("# hello markdown\n");
+ return 0;
+ }
+
+and end with a fenced code block:
+~~~ pseudocode
+#include <something.h>
+#include <else.h>
+
+a block {
+ a statement;
+ another statement;
+}
+~~~
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
new file mode 100644
index 0000000000..0c3f34e09d
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
@@ -0,0 +1,95 @@
+# QTextEdit
+
+The QTextEdit widget is an advanced editor that supports formatted rich text.
+It can be used to display HTML and other rich document formats. Internally,
+QTextEdit uses the QTextDocument class to describe both the high-level
+structure of each document and the low-level formatting of paragraphs.
+
+If you are viewing this document in the textedit example, you can edit this
+document to explore Qt's rich text editing features. We have included some
+comments in each of the following sections to encourage you to experiment.
+
+## Font and Paragraph Styles
+
+QTextEdit supports **bold**, *italic*, and ~~strikethrough~~ font styles, and can
+display multicolored text. Font families such as Times New Roman and `Courier`
+can also be used directly. *If you place the cursor in a region of styled text,
+the controls in the tool bars will change to reflect the current style.*
+
+Paragraphs can be formatted so that the text is left-aligned, right-aligned,
+centered, or fully justified.
+
+*Try changing the alignment of some text and resize the editor to see how the
+text layout changes.*
+
+## Lists
+
+Different kinds of lists can be included in rich text documents. Standard
+bullet lists can be nested, using different symbols for each level of the list:
+
+- Disc symbols are typically used for top-level list items.
+ * Circle symbols can be used to distinguish between items in lower-level
+ lists.
+ + Square symbols provide a reasonable alternative to discs and circles.
+
+Ordered lists can be created that can be used for tables of contents. Different
+characters can be used to enumerate items, and we can use both Roman and Arabic
+numerals in the same list structure:
+
+1. Introduction
+2. Qt Tools
+ 1) Qt Assistant
+ 2) Qt Designer
+ 1. Form Editor
+ 2. Component Architecture
+ 3) Qt Linguist
+
+The list will automatically be renumbered if you add or remove items. *Try
+adding new sections to the above list or removing existing item to see the
+numbers change.*
+
+## Images
+
+Inline images are treated like ordinary ranges of characters in the text
+editor, so they flow with the surrounding text. Images can also be selected in
+the same way as text, making it easy to cut, copy, and paste them.
+
+![image](images/logo32.png) *Try to select this image by clicking and dragging
+over it with the mouse, or use the text cursor to select it by holding down
+Shift and using the arrow keys. You can then cut or copy it, and paste it into
+different parts of this document.*
+
+## Tables
+
+QTextEdit can arrange and format tables, supporting features such as row and
+column spans, text formatting within cells, and size constraints for columns.
+
+
+| |Development Tools |Programming Techniques |Graphical User Interfaces|
+|-------------|------------------------------------|---------------------------|-------------------------|
+|9:00 - 11:00 |Introduction to Qt |||
+|11:00 - 13:00|Using qmake |Object-oriented Programming|Layouts in Qt |
+|13:00 - 15:00|Qt Designer Tutorial |Extreme Programming |Writing Custom Styles |
+|15:00 - 17:00|Qt Linguist and Internationalization|  |  |
+
+*Try adding text to the cells in the table and experiment with the alignment of
+the paragraphs.*
+
+## Hyperlinks
+
+QTextEdit is designed to support hyperlinks between documents, and this feature
+is used extensively in
+[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are
+automatically created when an HTML file is imported into an editor. Since the
+rich text framework supports hyperlinks natively, they can also be created
+programatically.
+
+## Undo and Redo
+
+Full support for undo and redo operations is built into QTextEdit and the
+underlying rich text framework. Operations on a document can be packaged
+together to make editing a more comfortable experience for the user.
+
+*Try making changes to this document and press `Ctrl+Z` to undo them. You can
+always recover the original contents of the document.*
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md b/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md
new file mode 100644
index 0000000000..d5d14fb168
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md
@@ -0,0 +1,12 @@
+# heading 1
+
+- list item 1
+- list item 2
+
+## heading 2
+
+1) list item 1
+2) list item 2
+
+the end paragraph
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md b/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
new file mode 100644
index 0000000000..dacb0acf77
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
@@ -0,0 +1,13 @@
+[The CommonMark Specification](https://spec.commonmark.org/0.29/) is the
+conservative formal specification of the Markdown format, while
+[GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)
+adds extra features such as task lists and tables.
+
+Qt owes thanks to the authors of the [MD4C parser](https://github.com/mity/md4c)
+for making markdown import possible. The QTextMarkdownWriter class does not
+have such dependencies, and also has not yet been tested as extensively, so we
+do not yet guarantee that we are able to rewrite every Markdown document that
+you are able to read and display with Text or QTextEdit. But you are free to
+write [bugs](https://bugreports.qt.io) about any troublesome cases that you
+encounter.
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
new file mode 100644
index 0000000000..6144710b99
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qtextmarkdownwriter
+QT += core-private gui-private testlib
+SOURCES += tst_qtextmarkdownwriter.cpp
+TESTDATA += \
+ data/example.md \
+ data/blockquotes.md \
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
new file mode 100644
index 0000000000..8d38cbb18a
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#include <private/qtextmarkdownwriter_p.h>
+
+// #define DEBUG_WRITE_OUTPUT
+
+class tst_QTextMarkdownWriter : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void testWriteParagraph_data();
+ void testWriteParagraph();
+ void testWriteList();
+ void testWriteNestedBulletLists_data();
+ void testWriteNestedBulletLists();
+ void testWriteNestedNumericLists();
+ void testWriteTable();
+ void rewriteDocument_data();
+ void rewriteDocument();
+ void fromHtml_data();
+ void fromHtml();
+
+private:
+ QString documentToUnixMarkdown();
+
+private:
+ QTextDocument *document;
+};
+
+void tst_QTextMarkdownWriter::init()
+{
+ document = new QTextDocument();
+}
+
+void tst_QTextMarkdownWriter::cleanup()
+{
+ delete document;
+}
+
+void tst_QTextMarkdownWriter::testWriteParagraph_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("output");
+
+ QTest::newRow("empty") << "" <<
+ "";
+ QTest::newRow("spaces") << "foobar word" <<
+ "foobar word\n\n";
+ QTest::newRow("starting spaces") << " starting spaces" <<
+ " starting spaces\n\n";
+ QTest::newRow("trailing spaces") << "trailing spaces " <<
+ "trailing spaces \n\n";
+ QTest::newRow("tab") << "word\ttab x" <<
+ "word\ttab x\n\n";
+ QTest::newRow("tab2") << "word\t\ttab\tx" <<
+ "word\t\ttab\tx\n\n";
+ QTest::newRow("misc") << "foobar word\ttab x" <<
+ "foobar word\ttab x\n\n";
+ QTest::newRow("misc2") << "\t \tFoo" <<
+ "\t \tFoo\n\n";
+}
+
+void tst_QTextMarkdownWriter::testWriteParagraph()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, output);
+
+ QTextCursor cursor(document);
+ cursor.insertText(input);
+
+ QCOMPARE(documentToUnixMarkdown(), output);
+}
+
+void tst_QTextMarkdownWriter::testWriteList()
+{
+ QTextCursor cursor(document);
+ QTextList *list = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list->add(cursor.block());
+ cursor.insertBlock();
+ cursor.insertText("ListItem 2");
+ list->add(cursor.block());
+
+ QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1(
+ "- ListItem 1\n- ListItem 2\n"));
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedBulletLists_data()
+{
+ QTest::addColumn<bool>("checkbox");
+ QTest::addColumn<bool>("checked");
+ QTest::addColumn<bool>("continuationLine");
+ QTest::addColumn<bool>("continuationParagraph");
+ QTest::addColumn<QString>("expectedOutput");
+
+ QTest::newRow("plain bullets") << false << false << false << false <<
+ "- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n";
+ QTest::newRow("bullets with continuation lines") << false << false << true << false <<
+ "- ListItem 1\n * ListItem 2\n + ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- ListItem 4\n * ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
+ QTest::newRow("bullets with continuation paragraphs") << false << false << false << true <<
+ "- ListItem 1\n\n * ListItem 2\n + ListItem 3\n\n continuation\n\n- ListItem 4\n\n * ListItem 5\n\n continuation\n\n";
+ QTest::newRow("unchecked") << true << false << false << false <<
+ "- [ ] ListItem 1\n * [ ] ListItem 2\n + [ ] ListItem 3\n- [ ] ListItem 4\n * [ ] ListItem 5\n";
+ QTest::newRow("checked") << true << true << false << false <<
+ "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3\n- [x] ListItem 4\n * [x] ListItem 5\n";
+ QTest::newRow("checked with continuation lines") << true << true << true << false <<
+ "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- [x] ListItem 4\n * [x] ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
+ QTest::newRow("checked with continuation paragraphs") << true << true << false << true <<
+ "- [x] ListItem 1\n\n * [x] ListItem 2\n + [x] ListItem 3\n\n continuation\n\n- [x] ListItem 4\n\n * [x] ListItem 5\n\n continuation\n\n";
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedBulletLists()
+{
+ QFETCH(bool, checkbox);
+ QFETCH(bool, checked);
+ QFETCH(bool, continuationParagraph);
+ QFETCH(bool, continuationLine);
+ QFETCH(QString, expectedOutput);
+
+ QTextCursor cursor(document);
+ QTextBlockFormat blockFmt = cursor.blockFormat();
+ if (checkbox) {
+ blockFmt.setMarker(checked ? QTextBlockFormat::Checked : QTextBlockFormat::Unchecked);
+ cursor.setBlockFormat(blockFmt);
+ }
+
+ QTextList *list1 = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list1->add(cursor.block());
+
+ QTextListFormat fmt2;
+ fmt2.setStyle(QTextListFormat::ListCircle);
+ fmt2.setIndent(2);
+ QTextList *list2 = cursor.insertList(fmt2);
+ cursor.insertText("ListItem 2");
+
+ QTextListFormat fmt3;
+ fmt3.setStyle(QTextListFormat::ListSquare);
+ fmt3.setIndent(3);
+ cursor.insertList(fmt3);
+ cursor.insertText(continuationLine ?
+ "ListItem 3 with text that won't fit on one line and thus needs a continuation" :
+ "ListItem 3");
+ if (continuationParagraph) {
+ QTextBlockFormat blockFmt;
+ blockFmt.setIndent(2);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("continuation");
+ }
+
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("ListItem 4");
+ list1->add(cursor.block());
+
+ cursor.insertBlock();
+ cursor.insertText(continuationLine ?
+ "ListItem 5 with text that won't fit on one line and thus needs a continuation" :
+ "ListItem 5");
+ list2->add(cursor.block());
+ if (continuationParagraph) {
+ QTextBlockFormat blockFmt;
+ blockFmt.setIndent(2);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("continuation");
+ }
+
+ QString output = documentToUnixMarkdown();
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
+ out.open(QFile::WriteOnly);
+ out.write(output.toUtf8());
+ out.close();
+ }
+#endif
+ QCOMPARE(documentToUnixMarkdown(), expectedOutput);
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
+{
+ QTextCursor cursor(document);
+
+ QTextList *list1 = cursor.createList(QTextListFormat::ListDecimal);
+ cursor.insertText("ListItem 1");
+ list1->add(cursor.block());
+
+ QTextListFormat fmt2;
+ fmt2.setStyle(QTextListFormat::ListLowerAlpha);
+ fmt2.setNumberSuffix(QLatin1String(")"));
+ fmt2.setIndent(2);
+ QTextList *list2 = cursor.insertList(fmt2);
+ cursor.insertText("ListItem 2");
+
+ QTextListFormat fmt3;
+ fmt3.setStyle(QTextListFormat::ListDecimal);
+ fmt3.setIndent(3);
+ cursor.insertList(fmt3);
+ cursor.insertText("ListItem 3");
+
+ cursor.insertBlock();
+ cursor.insertText("ListItem 4");
+ list1->add(cursor.block());
+
+ cursor.insertBlock();
+ cursor.insertText("ListItem 5");
+ list2->add(cursor.block());
+
+ // There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384)
+ QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1(
+ "1. ListItem 1\n 1) ListItem 2\n 1. ListItem 3\n2. ListItem 4\n 2) ListItem 5\n"));
+}
+
+void tst_QTextMarkdownWriter::testWriteTable()
+{
+ QTextCursor cursor(document);
+ QTextTable * table = cursor.insertTable(4, 3);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ // valid Markdown tables need headers, but QTextTable doesn't make that distinction
+ // so QTextMarkdownWriter assumes the first row of any table is a header
+ cursor.insertText("one");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("two");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("three");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("alice");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("bob");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("carl");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("dennis");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("eric");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("fiona");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("gina");
+ /*
+ |one |two |three|
+ |------|----|-----|
+ |alice |bob |carl |
+ |dennis|eric|fiona|
+ |gina | | |
+ */
+
+ QString md = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QString expected = QString::fromLatin1(
+ "\n|one |two |three|\n|------|----|-----|\n|alice |bob |carl |\n|dennis|eric|fiona|\n|gina | | |\n\n");
+ QCOMPARE(md, expected);
+
+ // create table with merged cells
+ document->clear();
+ cursor = QTextCursor(document);
+ table = cursor.insertTable(3, 3);
+ table->mergeCells(0, 0, 1, 2);
+ table->mergeCells(1, 1, 1, 2);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ cursor.insertText("a");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("b");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("c");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("d");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("e");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("f");
+ /*
+ +---+-+
+ |a |b|
+ +---+-+
+ |c| d|
+ +-+-+-+
+ |e|f| |
+ +-+-+-+
+
+ generates
+
+ |a ||b|
+ |-|-|-|
+ |c|d ||
+ |e|f| |
+
+ */
+
+ md = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table-merged-cells.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(md, QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n"));
+}
+
+void tst_QTextMarkdownWriter::rewriteDocument_data()
+{
+ QTest::addColumn<QString>("inputFile");
+
+ QTest::newRow("block quotes") << "blockquotes.md";
+ QTest::newRow("example") << "example.md";
+ QTest::newRow("list items after headings") << "headingsAndLists.md";
+ QTest::newRow("word wrap") << "wordWrap.md";
+}
+
+void tst_QTextMarkdownWriter::rewriteDocument()
+{
+ QFETCH(QString, inputFile);
+ QTextDocument doc;
+ QFile f(QFINDTESTDATA("data/" + inputFile));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString orig = QString::fromUtf8(f.readAll());
+ f.close();
+ doc.setMarkdown(orig);
+ QString md = doc.toMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ QFile out("/tmp/rewrite-" + inputFile);
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+#endif
+
+ QCOMPARE(md, orig);
+}
+
+void tst_QTextMarkdownWriter::fromHtml_data()
+{
+ QTest::addColumn<QString>("expectedInput");
+ QTest::addColumn<QString>("expectedOutput");
+
+ QTest::newRow("long URL") <<
+ "<span style=\"font-style:italic;\">https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/</span>" <<
+ "*https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/*\n\n";
+ QTest::newRow("non-emphasis inline asterisk") << "3 * 4" << "3 * 4\n\n";
+ QTest::newRow("arithmetic") << "(2 * a * x + b)^2 = b^2 - 4 * a * c" << "(2 * a * x + b)^2 = b^2 - 4 * a * c\n\n";
+ QTest::newRow("escaped asterisk after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a star. * This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a star.\n\\* This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("escaped plus after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a plus. + This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a plus.\n\\+ This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("escaped hyphen after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a minus. - This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a minus.\n\\- This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("list items with indented continuations") <<
+ "<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul>" <<
+ "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n";
+ QTest::newRow("nested list items with continuations") <<
+ "<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li><ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul></ul>" <<
+ "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n\n - bullet\n\n continuation paragraph\n\n - another bullet\n continuation line\n";
+ QTest::newRow("nested ordered list items with continuations") <<
+ "<ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li><ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li></ol><li>another</li><li>another</li></ol>" <<
+ "1. item\n\n continuation paragraph\n\n2. another item\n continuation line\n\n 1. item\n\n continuation paragraph\n\n 2. another item\n continuation line\n\n3. another\n4. another\n";
+ QTest::newRow("thematic break") <<
+ "something<hr/>something else" <<
+ "something\n\n- - -\nsomething else\n\n";
+ QTest::newRow("block quote") <<
+ "<p>In 1958, Mahatma Gandhi was quoted as follows:</p><blockquote>The Earth provides enough to satisfy every man's need but not for every man's greed.</blockquote>" <<
+ "In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n";
+ QTest::newRow("image") <<
+ "<img src=\"/url\" alt=\"foo\" title=\"title\"/>" <<
+ "![foo](/url \"title\")\n\n";
+ QTest::newRow("code") <<
+ "<pre class=\"language-pseudocode\">\n#include \"foo.h\"\n\nblock {\n statement();\n}\n\n</pre>" <<
+ "``` pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n```\n\n";
+ // TODO
+// QTest::newRow("escaped number and paren after double newline") <<
+// "<p>(The first sentence of this paragraph is a line, the next paragraph has a number</p>13) but that's not part of an ordered list" <<
+// "(The first sentence of this paragraph is a line, the next paragraph has a number\n\n13\\) but that's not part of an ordered list\n\n";
+// QTest::newRow("preformats with embedded backticks") <<
+// "<pre>none `one` ``two``</pre><pre>```three``` ````four````</pre>plain" <<
+// "``` none `one` ``two`` ```\n\n````` ```three``` ````four```` `````\n\nplain\n\n";
+}
+
+void tst_QTextMarkdownWriter::fromHtml()
+{
+ QFETCH(QString, expectedInput);
+ QFETCH(QString, expectedOutput);
+
+ document->setHtml(expectedInput);
+ QString output = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
+ out.open(QFile::WriteOnly);
+ out.write(output.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(output, expectedOutput);
+}
+
+QString tst_QTextMarkdownWriter::documentToUnixMarkdown()
+{
+ QString ret;
+ QTextStream ts(&ret, QIODevice::WriteOnly);
+ QTextMarkdownWriter writer(ts, QTextDocument::MarkdownDialectGitHub);
+ writer.writeAll(document);
+ return ret;
+}
+
+QTEST_MAIN(tst_QTextMarkdownWriter)
+#include "tst_qtextmarkdownwriter.moc"
diff --git a/tests/auto/gui/text/qtexttable/qtexttable.pro b/tests/auto/gui/text/qtexttable/qtexttable.pro
index 2faadfcb0d..73e94d5735 100644
--- a/tests/auto/gui/text/qtexttable/qtexttable.pro
+++ b/tests/auto/gui/text/qtexttable/qtexttable.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qtexttable
-QT += testlib
+QT += testlib gui-private
qtHaveModule(widgets): QT += widgets
SOURCES += tst_qtexttable.cpp
diff --git a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
index 22f00c677d..7b2ff4cc10 100644
--- a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
+++ b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
@@ -44,11 +44,14 @@
#include <QPainter>
#include <QPaintEngine>
#endif
+#include <private/qpagedpaintdevice_p.h>
typedef QList<int> IntList;
QT_FORWARD_DECLARE_CLASS(QTextDocument)
+Q_DECLARE_METATYPE(QTextFrameFormat::BorderStyle);
+
class tst_QTextTable : public QObject
{
Q_OBJECT
@@ -91,9 +94,11 @@ private slots:
void QTBUG11282_insertBeforeMergedEnding();
#endif
void QTBUG22011_insertBeforeRowSpan();
-#ifndef QT_NO_PRINTER
+#if !defined(QT_NO_PRINTER) && defined(QT_BUILD_INTERNAL)
void QTBUG31330_renderBackground();
#endif
+ void checkBorderAttributes_data();
+ void checkBorderAttributes();
private:
QTextTable *create2x2Table();
@@ -1025,7 +1030,7 @@ void tst_QTextTable::QTBUG22011_insertBeforeRowSpan()
QCOMPARE(table->columns(), 6);
}
-#ifndef QT_NO_PRINTER
+#if !defined(QT_NO_PRINTER) && defined(QT_BUILD_INTERNAL)
namespace {
class QTBUG31330_PaintDevice : public QPagedPaintDevice
{
@@ -1065,11 +1070,46 @@ public:
{}
};
+ class QDummyPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
+ {
+ bool setPageLayout(const QPageLayout &newPageLayout) override
+ {
+ m_pageLayout = newPageLayout;
+ return m_pageLayout.isEquivalentTo(newPageLayout);
+ }
+
+ bool setPageSize(const QPageSize &pageSize) override
+ {
+ m_pageLayout.setPageSize(pageSize);
+ return m_pageLayout.pageSize().isEquivalentTo(pageSize);
+ }
+
+ bool setPageOrientation(QPageLayout::Orientation orientation) override
+ {
+ m_pageLayout.setOrientation(orientation);
+ return m_pageLayout.orientation() == orientation;
+ }
+
+ bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) override
+ {
+ m_pageLayout.setUnits(units);
+ m_pageLayout.setMargins(margins);
+ return m_pageLayout.margins() == margins && m_pageLayout.units() == units;
+ }
+
+ QPageLayout pageLayout() const override
+ {
+ return m_pageLayout;
+ }
+
+ QPageLayout m_pageLayout;
+ };
+
int pages;
QPaintEngine* engine;
QTBUG31330_PaintDevice(QPaintEngine* engine)
- : pages(1), engine(engine)
+ : QPagedPaintDevice(new QDummyPagedPaintDevicePrivate), pages(1), engine(engine)
{
QPageLayout layout = pageLayout();
layout.setUnits(QPageLayout::Point);
@@ -1134,5 +1174,109 @@ void tst_QTextTable::QTBUG31330_renderBackground()
}
#endif
+void tst_QTextTable::checkBorderAttributes_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<qreal>("topBorderWidth");
+ QTest::addColumn<qreal>("bottomBorderWidth");
+ QTest::addColumn<qreal>("leftBorderWidth");
+ QTest::addColumn<qreal>("rightBorderWidth");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("topBorderStyle");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("bottomBorderStyle");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("leftBorderStyle");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("rightBorderStyle");
+ QTest::addColumn<QBrush>("topBorderBrush");
+ QTest::addColumn<QBrush>("bottomBorderBrush");
+ QTest::addColumn<QBrush>("leftBorderBrush");
+ QTest::addColumn<QBrush>("rightBorderBrush");
+
+ const QString tableHtmlStart = QStringLiteral("<html><head><style>");
+ const QString tableHtmlEnd = QStringLiteral("</style></head><body>"
+ "<table border=\"1\"><tr><td>One</td><td>Two</td></tr>"
+ "<tr><td>Three</td><td>Four</td></tr></table></body></html>");
+ QTest::newRow("1px-solid-colors")
+ << QString("%1"
+ "td {"
+ "border-top: 1px solid red;"
+ "border-bottom: 1px solid blue;"
+ "border-left: 1px solid green;"
+ "border-right: 1px solid yellow;"
+ "}"
+ "%2").arg(tableHtmlStart).arg(tableHtmlEnd)
+ << 1.0 << 1.0 << 1.0 << 1.0
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QBrush(Qt::red) << QBrush(Qt::blue) << QBrush(Qt::darkGreen) << QBrush(Qt::yellow);
+ QTest::newRow("MixedWidth-solid-colors")
+ << QString("%1"
+ "td {"
+ "border-top: 1px solid red;"
+ "border-bottom: 2px solid blue;"
+ "border-left: 3px solid green;"
+ "border-right: 4px solid yellow;"
+ "}"
+ "%2").arg(tableHtmlStart).arg(tableHtmlEnd)
+ << 1.0 << 2.0 << 3.0 << 4.0
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QBrush(Qt::red) << QBrush(Qt::blue) << QBrush(Qt::darkGreen) << QBrush(Qt::yellow);
+ QTest::newRow("MixedWidth-MixedStyle-colors")
+ << QString("%1"
+ "td {"
+ "border-top: 1px solid red;"
+ "border-bottom: 2px dotted blue;"
+ "border-left: 3px dashed green;"
+ "border-right: 4px inset yellow;"
+ "}"
+ "%2").arg(tableHtmlStart).arg(tableHtmlEnd)
+ << 1.0 << 2.0 << 3.0 << 4.0
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Dotted
+ << QTextFrameFormat::BorderStyle_Dashed << QTextFrameFormat::BorderStyle_Inset
+ << QBrush(Qt::red) << QBrush(Qt::blue) << QBrush(Qt::darkGreen) << QBrush(Qt::yellow);
+}
+
+void tst_QTextTable::checkBorderAttributes()
+{
+ QFETCH(QString, html);
+ QFETCH(qreal, topBorderWidth);
+ QFETCH(qreal, bottomBorderWidth);
+ QFETCH(qreal, leftBorderWidth);
+ QFETCH(qreal, rightBorderWidth);
+ QFETCH(QTextFrameFormat::BorderStyle, topBorderStyle);
+ QFETCH(QTextFrameFormat::BorderStyle, bottomBorderStyle);
+ QFETCH(QTextFrameFormat::BorderStyle, leftBorderStyle);
+ QFETCH(QTextFrameFormat::BorderStyle, rightBorderStyle);
+ QFETCH(QBrush, topBorderBrush);
+ QFETCH(QBrush, bottomBorderBrush);
+ QFETCH(QBrush, leftBorderBrush);
+ QFETCH(QBrush, rightBorderBrush);
+
+ QTextDocument doc;
+ doc.setHtml(html);
+ QTextCursor cursor(doc.firstBlock());
+ cursor.movePosition(QTextCursor::Right);
+
+ QTextTable *currentTable = cursor.currentTable();
+ QVERIFY(currentTable);
+ for (int row = 0; row < 2; row++) {
+ for (int column = 0; column < 2; column++) {
+ QTextTableCell cell = currentTable->cellAt(row, column);
+ QTextCharFormat cellFormat = cell.format();
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellTopBorder), topBorderWidth);
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellBottomBorder), bottomBorderWidth);
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellLeftBorder), leftBorderWidth);
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellRightBorder), rightBorderWidth);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellTopBorderStyle), topBorderStyle);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellBottomBorderStyle), bottomBorderStyle);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellLeftBorderStyle), leftBorderStyle);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellRightBorderStyle), rightBorderStyle);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellTopBorderBrush), topBorderBrush);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellBottomBorderBrush), bottomBorderBrush);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellLeftBorderBrush), leftBorderBrush);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellRightBorderBrush), rightBorderBrush);
+ }
+ }
+}
+
QTEST_MAIN(tst_QTextTable)
#include "tst_qtexttable.moc"
diff --git a/tests/auto/gui/text/text.pro b/tests/auto/gui/text/text.pro
index 6b033fb506..794d9ea8d3 100644
--- a/tests/auto/gui/text/text.pro
+++ b/tests/auto/gui/text/text.pro
@@ -28,12 +28,16 @@ SUBDIRS=\
win32:SUBDIRS -= qtextpiecetable
+qtConfig(textmarkdownreader): SUBDIRS += qtextmarkdownimporter
+qtConfig(textmarkdownwriter): SUBDIRS += qtextmarkdownwriter
+
!qtConfig(private_tests): SUBDIRS -= \
qfontcache \
qcssparser \
qtextlayout \
qtextpiecetable \
qzip \
+ qtextmarkdownwriter \
qtextodfwriter
!qtHaveModule(xml): SUBDIRS -= \
diff --git a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
index add23d46cf..4d95345de9 100644
--- a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
+++ b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
@@ -39,7 +39,9 @@ class tst_qdesktopservices : public QObject
private slots:
void openUrl();
void handlers();
+#if QT_DEPRECATED_SINCE(5, 0)
void testDataLocation();
+#endif
};
void tst_qdesktopservices::openUrl()
@@ -89,6 +91,7 @@ void tst_qdesktopservices::handlers()
#define Q_XDG_PLATFORM
#endif
+#if QT_DEPRECATED_SINCE(5, 0)
void tst_qdesktopservices::testDataLocation()
{
// This is the one point where QDesktopServices and QStandardPaths differ.
@@ -115,6 +118,7 @@ void tst_qdesktopservices::testDataLocation()
#endif
}
}
+#endif
QTEST_MAIN(tst_qdesktopservices)
diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h
index f162c3ae9f..77298342af 100644
--- a/tests/auto/network-settings.h
+++ b/tests/auto/network-settings.h
@@ -72,15 +72,20 @@ public:
}
#ifdef QT_NETWORK_LIB
- static QHostAddress serverIP()
+ static QHostAddress getServerIpImpl(const QString &serverName)
{
- const QHostInfo info = QHostInfo::fromName(serverName());
+ const QHostInfo info = QHostInfo::fromName(serverName);
if (info.error()) {
QTest::qFail(qPrintable(info.errorString()), __FILE__, __LINE__);
return QHostAddress();
}
return info.addresses().constFirst();
}
+
+ static QHostAddress serverIP()
+ {
+ return getServerIpImpl(serverName());
+ }
#endif
static bool compareReplyIMAP(QByteArray const& actual)
@@ -104,8 +109,8 @@ public:
static bool compareReplyFtp(QByteArray const& actual)
{
// output would be e.g. "220 (vsFTPd 2.3.5)\r\n221 Goodbye.\r\n"
- QRegExp ftpVersion(QStringLiteral("220 \\(vsFTPd \\d+\\.\\d+.\\d+\\)\\r\\n221 Goodbye.\\r\\n"));
- return ftpVersion.exactMatch(actual);
+ QRegularExpression ftpVersion(QRegularExpression::anchoredPattern(QStringLiteral("220 \\(vsFTPd \\d+\\.\\d+.\\d+\\)\\r\\n221 Goodbye.\\r\\n")));
+ return ftpVersion.match(actual).hasMatch();
}
static bool hasIPv6()
@@ -214,4 +219,67 @@ public:
return serverName();
#endif
}
+ static QString imapServerName()
+ {
+#ifdef QT_TEST_SERVER_NAME
+ return QString("cyrus.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+
+ static QString echoServerName()
+ {
+#ifdef QT_TEST_SERVER_NAME
+ return QString("echo.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+
+ static QString firewallServerName()
+ {
+#ifdef QT_TEST_SERVER_NAME
+ return QString("iptables.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+
+#ifdef QT_NETWORK_LIB
+ static QHostAddress imapServerIp()
+ {
+ return getServerIpImpl(imapServerName());
+ }
+
+ static QHostAddress httpServerIp()
+ {
+ return getServerIpImpl(httpServerName());
+ }
+
+ static QHostAddress httpProxyServerIp()
+ {
+ return getServerIpImpl(httpProxyServerName());
+ }
+
+ static QHostAddress socksProxyServerIp()
+ {
+ return getServerIpImpl(socksProxyServerName());
+ }
+
+ static QHostAddress ftpProxyServerIp()
+ {
+ return getServerIpImpl(ftpProxyServerName());
+ }
+
+ static QHostAddress ftpServerIp()
+ {
+ return getServerIpImpl(ftpServerName());
+ }
+
+ static QHostAddress firewallServerIp()
+ {
+ return getServerIpImpl(firewallServerName());
+ }
+#endif
};
diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp
index 5a99d4e50c..a8eebf5a24 100644
--- a/tests/auto/network/access/http2/http2srv.cpp
+++ b/tests/auto/network/access/http2/http2srv.cpp
@@ -76,7 +76,7 @@ void fill_push_header(const HttpHeader &originalRequest, HttpHeader &promisedReq
}
-Http2Server::Http2Server(H2Type type, const Http2::RawSettings &ss, const Http2::RawSettings &cs)
+Http2Server::Http2Server(H2Type type, const RawSettings &ss, const RawSettings &cs)
: connectionType(type),
serverSettings(ss),
expectedClientSettings(cs)
@@ -218,7 +218,7 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize)
quint32 bytesToSend = std::min<quint32>(windowSize, responseBody.size() - offset);
quint32 bytesSent = 0;
- const quint32 frameSizeLimit(clientSetting(Settings::MAX_FRAME_SIZE_ID, Http2::maxFrameSize));
+ const quint32 frameSizeLimit(clientSetting(Settings::MAX_FRAME_SIZE_ID, Http2::minPayloadLimit));
const uchar *src = reinterpret_cast<const uchar *>(responseBody.constData() + offset);
const bool last = offset + bytesToSend == quint32(responseBody.size());
@@ -236,6 +236,10 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize)
src += chunkSize;
bytesToSend -= chunkSize;
bytesSent += chunkSize;
+ if (frameSizeLimit != Http2::minPayloadLimit) {
+ // Our test is probably interested in how many DATA frames were sent.
+ emit sendingData();
+ }
}
if (interrupted.loadAcquire())
@@ -767,7 +771,7 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
Q_ASSERT(activeRequests.find(streamID) != activeRequests.end());
const quint32 maxFrameSize(clientSetting(Settings::MAX_FRAME_SIZE_ID,
- Http2::maxFrameSize));
+ Http2::maxPayloadSize));
if (pushPromiseEnabled) {
// A real server supporting PUSH_PROMISE will probably first send
diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h
index 4ef4b25101..3105684d59 100644
--- a/tests/auto/network/access/http2/http2srv.h
+++ b/tests/auto/network/access/http2/http2srv.h
@@ -42,6 +42,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qatomic.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qmap.h>
#include <vector>
#include <map>
@@ -69,13 +70,15 @@ enum class H2Type {
h2cDirect, // Clear text direct
};
+using RawSettings = QMap<Http2::Settings, quint32>;
+
class Http2Server : public QTcpServer
{
Q_OBJECT
public:
- Http2Server(H2Type type, const Http2::RawSettings &serverSettings,
- const Http2::RawSettings &clientSettings);
+ Http2Server(H2Type type, const RawSettings &serverSettings,
+ const RawSettings &clientSettings);
~Http2Server();
@@ -125,6 +128,7 @@ Q_SIGNALS:
void receivedRequest(quint32 streamID);
void receivedData(quint32 streamID);
void windowUpdate(quint32 streamID);
+ void sendingData();
private slots:
void connectionEstablished();
@@ -147,8 +151,8 @@ private:
bool settingsSent = false;
bool waitingClientAck = false;
- Http2::RawSettings serverSettings;
- Http2::RawSettings expectedClientSettings;
+ RawSettings serverSettings;
+ RawSettings expectedClientSettings;
bool connectionError = false;
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index ea939dfdea..c264956d7b 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -32,8 +32,10 @@
#include <QtNetwork/private/http2protocol_p.h>
#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qhttp2configuration.h>
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
+
#include <QtCore/qglobal.h>
#include <QtCore/qobject.h>
#include <QtCore/qthread.h>
@@ -66,6 +68,26 @@ Q_DECLARE_METATYPE(QNetworkRequest::Attribute)
QT_BEGIN_NAMESPACE
+QHttp2Configuration qt_defaultH2Configuration()
+{
+ QHttp2Configuration config;
+ config.setStreamReceiveWindowSize(Http2::qtDefaultStreamReceiveWindowSize);
+ config.setSessionReceiveWindowSize(Http2::maxSessionReceiveWindowSize);
+ config.setServerPushEnabled(false);
+ return config;
+}
+
+RawSettings qt_H2ConfigurationToSettings(const QHttp2Configuration &config = qt_defaultH2Configuration())
+{
+ RawSettings settings;
+ settings[Http2::Settings::ENABLE_PUSH_ID] = config.serverPushEnabled();
+ settings[Http2::Settings::INITIAL_WINDOW_SIZE_ID] = config.streamReceiveWindowSize();
+ if (config.maxFrameSize() != Http2::minPayloadLimit)
+ settings[Http2::Settings::MAX_FRAME_SIZE_ID] = config.maxFrameSize();
+ return settings;
+}
+
+
class tst_Http2 : public QObject
{
Q_OBJECT
@@ -87,6 +109,7 @@ private slots:
void earlyResponse();
void connectToHost_data();
void connectToHost();
+ void maxFrameSize();
protected slots:
// Slots to listen to our in-process server:
@@ -110,12 +133,13 @@ private:
// small payload.
void runEventLoop(int ms = 5000);
void stopEventLoop();
- Http2Server *newServer(const Http2::RawSettings &serverSettings, H2Type connectionType,
- const Http2::ProtocolParameters &clientSettings = {});
+ Http2Server *newServer(const RawSettings &serverSettings, H2Type connectionType,
+ const RawSettings &clientSettings = qt_H2ConfigurationToSettings());
// Send a get or post request, depending on a payload (empty or not).
void sendRequest(int streamNumber,
QNetworkRequest::Priority priority = QNetworkRequest::NormalPriority,
- const QByteArray &payload = QByteArray());
+ const QByteArray &payload = QByteArray(),
+ const QHttp2Configuration &clientConfiguration = qt_defaultH2Configuration());
QUrl requestUrl(H2Type connnectionType) const;
quint16 serverPort = 0;
@@ -131,14 +155,14 @@ private:
bool prefaceOK = false;
bool serverGotSettingsACK = false;
- static const Http2::RawSettings defaultServerSettings;
+ static const RawSettings defaultServerSettings;
};
#define STOP_ON_FAILURE \
if (QTest::currentTestFailed()) \
return;
-const Http2::RawSettings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}};
+const RawSettings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}};
namespace {
@@ -308,18 +332,15 @@ void tst_Http2::flowControlClientSide()
nRequests = 10;
windowUpdates = 0;
- Http2::ProtocolParameters params;
+ QHttp2Configuration params;
// A small window size for a session, and even a smaller one per stream -
// this will result in WINDOW_UPDATE frames both on connection stream and
// per stream.
- params.maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize * 5;
- params.settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = Http2::defaultSessionWindowSize;
- // Inform our manager about non-default settings:
- manager->setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
-
- const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}};
- ServerPtr srv(newServer(serverSettings, defaultConnectionType(), params));
+ params.setSessionReceiveWindowSize(Http2::defaultSessionWindowSize * 5);
+ params.setStreamReceiveWindowSize(Http2::defaultSessionWindowSize);
+ const RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}};
+ ServerPtr srv(newServer(serverSettings, defaultConnectionType(), qt_H2ConfigurationToSettings(params)));
const QByteArray respond(int(Http2::defaultSessionWindowSize * 10), 'x');
srv->setResponseBody(respond);
@@ -330,7 +351,7 @@ void tst_Http2::flowControlClientSide()
QVERIFY(serverPort != 0);
for (int i = 0; i < nRequests; ++i)
- sendRequest(i);
+ sendRequest(i, QNetworkRequest::NormalPriority, {}, params);
runEventLoop(120000);
STOP_ON_FAILURE
@@ -359,7 +380,7 @@ void tst_Http2::flowControlServerSide()
serverPort = 0;
nRequests = 10;
- const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, 7}};
+ const RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, 7}};
ServerPtr srv(newServer(serverSettings, defaultConnectionType()));
@@ -392,12 +413,11 @@ void tst_Http2::pushPromise()
serverPort = 0;
nRequests = 1;
- Http2::ProtocolParameters params;
+ QHttp2Configuration params;
// Defaults are good, except ENABLE_PUSH:
- params.settingsFrameData[Settings::ENABLE_PUSH_ID] = 1;
- manager->setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
+ params.setServerPushEnabled(true);
- ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType(), params));
+ ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType(), qt_H2ConfigurationToSettings(params)));
srv->enablePushPromise(true, QByteArray("/script.js"));
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
@@ -410,6 +430,7 @@ void tst_Http2::pushPromise()
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
+ request.setHttp2Configuration(params);
auto reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
@@ -681,6 +702,73 @@ void tst_Http2::connectToHost()
QVERIFY(reply->isFinished());
}
+void tst_Http2::maxFrameSize()
+{
+#if !QT_CONFIG(ssl)
+ QSKIP("TLS support is needed for this test");
+#endif // QT_CONFIG(ssl)
+
+ // Here we test we send 'MAX_FRAME_SIZE' setting in our
+ // 'SETTINGS'. If done properly, our server will not chunk
+ // the payload into several DATA frames.
+
+#if QT_CONFIG(securetransport)
+ // Normally on macOS we use plain text only for SecureTransport
+ // does not support ALPN on the server side. With 'direct encrytped'
+ // we have to use TLS sockets (== private key) and thus suppress a
+ // keychain UI asking for permission to use a private key.
+ // Our CI has this, but somebody testing locally - will have a problem.
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ auto envRollback = qScopeGuard([](){
+ qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN");
+ });
+#endif // QT_CONFIG(securetransport)
+
+ auto connectionType = H2Type::h2Alpn;
+ auto attribute = QNetworkRequest::HTTP2AllowedAttribute;
+ if (clearTextHTTP2) {
+ connectionType = H2Type::h2Direct;
+ attribute = QNetworkRequest::Http2DirectAttribute;
+ }
+
+ auto h2Config = qt_defaultH2Configuration();
+ h2Config.setMaxFrameSize(Http2::minPayloadLimit * 3);
+
+ serverPort = 0;
+ nRequests = 1;
+
+ ServerPtr srv(newServer(defaultServerSettings, connectionType,
+ qt_H2ConfigurationToSettings(h2Config)));
+ srv->setResponseBody(QByteArray(Http2::minPayloadLimit * 2, 'q'));
+ QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+ QVERIFY(serverPort != 0);
+
+ const QSignalSpy frameCounter(srv.data(), &Http2Server::sendingData);
+ auto url = requestUrl(connectionType);
+ url.setPath(QString("/stream1.html"));
+
+ QNetworkRequest request(url);
+ request.setAttribute(attribute, QVariant(true));
+ request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
+ request.setHttp2Configuration(h2Config);
+
+ QNetworkReply *reply = manager->get(request);
+ reply->ignoreSslErrors();
+ connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
+
+ runEventLoop();
+ STOP_ON_FAILURE
+
+ // Normally, with a 16kb limit, our server would split such
+ // a response into 3 'DATA' frames (16kb + 16kb + 0|END_STREAM).
+ QCOMPARE(frameCounter.count(), 1);
+
+ QVERIFY(nRequests == 0);
+ QVERIFY(prefaceOK);
+ QVERIFY(serverGotSettingsACK);
+}
+
void tst_Http2::serverStarted(quint16 port)
{
serverPort = port;
@@ -692,7 +780,6 @@ void tst_Http2::clearHTTP2State()
windowUpdates = 0;
prefaceOK = false;
serverGotSettingsACK = false;
- manager->setProperty(Http2::http2ParametersPropertyName, QVariant());
}
void tst_Http2::runEventLoop(int ms)
@@ -705,12 +792,11 @@ void tst_Http2::stopEventLoop()
eventLoop.exitLoop();
}
-Http2Server *tst_Http2::newServer(const Http2::RawSettings &serverSettings, H2Type connectionType,
- const Http2::ProtocolParameters &clientSettings)
+Http2Server *tst_Http2::newServer(const RawSettings &serverSettings, H2Type connectionType,
+ const RawSettings &clientSettings)
{
using namespace Http2;
- auto srv = new Http2Server(connectionType, serverSettings,
- clientSettings.settingsFrameData);
+ auto srv = new Http2Server(connectionType, serverSettings, clientSettings);
using Srv = Http2Server;
using Cl = tst_Http2;
@@ -732,7 +818,8 @@ Http2Server *tst_Http2::newServer(const Http2::RawSettings &serverSettings, H2Ty
void tst_Http2::sendRequest(int streamNumber,
QNetworkRequest::Priority priority,
- const QByteArray &payload)
+ const QByteArray &payload,
+ const QHttp2Configuration &h2Config)
{
auto url = requestUrl(defaultConnectionType());
url.setPath(QString("/stream%1.html").arg(streamNumber));
@@ -742,6 +829,7 @@ void tst_Http2::sendRequest(int streamNumber,
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, QVariant(true));
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
request.setPriority(priority);
+ request.setHttp2Configuration(h2Config);
QNetworkReply *reply = nullptr;
if (payload.size())
diff --git a/tests/auto/network/access/qabstractnetworkcache/BLACKLIST b/tests/auto/network/access/qabstractnetworkcache/BLACKLIST
deleted file mode 100644
index 2ad52f8b31..0000000000
--- a/tests/auto/network/access/qabstractnetworkcache/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[cacheControl]
-windows
diff --git a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
index 1874f001ab..c722100ead 100644
--- a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
+++ b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
@@ -5,3 +5,5 @@ SOURCES += tst_qabstractnetworkcache.cpp
TESTDATA += tests/*
+CONFIG += unsupported/testserver
+QT_TEST_SERVER_LIST = apache2
diff --git a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
index b8d9adf7a1..182e3e9547 100644
--- a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
+++ b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
@@ -39,7 +39,7 @@
#include <algorithm>
-#define TESTFILE QLatin1String("http://") + QtNetworkSettings::serverName() + QLatin1String("/qtest/cgi-bin/")
+#define TESTFILE QLatin1String("http://") + QtNetworkSettings::httpServerName() + QLatin1String("/qtest/cgi-bin/")
class tst_QAbstractNetworkCache : public QObject
{
@@ -127,8 +127,13 @@ Q_DECLARE_METATYPE(QNetworkRequest::CacheLoadControl)
void tst_QAbstractNetworkCache::initTestCase()
{
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
+
#ifndef QT_NO_BEARERMANAGEMENT
netConfMan = new QNetworkConfigurationManager(this);
networkConfiguration = netConfMan->defaultConfiguration();
diff --git a/tests/auto/network/access/qftp/BLACKLIST b/tests/auto/network/access/qftp/BLACKLIST
index 96d9274653..0a99f3eb00 100644
--- a/tests/auto/network/access/qftp/BLACKLIST
+++ b/tests/auto/network/access/qftp/BLACKLIST
@@ -6,5 +6,11 @@ redhatenterpriselinuxworkstation-6.6
[activeMode:WithoutProxyWithSession]
redhatenterpriselinuxworkstation-6.6
+[list]
+opensuse-leap
+windows-7sp1
+windows-10 msvc-2015
+ubuntu
+osx
[list:epsvNotSupported]
*
diff --git a/tests/auto/network/access/qftp/qftp.pro b/tests/auto/network/access/qftp/qftp.pro
index 1959c1acac..c78020c5f8 100644
--- a/tests/auto/network/access/qftp/qftp.pro
+++ b/tests/auto/network/access/qftp/qftp.pro
@@ -4,3 +4,6 @@ SOURCES += tst_qftp.cpp
requires(qtConfig(private_tests))
QT = core network network-private testlib
+
+CONFIG += unsupported/testserver
+QT_TEST_SERVER_LIST = vsftpd ftp-proxy squid danted
diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp
index 1a8f264c28..2068738a67 100644
--- a/tests/auto/network/access/qftp/tst_qftp.cpp
+++ b/tests/auto/network/access/qftp/tst_qftp.cpp
@@ -43,6 +43,7 @@
#include <QtNetwork/private/qnetworksession_p.h>
#include <QTcpServer>
#include <QHostInfo>
+#include <QElapsedTimer>
#include <QTcpSocket>
#include "../../../network-settings.h"
@@ -208,7 +209,14 @@ void tst_QFtp::initTestCase_data()
void tst_QFtp::initTestCase()
{
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
#ifndef QT_NO_BEARERMANAGEMENT
QNetworkConfigurationManager manager;
networkSessionImplicit = QSharedPointer<QNetworkSession>::create(manager.defaultConfiguration());
@@ -235,9 +243,9 @@ void tst_QFtp::init()
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
if (proxyType == QNetworkProxy::Socks5Proxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
} else if (proxyType == QNetworkProxy::HttpProxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
}
#else // !QT_NO_NETWORKPROXY
Q_UNUSED(proxyType);
@@ -316,8 +324,8 @@ void tst_QFtp::connectToHost_data()
QTest::addColumn<uint>("port");
QTest::addColumn<int>("state");
- QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << (int)QFtp::Connected;
- QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)2222 << (int)QFtp::Unconnected;
+ QTest::newRow( "ok01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << (int)QFtp::Connected;
+ QTest::newRow( "error01" ) << QtNetworkSettings::ftpServerName() << (uint)2222 << (int)QFtp::Unconnected;
QTest::newRow( "error02" ) << QString("foo.bar") << (uint)21 << (int)QFtp::Unconnected;
}
@@ -402,13 +410,13 @@ void tst_QFtp::login_data()
QTest::addColumn<QString>("password");
QTest::addColumn<int>("success");
- QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << 1;
- QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("") << 1;
- QTest::newRow( "ok03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << 1;
- QTest::newRow( "ok04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << 1;
+ QTest::newRow( "ok01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << 1;
+ QTest::newRow( "ok02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString("") << 1;
+ QTest::newRow( "ok03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString("foo") << 1;
+ QTest::newRow( "ok04" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << 1;
- QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("") << 0;
- QTest::newRow( "error02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("bar") << 0;
+ QTest::newRow( "error01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("foo") << QString("") << 0;
+ QTest::newRow( "error02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("foo") << QString("bar") << 0;
}
void tst_QFtp::login()
@@ -448,12 +456,12 @@ void tst_QFtp::close_data()
QTest::addColumn<QString>("password");
QTest::addColumn<bool>("login");
- QTest::newRow( "login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << true;
- QTest::newRow( "login02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << true;
- QTest::newRow( "login03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << true;
- QTest::newRow( "login04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << true;
+ QTest::newRow( "login01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << true;
+ QTest::newRow( "login02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString() << true;
+ QTest::newRow( "login03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString("foo") << true;
+ QTest::newRow( "login04" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << true;
- QTest::newRow( "no-login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("") << QString("") << false;
+ QTest::newRow( "no-login01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("") << QString("") << false;
}
void tst_QFtp::close()
@@ -503,17 +511,17 @@ void tst_QFtp::list_data()
flukeQtest << "rfc3252.txt";
flukeQtest << "upload";
- QTest::newRow( "workDir01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
- QTest::newRow( "workDir02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
+ QTest::newRow( "workDir01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
+ QTest::newRow( "workDir02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
- QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
- QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
- QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
// ### The microsoft server does not seem to work properly at the moment --
// I am also not able to open a data connection with other, non-Qt FTP
// clients to it.
@@ -573,14 +581,14 @@ void tst_QFtp::cd_data()
flukeQtest << "rfc3252.txt";
flukeQtest << "upload";
- QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
- QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
- QTest::newRow( "nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "nonExist03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
}
void tst_QFtp::cd()
@@ -635,19 +643,19 @@ void tst_QFtp::get_data()
// test the two get() overloads in one routine
for ( int i=0; i<2; i++ ) {
const QByteArray iB = QByteArray::number(i);
- QTest::newRow(("relPath01_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("relPath01_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("relPath02_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow(("relPath02_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("absPath01_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("absPath01_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("absPath02_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow(("absPath02_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "/var/ftp/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("nonExist01_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("nonExist01_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("foo") << 0 << QByteArray() << (bool)(i==1);
- QTest::newRow(("nonExist02_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("nonExist02_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("/foo") << 0 << QByteArray() << (bool)(i==1);
}
}
@@ -727,31 +735,31 @@ void tst_QFtp::put_data()
// test the two put() overloads in one routine with a file name containing
// U+0x00FC (latin small letter u with diaeresis) for QTBUG-52303, testing UTF-8
for ( int i=0; i<2; i++ ) {
- QTest::newRow(("relPath01_" + QByteArray::number(i)).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("relPath01_" + QByteArray::number(i)).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< (QLatin1String("qtest/upload/rel01_") + QChar(0xfc) + QLatin1String("%1")) << rfc3252
<< (bool)(i==1) << 1;
/*
- QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("qtest/upload/rel02_%1") << rfc3252
<< (bool)(i==1) << 1;
- QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("qtest/upload/rel03_%1") << QByteArray()
<< (bool)(i==1) << 1;
- QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("qtest/upload/rel04_%1") << bigData
<< (bool)(i==1) << 1;
- QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("/qtest/upload/abs01_%1") << rfc3252
<< (bool)(i==1) << 1;
- QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("/srv/ftp/qtest/upload/abs02_%1") << rfc3252
<< (bool)(i==1) << 1;
- QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("foo") << QByteArray()
<< (bool)(i==1) << 0;
- QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("/foo") << QByteArray()
<< (bool)(i==1) << 0;
*/
@@ -877,22 +885,22 @@ void tst_QFtp::mkdir_data()
QTest::addColumn<QString>("dirToCreate");
QTest::addColumn<int>("success");
- QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "qtest/upload" << QString("rel01_%1") << 1;
- QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "qtest/upload" << QString("rel02_%1") << 1;
- QTest::newRow( "relPath03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( "relPath03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "qtest/upload" << QString("rel03_%1") << 1;
- QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "." << QString("/qtest/upload/abs01_%1") << 1;
- QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "." << QString("/var/ftp/qtest/upload/abs02_%1") << 1;
- // QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0;
- QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ // QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 0;
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "." << QString("foo") << 0;
- QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "." << QString("/foo") << 0;
}
@@ -979,7 +987,7 @@ void tst_QFtp::mkdir()
void tst_QFtp::mkdir2()
{
ftp = new QFtp;
- ftp->connectToHost(QtNetworkSettings::serverName());
+ ftp->connectToHost(QtNetworkSettings::ftpServerName());
ftp->login();
current_id = ftp->cd("kake/test");
@@ -1026,39 +1034,39 @@ void tst_QFtp::rename_data()
QTest::addColumn<QString>("renamedFile");
QTest::addColumn<int>("success");
- QTest::newRow("relPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("relPath01") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< "qtest/upload"
<< QString("rel_old01_%1") << QString("rel_new01_%1")
<< QString("qtest/upload/rel_old01_%1") << QString("qtest/upload/rel_new01_%1")
<< 1;
- QTest::newRow("relPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ QTest::newRow("relPath02") << QtNetworkSettings::ftpServerName() << QString("ftptest") << "password"
<< "qtest/upload"
<< QString("rel_old02_%1") << QString("rel_new02_%1")
<< QString("qtest/upload/rel_old02_%1") << QString("qtest/upload/rel_new02_%1")
<< 1;
- QTest::newRow("relPath03") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ QTest::newRow("relPath03") << QtNetworkSettings::ftpServerName() << QString("ftptest") << "password"
<< "qtest/upload"
<< QString("rel_old03_%1")<< QString("rel_new03_%1")
<< QString("qtest/upload/rel_old03_%1") << QString("qtest/upload/rel_new03_%1")
<< 1;
- QTest::newRow("absPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("absPath01") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< QString()
<< QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
<< QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
<< 1;
- QTest::newRow("absPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ QTest::newRow("absPath02") << QtNetworkSettings::ftpServerName() << QString("ftptest") << "password"
<< QString()
<< QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
<< QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
<< 1;
- QTest::newRow("nonExist01") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("nonExist01") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< QString()
<< QString("foo") << "new_foo"
<< QString() << QString()
<< 0;
- QTest::newRow("nonExist02") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("nonExist02") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< QString()
<< QString("/foo") << QString("/new_foo")
<< QString() << QString()
@@ -1220,7 +1228,7 @@ void tst_QFtp::commandSequence_data()
{
// some "constants"
QStringList argConnectToHost01;
- argConnectToHost01 << QtNetworkSettings::serverName() << "21";
+ argConnectToHost01 << QtNetworkSettings::ftpServerName() << "21";
QStringList argLogin01, argLogin02, argLogin03, argLogin04;
argLogin01 << QString() << QString();
@@ -1351,13 +1359,13 @@ void tst_QFtp::abort_data()
QTest::addColumn<QString>("file");
QTest::addColumn<QByteArray>("uploadData");
- QTest::newRow( "get_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
- QTest::newRow( "get_fluke02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
+ QTest::newRow( "get_fluke01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
+ QTest::newRow( "get_fluke02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
// Qt/CE test environment has too little memory for this test
QByteArray bigData( 10*1024*1024, 0 );
bigData.fill( 'B' );
- QTest::newRow( "put_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
+ QTest::newRow( "put_fluke01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
}
void tst_QFtp::abort()
@@ -1402,7 +1410,7 @@ void tst_QFtp::abort()
if ( it.value().success ) {
// The FTP server on fluke is sadly returning a success, even when
// the operation was aborted. So we have to use some heuristics.
- if ( host == QtNetworkSettings::serverName() ) {
+ if ( host == QtNetworkSettings::ftpServerName() ) {
if ( cmd == QFtp::Get ) {
QVERIFY2(bytesDone <= bytesTotal, msgComparison(bytesDone, "<=", bytesTotal));
} else {
@@ -1449,11 +1457,11 @@ void tst_QFtp::bytesAvailable_data()
QTest::addColumn<qlonglong>("bytesAvailFinished");
QTest::addColumn<qlonglong>("bytesAvailDone");
- QTest::newRow( "fluke01" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
- QTest::newRow( "fluke02" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
+ QTest::newRow( "fluke01" ) << QtNetworkSettings::ftpServerName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
+ QTest::newRow( "fluke02" ) << QtNetworkSettings::ftpServerName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
- QTest::newRow( "fluke03" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
- QTest::newRow( "fluke04" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
+ QTest::newRow( "fluke03" ) << QtNetworkSettings::ftpServerName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
+ QTest::newRow( "fluke04" ) << QtNetworkSettings::ftpServerName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
}
void tst_QFtp::bytesAvailable()
@@ -1498,7 +1506,7 @@ void tst_QFtp::activeMode()
file.open(QIODevice::ReadWrite);
QFtp ftp;
ftp.setTransferMode(QFtp::Active);
- ftp.connectToHost(QtNetworkSettings::serverName(), 21);
+ ftp.connectToHost(QtNetworkSettings::ftpServerName(), 21);
ftp.login();
ftp.list();
ftp.get("/qtest/rfc3252.txt", &file);
@@ -1534,14 +1542,14 @@ void tst_QFtp::proxy_data()
flukeQtest << "rfc3252.txt";
flukeQtest << "upload";
- QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
- QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+ QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
}
void tst_QFtp::proxy()
@@ -1553,7 +1561,7 @@ void tst_QFtp::proxy()
QFETCH( QString, dir );
ftp = newFtp();
- addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::serverName(), 2121 ) );
+ addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::ftpProxyServerName(), 2121 ) );
addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
addCommand( QFtp::Login, ftp->login( user, password ) );
addCommand( QFtp::Cd, ftp->cd( dir ) );
@@ -1589,7 +1597,7 @@ void tst_QFtp::binaryAscii()
init();
ftp = newFtp();
- addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::ftpServerName(), 21));
addCommand(QFtp::Login, ftp->login("ftptest", "password"));
addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
addCommand(QFtp::Put, ftp->put(putData, file, QFtp::Ascii));
@@ -1599,7 +1607,7 @@ void tst_QFtp::binaryAscii()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(QtNetworkSettings::serverName()) );
+ QFAIL( msgTimedOut(QtNetworkSettings::ftpServerName()) );
ResMapIt it = resultMap.find(QFtp::Put);
QVERIFY(it != resultMap.end());
@@ -1611,7 +1619,7 @@ void tst_QFtp::binaryAscii()
init();
ftp = newFtp();
- addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::ftpServerName(), 21));
addCommand(QFtp::Login, ftp->login("ftptest", "password"));
addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
addCommand(QFtp::Get, ftp->get(file, &getBuf, QFtp::Binary));
@@ -1621,7 +1629,7 @@ void tst_QFtp::binaryAscii()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(QtNetworkSettings::serverName()) );
+ QFAIL( msgTimedOut(QtNetworkSettings::ftpServerName()) );
ResMapIt it2 = resultMap.find(QFtp::Get);
QVERIFY(it2 != resultMap.end());
@@ -1634,7 +1642,7 @@ void tst_QFtp::binaryAscii()
// cleanup (i.e. remove the file) -- this also tests the remove command
init();
ftp = newFtp();
- addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::ftpServerName(), 21));
addCommand(QFtp::Login, ftp->login("ftptest", "password"));
addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
addCommand(QFtp::Remove, ftp->remove(file));
@@ -1644,13 +1652,13 @@ void tst_QFtp::binaryAscii()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(QtNetworkSettings::serverName()) );
+ QFAIL( msgTimedOut(QtNetworkSettings::ftpServerName()) );
it = resultMap.find( QFtp::Remove );
QVERIFY( it != resultMap.end() );
QCOMPARE( it.value().success, 1 );
- QVERIFY(!fileExists(QtNetworkSettings::serverName(), 21, "ftptest", "password", file));
+ QVERIFY(!fileExists(QtNetworkSettings::ftpServerName(), 21, "ftptest", "password", file));
}
@@ -2067,7 +2075,7 @@ void tst_QFtp::doneSignal()
QFtp ftp;
QSignalSpy spy(&ftp, SIGNAL(done(bool)));
- ftp.connectToHost(QtNetworkSettings::serverName());
+ ftp.connectToHost(QtNetworkSettings::ftpServerName());
ftp.login("anonymous");
ftp.list();
ftp.close();
@@ -2137,7 +2145,7 @@ void tst_QFtp::qtbug7359Crash()
QFtp ftp;
ftp.connectToHost("127.0.0.1");
- QTime t;
+ QElapsedTimer t;
int elapsed;
t.start();
diff --git a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
index d32b651b86..84e6f857a1 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
+++ b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
@@ -4,3 +4,6 @@ SOURCES += tst_qhttpnetworkconnection.cpp
requires(qtConfig(private_tests))
QT = core-private network-private testlib
+
+CONFIG += unsupported/testserver
+QT_TEST_SERVER_LIST = apache2
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index 84766f5484..0a9320118d 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -50,6 +50,7 @@ private:
bool finishedCalled;
bool finishedWithErrorCalled;
QNetworkReply::NetworkError netErrorCode;
+ QString (*httpServerName)() = QtNetworkSettings::httpServerName;
private Q_SLOTS:
void initTestCase();
@@ -101,7 +102,11 @@ private Q_SLOTS:
void tst_QHttpNetworkConnection::initTestCase()
{
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(httpServerName(), 80));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
void tst_QHttpNetworkConnection::options_data()
@@ -126,10 +131,9 @@ void tst_QHttpNetworkConnection::head_data()
QTest::addColumn<QString>("statusString");
QTest::addColumn<int>("contentLength");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
-
- QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
- QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
+ QTest::newRow("failure-path") << "http://" << httpServerName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
+ QTest::newRow("failure-protocol") << "" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
}
void tst_QHttpNetworkConnection::head()
@@ -175,10 +179,10 @@ void tst_QHttpNetworkConnection::get_data()
QTest::addColumn<int>("contentLength");
QTest::addColumn<int>("downloadSize");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
- QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1;
- QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1;
+ QTest::newRow("failure-path") << "http://" << httpServerName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1;
+ QTest::newRow("failure-protocol") << "" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1;
}
void tst_QHttpNetworkConnection::get()
@@ -244,8 +248,8 @@ void tst_QHttpNetworkConnection::put_data()
QTest::addColumn<QString>("data");
QTest::addColumn<bool>("succeed");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
- QTest::newRow("fail-internal") << "http://" << QtNetworkSettings::serverName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
+ QTest::newRow("fail-internal") << "http://" << httpServerName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
QTest::newRow("fail-host") << "http://" << "invalid.test.qt-project.org" << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
}
@@ -324,8 +328,8 @@ void tst_QHttpNetworkConnection::post_data()
QTest::addColumn<int>("contentLength");
QTest::addColumn<int>("downloadSize");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
- QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
+ QTest::newRow("failure-internal") << "http://" << httpServerName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1;
}
void tst_QHttpNetworkConnection::post()
@@ -449,11 +453,11 @@ void tst_QHttpNetworkConnection::get401_data()
QTest::addColumn<QString>("password");
QTest::addColumn<int>("statusCode");
- QTest::newRow("no-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
- QTest::newRow("invalid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
- QTest::newRow("valid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
- QTest::newRow("digest-authentication-invalid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
- QTest::newRow("digest-authentication-valid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+ QTest::newRow("no-credentials") << "http://" << httpServerName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
+ QTest::newRow("invalid-credentials") << "http://" << httpServerName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
+ QTest::newRow("valid-credentials") << "http://" << httpServerName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+ QTest::newRow("digest-authentication-invalid") << "http://" << httpServerName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
+ QTest::newRow("digest-authentication-valid") << "http://" << httpServerName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
}
void tst_QHttpNetworkConnection::get401()
@@ -508,9 +512,9 @@ void tst_QHttpNetworkConnection::compression_data()
QTest::addColumn<bool>("autoCompress");
QTest::addColumn<QString>("contentCoding");
- QTest::newRow("success-autogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
- QTest::newRow("success-nogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
- QTest::newRow("success-manualgzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
+ QTest::newRow("success-autogzip-temp") << "http://" << httpServerName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
+ QTest::newRow("success-nogzip-temp") << "http://" << httpServerName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
+ QTest::newRow("success-manualgzip-temp") << "http://" << httpServerName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
}
@@ -586,9 +590,9 @@ void tst_QHttpNetworkConnection::ignoresslerror_data()
// fluke's certificate is signed by a non-standard authority.
// Since we don't introduce that CA into the SSL verification chain,
// connecting should fail.
- QTest::newRow("success-init") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << true << false << 200;
- QTest::newRow("success-fromSignal") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << true << 200;
- QTest::newRow("failure") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << false << 100;
+ QTest::newRow("success-init") << "https://" << httpServerName() << "/" << ushort(443) << true << true << false << 200;
+ QTest::newRow("success-fromSignal") << "https://" << httpServerName() << "/" << ushort(443) << true << false << true << 200;
+ QTest::newRow("failure") << "https://" << httpServerName() << "/" << ushort(443) << true << false << false << 100;
}
void tst_QHttpNetworkConnection::ignoresslerror()
@@ -635,7 +639,7 @@ void tst_QHttpNetworkConnection::nossl_data()
QTest::addColumn<bool>("encrypt");
QTest::addColumn<QNetworkReply::NetworkError>("networkError");
- QTest::newRow("protocol-error") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
+ QTest::newRow("protocol-error") << "https://" << httpServerName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
}
void tst_QHttpNetworkConnection::nossl()
@@ -696,7 +700,7 @@ void tst_QHttpNetworkConnection::getMultiple()
QFETCH(bool, pipeliningAllowed);
QFETCH(int, requestCount);
- QHttpNetworkConnection connection(connectionCount, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(connectionCount, httpServerName());
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -705,7 +709,7 @@ void tst_QHttpNetworkConnection::getMultiple()
// depending on what you use the results will vary.
// for the "real" results, use a URL that has "internet latency" for you. Then (6 connections, pipelining) will win.
// for LAN latency, you will possibly get that (1 connection, no pipelining) is the fastest
- QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + httpServerName() + "/qtest/rfc3252.txt");
if (pipeliningAllowed)
request->setPipeliningAllowed(true);
requests.append(request);
@@ -723,7 +727,7 @@ void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities(
quint16 requestCount = 100;
// use 2 connections.
- QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(2, httpServerName());
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -731,9 +735,9 @@ void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities(
for (int i = 0; i < requestCount; i++) {
QHttpNetworkRequest *request = 0;
if (i % 3)
- request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get);
+ request = new QHttpNetworkRequest("http://" + httpServerName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get);
else
- request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head);
+ request = new QHttpNetworkRequest("http://" + httpServerName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head);
if (i % 2 || i % 3)
request->setPipeliningAllowed(true);
@@ -800,9 +804,9 @@ void tst_QHttpNetworkConnection::getMultipleWithPriorities()
{
quint16 requestCount = 100;
// use 2 connections.
- QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(2, httpServerName());
GetMultipleWithPrioritiesReceiver receiver(requestCount);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QUrl url("http://" + httpServerName() + "/qtest/rfc3252.txt");
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -854,10 +858,10 @@ void tst_QHttpNetworkConnection::getEmptyWithPipelining()
{
quint16 requestCount = 50;
// use 2 connections.
- QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(2, httpServerName());
GetEmptyWithPipeliningReceiver receiver(requestCount);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/cgi-bin/echo.cgi"); // a get on this = getting an empty file
+ QUrl url("http://" + httpServerName() + "/cgi-bin/echo.cgi"); // a get on this = getting an empty file
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -901,8 +905,8 @@ void tst_QHttpNetworkConnection::getAndEverythingShouldBePipelined()
{
quint16 requestCount = 100;
// use 1 connection.
- QHttpNetworkConnection connection(1, QtNetworkSettings::serverName());
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QHttpNetworkConnection connection(1, httpServerName());
+ QUrl url("http://" + httpServerName() + "/qtest/rfc3252.txt");
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -937,8 +941,8 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject_data()
void tst_QHttpNetworkConnection::getAndThenDeleteObject()
{
// yes, this will leak if the testcase fails. I don't care. It must not fail then :P
- QHttpNetworkConnection *connection = new QHttpNetworkConnection(QtNetworkSettings::serverName());
- QHttpNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QHttpNetworkConnection *connection = new QHttpNetworkConnection(httpServerName());
+ QHttpNetworkRequest request("http://" + httpServerName() + "/qtest/bigfile");
QHttpNetworkReply *reply = connection->sendRequest(request);
reply->setDownstreamLimited(true);
diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
index 6c3443a735..1ef2c118b9 100644
--- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
+++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
@@ -60,12 +60,13 @@ private slots:
class MyCookieJar: public QNetworkCookieJar
{
public:
- inline QList<QNetworkCookie> allCookies() const
- { return QNetworkCookieJar::allCookies(); }
- inline void setAllCookies(const QList<QNetworkCookie> &cookieList)
- { QNetworkCookieJar::setAllCookies(cookieList); }
+ ~MyCookieJar() override;
+ using QNetworkCookieJar::allCookies;
+ using QNetworkCookieJar::setAllCookies;
};
+MyCookieJar::~MyCookieJar() = default;
+
void tst_QNetworkCookieJar::getterSetter()
{
MyCookieJar jar;
diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST
index 4d29a830e9..2a0651f96f 100644
--- a/tests/auto/network/access/qnetworkreply/BLACKLIST
+++ b/tests/auto/network/access/qnetworkreply/BLACKLIST
@@ -1,47 +1,128 @@
# See qtbase/src/testlib/qtestblacklist.cpp for format
-osx
[authenticationCacheAfterCancel]
-windows
-[httpAbort]
-*
+windows-7sp1
+windows-10 msvc-2015
+[backgroundRequestInterruption]
+opensuse-leap
+windows-10 msvc-2015
+b2qt
+ubuntu
+osx
[backgroundRequestInterruption:ftp, bg, nobg]
*
[getErrors:ftp-host]
linux
# QTBUG-71953
+[getFromHttp]
+* !android !winrt
[getFromHttp:success-external]
*
[getFromHttpIntoBuffer]
-windows
+osx
[getFromHttpIntoBuffer2]
-windows
+windows-10
[headFromHttp]
-windows
-[ioGetFromHttpWithSocksProxy]
-windows
+windows-10 msvc-2017
[ioPostToHttpFromSocket]
-windows
# QTBUG-66247
+windows-7sp1
+windows-10 msvc-2017
+osx
[ioHttpRedirect]
-windows
# QTBUG-66602
+windows-10
[ioHttpRedirectMultipartPost]
-*
# QTBUG-66247
+b2qt
+windows-10 msvc-2015
+ubuntu
+rhel
[ioHttpRedirectPolicy]
-*
-[ioHttpRedirectPostPut]
-linux
-windows
+opensuse-leap
+b2qt
+ubuntu
+windows-10
[putToFtp]
-windows ci
-[putToFtpWithInvalidCredentials]
-windows ci
+windows-10
[putWithServerClosingConnectionImmediately]
-windows
-[qtbug28035browserDoesNotLoadQtProjectOrgCorrectly]
-windows
-[getFromUnreachableIp]
-windows msvc-2017
-[ioHttpRedirectErrors:too-many-redirects]
-rhel-6.6 ci
+windows-7sp1
+windows-10
+osx
+[backgroundRequest]
+osx-10.12
+[connectToIPv6Address]
+osx-10.12
+[deleteFromHttp]
+osx-10.12
+[downloadProgress]
+osx-10.12
+[encrypted]
+osx-10.13
+[httpCanReadLine]
+osx-10.12
+[httpRecursiveCreation]
+osx
+[httpWithNoCredentialUsage]
+osx-10.12
+[ignoreSslErrorsList]
+osx
+[ignoreSslErrorsListWithSlot]
+osx
+[ioGetFromBuiltinHttp]
+osx
+[ioGetFromHttp]
+osx-10.12
+[ioPostToHttpFromFile]
+osx-10.13
+[ioPostToHttpFromSocketSynchronous]
+osx
+[ioPostToHttpUploadProgress]
+osx
+[ioPutToHttpFromFile]
+osx-10.13
+[lastModifiedHeaderForHttp]
+osx-10.12
+[multipartSkipIndices]
+osx-10.12
+[nestedEventLoops]
+osx
+[postToHttp]
+osx-10.12
+[postToHttpMultipart]
+osx-10.12
+[postToHttpSynchronous]
+osx-10.12
+[postToHttps]
+osx
+[postToHttpsMultipart]
+osx
+[postToHttpsSynchronous]
+osx
+[putGetDeleteGetFromHttp]
+osx-10.12
+[putToHttpSynchronous]
+osx-10.12
+[putToHttps]
+osx
+[putToHttpsSynchronous]
+osx
+[putWithRateLimiting]
+osx-10.13
+[qtbug13431replyThrottling]
+osx-10.12
+[receiveCookiesFromHttp]
+osx
+[receiveCookiesFromHttpSynchronous]
+osx
+[sendCookies]
+osx
+[sendCookiesSynchronous]
+osx
+[sendCustomRequestToHttp]
+osx-10.12
+[sslConfiguration]
+osx
+[synchronousRequest]
+osx
+[backgroundRequestConnectInBackground]
+osx
diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro
index 9d36352abc..4cc1f6431e 100644
--- a/tests/auto/network/access/qnetworkreply/test/test.pro
+++ b/tests/auto/network/access/qnetworkreply/test/test.pro
@@ -15,5 +15,5 @@ TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \
!android:!winrt: TEST_HELPER_INSTALLS = ../echo/echo
+CONFIG += unsupported/testserver
QT_TEST_SERVER_LIST = vsftpd apache2 ftp-proxy danted squid
-include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri)
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 8627a37e12..418e1caf68 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -32,8 +32,11 @@
#include <QtCore/QDataStream>
#include <QtCore/QUrl>
#include <QtCore/QEventLoop>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QRandomGenerator>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QRegularExpressionMatch>
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
#include <QtCore/QTemporaryFile>
@@ -123,7 +126,7 @@ class tst_QNetworkReply: public QObject
if (!seedCreated) {
seedCreated = true; // not thread-safe, but who cares
}
- return QString::number(QTime(0, 0, 0).msecsTo(QTime::currentTime()))
+ return QString::number(QTime::currentTime().msecsSinceStartOfDay())
+ QLatin1Char('-') + QString::number(QCoreApplication::applicationPid())
+ QLatin1Char('-') + QString::number(QRandomGenerator::global()->generate());
}
@@ -503,6 +506,11 @@ private Q_SLOTS:
void putWithServerClosingConnectionImmediately();
#endif
+ void autoDeleteRepliesAttribute_data();
+ void autoDeleteRepliesAttribute();
+ void autoDeleteReplies_data();
+ void autoDeleteReplies();
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
private:
@@ -1142,7 +1150,7 @@ protected:
}
// now write in "blocking mode", this is where the rate measuring starts
- QTime timer;
+ QElapsedTimer timer;
timer.start();
//const qint64 writtenBefore = dataIndex;
//qint64 measuredTotalBytes = wantedSize - writtenBefore;
@@ -1241,7 +1249,7 @@ protected:
}
qint64 bytesRead = 0;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
do {
if (device->bytesAvailable() == 0) {
@@ -1552,7 +1560,7 @@ void tst_QNetworkReply::initTestCase()
QDir::setSearchPaths("testdata", QStringList() << testDataDir);
#ifndef QT_NO_SSL
- QSslSocket::defaultCaCertificates(); //preload certificates
+ QSslConfiguration::defaultConfiguration().caCertificates(); //preload certificates
#endif
#ifndef QT_NO_BEARERMANAGEMENT
netConfMan = new QNetworkConfigurationManager(this);
@@ -4142,10 +4150,10 @@ void tst_QNetworkReply::ioGetFromHttpWithCache()
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
QFETCH(QStringList, extraHttpHeaders);
- QStringListIterator it(extraHttpHeaders);
- while (it.hasNext()) {
- QString header = it.next();
- QString value = it.next();
+ QVERIFY(extraHttpHeaders.size() % 2 == 0);
+ for (auto it = extraHttpHeaders.cbegin(), end = extraHttpHeaders.cend(); it != end; /*double-stepping*/) {
+ QString header = *it++;
+ QString value = *it++;
request.setRawHeader(header.toLatin1(), value.toLatin1()); // To latin1? Deal with it!
}
@@ -5143,8 +5151,8 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp()
const int rate = 200; // in kB per sec
RateControlledReader reader(server, reply.data(), rate, bufferSize);
- QTime loopTime;
- loopTime.start();
+ QElapsedTimer loopTimer;
+ loopTimer.start();
const int result = waitForFinish(reply);
if (notEnoughDataForFastSender) {
@@ -5154,7 +5162,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp()
QVERIFY2(result == Success, msgWaitForFinished(reply));
- const int elapsedTime = loopTime.elapsed();
+ const int elapsedTime = loopTimer.elapsed();
server.wait();
reader.wrapUp();
@@ -5440,12 +5448,12 @@ void tst_QNetworkReply::rateControl()
RateControlledReader reader(sender, reply.data(), rate, 20);
// this test is designed to run for 25 seconds at most
- QTime loopTime;
- loopTime.start();
+ QElapsedTimer loopTimer;
+ loopTimer.start();
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
- int elapsedTime = loopTime.elapsed();
+ int elapsedTime = loopTimer.elapsed();
if (!errorSpy.isEmpty()) {
qDebug() << "ERROR!" << errorSpy[0][0] << reply->errorString();
@@ -6115,8 +6123,8 @@ void tst_QNetworkReply::httpConnectionCount()
}
int pendingConnectionCount = 0;
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
while(pendingConnectionCount <= 20) {
QTestEventLoop::instance().enterLoop(1);
@@ -6128,7 +6136,7 @@ void tst_QNetworkReply::httpConnectionCount()
}
// at max. wait 10 sec
- if (time.elapsed() > 10000)
+ if (timer.elapsed() > 10000)
break;
}
@@ -6418,7 +6426,8 @@ void tst_QNetworkReply::abortOnEncrypted()
QSKIP("Server fails to listen. Skipping since QTcpServer is covered in another test.");
server.connect(&server, &SslServer::newEncryptedConnection, [&server]() {
- connect(server.socket, &QTcpSocket::readyRead, server.socket, []() {
+ // MSVC 201X C4573-misunderstands connect() or QObject::connect(), so use server.connect():
+ server.connect(server.socket, &QTcpSocket::readyRead, server.socket, []() {
// This slot must not be invoked!
QVERIFY(false);
});
@@ -6466,8 +6475,8 @@ void tst_QNetworkReply::sslSessionSharing_data()
void tst_QNetworkReply::sslSessionSharing()
{
-#ifdef QT_SECURETRANSPORT
- QSKIP("Not implemented with SecureTransport");
+#if QT_CONFIG(schannel) || defined(QT_SECURETRANSPORT)
+ QSKIP("Not implemented with SecureTransport/Schannel");
#endif
QString urlString("https://" + QtNetworkSettings::httpServerName());
@@ -6534,8 +6543,8 @@ void tst_QNetworkReply::sslSessionSharingFromPersistentSession_data()
void tst_QNetworkReply::sslSessionSharingFromPersistentSession()
{
-#ifdef QT_SECURETRANSPORT
- QSKIP("Not implemented with SecureTransport");
+#if QT_CONFIG(schannel) || defined(QT_SECURETRANSPORT)
+ QSKIP("Not implemented with SecureTransport/Schannel");
#endif
QString urlString("https://" + QtNetworkSettings::httpServerName());
@@ -7905,9 +7914,10 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
"Content-Type: text/plain\r\n"
"\r\n"
"auth";
- QRegExp rx("Authorization: Basic ([^\r\n]*)\r\n");
- if (rx.indexIn(receivedData) > 0) {
- if (QByteArray::fromBase64(rx.cap(1).toLatin1()) == "login:password") {
+ QRegularExpression rx("Authorization: Basic ([^\r\n]*)\r\n");
+ QRegularExpressionMatch match = rx.match(receivedData);
+ if (match.hasMatch()) {
+ if (QByteArray::fromBase64(match.captured(1).toLatin1()) == "login:password") {
dataToTransmit =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/plain\r\n"
@@ -8143,16 +8153,17 @@ void tst_QNetworkReply::backgroundRequest()
SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
- const QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
- QVERIFY(session);
- QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::UsagePolicies(policy));
+ const QWeakPointer<const QNetworkSession> sessionWeakPtr = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
+ QVERIFY(!sessionWeakPtr.isNull());
+ auto session = const_cast<QNetworkSession *>(sessionWeakPtr.toStrongRef().data());
+ QNetworkSession::UsagePolicies original = session->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*session, QNetworkSession::UsagePolicies(policy));
QNetworkReplyPtr reply(manager.get(request));
QVERIFY(waitForFinish(reply) != Timeout);
if (session)
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+ QNetworkSessionPrivate::setUsagePolicies(*session, original);
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), error);
@@ -8190,6 +8201,9 @@ void tst_QNetworkReply::backgroundRequestInterruption_data()
void tst_QNetworkReply::backgroundRequestInterruption()
{
#ifndef QT_NO_BEARERMANAGEMENT
+ if (QNetworkStatusMonitor::isEnabled() && QByteArray(QTest::currentDataTag()).startsWith("http"))
+ QSKIP("This test (currently) doesn't make any sense when QNetworkStatusMonitor is enabled");
+
QFETCH(QUrl, url);
QFETCH(bool, background);
QFETCH(QNetworkReply::NetworkError, error);
@@ -8207,10 +8221,11 @@ void tst_QNetworkReply::backgroundRequestInterruption()
SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
- const QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
- QVERIFY(session);
- QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoPolicy);
+ const QWeakPointer<const QNetworkSession> sessionWeakPtr = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
+ QVERIFY(!sessionWeakPtr.isNull());
+ auto session = const_cast<QNetworkSession *>(sessionWeakPtr.toStrongRef().data());
+ QNetworkSession::UsagePolicies original = session->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*session, QNetworkSession::NoPolicy);
request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 8192);
QNetworkReplyPtr reply(manager.get(request));
@@ -8219,14 +8234,14 @@ void tst_QNetworkReply::backgroundRequestInterruption()
QSignalSpy spy(reply.data(), SIGNAL(readyRead()));
QTRY_VERIFY(spy.count() > 0);
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoBackgroundTrafficPolicy);
+ QNetworkSessionPrivate::setUsagePolicies(*session, QNetworkSession::NoBackgroundTrafficPolicy);
// After we have changed the policy we can download at full speed.
reply->setReadBufferSize(0);
QVERIFY(waitForFinish(reply) != Timeout);
if (session)
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+ QNetworkSessionPrivate::setUsagePolicies(*session, original);
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), error);
@@ -8266,8 +8281,8 @@ void tst_QNetworkReply::backgroundRequestConnectInBackground()
QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
//force QNAM to reopen the session.
- if (session && session.data()->isOpen()) {
- const_cast<QNetworkSession *>(session.data())->close();
+ if (session && session.toStrongRef().data()->isOpen()) {
+ const_cast<QNetworkSession *>(session.toStrongRef().data())->close();
QCoreApplication::processEvents(); //let signals propagate inside QNAM
}
@@ -8276,19 +8291,19 @@ void tst_QNetworkReply::backgroundRequestConnectInBackground()
session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
QVERIFY(session);
- QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoPolicy);
+ QNetworkSession::UsagePolicies original = session.toStrongRef().data()->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.toStrongRef().data()), QNetworkSession::NoPolicy);
QNetworkReplyPtr reply(manager.get(request));
QVERIFY(waitForFinish(reply) != Timeout);
session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
if (session) {
- QVariant cib = session.data()->sessionProperty(QStringLiteral("ConnectInBackground"));
+ QVariant cib = session.toStrongRef().data()->sessionProperty(QStringLiteral("ConnectInBackground"));
if (!cib.isValid())
QSKIP("inconclusive - ConnectInBackground session property not supported by the bearer plugin");
QCOMPARE(cib.toBool(), background);
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.toStrongRef().data()), original);
} else {
QSKIP("inconclusive - network session has been destroyed");
}
@@ -9167,6 +9182,166 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
#endif
+void tst_QNetworkReply::autoDeleteRepliesAttribute_data()
+{
+ QTest::addColumn<QUrl>("destination");
+
+ QTest::newRow("http") << QUrl("http://QInvalidDomain.qt/test");
+ QTest::newRow("https") << QUrl("https://QInvalidDomain.qt/test");
+ QTest::newRow("ftp") << QUrl("ftp://QInvalidDomain.qt/test");
+ QTest::newRow("file") << QUrl("file:///thisfolderdoesn'texist/probably.txt");
+#ifdef Q_OS_WIN
+ // Only supported on windows.
+ QTest::newRow("remote-file") << QUrl("file://QInvalidHost/thisfolderdoesn'texist/probably.txt");
+#endif
+ QTest::newRow("qrc") << QUrl("qrc:///path/to/nowhere");
+ QTest::newRow("data") << QUrl("data:,Some%20plaintext%20data");
+}
+
+void tst_QNetworkReply::autoDeleteRepliesAttribute()
+{
+ QFETCH(QUrl, destination);
+ {
+ // Get
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true);
+ QNetworkReply *reply = manager.get(request);
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true);
+ QNetworkReply *reply = manager.post(request, QByteArrayLiteral("datastring"));
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ // Now repeated, but without the attribute to make sure it does not get deleted automatically.
+ // We need two calls to processEvents to test that the QNetworkReply doesn't get deleted.
+ // The first call executes a metacall event which adds the deleteLater meta event which
+ // would be executed in the second call. But that shouldn't happen without the attribute.
+ {
+ // Get
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring")));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+}
+
+void tst_QNetworkReply::autoDeleteReplies_data()
+{
+ autoDeleteRepliesAttribute_data();
+}
+
+void tst_QNetworkReply::autoDeleteReplies()
+{
+ QFETCH(QUrl, destination);
+ manager.setAutoDeleteReplies(true);
+ auto cleanup = qScopeGuard([this] { manager.setAutoDeleteReplies(false); });
+ {
+ // Get
+ QNetworkRequest request(destination);
+ QNetworkReply *reply = manager.get(request);
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ QNetworkReply *reply = manager.post(request, QByteArrayLiteral("datastring"));
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ // Here we repeat the test, but override the auto-deletion in the QNetworkRequest
+ // We need two calls to processEvents to test that the QNetworkReply doesn't get deleted.
+ // The first call executes a metacall event which adds the deleteLater meta event which
+ // would be executed in the second call. But that shouldn't happen in this case.
+ {
+ // Get
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false);
+ QScopedPointer<QNetworkReply> reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false);
+ QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring")));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ // Now we repeat the test with autoDeleteReplies set to false
+ cleanup.dismiss();
+ manager.setAutoDeleteReplies(false);
+ {
+ // Get
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring")));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+}
+
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
{
diff --git a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
index 7a3def410a..6637be0174 100644
--- a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
+++ b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
@@ -41,6 +41,7 @@ class tst_QNetworkRequest: public QObject
private slots:
void ctor_data();
void ctor();
+ void implicitDefaultCtor();
void setUrl_data();
void setUrl();
void setRawHeader_data();
@@ -78,6 +79,12 @@ void tst_QNetworkRequest::ctor()
}
}
+void tst_QNetworkRequest::implicitDefaultCtor()
+{
+ QNetworkRequest r = {};
+ Q_UNUSED(r);
+}
+
void tst_QNetworkRequest::setUrl_data()
{
ctor_data();
diff --git a/tests/auto/network/access/spdy/BLACKLIST b/tests/auto/network/access/spdy/BLACKLIST
index b13eae1000..5cf79327be 100644
--- a/tests/auto/network/access/spdy/BLACKLIST
+++ b/tests/auto/network/access/spdy/BLACKLIST
@@ -1,4 +1,7 @@
[download]
-linux
+opensuse-leap
[upload]
-linux
+opensuse-leap
+ubuntu-18.04
+b2qt
+
diff --git a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
index 55053842dc..8cef351554 100644
--- a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
+++ b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
@@ -93,7 +93,7 @@ void tst_QAuthenticator::basicAuth()
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
- QCOMPARE(priv->calculateResponse("GET", "/").constData(), QByteArray("Basic " + expectedReply).constData());
+ QCOMPARE(priv->calculateResponse("GET", "/", "").constData(), QByteArray("Basic " + expectedReply).constData());
}
void tst_QAuthenticator::ntlmAuth_data()
@@ -133,9 +133,9 @@ void tst_QAuthenticator::ntlmAuth()
headers << qMakePair<QByteArray, QByteArray>("WWW-Authenticate", "NTLM");
priv->parseHttpResponse(headers, /*isProxy = */ false);
if (sso)
- QVERIFY(priv->calculateResponse("GET", "/").startsWith("NTLM "));
+ QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
else
- QCOMPARE(priv->calculateResponse("GET", "/").constData(), "NTLM TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAA=");
+ QCOMPARE(priv->calculateResponse("GET", "/", "").constData(), "NTLM TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAA=");
// NTLM phase 2: challenge
headers.clear();
@@ -146,7 +146,7 @@ void tst_QAuthenticator::ntlmAuth()
QEXPECT_FAIL("with-realm-sso", "NTLM authentication code doesn't extract the realm", Continue);
QCOMPARE(auth.realm(), realm);
- QVERIFY(priv->calculateResponse("GET", "/").startsWith("NTLM "));
+ QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
}
void tst_QAuthenticator::equalityOperators()
diff --git a/tests/auto/network/kernel/qdnslookup/BLACKLIST b/tests/auto/network/kernel/qdnslookup/BLACKLIST
index edf6436384..f07a8ce9a3 100644
--- a/tests/auto/network/kernel/qdnslookup/BLACKLIST
+++ b/tests/auto/network/kernel/qdnslookup/BLACKLIST
@@ -1,2 +1,2 @@
[lookup]
-ci
+*
diff --git a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro
index b5d6ea6459..d170d879e6 100644
--- a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro
+++ b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro
@@ -4,4 +4,4 @@ SOURCES += tst_qhostaddress.cpp
QT = core network-private testlib
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
index 224e4d61a9..48f05a4604 100644
--- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
+++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
@@ -375,11 +375,14 @@ QT_WARNING_DISABLE_DEPRECATED
void tst_QHostAddress::assignment()
{
QHostAddress address;
+
+#if QT_DEPRECATED_SINCE(5, 8)
address = "127.0.0.1";
QCOMPARE(address, QHostAddress("127.0.0.1"));
address = "::1";
QCOMPARE(address, QHostAddress("::1"));
+#endif
// WinRT does not support sockaddr_in
#ifndef Q_OS_WINRT
diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro
index 3d8457dd46..d358cdf52c 100644
--- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro
+++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro
@@ -6,6 +6,6 @@ SOURCES += tst_qhostinfo.cpp
requires(qtConfig(private_tests))
QT = core-private network-private testlib
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
winrt: WINRT_MANIFEST.capabilities += internetClientServer
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index 7640d52583..a603b2d879 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -180,7 +180,6 @@ void tst_QHostInfo::staticInformation()
void tst_QHostInfo::initTestCase()
{
- QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
#ifndef QT_NO_BEARERMANAGEMENT
//start the default network
netConfMan = new QNetworkConfigurationManager(this);
@@ -241,8 +240,6 @@ void tst_QHostInfo::lookupIPv4_data()
QTest::addColumn<QString>("addresses");
QTest::addColumn<int>("err");
- // Test server lookup
- QTest::newRow("lookup_01") << QtNetworkSettings::serverName() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError);
QTest::newRow("empty") << "" << "" << int(QHostInfo::HostNotFound);
QTest::newRow("single_ip4") << "a-single" TEST_DOMAIN << "192.0.2.1" << int(QHostInfo::NoError);
diff --git a/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp b/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
index 5eedd1043b..cd6019090f 100644
--- a/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
+++ b/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
@@ -131,7 +131,7 @@ void tst_QNetworkDatagram::makeReply()
QNetworkDatagram copy = dgram;
copy.setData(copy.data());
{
- QNetworkDatagram reply = qMove(copy).makeReply("World");
+ QNetworkDatagram reply = std::move(copy).makeReply("World");
QCOMPARE(reply.data(), QByteArray("World"));
QCOMPARE(reply.senderAddress(), QHostAddress(localAddress));
QCOMPARE(reply.senderPort(), localAddress.isEmpty() ? -1 : dgram.destinationPort());
diff --git a/tests/auto/network/socket/platformsocketengine/BLACKLIST b/tests/auto/network/socket/platformsocketengine/BLACKLIST
index 8e1a55995e..f1f88d26d1 100644
--- a/tests/auto/network/socket/platformsocketengine/BLACKLIST
+++ b/tests/auto/network/socket/platformsocketengine/BLACKLIST
@@ -1 +1,11 @@
+[tcpLoopbackPerformance]
+windows-10 msvc-2015
+windows-7sp1
+[receiveUrgentData]
+windows-10 msvc-2015
+windows-7sp1
+[serverTest]
+windows-10 msvc-2015
+windows-7sp1
+[tcpLoopbackPerformance]
windows
diff --git a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri
index 46c722deba..868439de6a 100644
--- a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri
+++ b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri
@@ -4,7 +4,7 @@ QNETWORK_SRC = $$QT_SOURCE_TREE/src/network
INCLUDEPATH += $$QNETWORK_SRC
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
unix:qtConfig(reduce_exports) {
SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine_unix.cpp
diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
index 01168cc0d6..ffc63ee46a 100644
--- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
+++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
@@ -32,7 +32,7 @@
#include <qcoreapplication.h>
#include <qdatastream.h>
#include <qhostaddress.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#ifdef Q_OS_UNIX
#include <unistd.h>
@@ -403,7 +403,7 @@ void tst_PlatformSocketEngine::udpLoopbackPerformance()
QHostAddress localhost = QHostAddress::LocalHost;
qlonglong readBytes = 0;
- QTime timer;
+ QElapsedTimer timer;
timer.start();
while (timer.elapsed() < 5000) {
udpSocket2.write(message1.data(), message1.size());
@@ -462,7 +462,7 @@ void tst_PlatformSocketEngine::tcpLoopbackPerformance()
QByteArray message1(messageSize, '@');
QByteArray answer(messageSize, '@');
- QTime timer;
+ QElapsedTimer timer;
timer.start();
qlonglong readBytes = 0;
while (timer.elapsed() < 5000) {
diff --git a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
index 8e1a55995e..ceb3b7862e 100644
--- a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
+++ b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
@@ -1 +1,5 @@
+[downloadBigFile]
+windows-10 msvc-2015
+windows-7sp1
+[ensureEofTriggersNotification]
windows
diff --git a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro
index 56a4fb8aee..63f41f4eb7 100644
--- a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro
+++ b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro
@@ -10,3 +10,8 @@ MOC_DIR=tmp
requires(qtConfig(private_tests))
QT = core-private network-private testlib
+# TODO: For now linux-only, because cyrus is linux-only atm ...
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted cyrus apache2
+}
diff --git a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
index 68f3ea059b..64241014d7 100644
--- a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
+++ b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
@@ -38,6 +38,7 @@
#include <qhostaddress.h>
#include <qtcpsocket.h>
#include <qdebug.h>
+#include <qelapsedtimer.h>
#include <qtcpserver.h>
#include "../../../network-settings.h"
@@ -122,7 +123,14 @@ public slots:
void tst_QHttpSocketEngine::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
void tst_QHttpSocketEngine::init()
@@ -171,7 +179,7 @@ void tst_QHttpSocketEngine::errorTest_data()
QTest::newRow("proxy-host-not-found") << "this-host-does-not-exist." << 1080 << QString()
<< QString()
<< int(QAbstractSocket::ProxyNotFoundError);
- QTest::newRow("proxy-connection-refused") << QtNetworkSettings::serverName() << 2 << QString()
+ QTest::newRow("proxy-connection-refused") << QtNetworkSettings::socksProxyServerName() << 2 << QString()
<< QString()
<< int(QAbstractSocket::ProxyConnectionRefusedError);
@@ -278,13 +286,12 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
-
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
QVERIFY(!socketDevice.localAddress().isNull());
QVERIFY(socketDevice.localPort() > 0);
@@ -292,10 +299,10 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
QVERIFY(socketDevice.waitForRead());
// Read the greeting
- qint64 available = socketDevice.bytesAvailable();
+ qint64 available = int(socketDevice.bytesAvailable());
QVERIFY(available > 0);
QByteArray array;
- array.resize(available);
+ array.resize(int(available));
QVERIFY(socketDevice.read(array.data(), array.size()) == available);
// Check that the greeting is what we expect it to be
@@ -310,9 +317,9 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
// Wait for the response
QVERIFY(socketDevice.waitForRead());
- available = socketDevice.bytesAvailable();
+ available = int(socketDevice.bytesAvailable());
QVERIFY(available > 0);
- array.resize(available);
+ array.resize(int(available));
QVERIFY(socketDevice.read(array.data(), array.size()) == available);
// Check that the greeting is what we expect it to be
@@ -321,7 +328,7 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
// Wait for the response
QVERIFY(socketDevice.waitForRead());
char c;
- QCOMPARE(socketDevice.read(&c, sizeof(c)), (qint64) -1);
+ QCOMPARE(socketDevice.read(&c, sizeof(c)), qint64(-1));
QCOMPARE(socketDevice.error(), QAbstractSocket::RemoteHostClosedError);
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
}
@@ -335,10 +342,10 @@ void tst_QHttpSocketEngine::simpleErrorsAndStates()
// Initialize device
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- QVERIFY(!socketDevice.connectToHost(QHostAddress(QtNetworkSettings::serverName()), 8088));
+ QVERIFY(!socketDevice.connectToHost(QHostAddress(QtNetworkSettings::socksProxyServerName()), 8088));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
if (socketDevice.waitForWrite(30000)) {
QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState ||
@@ -391,7 +398,7 @@ void tst_QHttpSocketEngine::tcpLoopbackPerformance()
QByteArray message1(messageSize, '@');
QByteArray answer(messageSize, '@');
- QTime timer;
+ QElapsedTimer timer;
timer.start();
qlonglong readBytes = 0;
while (timer.elapsed() < 30000) {
@@ -422,7 +429,7 @@ void tst_QHttpSocketEngine::tcpSocketBlockingTest()
QTcpSocket socket;
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.waitForConnected());
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
@@ -479,7 +486,7 @@ void tst_QHttpSocketEngine::tcpSocketNonBlockingTest()
tcpSocketNonBlocking_socket = &socket;
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.state() == QTcpSocket::HostLookupState ||
socket.state() == QTcpSocket::ConnectingState);
@@ -607,13 +614,13 @@ void tst_QHttpSocketEngine::downloadBigFile()
connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
- tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
+ tmpSocket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QTestEventLoop::instance().enterLoop(30);
if (QTestEventLoop::instance().timeout())
QFAIL("Network operation timed out");
- QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
+ QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
QVERIFY(tmpSocket->write("Host: ") > 0);
@@ -623,7 +630,7 @@ void tst_QHttpSocketEngine::downloadBigFile()
bytesAvailable = 0;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
QTestEventLoop::instance().enterLoop(60);
@@ -664,13 +671,13 @@ void tst_QHttpSocketEngine::passwordAuth()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128, "qsockstest", "password"));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128, "qsockstest", "password"));
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
// Wait for the greeting
QVERIFY(socketDevice.waitForRead());
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 45ab275510..732f7eef00 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -32,6 +32,7 @@
#include <qtextstream.h>
#include <qdatastream.h>
+#include <qelapsedtimer.h>
#include <QtNetwork/qlocalsocket.h>
#include <QtNetwork/qlocalserver.h>
@@ -552,7 +553,7 @@ void tst_QLocalSocket::sendData()
QCOMPARE(serverSocket->state(), QLocalSocket::ConnectedState);
QTextStream out(serverSocket);
QTextStream in(&socket);
- out << testLine << endl;
+ out << testLine << Qt::endl;
bool wrote = serverSocket->waitForBytesWritten(3000);
if (!socket.canReadLine()) {
@@ -877,7 +878,7 @@ public:
QLocalSocket *serverSocket = server.nextPendingConnection();
QVERIFY(serverSocket);
QTextStream out(serverSocket);
- out << testLine << endl;
+ out << testLine << Qt::endl;
QCOMPARE(serverSocket->state(), QLocalSocket::ConnectedState);
QVERIFY2(serverSocket->waitForBytesWritten(), serverSocket->errorString().toLatin1().constData());
QCOMPARE(serverSocket->errorString(), QString("Unknown error"));
@@ -1031,7 +1032,7 @@ void tst_QLocalSocket::waitForDisconnect()
QLocalSocket *serverSocket = server.nextPendingConnection();
QVERIFY(serverSocket);
socket.disconnectFromServer();
- QTime timer;
+ QElapsedTimer timer;
timer.start();
QVERIFY(serverSocket->waitForDisconnected(3000));
QVERIFY(timer.elapsed() < 2000);
diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
index 60526827bf..61fff6ee00 100644
--- a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
+++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
@@ -1,8 +1,11 @@
[udpTest]
*
[passwordAuth]
-*
-[serverTest]
-windows
+ubuntu-18.04
+# QTBUG-74162
+[passwordAuth2]
+ubuntu
[downloadBigFile]
-windows
+windows-10 msvc-2015
+windows-7sp1
+
diff --git a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro
index 71ceafa133..243eab9480 100644
--- a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro
+++ b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro
@@ -11,3 +11,9 @@ MOC_DIR=tmp
QT = core-private network-private testlib
requires(qtConfig(private_tests))
+
+# Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted apache2 cyrus
+}
diff --git a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
index 1212ea20e5..464054f8a6 100644
--- a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
+++ b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
@@ -137,7 +137,13 @@ private slots:
void tst_QSocks5SocketEngine::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
//---------------------------------------------------------------------------
@@ -293,13 +299,13 @@ void tst_QSocks5SocketEngine::simpleConnectToIMAP()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
// Wait for the greeting
QVERIFY(socketDevice.waitForRead());
@@ -347,10 +353,10 @@ void tst_QSocks5SocketEngine::simpleErrorsAndStates()
// Initialize device
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- QVERIFY(!socketDevice.connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(), 8088));
+ QVERIFY(!socketDevice.connectToHost(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().first(), 8088));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
if (socketDevice.waitForWrite(15000)) {
QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState ||
@@ -433,7 +439,7 @@ void tst_QSocks5SocketEngine::serverTest()
// Initialize a Tcp socket
QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
- QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
server.setProxy(proxy);
@@ -510,7 +516,7 @@ void tst_QSocks5SocketEngine::udpTest()
QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
QVERIFY(udpSocket.isValid());
- QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
udpSocket.setProxy(proxy);
@@ -564,7 +570,7 @@ void tst_QSocks5SocketEngine::tcpSocketBlockingTest()
QTcpSocket socket;
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.waitForConnected());
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
@@ -635,7 +641,7 @@ void tst_QSocks5SocketEngine::tcpSocketNonBlockingTest()
});
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.state() == QTcpSocket::HostLookupState ||
socket.state() == QTcpSocket::ConnectingState);
@@ -754,13 +760,13 @@ void tst_QSocks5SocketEngine::downloadBigFile()
<< " (" << stopWatch.elapsed() << "ms)";
});
- socket.connectToHost(QtNetworkSettings::serverName(), 80);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 80);
QTestEventLoop::instance().enterLoop(30);
if (QTestEventLoop::instance().timeout())
QFAIL("Network operation timed out");
- QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
+ QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
QVERIFY(socket.write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
QVERIFY(socket.write("HOST: ") > 0);
@@ -791,13 +797,13 @@ void tst_QSocks5SocketEngine::passwordAuth()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080, "qsockstest", "password"));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080, "qsockstest", "password"));
// Connect to imap.trolltech.com's IP
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
- if (!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143)) {
+ if (!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143)) {
qDebug("%d, %s", socketDevice.error(), socketDevice.errorString().toLatin1().constData());
}
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
@@ -857,19 +863,19 @@ void tst_QSocks5SocketEngine::passwordAuth2()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081));
socketDevice.setReceiver(this);
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
while (socketDevice.state() == QAbstractSocket::ConnectingState) {
QVERIFY(socketDevice.waitForWrite());
- socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143);
+ socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143);
}
if (socketDevice.state() != QAbstractSocket::ConnectedState)
qDebug("%d, %s", socketDevice.error(), socketDevice.errorString().toLatin1().constData());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
// Wait for the greeting
QVERIFY(socketDevice.waitForRead());
diff --git a/tests/auto/network/socket/qtcpserver/BLACKLIST b/tests/auto/network/socket/qtcpserver/BLACKLIST
index f8b61808cc..e268468bdb 100644
--- a/tests/auto/network/socket/qtcpserver/BLACKLIST
+++ b/tests/auto/network/socket/qtcpserver/BLACKLIST
@@ -1,13 +1,16 @@
-windows
-[linkLocal]
-linux
[listenWhileListening:WithSocks5Proxy]
linux
windows
+[ipv6Server]
+windows-7sp1
+windows-10 msvc-2017
[ipv6Server:WithoutProxy]
windows
osx
-[clientServerLoop:WithSocks5Proxy]
-linux
-[crashTests:WithSocks5Proxy]
-linux
+[eagainBlockingAccept]
+windows-7sp1
+windows-10
+[serverAddress]
+windows-7sp1
+windows-10
+
diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
index 1a8e7920d3..5c66ef6520 100644
--- a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
+++ b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
@@ -29,14 +29,14 @@
#include <QtCore>
#include <QtNetwork>
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
# include <crtdbg.h>
#endif
int main(int argc, char *argv[])
{
// Windows: Suppress crash notification dialog.
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif
QCoreApplication app(argc, argv);
diff --git a/tests/auto/network/socket/qtcpserver/test/test.pro b/tests/auto/network/socket/qtcpserver/test/test.pro
index 4491523383..7e2e60a1e3 100644
--- a/tests/auto/network/socket/qtcpserver/test/test.pro
+++ b/tests/auto/network/socket/qtcpserver/test/test.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
SOURCES += ../tst_qtcpserver.cpp
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
TARGET = ../tst_qtcpserver
@@ -16,3 +16,9 @@ win32 {
QT = core network testlib
MOC_DIR=tmp
+
+# Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted cyrus squid ftp-proxy
+}
diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
index 161d94d642..849d8b0ed1 100644
--- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
+++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
@@ -160,8 +160,15 @@ void tst_QTcpServer::initTestCase_data()
void tst_QTcpServer::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
#ifndef QT_NO_BEARERMANAGEMENT
QNetworkConfigurationManager man;
networkSession = new QNetworkSession(man.defaultConfiguration(), this);
@@ -177,7 +184,7 @@ void tst_QTcpServer::init()
#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(int, proxyType);
if (proxyType == QNetworkProxy::Socks5Proxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
}
#else // !QT_NO_NETWORKPROXY
QSKIP("No proxy support");
@@ -513,7 +520,7 @@ void tst_QTcpServer::waitForConnectionTest()
}
QTcpSocket findLocalIpSocket;
- findLocalIpSocket.connectToHost(QtNetworkSettings::serverName(), 143);
+ findLocalIpSocket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(findLocalIpSocket.waitForConnected(5000));
QTcpServer server;
@@ -668,16 +675,18 @@ void tst_QTcpServer::invalidProxy_data()
QTest::addColumn<int>("port");
QTest::addColumn<int>("expectedError");
- QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
- QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 143
+ const QString imapIp = QtNetworkSettings::imapServerIp().toString();
+ const QString httpProxyIp = QtNetworkSettings::httpProxyServerIp().toString();
+ const QString socksIp = QtNetworkSettings::socksProxyServerIp().toString();
+ QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << imapIp << 143
<< int(QAbstractSocket::UnsupportedSocketOperationError);
- QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << fluke << 3128
+ QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << httpProxyIp << 3128
<< int(QAbstractSocket::UnsupportedSocketOperationError);
QTest::newRow("no-such-host") << int(QNetworkProxy::Socks5Proxy)
<< "invalid.test.qt-project.org" << 1080
<< int(QAbstractSocket::ProxyNotFoundError);
- QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128
+ QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << httpProxyIp << 3128
<< int(QAbstractSocket::SocketTimeoutError);
}
@@ -740,48 +749,48 @@ void tst_QTcpServer::proxyFactory_data()
// tests that do get to listen
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
QTest::newRow("socks5")
<< proxyList << proxyList.at(0)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
QTest::newRow("cachinghttp+socks5")
<< proxyList << proxyList.at(1)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
QTest::newRow("ftp+cachinghttp+socks5")
<< proxyList << proxyList.at(2)
<< false << int(QAbstractSocket::UnknownSocketError);
// tests that fail to listen
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128);
QTest::newRow("http")
<< proxyList << proxyList.at(0)
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128);
QTest::newRow("cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128);
QTest::newRow("ftp+cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
@@ -872,11 +881,6 @@ void tst_QTcpServer::serverAddress_data()
{
QTest::addColumn<QHostAddress>("listenAddress");
QTest::addColumn<QHostAddress>("serverAddress");
-#ifdef Q_OS_WIN
- if (QSysInfo::windowsVersion() < QSysInfo::WV_6_0)
- QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4); //windows XP doesn't support dual stack sockets
- else
-#endif
if (QtNetworkSettings::hasIPv6())
QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::Any);
else
diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST
index d724897b74..07532710b3 100644
--- a/tests/auto/network/socket/qtcpsocket/BLACKLIST
+++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST
@@ -1,13 +1,11 @@
-[bindThenResolveHost:first-fail]
-windows
+[bind]
+windows-10 msvc-2015
+windows-7sp1
[bind:[::]]
windows
[bind:[::]:randomport]
windows
-[invalidProxy:socks5-on-http]
-windows
[timeoutConnect:ip]
windows
# QTBUG-66247
-[taskQtBug5799ConnectionErrorEventLoop]
-windows
+
diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro
index 337e75b372..4c07b1ec66 100644
--- a/tests/auto/network/socket/qtcpsocket/test/test.pro
+++ b/tests/auto/network/socket/qtcpsocket/test/test.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
QT = core-private network-private testlib
SOURCES += ../tst_qtcpsocket.cpp
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
TARGET = tst_qtcpsocket
win32 {
@@ -15,3 +15,9 @@ win32 {
} else {
DESTDIR = ../
}
+
+# Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted squid apache2 ftp-proxy vsftpd iptables cyrus
+}
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index 10b09629bc..75b9b23259 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -66,7 +66,7 @@
#endif
#include <QTextStream>
#include <QThread>
-#include <QTime>
+#include <QElapsedTimer>
#include <QTimer>
#include <QDebug>
// RVCT compiles also unused inline methods
@@ -236,7 +236,6 @@ private:
qint64 bytesAvailable;
qint64 expectedLength;
bool readingBody;
- QTime timer;
QByteArray expectedReplyIMAP_cached;
@@ -316,7 +315,7 @@ tst_QTcpSocket::tst_QTcpSocket()
connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64)));
earlyConstructedSockets->endPoints[1]->write("hello work");
- firstFailInfo.setAddresses(QList<QHostAddress>() << QHostAddress("224.0.0.0") << QtNetworkSettings::serverIP());
+ firstFailInfo.setAddresses(QList<QHostAddress>() << QHostAddress("224.0.0.0") << QtNetworkSettings::httpServerIp());
}
void tst_QTcpSocket::initTestCase_data()
@@ -325,7 +324,6 @@ void tst_QTcpSocket::initTestCase_data()
QTest::addColumn<int>("proxyType");
QTest::addColumn<bool>("ssl");
- qDebug() << QtNetworkSettings::serverName();
QTest::newRow("WithoutProxy") << false << 0 << false;
QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false;
QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false;
@@ -351,7 +349,17 @@ void tst_QTcpSocket::initTestCase_data()
void tst_QTcpSocket::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+ //QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::firewallServerName(), 1357));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
void tst_QTcpSocket::init()
@@ -360,30 +368,33 @@ void tst_QTcpSocket::init()
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(int, proxyType);
- QList<QHostAddress> addresses = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses();
- QVERIFY2(addresses.count() > 0, "failed to get ip address for test server");
- QString fluke = addresses.first().toString();
+ QList<QHostAddress> socks5Addresses = QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses();
+ QList<QHostAddress> httpProxyAddresses = QHostInfo::fromName(QtNetworkSettings::httpProxyServerName()).addresses();
+ QVERIFY2(socks5Addresses.count() > 0, "failed to get ip address for SOCKS5 proxy server");
+ QVERIFY2(httpProxyAddresses.count() > 0, "failed to get ip address for HTTP proxy server");
+ QString socks5Address = socks5Addresses.first().toString();
+ QString httpProxyAddress = httpProxyAddresses.first().toString();
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socks5Address, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socks5Address, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddress, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddress, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddress, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
@@ -643,8 +654,8 @@ void tst_QTcpSocket::bind()
void tst_QTcpSocket::bindThenResolveHost_data()
{
QTest::addColumn<QString>("hostName");
- QTest::newRow("ip-literal") << QtNetworkSettings::serverIP().toString();
- QTest::newRow("name") << QtNetworkSettings::serverName();
+ QTest::newRow("ip-literal") << QtNetworkSettings::httpServerIp().toString();
+ QTest::newRow("name") << QtNetworkSettings::httpServerName();
QTest::newRow("first-fail") << firstFailName;
}
@@ -714,7 +725,7 @@ void tst_QTcpSocket::setSocketDescriptor()
#ifdef Q_OS_WIN
// need the dummy to ensure winsock is started
QTcpSocket *dummy = newSocket();
- dummy->connectToHost(QtNetworkSettings::serverName(), 143);
+ dummy->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(dummy->waitForConnected());
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -736,7 +747,7 @@ void tst_QTcpSocket::setSocketDescriptor()
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test.
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QCOMPARE(socket->state(), QTcpSocket::HostLookupState);
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
QVERIFY(socket->waitForConnected(10000));
@@ -757,7 +768,7 @@ void tst_QTcpSocket::socketDescriptor()
QTcpSocket *socket = newSocket();
QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
socket->state() == QAbstractSocket::ConnectingState);
QVERIFY(socket->waitForConnected(10000));
@@ -774,7 +785,7 @@ void tst_QTcpSocket::blockingIMAP()
QTcpSocket *socket = newSocket();
// Connect
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
QVERIFY(socket->isValid());
@@ -851,6 +862,15 @@ void tst_QTcpSocket::hostNotFound()
socket->connectToHost("nosuchserver.qt-project.org", 80);
QVERIFY(!socket->waitForConnected());
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
+#ifdef QT_TEST_SERVER
+ QFETCH_GLOBAL(bool, setProxy);
+ QFETCH_GLOBAL(int, proxyType);
+ if (setProxy && (proxyType & HttpProxy) == HttpProxy) {
+ QEXPECT_FAIL("", "QTBUG-73953: The version of Squid in the docker container behaves "
+ "differently to the one in the network testing server, returning 503 "
+ "when we expect 404", Continue);
+ }
+#endif
QCOMPARE(int(socket->error()), int(QTcpSocket::HostNotFoundError));
delete socket;
@@ -860,8 +880,8 @@ void tst_QTcpSocket::hostNotFound()
void tst_QTcpSocket::timeoutConnect_data()
{
QTest::addColumn<QString>("address");
- QTest::newRow("host") << QtNetworkSettings::serverName();
- QTest::newRow("ip") << QtNetworkSettings::serverIP().toString();
+ QTest::newRow("host") << QtNetworkSettings::firewallServerName();
+ QTest::newRow("ip") << QtNetworkSettings::firewallServerIp().toString();
}
void tst_QTcpSocket::timeoutConnect()
@@ -909,7 +929,7 @@ void tst_QTcpSocket::nonBlockingIMAP()
nonBlockingIMAP_socket = socket;
// Connect
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->state() == QTcpSocket::HostLookupState ||
socket->state() == QTcpSocket::ConnectingState);
@@ -1035,7 +1055,7 @@ void tst_QTcpSocket::delayedClose()
connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
enterLoop(30);
if (timeout())
@@ -1081,7 +1101,7 @@ QByteArray tst_QTcpSocket::expectedReplyIMAP()
void tst_QTcpSocket::fetchExpectedReplyIMAP()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
QVERIFY2(socket->state() == QTcpSocket::ConnectedState, qPrintable(socket->errorString()));
@@ -1100,7 +1120,7 @@ void tst_QTcpSocket::fetchExpectedReplyIMAP()
void tst_QTcpSocket::partialRead()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
char buf[512];
@@ -1124,7 +1144,7 @@ void tst_QTcpSocket::partialRead()
void tst_QTcpSocket::unget()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
char buf[512];
@@ -1161,7 +1181,7 @@ void tst_QTcpSocket::readRegularFile_readyRead()
void tst_QTcpSocket::readAllAfterClose()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
connect(socket, SIGNAL(readyRead()), SLOT(readRegularFile_readyRead()));
enterLoop(10);
if (timeout())
@@ -1201,7 +1221,7 @@ void tst_QTcpSocket::openCloseOpenClose()
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
socket->close();
}
@@ -1224,7 +1244,7 @@ void tst_QTcpSocket::connectDisconnectConnectDisconnect()
QCOMPARE(int(socket->peerPort()), 0);
QCOMPARE(socket->peerAddress(), QHostAddress());
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForReadyRead(10000));
QCOMPARE(QString::fromLatin1(socket->read(4)), QString("* OK"));
@@ -1428,7 +1448,7 @@ void tst_QTcpSocket::disconnectWhileLookingUp()
// just connect and disconnect, then make sure nothing weird happened
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 21);
+ socket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
// check that connect is in progress
QVERIFY(socket->state() != QAbstractSocket::UnconnectedState);
@@ -1476,7 +1496,7 @@ void tst_QTcpSocket::downloadBigFile()
connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
- tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
+ tmpSocket->connectToHost(QtNetworkSettings::httpServerName(), 80);
enterLoop(30);
if (timeout()) {
@@ -1485,7 +1505,7 @@ void tst_QTcpSocket::downloadBigFile()
QFAIL("Network operation timed out");
}
- QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
+ QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
QVERIFY(tmpSocket->write("HOST: ") > 0);
@@ -1497,7 +1517,7 @@ void tst_QTcpSocket::downloadBigFile()
expectedLength = 0;
readingBody = false;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
enterLoop(600);
@@ -1551,7 +1571,7 @@ void tst_QTcpSocket::downloadBigFileSlot()
void tst_QTcpSocket::readLine()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
while (!socket->canReadLine())
@@ -1600,7 +1620,7 @@ void tst_QTcpSocket::readLine()
void tst_QTcpSocket::readLineString()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForReadyRead(10000));
QByteArray arr = socket->readLine();
@@ -1613,7 +1633,7 @@ void tst_QTcpSocket::readLineString()
void tst_QTcpSocket::readChunks()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QVERIFY(socket->waitForReadyRead(5000));
@@ -1633,7 +1653,7 @@ void tst_QTcpSocket::readChunks()
void tst_QTcpSocket::waitForBytesWritten()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QVERIFY(socket->waitForConnected(10000));
socket->write("GET / HTTP/1.0\r\n\r\n");
@@ -1651,7 +1671,7 @@ void tst_QTcpSocket::waitForBytesWrittenMinusOne()
QSKIP("QTBUG-24451 - indefinite wait may hang");
#endif
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QVERIFY(socket->waitForConnected(10000));
socket->write("GET / HTTP/1.0\r\n\r\n");
@@ -1666,7 +1686,7 @@ void tst_QTcpSocket::waitForBytesWrittenMinusOne()
void tst_QTcpSocket::waitForReadyRead()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\n\r\n");
QVERIFY(socket->waitForReadyRead(5000));
delete socket;
@@ -1679,7 +1699,7 @@ void tst_QTcpSocket::waitForReadyReadMinusOne()
QSKIP("QTBUG-24451 - indefinite wait may hang");
#endif
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\n\r\n");
QVERIFY(socket->waitForReadyRead(-1));
delete socket;
@@ -1692,7 +1712,7 @@ void tst_QTcpSocket::flush()
socket->flush();
connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
enterLoop(60);
QVERIFY(socket->isOpen());
@@ -1709,7 +1729,7 @@ void tst_QTcpSocket::flush()
void tst_QTcpSocket::synchronousApi()
{
QTcpSocket *ftpSocket = newSocket();
- ftpSocket->connectToHost(QtNetworkSettings::serverName(), 21);
+ ftpSocket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
ftpSocket->write("QUIT\r\n");
QVERIFY(ftpSocket->waitForDisconnected(10000));
QVERIFY(ftpSocket->bytesAvailable() > 0);
@@ -1756,10 +1776,10 @@ void tst_QTcpSocket::recursiveReadyRead()
QSignalSpy spy(testSocket, SIGNAL(readyRead()));
- testSocket->connectToHost(QtNetworkSettings::serverName(), 143);
+ testSocket->connectToHost(QtNetworkSettings::imapServerName(), 143);
enterLoop(30);
QVERIFY2(!timeout(),
- "Timed out when connecting to QtNetworkSettings::serverName().");
+ "Timed out when connecting to QtNetworkSettings::imapServerName().");
enterLoop(30);
QVERIFY2(!timeout(),
@@ -1793,7 +1813,7 @@ void tst_QTcpSocket::recursiveReadyReadSlot()
void tst_QTcpSocket::atEnd()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 21);
+ socket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
QVERIFY(socket->waitForReadyRead(15000));
QTextStream stream(socket);
@@ -1801,9 +1821,15 @@ void tst_QTcpSocket::atEnd()
QString greeting = stream.readLine();
QVERIFY(stream.atEnd());
+#ifdef QT_TEST_SERVER
+ // Test server must use some vsFTPd 3.x.x version
+ QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 3.x.x)")-1, qPrintable(greeting));
+ QVERIFY2(greeting.startsWith("220 (vsFTPd 3."), qPrintable(greeting));
+#else
// Test server must use some vsFTPd 2.x.x version
QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
QVERIFY2(greeting.startsWith("220 (vsFTPd 2."), qPrintable(greeting));
+#endif
QVERIFY2(greeting.endsWith(QLatin1Char(')')), qPrintable(greeting));
delete socket;
@@ -1834,7 +1860,7 @@ protected:
connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), Qt::DirectConnection);
- socket->connectToHost(QtNetworkSettings::serverName(), 21);
+ socket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
socket->write("QUIT\r\n");
exec();
@@ -1908,7 +1934,7 @@ void tst_QTcpSocket::waitForReadyReadInASlot()
tmpSocket = socket;
connect(socket, SIGNAL(connected()), this, SLOT(waitForReadyReadInASlotSlot()));
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\n\r\n");
enterLoop(30);
@@ -2092,7 +2118,7 @@ void tst_QTcpSocket::waitForConnectedInHostLookupSlot()
timer.start(15000);
connect(tmpSocket, SIGNAL(hostFound()), this, SLOT(hostLookupSlot()));
- tmpSocket->connectToHost(QtNetworkSettings::serverName(), 143);
+ tmpSocket->connectToHost(QtNetworkSettings::imapServerName(), 143);
// only execute the loop if not already connected
if (tmpSocket->state() != QAbstractSocket::ConnectedState)
@@ -2147,7 +2173,7 @@ public slots:
inline void doIt()
{
attemptedToConnect = true;
- sock->connectToHost(QtNetworkSettings::serverName(), 80);
+ sock->connectToHost(QtNetworkSettings::httpServerName(), 80);
#if defined(Q_OS_MAC)
pthread_yield_np();
@@ -2198,7 +2224,7 @@ void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
// Connect
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
// Wait for the read
QVERIFY(socket->waitForReadyRead(10000));
@@ -2334,7 +2360,7 @@ void tst_QTcpSocket::localAddressEmptyOnBSD()
void tst_QTcpSocket::zeroAndMinusOneReturns()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
QVERIFY(socket->waitForReadyRead(15000));
@@ -2395,7 +2421,7 @@ void tst_QTcpSocket::connectionRefused()
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
&QTestEventLoop::instance(), SLOT(exitLoop()));
- socket->connectToHost(QtNetworkSettings::serverName(), 144);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 144);
enterLoop(10);
disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
@@ -2475,7 +2501,7 @@ void tst_QTcpSocket::suddenRemoteDisconnect()
QEventLoop loop;
connect(&serverProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
connect(&clientProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
QTimer::singleShot(20000, &loop, SLOT(quit()));
@@ -2515,7 +2541,7 @@ void tst_QTcpSocket::connectToMultiIP()
// rationale: this domain resolves to 3 A-records, 2 of them are
// invalid. QTcpSocket should never spend more than 30 seconds per IP, and
// 30s*2 = 60s.
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
socket->connectToHost("multi.dev.qt-project.org", 80);
QVERIFY(socket->waitForConnected(60500));
@@ -2542,7 +2568,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 1: Moved after connecting, before waiting for connection.
QTcpSocket *socket = newSocket();;
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
socket->moveToThread(0);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
@@ -2554,7 +2580,7 @@ void tst_QTcpSocket::moveToThread0()
// Case 2: Moved before connecting
QTcpSocket *socket = newSocket();
socket->moveToThread(0);
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
QVERIFY(socket->waitForBytesWritten(5000));
@@ -2564,7 +2590,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 3: Moved after writing, while waiting for bytes to be written.
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
socket->moveToThread(0);
@@ -2575,7 +2601,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 4: Moved after writing, while waiting for response.
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
QVERIFY(socket->waitForBytesWritten(5000));
@@ -2706,8 +2732,8 @@ void tst_QTcpSocket::taskQtBug5799ConnectionErrorWaitForConnected()
// use waitForConnected, e.g. this should use a synchronous select() on the OS level
QTcpSocket socket;
- socket.connectToHost(QtNetworkSettings::serverName(), 12346);
- QTime timer;
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 12346);
+ QElapsedTimer timer;
timer.start();
socket.waitForConnected(10000);
QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
@@ -2726,7 +2752,7 @@ void tst_QTcpSocket::taskQtBug5799ConnectionErrorEventLoop()
// This testcase uses an event loop
QTcpSocket socket;
connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
- socket.connectToHost(QtNetworkSettings::serverName(), 12346);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 12346);
QTestEventLoop::instance().enterLoop(10);
QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong");
@@ -2739,7 +2765,7 @@ void tst_QTcpSocket::taskQtBug7054TimeoutErrorResetting()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY(socket->waitForConnected(5*1000));
QCOMPARE(socket->error(), QAbstractSocket::UnknownSocketError);
@@ -2768,10 +2794,12 @@ void tst_QTcpSocket::invalidProxy_data()
QTest::addColumn<bool>("failsAtConnect");
QTest::addColumn<int>("expectedError");
- QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
- QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 21 << true
+ const QString ftpAddress = QtNetworkSettings::ftpServerIp().toString();
+ const QString httpProxyAddress = QtNetworkSettings::httpProxyServerIp().toString();
+ const QString socksProxyAddress = QtNetworkSettings::socksProxyServerIp().toString();
+ QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << ftpAddress << 21 << true
<< int(QAbstractSocket::UnsupportedSocketOperationError);
- QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << fluke << 3128 << true
+ QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << httpProxyAddress << 3128 << true
<< int(QAbstractSocket::UnsupportedSocketOperationError);
QTest::newRow("no-such-host-socks5") << int(QNetworkProxy::Socks5Proxy)
<< "this-host-will-never-exist.qt-project.org" << 1080 << false
@@ -2779,9 +2807,9 @@ void tst_QTcpSocket::invalidProxy_data()
QTest::newRow("no-such-host-http") << int(QNetworkProxy::HttpProxy)
<< "this-host-will-never-exist.qt-project.org" << 3128 << false
<< int(QAbstractSocket::ProxyNotFoundError);
- QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << fluke << 1080 << false
+ QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << socksProxyAddress << 1080 << false
<< int(QAbstractSocket::ProxyConnectionClosedError);
- QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128 << false
+ QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << httpProxyAddress << 3128 << false
<< int(QAbstractSocket::SocketTimeoutError);
}
@@ -2800,7 +2828,7 @@ void tst_QTcpSocket::invalidProxy()
QTcpSocket *socket = newSocket();
socket->setProxy(proxy);
- socket->connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerIp().toString(), 80);
if (failsAtConnect) {
QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
@@ -2852,48 +2880,48 @@ void tst_QTcpSocket::proxyFactory_data()
// tests that do connect
- proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("http")
<< proxyList << proxyList.at(0)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("socks5")
<< proxyList << proxyList.at(0)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("cachinghttp+socks5")
<< proxyList << proxyList.at(1)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("ftp+cachinghttp+socks5")
<< proxyList << proxyList.at(2)
<< false << int(QAbstractSocket::UnknownSocketError);
// tests that fail to connect
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("ftp+cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
@@ -2914,7 +2942,7 @@ void tst_QTcpSocket::proxyFactory()
QNetworkProxyFactory::setApplicationProxyFactory(factory);
QTcpSocket *socket = newSocket();
- QString host = QtNetworkSettings::serverName();
+ QString host = QtNetworkSettings::httpServerName();
socket->connectToHost(host, 80);
// Verify that the factory was called properly
diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST
index 0d56f6c827..bc6068d695 100644
--- a/tests/auto/network/socket/qudpsocket/BLACKLIST
+++ b/tests/auto/network/socket/qudpsocket/BLACKLIST
@@ -1,26 +1,10 @@
[writeDatagramToNonExistingPeer]
-windows
-osx
-[asyncReadDatagram]
-osx
-[multicastLeaveAfterClose]
-osx
-[readyRead]
-osx
+windows-10 msvc-2017
+windows-10 msvc-2015
+windows-7sp1
[readyReadForEmptyDatagram]
-osx
+opensuse-leap
[echo]
-linux
-osx
-[ipv6Loop]
-osx
-[loop]
-osx
-[broadcasting]
-osx
-[zeroLengthDatagram]
-osx
-[linkLocalIPv6]
-linux
+opensuse-42.3
[readyReadForEmptyDatagram]
linux
diff --git a/tests/auto/network/socket/qudpsocket/clientserver/main.cpp b/tests/auto/network/socket/qudpsocket/clientserver/main.cpp
index cc3e90671a..8172cd4f6f 100644
--- a/tests/auto/network/socket/qudpsocket/clientserver/main.cpp
+++ b/tests/auto/network/socket/qudpsocket/clientserver/main.cpp
@@ -54,7 +54,7 @@ public:
printf("ok\n");
break;
case UnconnectedClient:
- peerAddress = host;
+ peerAddress = QHostAddress(host);
peerPort = port;
if (bind(QHostAddress::Any, port + 1, ShareAddress | ReuseAddressHint)) {
startTimer(250);
diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro
index e856776ddc..969e4d72cf 100644
--- a/tests/auto/network/socket/qudpsocket/test/test.pro
+++ b/tests/auto/network/socket/qudpsocket/test/test.pro
@@ -17,3 +17,9 @@ win32 {
}
TARGET = tst_qudpsocket
+
+# Only on Linux until 'echo' has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted echo
+}
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
index 707c1acf48..0f419e9de4 100644
--- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
@@ -40,6 +40,7 @@
#include <qhostinfo.h>
#include <qtcpsocket.h>
#include <qmap.h>
+#include <qelapsedtimer.h>
#include <qnetworkdatagram.h>
#include <QNetworkProxy>
#include <QNetworkInterface>
@@ -235,6 +236,7 @@ void tst_QUdpSocket::initTestCase_data()
// hack: we only enable the Socks5 over UDP tests on the old
// test server, because they fail on the new one. See QTBUG-35490
bool newTestServer = true;
+#ifndef QT_TEST_SERVER
QTcpSocket socket;
socket.connectToHost(QtNetworkSettings::serverName(), 22);
if (socket.waitForConnected(10000)) {
@@ -244,6 +246,7 @@ void tst_QUdpSocket::initTestCase_data()
newTestServer = false;
socket.disconnectFromHost();
}
+#endif
QTest::addColumn<bool>("setProxy");
QTest::addColumn<int>("proxyType");
@@ -257,8 +260,13 @@ void tst_QUdpSocket::initTestCase_data()
void tst_QUdpSocket::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::echoServerName(), 7));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
allAddresses = QNetworkInterface::allAddresses();
m_skipUnsupportedIPv6Tests = shouldSkipIpv6TestsForBrokenSetsockopt();
@@ -300,7 +308,7 @@ void tst_QUdpSocket::init()
#if QT_CONFIG(socks5)
QFETCH_GLOBAL(int, proxyType);
if (proxyType == QNetworkProxy::Socks5Proxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
}
#else
QSKIP("No proxy support");
@@ -915,7 +923,7 @@ void tst_QUdpSocket::performance()
client.connectToHost(serverAddress, server.localPort());
QVERIFY(client.waitForConnected(10000));
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
qint64 nbytes = 0;
@@ -981,7 +989,7 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer_data()
QTest::addColumn<bool>("bind");
QTest::addColumn<QHostAddress>("peerAddress");
QHostAddress localhost(QHostAddress::LocalHost);
- QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses());
+ QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses());
if (serverAddresses.isEmpty())
return;
@@ -995,7 +1003,7 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer_data()
void tst_QUdpSocket::writeDatagramToNonExistingPeer()
{
- if (QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().isEmpty())
+ if (QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().isEmpty())
QFAIL("Could not find test server address");
QFETCH(bool, bind);
QFETCH(QHostAddress, peerAddress);
@@ -1015,7 +1023,7 @@ void tst_QUdpSocket::writeToNonExistingPeer_data()
{
QTest::addColumn<QHostAddress>("peerAddress");
QHostAddress localhost(QHostAddress::LocalHost);
- QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses());
+ QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses());
if (serverAddresses.isEmpty())
return;
@@ -1028,7 +1036,7 @@ void tst_QUdpSocket::writeToNonExistingPeer_data()
void tst_QUdpSocket::writeToNonExistingPeer()
{
QSKIP("Connected-mode UDP sockets and their behaviour are erratic");
- if (QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().isEmpty())
+ if (QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().isEmpty())
QFAIL("Could not find test server address");
QFETCH(QHostAddress, peerAddress);
quint16 peerPort = 34534;
@@ -1551,7 +1559,7 @@ void tst_QUdpSocket::echo_data()
void tst_QUdpSocket::echo()
{
QFETCH(bool, connect);
- QHostInfo info = QHostInfo::fromName(QtNetworkSettings::serverName());
+ QHostInfo info = QHostInfo::fromName(QtNetworkSettings::echoServerName());
QVERIFY(info.addresses().count());
QHostAddress remote = info.addresses().first();
diff --git a/tests/auto/network/ssl/qsslcertificate/BLACKLIST b/tests/auto/network/ssl/qsslcertificate/BLACKLIST
index 25509a5ca8..9494ee2278 100644
--- a/tests/auto/network/ssl/qsslcertificate/BLACKLIST
+++ b/tests/auto/network/ssl/qsslcertificate/BLACKLIST
@@ -1,3 +1,13 @@
# OpenSSL version is too new. Rich will fix :)
[subjectAndIssuerAttributes]
-*
+ubuntu-16.04
+rhel-7.6
+opensuse-leap
+windows-7sp1
+ubuntu-18.04
+rhel-7.4
+b2qt
+windows-10 msvc-2017
+windows-10 msvc-2015
+opensuse-42.3
+
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index 88be13f41d..efc0c26076 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -401,9 +401,7 @@ void tst_QSslCertificate::subjectAlternativeNames()
certificate.subjectAlternativeNames();
// verify that each entry in subjAltNames is present in fileContents
- QMapIterator<QSsl::AlternativeNameEntryType, QString> it(altSubjectNames);
- while (it.hasNext()) {
- it.next();
+ for (auto it = altSubjectNames.cbegin(), end = altSubjectNames.cend(); it != end; ++it) {
QByteArray type;
if (it.key() == QSsl::EmailEntry)
type = "email";
@@ -814,7 +812,7 @@ void tst_QSslCertificate::task256066toPem()
void tst_QSslCertificate::nulInCN()
{
-#if defined(QT_SECURETRANSPORT) || defined(Q_OS_WINRT) || QT_CONFIG(schannel)
+#if QT_CONFIG(securetransport) || defined(Q_OS_WINRT) || QT_CONFIG(schannel)
QSKIP("Generic QSslCertificatePrivate fails this test");
#endif
QList<QSslCertificate> certList =
@@ -833,7 +831,7 @@ void tst_QSslCertificate::nulInCN()
void tst_QSslCertificate::nulInSan()
{
-#if defined(QT_SECURETRANSPORT) || defined(Q_OS_WINRT) || QT_CONFIG(schannel)
+#if QT_CONFIG(securetransport) || defined(Q_OS_WINRT) || QT_CONFIG(schannel)
QSKIP("Generic QSslCertificatePrivate fails this test");
#endif
QList<QSslCertificate> certList =
@@ -968,7 +966,7 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
void tst_QSslCertificate::verify()
{
-#ifdef QT_SECURETRANSPORT
+#if QT_CONFIG(securetransport)
QSKIP("Not implemented in SecureTransport");
#endif
QList<QSslError> errors;
diff --git a/tests/auto/network/ssl/qsslkey/BLACKLIST b/tests/auto/network/ssl/qsslkey/BLACKLIST
index f9bc0af6de..19fb15cd1f 100644
--- a/tests/auto/network/ssl/qsslkey/BLACKLIST
+++ b/tests/auto/network/ssl/qsslkey/BLACKLIST
@@ -1,2 +1,9 @@
-redhatenterpriselinuxworkstation
+[constructor]
rhel
+[length]
+rhel
+[toEncryptedPemOrDer]
+rhel
+[toPemOrDer]
+rhel
+
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem
new file mode 100644
index 0000000000..1a8751874e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,A2A6F6BA67CFB2A992BA4FD3A0984B59
+
+L5G1mwcXwW30lFty1HaEHlswFXAGk9+qf0TdYYNAAvVrsTMgfMq/6xM5XWo3IgbN
+gG4K6T57gQkAywn+upqMHobB+7qc3DRzYlrm89gb74gHOe95l/iUJp4ii+ROLcmY
+fg/vNmDSB/D0eM91WfwId7ticYD29+BUbbnqSYyY2S7K7DytYLpXqg3u335GYCdT
+JwOsgcgbOICytkgK6c9ZDF3IrkzvWospVuiG5IfpLQkUXlJO3YGJ/oGf1BXnRd/b
+kTzUiimUVunX62muHaUXKkAmXS8FCdB0puI+52pzLJ5FHdFxCcnwSG09TmoXbwwa
+KoNM+IshNHPBGM7QxflVbSDxDaF1FWLwWSb8+Fhb2fTpfEGMxRCQ8HB1ZeMV4E5W
+DSiNhih8ziC0k957ZYv8iuLanoM1YYIdToHeBwjyBJA836eIcq/ElY2QtKUq5PRw
++sU1BdG+f9rf4iAPHpgWZAKFmJ42ya71bEEVAmfysAOPuc4hpn3SsDTtihm9RKc9
+l7LWJHaTnTu6yJA+vMJwAmPWg+IdG5vntbb93X4cgl5ZadBySRtv37wWyQPnQcFh
+ytX8z2CJNIFJb0ik8bXc39zOxExoTu/o86IuVJ87jFdS1wz3PRek6dJdl15icx76
+yAT0YB2/ZlRcRrO9hSm0D6P+sLOh//dyhhFAlUrDxqrKngI3KF4kgIrSlva3wmx2
+t16SiUKu6FGQZk6/KYOV27Cy+8UJEqlrNJzy+wSFi26d6e6xWTIR2ItzQCxhYDmq
+Tpx0Mh0ml2+bgrKRoDAL5z6UNy0Pc6bYQjvMznIeiuGvL8bAKTDUFwbmrZqNScsl
+tW7yNZG9iSJnAZGMTxuOhSvJRpQkxIcLICd+lsUxWZ2YvFxtSORuRNSwaC7oxtTD
+gIXV08ayoDbDmcguqTXWuCxtguxNANjhsUOetNHL8iP8QFrzAd5Ith9FgASCIBJJ
+3X7vL2YGc3E6DlAJE01loqySU/cnu6/zQapLB9BIzdtoLliwdrJ7PS8FSsBDfZ2X
+i6/7gb1jxYkJAS1NqrUMJw6BphRAwF8ny+FtPJ23Oaf+1vRIGiHsh8qw6XBfwFw9
+vtsUUL19r+8zMpvIB6gf34TLuM7AW7idu3c/486EWgZBDL3mOTd3fsyADKv/HCk7
+c8M2dsafxI6QkTlWsB8G5vkZ8lCGKHjrmPWjfD7NXi+CvXIrDY+gOeVN3PlQCU/2
+zF2vIxKtR0CXuxLzIjFhIgTYR5G5ZnddMmHeVkZdPRl7szGtrxOA4QGJQ6ZT4W2e
+O1whVU2KB0aBYskhClimapM5ypRkcNQ97cUR6/iNgdgSLqxGHCGeMR9bEyLl7/wr
+M0XeDjdVfm/Tj548oHgb0SKLsfL6nnKwqB2viKj81moK9A/wO1Ec9RNaw0jtp2j3
+VIUnPj0GqEjnkHc2jWY2yt4SD6e2AZHwLyWi1q3pixZo1CFiEgFXxwNyYwyeJ6jV
+CJHPRzoNjZ8dkvgRjsXdnWwN316JBNVcH8k7CCmg/8Gq3yAojXG1z8VJZ06GHckd
+meCL1t89OgwIAmIsysKu7+DrKtSlhkQclZmdG6IrQzuPKaHzTPTDgg3ef3jQ4YQO
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem
new file mode 100644
index 0000000000..db74877a5a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,B408346ADE790F8CF0C902A4F0712B34
+
+SwzPBGxmwW2JddOyug1LrWjlZn8siSp5yezjK1x/z2+J2r/vvH8OjGnA387tFtae
+WVTmhT1ixQXMDI1UJuKx0gzrG2449c+BUVe2VXFPLZ2ocSgoXbBpVkfhEqtLAn91
+MSOpQMxvobQKltKhxgXGvuBJwhwfT7yK5HamohFGbxLUh4Dh+NBXwoYH4Qt+kM7C
+kV8VIKvkr/QAL/SRxNoY8rVResPgYvUjdtiGSNZ6CZhNRu42Q2FqbH817cE0NDsN
+il/xvWu4T/6VY1KpwMad/v6BhO45EeKz7YjbF/3Y5jj2JV9r45uf79lM9htMBw0d
+L+Cc3YHeFffgU8NZo0+iUoroXcb7mjWNmgYksbkaZPbLG383YXAXwbkQS7zDMVIx
+QhXn9w+78hNmEV/7PQ8mGXHEFwnfSR05phXoj8IyL5v0grRMA2dsjfxCgfQjH+kc
+Miwr5pD/Flw175OpPFCb2qladdTKoIWiVShspbteoRC0EuiWHzkl5z6Tneyb/sam
+yduLmSYD+RA6OBgUPY95Xm4AowlFFsuV/fxYZ53rFf4cZn9Z6VBVmvIEmapV7CtB
+JzyIVclocwM0ag5u/esdEt/jndJq9chZlIsDS30y3gP6Rlqk5mj90DAs98l28FVG
+WY9jP0babk8mxjYCcnAy7ikUc0D+vJVO6OTmfO3dkGjLpMBM6OlvfhN/0qeXrMDI
+nU2qOshUrVna2kRe6FrcvosFTD8wvQ1/BjmCp1iWWsGdc/q1BqI3pgOlgq3TYfl6
+iUJoji3V2iexH+GPkHsrs+kii1clsO2tgIP7doIooSVkcTsRTHHxKeeHn3qL2028
+pTvieIFD/T4biLZ9Q8sX3XWiHNmXZlCx8lX8MDjTavWES8gY4H5Sr6FjRMy1qpZY
+5w1aAyJ9YZ0J/jLPmFxt8mWgqHPiPlrQkryBBE3l1MSQ/hCEwlf9dP8a+ayINfd7
+3yNkHKjZ5fuoA+TZUQb/fyVM5o1zJ8ML01PaXWrMEgr3b36QL+Ivo2Rpnp9FpwuH
+E405cwCEy5fNSyhHFqqatCbsPl80nkP8OpW6jdWvNy9u0Ap9PS+MbHGq/pfkaazl
+fbKGOckrENzEXi6Uj/yY/0sMtbTJuC70n09X3edHyhl/RJPPUoNnwDM5W1FHfS3r
+qqSOl/r3y5pEErRdBpR4wEgB7DCLBALGDPfXNAAga4ez/Z2X9Zj234+4ZbUzWoLN
+1ER0QYyxLN7oz1qMA15J7nRyRIhDXNlXjyISOqy26T6/d4X0M+6RhNWfT/MHAjJ8
+6ogoGlQUITV3gPO4R6+FGZMF4R6zZXuKVtOXyzRwWnCLfo4gzBHmq+5mmCjGWRq8
+rSSkc6334bYuZOaEoR5EM5sh6ewkjSDPRrKR7EHO02YbiscyT/99TwT5pdIOPK3u
+2T6/40fSmCWQyBLuWxV9CMD+rB/q8Ja5KisEseck7PgI2pMmHfiD5yQXhKR9eDrB
+sRqZxjgRYxup+/0CIBshL8s1R88xelhXyIKyqFfVudM09yAZxEJLQhpDZ27g45ea
+FMX2Ve+ah2NjYBgzAhwKouWg5RyWb6X99NsrCEU75fn/ek86LGs3FxRgB4Uv7Udv
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem
new file mode 100644
index 0000000000..3d96b3166e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,0F2F4695C8FFA35F4076FA0273A3A4E3
+
+GCnMcAhhGuNkJ7SSMBrgNOaDfRtG22J0mdf/0VbrMOJF40P13YBjN3Kd6LpTqBya
+TCIaxQqtfjH1ffhJk8qhwG7uJFGgcY9i0dkrEYklgThzTVqHp7FsQ2jjgJs5HKpc
+euuVD1bxtuc9qI2hq4miA7Z/uDe3M34n+3xcpqccWS1dLFNFZ+fIDwIazfDCu3ah
+fUQHDeWLwOqYiQxhUjjrHpZkI1FE2JYZFaf4zIagIIgzI2O+33fgbrTSoeN5meRs
+F7V2fhDpyEoIlchwAmp6HE6ngtKP4Ecju00yn99AO42fn097yEVwvGFClQTaIzur
+aPEtuKZ4kdc/lmzL2tqNcZckq28ZxpeMq0Fgdcpeg5sDcut811scOjQLFs551On1
+j3E1WfiLoBLKgd9cgmCrZb8hMO+UjcCaV7Jv3T9vDrbvhWs/YhTTwo8UFVplh7Vx
+R1h3cKfzlbtOC5WHXGNK5dBu7SnpEk0+pscY5cxTrzN0odjMbbsjZQmKDZXbmZON
+USzG3Qtafm6Nw/jwQeIjeqaxSho6xGdadTteGaURw6iGio3h0c6/dHayCsxye4tk
+vODa0ZdJASwVh1605qDk9n/iYUT5B46KJCYwO/iN2kUmOcUcZeBqEfV1GfRmepZJ
+bwM4sipzE15hOJ5DKSkHWnSlByRMAdSrMxZWraKUczn5frEBAqEFLlBAvf/FnjWa
+yZJitgryCI2Y2bww1DEMnTCX345kUQIFmmjbzTIXnM28gW+fR3Br9dCf2FAsLNKr
+tru1cYXocPaCUHEqS+XZqVb6BQVQ11YAAde0+x9RknJgsBc9Y7TLobaDBvrV5/nK
+T3vm8el08upum6qPTPh6Z0zBbjx4sp6DYT977N1dYeH4n+0JqcSwIeZg/VAdG0RL
+GzgZVADpiRlStmy65W95KExBjbO0tRTVk/nB1U1nfLbsswp9EKxXgwtpE/ECeTOi
+hzeJBSsXGZ/ZXu/y+NlIu0B/GasFbfrHKslSSrUPTjGEtaEbLNiOEu2Etu3lRcMZ
+oDtMxgNR0TUgCS5nte8lLauYYfB6IuxZXpvJdcI5ushqdOJvvYgJ9Yb2ZPlY8Bt5
+C92Ga69aPcMYk24BPpe15eBbXMsFF8RF+CprVoUPCc+PcuROtxdt+rqoqjQeZPmV
+WQqq+pT2bychpwD7U5jxQnu4u2m+zeBXyk80euBbwEld9BCgfk9mFj6CdBJSEiGV
+qL0ivxd3mDaIKPGd5tcbrOMK2uD7duZY7FrQpAYgryoQJoUHccL7cr9fDC75akHg
+AbrG1+vAYEla/y+SlOg5VTHhiuIl17ZGMViXSqh7iqnnD0dNsZ/HDvk3XouhNxQy
+RQmfdqyIqLuAcfWwQxCQ2E/oMUIHjNhyYmfLVLVGsfxuevMa1eJv7rZ5vIkD2Vpe
+4VveZkNDSpCCNqnvub8+bMW+UXyzbxEZbK5PLkRp7cvtKdA5CUbTlT4060IV0YZ1
+vfMtzXRw8JDD9c1F1WF14afk+y9kvZN88XOH12bSKj+Re06Xx7OzuYU8fclq/pZB
+UZVtRETFnLgb8neMuz3vCoPWK/DSHDZGAAicxq7vTljyoU/QP71Dw7UJIAuYx6Mc
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
index 28476fce5b..f94756ed73 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -30,6 +30,7 @@
#include <QtTest/QtTest>
#include <qsslkey.h>
#include <qsslsocket.h>
+#include <QScopeGuard>
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qnetworkproxy.h>
@@ -233,15 +234,50 @@ void tst_QSslKey::constructorHandle()
QByteArray passphrase;
if (QByteArray(QTest::currentDataTag()).contains("-pkcs8-"))
passphrase = "1234";
+
BIO* bio = q_BIO_new(q_BIO_s_mem());
q_BIO_write(bio, pem.constData(), pem.length());
- QSslKey key(func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data())), type);
+ EVP_PKEY *origin = func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data()));
+#if QT_CONFIG(opensslv11)
+ q_EVP_PKEY_up_ref(origin);
+#endif
+ QSslKey key(origin, type);
+#if !QT_CONFIG(opensslv11)
+ q_BIO_write(bio, pem.constData(), pem.length());
+ origin = func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data()));
+#endif
q_BIO_free(bio);
+ EVP_PKEY *handle = q_EVP_PKEY_new();
+ switch (algorithm) {
+ case QSsl::Rsa:
+ q_EVP_PKEY_set1_RSA(handle, static_cast<RSA *>(key.handle()));
+ break;
+ case QSsl::Dsa:
+ q_EVP_PKEY_set1_DSA(handle, static_cast<DSA *>(key.handle()));
+ break;
+ case QSsl::Dh:
+ q_EVP_PKEY_set1_DH(handle, static_cast<DH *>(key.handle()));
+ break;
+#ifndef OPENSSL_NO_EC
+ case QSsl::Ec:
+ q_EVP_PKEY_set1_EC_KEY(handle, static_cast<EC_KEY *>(key.handle()));
+ break;
+#endif
+ default:
+ break;
+ }
+
+ auto cleanup = qScopeGuard([origin, handle] {
+ q_EVP_PKEY_free(origin);
+ q_EVP_PKEY_free(handle);
+ });
+
QVERIFY(!key.isNull());
QCOMPARE(key.algorithm(), algorithm);
QCOMPARE(key.type(), type);
QCOMPARE(key.length(), length);
+ QCOMPARE(q_EVP_PKEY_cmp(origin, handle), 1);
#endif
}
@@ -430,15 +466,25 @@ void tst_QSslKey::toEncryptedPemOrDer()
void tst_QSslKey::passphraseChecks_data()
{
QTest::addColumn<QString>("fileName");
-
- QTest::newRow("DES") << (testDataDir + "rsa-with-passphrase-des.pem");
- QTest::newRow("3DES") << (testDataDir + "rsa-with-passphrase-3des.pem");
- QTest::newRow("RC2") << (testDataDir + "rsa-with-passphrase-rc2.pem");
+ QTest::addColumn<QByteArray>("passphrase");
+
+ const QByteArray pass("123");
+ const QByteArray aesPass("1234");
+
+ QTest::newRow("DES") << QString(testDataDir + "rsa-with-passphrase-des.pem") << pass;
+ QTest::newRow("3DES") << QString(testDataDir + "rsa-with-passphrase-3des.pem") << pass;
+ QTest::newRow("RC2") << QString(testDataDir + "rsa-with-passphrase-rc2.pem") << pass;
+#if (!defined(QT_NO_OPENSSL) && !defined(OPENSSL_NO_AES)) || (defined(QT_NO_OPENSSL) && QT_CONFIG(ssl))
+ QTest::newRow("AES128") << QString(testDataDir + "rsa-with-passphrase-aes128.pem") << aesPass;
+ QTest::newRow("AES192") << QString(testDataDir + "rsa-with-passphrase-aes192.pem") << aesPass;
+ QTest::newRow("AES256") << QString(testDataDir + "rsa-with-passphrase-aes256.pem") << aesPass;
+#endif // (OpenSSL && AES) || generic backend
}
void tst_QSslKey::passphraseChecks()
{
QFETCH(QString, fileName);
+ QFETCH(QByteArray, passphrase);
QFile keyFile(fileName);
QVERIFY(keyFile.exists());
@@ -471,7 +517,7 @@ void tst_QSslKey::passphraseChecks()
keyFile.open(QIODevice::ReadOnly);
else
keyFile.reset();
- QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "123");
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, passphrase);
QVERIFY(!key.isNull()); // correct passphrase
}
}
@@ -516,79 +562,135 @@ void tst_QSslKey::encrypt_data()
QTest::addColumn<QByteArray>("key");
QTest::addColumn<QByteArray>("plainText");
QTest::addColumn<QByteArray>("cipherText");
+ QTest::addColumn<QByteArray>("iv");
+ QByteArray iv("abcdefgh");
QTest::newRow("DES-CBC, length 0")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray()
- << QByteArray::fromHex("956585228BAF9B1F");
+ << QByteArray::fromHex("956585228BAF9B1F")
+ << iv;
QTest::newRow("DES-CBC, length 1")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(1, 'a')
- << QByteArray::fromHex("E6880AF202BA3C12");
+ << QByteArray::fromHex("E6880AF202BA3C12")
+ << iv;
QTest::newRow("DES-CBC, length 2")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(2, 'a')
- << QByteArray::fromHex("A82492386EED6026");
+ << QByteArray::fromHex("A82492386EED6026")
+ << iv;
QTest::newRow("DES-CBC, length 3")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(3, 'a')
- << QByteArray::fromHex("90B76D5B79519CBA");
+ << QByteArray::fromHex("90B76D5B79519CBA")
+ << iv;
QTest::newRow("DES-CBC, length 4")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(4, 'a')
- << QByteArray::fromHex("63E3DD6FED87052A");
+ << QByteArray::fromHex("63E3DD6FED87052A")
+ << iv;
QTest::newRow("DES-CBC, length 5")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(5, 'a')
- << QByteArray::fromHex("03ACDB0EACBDFA94");
+ << QByteArray::fromHex("03ACDB0EACBDFA94")
+ << iv;
QTest::newRow("DES-CBC, length 6")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(6, 'a')
- << QByteArray::fromHex("7D95024E42A3A88A");
+ << QByteArray::fromHex("7D95024E42A3A88A")
+ << iv;
QTest::newRow("DES-CBC, length 7")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(7, 'a')
- << QByteArray::fromHex("5003436B8A8E42E9");
+ << QByteArray::fromHex("5003436B8A8E42E9")
+ << iv;
QTest::newRow("DES-CBC, length 8")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("E4C1F054BF5521C0A4A0FD4A2BC6C1B1");
+ << QByteArray::fromHex("E4C1F054BF5521C0A4A0FD4A2BC6C1B1")
+ << iv;
QTest::newRow("DES-EDE3-CBC, length 0")
<< QSslKeyPrivate::DesEde3Cbc << QByteArray("0123456789abcdefghijklmn")
<< QByteArray()
- << QByteArray::fromHex("3B2B4CD0B0FD495F");
+ << QByteArray::fromHex("3B2B4CD0B0FD495F")
+ << iv;
QTest::newRow("DES-EDE3-CBC, length 8")
<< QSslKeyPrivate::DesEde3Cbc << QByteArray("0123456789abcdefghijklmn")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("F2A5A87763C54A72A3224103D90CDB03");
+ << QByteArray::fromHex("F2A5A87763C54A72A3224103D90CDB03")
+ << iv;
QTest::newRow("RC2-40-CBC, length 0")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234")
<< QByteArray()
- << QByteArray::fromHex("6D05D52392FF6E7A");
+ << QByteArray::fromHex("6D05D52392FF6E7A")
+ << iv;
QTest::newRow("RC2-40-CBC, length 8")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("75768E64C5749072A5D168F3AFEB0005");
+ << QByteArray::fromHex("75768E64C5749072A5D168F3AFEB0005")
+ << iv;
QTest::newRow("RC2-64-CBC, length 0")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234567")
<< QByteArray()
- << QByteArray::fromHex("ADAE6BF70F420130");
+ << QByteArray::fromHex("ADAE6BF70F420130")
+ << iv;
QTest::newRow("RC2-64-CBC, length 8")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234567")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("C7BF5C80AFBE9FBEFBBB9FD935F6D0DF");
+ << QByteArray::fromHex("C7BF5C80AFBE9FBEFBBB9FD935F6D0DF")
+ << iv;
QTest::newRow("RC2-128-CBC, length 0")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("012345679abcdefg")
<< QByteArray()
- << QByteArray::fromHex("1E965D483A13C8FB");
+ << QByteArray::fromHex("1E965D483A13C8FB")
+ << iv;
QTest::newRow("RC2-128-CBC, length 8")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("012345679abcdefg")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("5AEC1A5B295660B02613454232F7DECE");
+ << QByteArray::fromHex("5AEC1A5B295660B02613454232F7DECE")
+ << iv;
+
+#if (!defined(QT_NO_OPENSSL) && !defined(OPENSSL_NO_AES)) || (defined(QT_NO_OPENSSL) && QT_CONFIG(ssl))
+ // AES needs a longer IV
+ iv = QByteArray("abcdefghijklmnop");
+ QTest::newRow("AES-128-CBC, length 0")
+ << QSslKeyPrivate::Aes128Cbc << QByteArray("012345679abcdefg")
+ << QByteArray()
+ << QByteArray::fromHex("28DE1A9AA26601C30DD2527407121D1A")
+ << iv;
+ QTest::newRow("AES-128-CBC, length 8")
+ << QSslKeyPrivate::Aes128Cbc << QByteArray("012345679abcdefg")
+ << QByteArray(8, 'a')
+ << QByteArray::fromHex("08E880B1BA916F061C1E801D7F44D0EC")
+ << iv;
+
+ QTest::newRow("AES-192-CBC, length 0")
+ << QSslKeyPrivate::Aes192Cbc << QByteArray("0123456789abcdefghijklmn")
+ << QByteArray()
+ << QByteArray::fromHex("E169E0E205CDC2BA895B7CF6097673B1")
+ << iv;
+ QTest::newRow("AES-192-CBC, length 8")
+ << QSslKeyPrivate::Aes192Cbc << QByteArray("0123456789abcdefghijklmn")
+ << QByteArray(8, 'a')
+ << QByteArray::fromHex("3A227D6A3A13237316D30AA17FF9B0A7")
+ << iv;
+
+ QTest::newRow("AES-256-CBC, length 0")
+ << QSslKeyPrivate::Aes256Cbc << QByteArray("0123456789abcdefghijklmnopqrstuv")
+ << QByteArray()
+ << QByteArray::fromHex("4BAACAA0D22199C97DE206C465B7B14A")
+ << iv;
+ QTest::newRow("AES-256-CBC, length 8")
+ << QSslKeyPrivate::Aes256Cbc << QByteArray("0123456789abcdefghijklmnopqrstuv")
+ << QByteArray(8, 'a')
+ << QByteArray::fromHex("879C8C25EC135CDF0B14490A0A7C2F67")
+ << iv;
+#endif // (OpenSSL && AES) || generic backend
}
void tst_QSslKey::encrypt()
@@ -597,7 +699,7 @@ void tst_QSslKey::encrypt()
QFETCH(QByteArray, key);
QFETCH(QByteArray, plainText);
QFETCH(QByteArray, cipherText);
- QByteArray iv("abcdefgh");
+ QFETCH(QByteArray, iv);
#if defined(Q_OS_WINRT) || QT_CONFIG(schannel)
QEXPECT_FAIL("RC2-40-CBC, length 0", "WinRT/Schannel treats RC2 as 128-bit", Abort);
diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST
index 555822d1e6..7b4a29f463 100644
--- a/tests/auto/network/ssl/qsslsocket/BLACKLIST
+++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST
@@ -1,7 +1,11 @@
+[deprecatedProtocols]
windows
+[spontaneousWrite]
+windows-7sp1
[connectToHostEncrypted]
osx-10.13
[setSslConfiguration]
-osx-10.13
+windows-10 msvc-2015
+windows-7sp1
[connectToHostEncryptedWithVerificationPeerName]
osx-10.13
diff --git a/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem b/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem
new file mode 100644
index 0000000000..43c8794ce2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf4CCQC2xMhNhwvATDANBgkqhkiG9w0BAQQFADCBjjELMAkGA1UEChMC
+UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v
+Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE
+BhMCTk8xHDAaBgNVBAMUEyoudGVzdC1uZXQucXQubG9jYWwwHhcNMTgwNzAxMTgz
+NjI3WhcNNDgwNjIzMTgzNjI3WjCBjjELMAkGA1UEChMCUXQxGTAXBgNVBAsTEENv
+cmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5vYm9keS5xdC5pbzENMAsG
+A1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UEBhMCTk8xHDAaBgNVBAMU
+EyoudGVzdC1uZXQucXQubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS
+18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXMIChiMPAsFeYzGa/D6xzAkfcR
+aJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcN
+AQEEBQADgYEAZu/lQPy8PXeyyYGamOVms/FZKJ48BH1y8KC3BeBU5FYnhvgG7pz8
+Wz9JKvt2t/r45wQeAkNL6HnGUBhPJsHMjPHl5KktqN+db3D+FQygBeS2V1+zmC0X
+UZNRE4aWiHvt1Lq+pTx89SOMOpfqWfh4qTQKiE5jC2V4DeCNQ3u7uI8=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
index 1260dc9410..51fcff9a8d 100644
--- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
+++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
@@ -18,3 +18,10 @@ TESTDATA += certs
DEFINES += SRCDIR=\\\"$$PWD/\\\"
requires(qtConfig(private_tests))
+
+# DOCKERTODO: it's 'linux' because it requires cyrus, which
+# is linux-only for now ...
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted cyrus apache2 echo
+}
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 66475e55ad..4e02320362 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -29,6 +29,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qthread.h>
+#include <QtCore/qelapsedtimer.h>
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qhostinfo.h>
#include <QtNetwork/qnetworkproxy.h>
@@ -310,6 +311,21 @@ Q_DECLARE_METATYPE(tst_QSslSocket::PskConnectTestType)
int tst_QSslSocket::loopLevel = 0;
+namespace {
+
+QString httpServerCertChainPath()
+{
+ // DOCKERTODO: note how we use CA certificate on the real server. The docker container
+ // is using a different cert with a "special" CN. Check if it's important!
+#ifdef QT_TEST_SERVER
+ return tst_QSslSocket::testDataDir + QStringLiteral("certs/qt-test-server-cert.pem");
+#else
+ return tst_QSslSocket::testDataDir + QStringLiteral("certs/qt-test-server-cacert.pem");
+#endif // QT_TEST_SERVER
+}
+
+} // unnamed namespace
+
tst_QSslSocket::tst_QSslSocket()
{
#ifndef QT_NO_SSL
@@ -363,8 +379,19 @@ void tst_QSslSocket::initTestCase()
qDebug("Using SSL library %s (%ld)",
qPrintable(QSslSocket::sslLibraryVersionString()),
QSslSocket::sslLibraryVersionNumber());
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 443));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 993));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::echoServerName(), 13));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
-#endif
+#endif // QT_TEST_SERVER
+#endif // QT_NO_SSL
}
void tst_QSslSocket::init()
@@ -373,28 +400,29 @@ void tst_QSslSocket::init()
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(int, proxyType);
- QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ const QString socksProxyAddr = QtNetworkSettings::socksProxyServerIp().toString();
+ const QString httpProxyAddr = QtNetworkSettings::httpProxyServerIp().toString();
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksProxyAddr, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksProxyAddr, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddr, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddr, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddr, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
@@ -518,6 +546,7 @@ void tst_QSslSocket::constructing()
// verify that changing the default config doesn't affect this socket
// (on Unix, the ca certs might be empty, depending on whether we load
// them on demand or not, so set them explicitly)
+#if QT_DEPRECATED_SINCE(5, 5)
socket.setCaCertificates(QSslSocket::systemCaCertificates());
QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>());
QSslSocket::setDefaultCiphers(QList<QSslCipher>());
@@ -529,6 +558,25 @@ void tst_QSslSocket::constructing()
QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty());
QSslConfiguration::setDefaultConfiguration(savedDefault);
+#endif
+
+ auto sslConfig = socket.sslConfiguration();
+ sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates());
+ socket.setSslConfiguration(sslConfig);
+
+ auto defaultConfig = QSslConfiguration::defaultConfiguration();
+ defaultConfig.setCaCertificates(QList<QSslCertificate>());
+ defaultConfig.setCiphers(QList<QSslCipher>());
+ QSslConfiguration::setDefaultConfiguration(defaultConfig);
+
+ QVERIFY(!socket.sslConfiguration().caCertificates().isEmpty());
+ QVERIFY(!socket.sslConfiguration().ciphers().isEmpty());
+
+ // verify the default as well:
+ QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty());
+ QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty());
+
+ QSslConfiguration::setDefaultConfiguration(savedDefault);
}
void tst_QSslSocket::simpleConnect()
@@ -555,7 +603,7 @@ void tst_QSslSocket::simpleConnect()
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(exitLoop()));
// Start connecting
- socket.connectToHost(QtNetworkSettings::serverName(), 993);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 993);
QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
enterLoop(10);
@@ -610,7 +658,7 @@ void tst_QSslSocket::simpleConnectWithIgnore()
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(exitLoop()));
// Start connecting
- socket.connectToHost(QtNetworkSettings::serverName(), 993);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 993);
QVERIFY(socket.state() != QAbstractSocket::UnconnectedState); // something must be in progress
enterLoop(10);
@@ -642,7 +690,7 @@ void tst_QSslSocket::sslErrors_data()
QString name = QtNetworkSettings::serverLocalName();
QTest::newRow(qPrintable(name)) << name << 993;
- name = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ name = QtNetworkSettings::httpServerIp().toString();
QTest::newRow(qPrintable(name)) << name << 443;
}
@@ -659,7 +707,20 @@ void tst_QSslSocket::sslErrors()
QSignalSpy sslErrorsSpy(socket.data(), SIGNAL(sslErrors(QList<QSslError>)));
QSignalSpy peerVerifyErrorSpy(socket.data(), SIGNAL(peerVerifyError(QSslError)));
- socket->connectToHostEncrypted(host, port);
+#ifdef QT_TEST_SERVER
+ // On the old test server we had the same certificate on different services.
+ // The idea of this test is to fail with 'HostNameMismatch', when we're using
+ // either serverLocalName() or IP address directly. With Docker we connect
+ // to IMAP server, and we have to connect using imapServerName() and passing
+ // 'host' as peerVerificationName to the overload of connectToHostEncrypted().
+ if (port == 993) {
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), port, host);
+ } else
+#endif // QT_TEST_SERVER
+ {
+ socket->connectToHostEncrypted(host, port);
+ }
+
if (!socket->waitForConnected())
QSKIP("Skipping flaky test - See QTBUG-29941");
socket->waitForEncrypted(10000);
@@ -670,7 +731,7 @@ void tst_QSslSocket::sslErrors()
const auto socketSslErrors = socket->sslErrors();
for (const QSslError &err : socketSslErrors)
sslErrors << err.error();
- qSort(sslErrors);
+ std::sort(sslErrors.begin(), sslErrors.end());
QVERIFY(sslErrors.contains(QSslError::HostNameMismatch));
QVERIFY(sslErrors.contains(FLUKE_CERTIFICATE_ERROR));
@@ -680,7 +741,7 @@ void tst_QSslSocket::sslErrors()
const auto sslErrorsSpyErrors = qvariant_cast<QList<QSslError> >(qAsConst(sslErrorsSpy).first().first());
for (const QSslError &err : sslErrorsSpyErrors)
emittedErrors << err.error();
- qSort(emittedErrors);
+ std::sort(emittedErrors.begin(), emittedErrors.end());
QCOMPARE(sslErrors, emittedErrors);
// check the same errors were emitted by peerVerifyError
@@ -689,7 +750,7 @@ void tst_QSslSocket::sslErrors()
const QList<QVariantList> &peerVerifyList = peerVerifyErrorSpy;
for (const QVariantList &args : peerVerifyList)
peerErrors << qvariant_cast<QSslError>(args.first()).error();
- qSort(peerErrors);
+ std::sort(peerErrors.begin(), peerErrors.end());
QCOMPARE(sslErrors, peerErrors);
}
@@ -715,18 +776,41 @@ void tst_QSslSocket::ciphers()
{
if (!QSslSocket::supportsSsl())
return;
-
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ QSslSocket socket;
+ QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
+ socket.setCiphers(QList<QSslCipher>());
+ QVERIFY(socket.ciphers().isEmpty());
+ socket.setCiphers(socket.defaultCiphers());
+ QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
+ socket.setCiphers(socket.defaultCiphers());
+ QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
+
+ // Task 164356
+ socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+ }
+#endif
QSslSocket socket;
- QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
- socket.setCiphers(QList<QSslCipher>());
- QVERIFY(socket.ciphers().isEmpty());
- socket.setCiphers(socket.defaultCiphers());
- QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
- socket.setCiphers(socket.defaultCiphers());
- QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
+ QCOMPARE(socket.sslConfiguration().ciphers(), QSslConfiguration::defaultConfiguration().ciphers());
+
+ auto sslConfig = socket.sslConfiguration();
+ sslConfig.setCiphers(QList<QSslCipher>());
+ socket.setSslConfiguration(sslConfig);
+ QVERIFY(socket.sslConfiguration().ciphers().isEmpty());
+
+ sslConfig.setCiphers(QSslConfiguration::defaultConfiguration().ciphers());
+ socket.setSslConfiguration(sslConfig);
+ QCOMPARE(socket.sslConfiguration().ciphers(), QSslConfiguration::defaultConfiguration().ciphers());
+
+ sslConfig.setCiphers(QSslConfiguration::defaultConfiguration().ciphers());
+ socket.setSslConfiguration(sslConfig);
+ QCOMPARE(socket.sslConfiguration().ciphers(), QSslConfiguration::defaultConfiguration().ciphers());
// Task 164356
- socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+ sslConfig.setCiphers({QSslCipher("ALL"), QSslCipher("!ADH"), QSslCipher("!LOW"),
+ QSslCipher("!EXP"), QSslCipher("!MD5"), QSslCipher("@STRENGTH")});
+ socket.setSslConfiguration(sslConfig);
}
void tst_QSslSocket::connectToHostEncrypted()
@@ -739,13 +823,13 @@ void tst_QSslSocket::connectToHostEncrypted()
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
this->socket = socket.data();
- QVERIFY(socket->addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem"));
+ QVERIFY(socket->addCaCertificates(httpServerCertChainPath()));
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
#endif
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
// This should pass unconditionally when using fluke's CA certificate.
// or use untrusted certificate workaround
@@ -758,7 +842,7 @@ void tst_QSslSocket::connectToHostEncrypted()
QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
- socket->connectToHost(QtNetworkSettings::serverName(), 13);
+ socket->connectToHost(QtNetworkSettings::echoServerName(), 13);
QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
@@ -776,14 +860,18 @@ void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
#endif
this->socket = socket.data();
- socket->addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem");
+ socket->addCaCertificates(httpServerCertChainPath());
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
#endif
- // connect to the server with its local name, but use the full name for verification.
- socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName());
+#ifdef QT_TEST_SERVER
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443, QtNetworkSettings::httpServerName());
+#else
+ // Connect to the server with its local name, but use the full name for verification.
+ socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::httpServerName());
+#endif
// This should pass unconditionally when using fluke's CA certificate.
QFETCH_GLOBAL(bool, setProxy);
@@ -805,7 +893,7 @@ void tst_QSslSocket::sessionCipher()
this->socket = socket.data();
connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
QVERIFY(socket->sessionCipher().isNull());
- socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443 /* https */);
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
QVERIFY(socket->sessionCipher().isNull());
socket->startClientEncryption();
@@ -813,11 +901,14 @@ void tst_QSslSocket::sessionCipher()
QSKIP("Skipping flaky test - See QTBUG-29941");
QVERIFY(!socket->sessionCipher().isNull());
- qDebug() << "Supported Ciphers:" << QSslSocket::supportedCiphers();
- qDebug() << "Default Ciphers:" << QSslSocket::defaultCiphers();
+ qDebug() << "Supported Ciphers:" << QSslConfiguration::supportedCiphers();
+ qDebug() << "Default Ciphers:" << QSslConfiguration::defaultConfiguration().ciphers();
qDebug() << "Session Cipher:" << socket->sessionCipher();
+#if QT_DEPRECATED_SINCE(5, 5)
QVERIFY(QSslSocket::supportedCiphers().contains(socket->sessionCipher()));
+#endif
+ QVERIFY(QSslConfiguration::supportedCiphers().contains(socket->sessionCipher()));
socket->disconnectFromHost();
QVERIFY(socket->waitForDisconnected());
}
@@ -840,12 +931,16 @@ void tst_QSslSocket::localCertificate()
// values. This test should just run the codepath inside qsslsocket_openssl.cpp
QSslSocketPtr socket = newSocket();
- QList<QSslCertificate> localCert = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
- socket->setCaCertificates(localCert);
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(httpServerCertChainPath());
+
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCaCertificates(localCert);
+ socket->setSslConfiguration(sslConfig);
+
socket->setLocalCertificate(testDataDir + "certs/fluke.cert");
socket->setPrivateKey(testDataDir + "certs/fluke.key");
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -868,8 +963,7 @@ void tst_QSslSocket::peerCertificateChain()
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
-
- QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(httpServerCertChainPath());
QCOMPARE(caCertificates.count(), 1);
socket->addCaCertificates(caCertificates);
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
@@ -877,7 +971,7 @@ void tst_QSslSocket::peerCertificateChain()
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
#endif
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
QVERIFY(socket->peerCertificateChain().isEmpty());
QFETCH_GLOBAL(bool, setProxy);
@@ -906,7 +1000,7 @@ void tst_QSslSocket::peerCertificateChain()
QVERIFY(socket->waitForDisconnected());
// now do it again back to the original server
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
QVERIFY(socket->peerCertificateChain().isEmpty());
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
@@ -945,13 +1039,17 @@ void tst_QSslSocket::privateKeyOpaque()
// values. This test should just run the codepath inside qsslsocket_openssl.cpp
QSslSocketPtr socket = newSocket();
- QList<QSslCertificate> localCert = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
- socket->setCaCertificates(localCert);
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(httpServerCertChainPath());
+
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCaCertificates(localCert);
+ socket->setSslConfiguration(sslConfig);
+
socket->setLocalCertificate(testDataDir + "certs/fluke.cert");
socket->setPrivateKey(QSslKey(reinterpret_cast<Qt::HANDLE>(pkey)));
socket->setPeerVerifyMode(QSslSocket::QueryPeer);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -965,9 +1063,12 @@ void tst_QSslSocket::protocol()
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(httpServerCertChainPath());
+
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCaCertificates(certs);
+ socket->setSslConfiguration(sslConfig);
- socket->setCaCertificates(certs);
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
@@ -979,13 +1080,13 @@ void tst_QSslSocket::protocol()
// qt-test-server allows TLSV1.
socket->setProtocol(QSsl::TlsV1_0);
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -998,13 +1099,13 @@ void tst_QSslSocket::protocol()
// qt-test-server probably doesn't allow TLSV1.1
socket->setProtocol(QSsl::TlsV1_1);
QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1016,13 +1117,13 @@ void tst_QSslSocket::protocol()
// qt-test-server probably doesn't allows TLSV1.2
socket->setProtocol(QSsl::TlsV1_2);
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1036,13 +1137,13 @@ void tst_QSslSocket::protocol()
// qt-test-server probably doesn't allow TLSV1.3
socket->setProtocol(QSsl::TlsV1_3);
QCOMPARE(socket->protocol(), QSsl::TlsV1_3);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("TLS 1.3 is not supported by the test server or the test is flaky - see QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_3);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_3);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1055,13 +1156,13 @@ void tst_QSslSocket::protocol()
// qt-test-server allows SSLV3, so it allows AnyProtocol.
socket->setProtocol(QSsl::AnyProtocol);
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1073,13 +1174,13 @@ void tst_QSslSocket::protocol()
// qt-test-server allows TlsV1, so it allows TlsV1SslV3
socket->setProtocol(QSsl::TlsV1SslV3);
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForConnected())
QSKIP("Skipping flaky test - See QTBUG-29941");
socket->startClientEncryption();
@@ -1115,7 +1216,7 @@ public:
QString m_keyFile;
QString m_certFile;
QString m_interFile;
- QString ciphers;
+ QList<QSslCipher> ciphers;
signals:
void socketError(QAbstractSocket::SocketError);
@@ -1165,7 +1266,9 @@ protected:
}
if (!ciphers.isEmpty()) {
- socket->setCiphers(ciphers);
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCiphers(ciphers);
+ socket->setSslConfiguration(sslConfig);
}
QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
@@ -1315,7 +1418,7 @@ void tst_QSslSocket::serverCipherPreferences()
// First using the default (server preference)
{
SslServer server;
- server.ciphers = QString("AES128-SHA:AES256-SHA");
+ server.ciphers = {QSslCipher("AES128-SHA"), QSslCipher("AES256-SHA")};
QVERIFY(server.listen());
QEventLoop loop;
@@ -1323,7 +1426,10 @@ void tst_QSslSocket::serverCipherPreferences()
QSslSocket client;
socket = &client;
- socket->setCiphers("AES256-SHA:AES128-SHA");
+
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCiphers({QSslCipher("AES256-SHA"), QSslCipher("AES128-SHA")});
+ socket->setSslConfiguration(sslConfig);
// upon SSL wrong version error, error will be triggered, not sslErrors
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
@@ -1344,7 +1450,7 @@ void tst_QSslSocket::serverCipherPreferences()
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setSslOption(QSsl::SslOptionDisableServerCipherPreference, true);
server.config = config;
- server.ciphers = QString("AES128-SHA:AES256-SHA");
+ server.ciphers = {QSslCipher("AES128-SHA"), QSslCipher("AES256-SHA")};
QVERIFY(server.listen());
QEventLoop loop;
@@ -1352,7 +1458,10 @@ void tst_QSslSocket::serverCipherPreferences()
QSslSocket client;
socket = &client;
- socket->setCiphers("AES256-SHA:AES128-SHA");
+
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCiphers({QSslCipher("AES256-SHA"), QSslCipher("AES128-SHA")});
+ socket->setSslConfiguration(sslConfig);
// upon SSL wrong version error, error will be triggered, not sslErrors
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
@@ -1376,12 +1485,30 @@ void tst_QSslSocket::setCaCertificates()
if (!QSslSocket::supportsSsl())
return;
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ QSslSocket socket;
+ QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
+ socket.setCaCertificates(QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem"));
+ QCOMPARE(socket.caCertificates().size(), 1);
+ socket.setCaCertificates(socket.defaultCaCertificates());
+ QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
+ }
+#endif
QSslSocket socket;
- QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
- socket.setCaCertificates(QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem"));
- QCOMPARE(socket.caCertificates().size(), 1);
- socket.setCaCertificates(socket.defaultCaCertificates());
- QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
+ QCOMPARE(socket.sslConfiguration().caCertificates(),
+ QSslConfiguration::defaultConfiguration().caCertificates());
+
+ auto sslConfig = socket.sslConfiguration();
+ sslConfig.setCaCertificates(
+ QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem"));
+ socket.setSslConfiguration(sslConfig);
+ QCOMPARE(socket.sslConfiguration().caCertificates().size(), 1);
+
+ sslConfig.setCaCertificates(QSslConfiguration::defaultConfiguration().caCertificates());
+ socket.setSslConfiguration(sslConfig);
+ QCOMPARE(socket.sslConfiguration().caCertificates(),
+ QSslConfiguration::defaultConfiguration().caCertificates());
}
void tst_QSslSocket::setLocalCertificate()
@@ -1491,7 +1618,7 @@ void tst_QSslSocket::setSslConfiguration_data()
QTest::newRow("empty") << QSslConfiguration() << false;
QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
QTest::newRow("default") << conf << false; // does not contain test server cert
- QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(httpServerCertChainPath());
conf.setCaCertificates(testServerCert);
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
@@ -1510,7 +1637,7 @@ void tst_QSslSocket::setSslConfiguration()
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
this->socket = socket.data();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH(bool, works);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && (socket->waitForEncrypted(10000) != works))
@@ -1530,7 +1657,7 @@ void tst_QSslSocket::waitForEncrypted()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
@@ -1549,7 +1676,7 @@ void tst_QSslSocket::waitForEncryptedMinusOne()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(-1))
@@ -1565,7 +1692,7 @@ void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
QFETCH_GLOBAL(bool, setProxy);
@@ -1594,19 +1721,43 @@ void tst_QSslSocket::addDefaultCaCertificate()
if (!QSslSocket::supportsSsl())
return;
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ // Reset the global CA chain
+ QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+
+ QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(httpServerCertChainPath());
+ QCOMPARE(flukeCerts.size(), 1);
+ QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates();
+ QVERIFY(!globalCerts.contains(flukeCerts.first()));
+ QSslSocket::addDefaultCaCertificate(flukeCerts.first());
+ QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1);
+ QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first()));
+
+ // Restore the global CA chain
+ QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+ }
+#endif
+
// Reset the global CA chain
- QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+ auto sslConfig = QSslConfiguration::defaultConfiguration();
+ sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates());
+ QSslConfiguration::setDefaultConfiguration(sslConfig);
- QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(httpServerCertChainPath());
QCOMPARE(flukeCerts.size(), 1);
- QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates();
+ QList<QSslCertificate> globalCerts = QSslConfiguration::defaultConfiguration().caCertificates();
QVERIFY(!globalCerts.contains(flukeCerts.first()));
QSslSocket::addDefaultCaCertificate(flukeCerts.first());
- QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1);
- QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first()));
+ QCOMPARE(QSslConfiguration::defaultConfiguration().caCertificates().size(),
+ globalCerts.size() + 1);
+ QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates()
+ .contains(flukeCerts.first()));
// Restore the global CA chain
- QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+ sslConfig = QSslConfiguration::defaultConfiguration();
+ sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates());
+ QSslConfiguration::setDefaultConfiguration(sslConfig);
}
void tst_QSslSocket::addDefaultCaCertificates()
@@ -1622,9 +1773,16 @@ void tst_QSslSocket::defaultCaCertificates()
if (!QSslSocket::supportsSsl())
return;
- QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
+ QVERIFY(certs.size() > 1);
+ QCOMPARE(certs, QSslSocket::systemCaCertificates());
+ }
+#endif
+ QList<QSslCertificate> certs = QSslConfiguration::defaultConfiguration().caCertificates();
QVERIFY(certs.size() > 1);
- QCOMPARE(certs, QSslSocket::systemCaCertificates());
+ QCOMPARE(certs, QSslConfiguration::systemCaCertificates());
}
void tst_QSslSocket::defaultCiphers()
@@ -1632,12 +1790,22 @@ void tst_QSslSocket::defaultCiphers()
if (!QSslSocket::supportsSsl())
return;
- QList<QSslCipher> ciphers = QSslSocket::defaultCiphers();
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ QList<QSslCipher> ciphers = QSslSocket::defaultCiphers();
+ QVERIFY(ciphers.size() > 1);
+
+ QSslSocket socket;
+ QCOMPARE(socket.defaultCiphers(), ciphers);
+ QCOMPARE(socket.ciphers(), ciphers);
+ }
+#endif
+ QList<QSslCipher> ciphers = QSslConfiguration::defaultConfiguration().ciphers();
QVERIFY(ciphers.size() > 1);
QSslSocket socket;
- QCOMPARE(socket.defaultCiphers(), ciphers);
- QCOMPARE(socket.ciphers(), ciphers);
+ QCOMPARE(socket.sslConfiguration().defaultConfiguration().ciphers(), ciphers);
+ QCOMPARE(socket.sslConfiguration().ciphers(), ciphers);
}
void tst_QSslSocket::resetDefaultCiphers()
@@ -1657,11 +1825,21 @@ void tst_QSslSocket::supportedCiphers()
if (!QSslSocket::supportsSsl())
return;
- QList<QSslCipher> ciphers = QSslSocket::supportedCiphers();
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ QList<QSslCipher> ciphers = QSslSocket::supportedCiphers();
+ QVERIFY(ciphers.size() > 1);
+
+ QSslSocket socket;
+ QCOMPARE(socket.supportedCiphers(), ciphers);
+ }
+#endif
+
+ QList<QSslCipher> ciphers = QSslConfiguration::supportedCiphers();
QVERIFY(ciphers.size() > 1);
QSslSocket socket;
- QCOMPARE(socket.supportedCiphers(), ciphers);
+ QCOMPARE(socket.sslConfiguration().supportedCiphers(), ciphers);
}
void tst_QSslSocket::systemCaCertificates()
@@ -1669,9 +1847,16 @@ void tst_QSslSocket::systemCaCertificates()
if (!QSslSocket::supportsSsl())
return;
- QList<QSslCertificate> certs = QSslSocket::systemCaCertificates();
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ QList<QSslCertificate> certs = QSslSocket::systemCaCertificates();
+ QVERIFY(certs.size() > 1);
+ QCOMPARE(certs, QSslSocket::defaultCaCertificates());
+ }
+#endif
+ QList<QSslCertificate> certs = QSslConfiguration::systemCaCertificates();
QVERIFY(certs.size() > 1);
- QCOMPARE(certs, QSslSocket::defaultCaCertificates());
+ QCOMPARE(certs, QSslConfiguration::defaultConfiguration().systemCaCertificates());
}
void tst_QSslSocket::wildcardCertificateNames()
@@ -1946,7 +2131,7 @@ public slots:
QTestEventLoop::instance().exitLoop();
}
void waitSomeMore(QSslSocket *socket) {
- QTime t;
+ QElapsedTimer t;
t.start();
while (!socket->encryptedBytesAvailable()) {
QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250);
@@ -1968,7 +2153,7 @@ void tst_QSslSocket::setReadBufferSize_task_250027()
QSslSocketPtr socket = newSocket();
socket->setReadBufferSize(1000); // limit to 1 kb/sec
socket->ignoreSslErrors();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
socket->ignoreSslErrors();
QVERIFY2(socket->waitForConnected(10*1000), qPrintable(socket->errorString()));
if (setProxy && !socket->waitForEncrypted(10*1000))
@@ -1981,7 +2166,7 @@ void tst_QSslSocket::setReadBufferSize_task_250027()
// provoke a response by sending a request
socket->write("GET /qtest/fluke.gif HTTP/1.0\n"); // this file is 27 KB
socket->write("Host: ");
- socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
+ socket->write(QtNetworkSettings::httpServerName().toLocal8Bit().constData());
socket->write("\n");
socket->write("Connection: close\n");
socket->write("\n");
@@ -2232,7 +2417,7 @@ void tst_QSslSocket::verifyMode()
socket.setPeerVerifyMode(QSslSocket::VerifyPeer);
QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyPeer);
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (socket.waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -2271,7 +2456,7 @@ void tst_QSslSocket::verifyDepth()
void tst_QSslSocket::disconnectFromHostWhenConnecting()
{
QSslSocketPtr socket = newSocket();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
socket->ignoreSslErrors();
socket->write("XXXX LOGOUT\r\n");
QAbstractSocket::SocketState state = socket->state();
@@ -2300,7 +2485,7 @@ void tst_QSslSocket::disconnectFromHostWhenConnecting()
void tst_QSslSocket::disconnectFromHostWhenConnected()
{
QSslSocketPtr socket = newSocket();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
socket->ignoreSslErrors();
if (!socket->waitForEncrypted(5000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -2387,13 +2572,13 @@ void tst_QSslSocket::resetProxy()
// make sure the connection works, and then set a nonsense proxy, and then
// make sure it does not work anymore
QSslSocket socket;
- socket.addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem");
+ socket.addCaCertificates(httpServerCertChainPath());
socket.setProxy(goodProxy);
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString()));
socket.abort();
socket.setProxy(badProxy);
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY(! socket.waitForConnected(10000));
// don't forget to login
@@ -2406,13 +2591,13 @@ void tst_QSslSocket::resetProxy()
// set the nonsense proxy and make sure the connection does not work,
// and then set the right proxy and make sure it works
QSslSocket socket2;
- socket2.addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem");
+ socket2.addCaCertificates(httpServerCertChainPath());
socket2.setProxy(badProxy);
- socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket2.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY(! socket2.waitForConnected(10000));
socket2.abort();
socket2.setProxy(goodProxy);
- socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket2.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
#endif // QT_NO_NETWORKPROXY
}
@@ -2425,7 +2610,7 @@ void tst_QSslSocket::ignoreSslErrorsList_data()
// construct the list of errors that we will get with the SSL handshake and that we will ignore
QList<QSslError> expectedSslErrors;
// fromPath gives us a list of certs, but it actually only contains one
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(httpServerCertChainPath());
QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0));
QSslError wrongError(FLUKE_CERTIFICATE_ERROR);
@@ -2456,7 +2641,7 @@ void tst_QSslSocket::ignoreSslErrorsList()
QFETCH(int, expectedSslErrorSignalCount);
QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
if (socket.waitForEncrypted(10000) != expectEncryptionSuccess)
@@ -2487,7 +2672,7 @@ void tst_QSslSocket::ignoreSslErrorsListWithSlot()
this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(ignoreErrorListSlot(QList<QSslError>)));
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH(int, expectedSslErrorSignalCount);
bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
@@ -2529,14 +2714,14 @@ void tst_QSslSocket::readFromClosedSocket()
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
socket->ignoreSslErrors();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
socket->ignoreSslErrors();
socket->waitForConnected();
socket->waitForEncrypted();
// provoke a response by sending a request
socket->write("GET /qtest/fluke.gif HTTP/1.1\n");
socket->write("Host: ");
- socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
+ socket->write(QtNetworkSettings::httpServerName().toLocal8Bit().constData());
socket->write("\n");
socket->write("\n");
socket->waitForBytesWritten();
@@ -2560,7 +2745,7 @@ void tst_QSslSocket::writeBigChunk()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QByteArray data;
data.resize(1024*1024*10); // 10 MB
@@ -2719,7 +2904,9 @@ void tst_QSslSocket::resume_data()
QTest::newRow("DoNotIgnoreErrors") << false << QList<QSslError>() << false;
QTest::newRow("ignoreAllErrors") << true << QList<QSslError>() << true;
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ // Note, httpServerCertChainPath() it's ... because we use the same certificate on
+ // different services. We'll be actually connecting to IMAP server.
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(httpServerCertChainPath());
QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0));
QSslError wrongError(FLUKE_CERTIFICATE_ERROR);
errorsList.append(wrongError);
@@ -2733,7 +2920,9 @@ void tst_QSslSocket::resume()
{
// make sure the server certificate is not in the list of accepted certificates,
// we want to trigger the sslErrors signal
- QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+ auto sslConfig = QSslConfiguration::defaultConfiguration();
+ sslConfig.setCaCertificates(QSslConfiguration::systemCaCertificates());
+ QSslConfiguration::setDefaultConfiguration(sslConfig);
QFETCH(bool, ignoreErrorsAfterPause);
QFETCH(QList<QSslError>, errorsToIgnore);
@@ -2752,7 +2941,7 @@ void tst_QSslSocket::resume()
this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket.connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
QTestEventLoop::instance().enterLoop(10);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && QTestEventLoop::instance().timeout())
@@ -3053,7 +3242,7 @@ void tst_QSslSocket::dhServer()
return;
SslServer server;
- server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA");
+ server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")};
QVERIFY(server.listen());
QEventLoop loop;
@@ -3082,7 +3271,7 @@ void tst_QSslSocket::dhServerCustomParamsNull()
return;
SslServer server;
- server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA");
+ server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")};
QSslConfiguration cfg = server.config;
cfg.setDiffieHellmanParameters(QSslDiffieHellmanParameters());
@@ -3118,7 +3307,7 @@ void tst_QSslSocket::dhServerCustomParams()
return;
SslServer server;
- server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA");
+ server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")};
QSslConfiguration cfg = server.config;
@@ -3167,7 +3356,7 @@ void tst_QSslSocket::ecdhServer()
return;
SslServer server;
- server.ciphers = QLatin1String("ECDHE-RSA-AES128-SHA");
+ server.ciphers = {QSslCipher("ECDHE-RSA-AES128-SHA")};
QVERIFY(server.listen());
QEventLoop loop;
@@ -3255,14 +3444,14 @@ void tst_QSslSocket::verifyClientCertificate_data()
void tst_QSslSocket::verifyClientCertificate()
{
-#ifdef QT_SECURETRANSPORT
+#if QT_CONFIG(securetransport)
// We run both client and server on the same machine,
// this means, client can update keychain with client's certificates,
// and server later will use the same certificates from the same
// keychain thus making tests fail (wrong number of certificates,
// success instead of failure etc.).
QSKIP("This test can not work with Secure Transport");
-#endif
+#endif // QT_CONFIG(securetransport)
#ifdef Q_OS_WINRT
QSKIP("Server-side encryption is not implemented on WinRT.");
#endif
@@ -3344,7 +3533,7 @@ void tst_QSslSocket::verifyClientCertificate()
void tst_QSslSocket::readBufferMaxSize()
{
-#if defined(QT_SECURETRANSPORT) || QT_CONFIG(schannel)
+#if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
// QTBUG-55170:
// SecureTransport back-end was ignoring read-buffer
// size limit, resulting (potentially) in a constantly
@@ -3401,7 +3590,7 @@ void tst_QSslSocket::readBufferMaxSize()
QCOMPARE(client->bytesAvailable() + readSoFar, message.size());
#else
// Not needed, QSslSocket works correctly with other back-ends.
-#endif
+#endif // QT_CONFIG(securetransport) || QT_CONFIG(schannel)
}
void tst_QSslSocket::setEmptyDefaultConfiguration() // this test should be last, as it has some side effects
@@ -3418,7 +3607,7 @@ void tst_QSslSocket::setEmptyDefaultConfiguration() // this test should be last,
socket = client.data();
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && socket->waitForEncrypted(4000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -3537,7 +3726,7 @@ public:
bool ignoreSslErrors;
QSslSocket::PeerVerifyMode peerVerifyMode;
QSsl::SslProtocol protocol;
- QString ciphers;
+ QList<QSslCipher> ciphers;
PskProvider m_pskProvider;
protected:
@@ -3551,7 +3740,9 @@ protected:
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
if (!ciphers.isEmpty()) {
- socket->setCiphers(ciphers);
+ auto sslConfig = socket->sslConfiguration();
+ sslConfig.setCiphers(ciphers);
+ socket->setSslConfiguration(sslConfig);
}
QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
@@ -3593,7 +3784,7 @@ void tst_QSslSocket::simplePskConnect()
QSKIP("No SSL support");
bool pskCipherFound = false;
- const QList<QSslCipher> supportedCiphers = QSslSocket::supportedCiphers();
+ const QList<QSslCipher> supportedCiphers = QSslConfiguration::supportedCiphers();
for (const QSslCipher &cipher : supportedCiphers) {
if (cipher.name() == PSK_CIPHER_WITHOUT_AUTH) {
pskCipherFound = true;
@@ -3645,7 +3836,9 @@ void tst_QSslSocket::simplePskConnect()
connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop()));
// force a PSK cipher w/o auth
- socket.setCiphers(PSK_CIPHER_WITHOUT_AUTH);
+ auto sslConfig = socket.sslConfiguration();
+ sslConfig.setCiphers({QSslCipher(PSK_CIPHER_WITHOUT_AUTH)});
+ socket.setSslConfiguration(sslConfig);
PskProvider provider;
@@ -3914,7 +4107,9 @@ void tst_QSslSocket::pskServer()
connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop()));
// force a PSK cipher w/o auth
- socket.setCiphers(PSK_CIPHER_WITHOUT_AUTH);
+ auto sslConfig = socket.sslConfiguration();
+ sslConfig.setCiphers({QSslCipher(PSK_CIPHER_WITHOUT_AUTH)});
+ socket.setSslConfiguration(sslConfig);
PskProvider provider;
provider.setIdentity(PSK_CLIENT_IDENTITY);
@@ -4117,7 +4312,7 @@ void tst_QSslSocket::forwardReadChannelFinished()
});
connect(&socket, &QSslSocket::readChannelFinished,
&QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
- socket.connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
enterLoop(10);
QVERIFY(readChannelFinishedSpy.count());
}
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
index 05755ff606..8585a3c861 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
@@ -17,3 +17,9 @@ win32 {
DEFINES += SRCDIR=\\\"$$PWD/\\\"
requires(qtConfig(private_tests))
+
+# DOCKERTODO: linux, docker is disabled on macOS/Windows.
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted
+}
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
index 25c2701f69..3b28e7a803 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
@@ -102,7 +102,15 @@ void tst_QSslSocket_onDemandCertificates_member::initTestCase_data()
void tst_QSslSocket_onDemandCertificates_member::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif // QT_TEST_SERVER
}
void tst_QSslSocket_onDemandCertificates_member::init()
@@ -110,28 +118,29 @@ void tst_QSslSocket_onDemandCertificates_member::init()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy) {
QFETCH_GLOBAL(int, proxyType);
- QString testServer = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ const auto socksAddr = QtNetworkSettings::socksProxyServerIp().toString();
+ const auto squidAddr = QtNetworkSettings::httpProxyServerIp().toString();
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
@@ -202,10 +211,23 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe
{
const QString host("www.qt.io");
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ // not using any root certs -> should not work
+ QSslSocketPtr socket2 = newSocket();
+ this->socket = socket2.data();
+ socket2->setCaCertificates(QList<QSslCertificate>());
+ socket2->connectToHostEncrypted(host, 443);
+ QVERIFY(!waitForEncrypted(socket2.data()));
+ }
+#endif
+
// not using any root certs -> should not work
QSslSocketPtr socket2 = newSocket();
this->socket = socket2.data();
- socket2->setCaCertificates(QList<QSslCertificate>());
+ auto sslConfig = socket2->sslConfiguration();
+ sslConfig.setCaCertificates(QList<QSslCertificate>());
+ socket2->setSslConfiguration(sslConfig);
socket2->connectToHostEncrypted(host, 443);
QVERIFY(!waitForEncrypted(socket2.data()));
@@ -215,10 +237,23 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe
socket->connectToHostEncrypted(host, 443);
QVERIFY2(waitForEncrypted(socket.data()), qPrintable(socket->errorString()));
+#if QT_DEPRECATED_SINCE(5, 5)
+ {
+ // not using any root certs again -> should not work
+ QSslSocketPtr socket3 = newSocket();
+ this->socket = socket3.data();
+ socket3->setCaCertificates(QList<QSslCertificate>());
+ socket3->connectToHostEncrypted(host, 443);
+ QVERIFY(!waitForEncrypted(socket3.data()));
+ }
+#endif
+
// not using any root certs again -> should not work
QSslSocketPtr socket3 = newSocket();
this->socket = socket3.data();
- socket3->setCaCertificates(QList<QSslCertificate>());
+ sslConfig = socket3->sslConfiguration();
+ sslConfig.setCaCertificates(QList<QSslCertificate>());
+ socket3->setSslConfiguration(sslConfig);
socket3->connectToHostEncrypted(host, 443);
QVERIFY(!waitForEncrypted(socket3.data()));
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
index c345d7379f..158ecbee37 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
@@ -16,3 +16,9 @@ win32 {
DEFINES += SRCDIR=\\\"$$PWD/\\\"
requires(qtConfig(private_tests))
+
+#DOCKERTODO Linux, docker is disabled on macOS and Windows.
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted
+}
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
index 503edc0bff..a441d13619 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
@@ -98,7 +98,15 @@ void tst_QSslSocket_onDemandCertificates_static::initTestCase_data()
void tst_QSslSocket_onDemandCertificates_static::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif // QT_TEST_SERVER
}
void tst_QSslSocket_onDemandCertificates_static::init()
@@ -106,28 +114,30 @@ void tst_QSslSocket_onDemandCertificates_static::init()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy) {
QFETCH_GLOBAL(int, proxyType);
- QString testServer = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ const auto socksAddr = QtNetworkSettings::socksProxyServerIp().toString();
+ const auto squidAddr = QtNetworkSettings::httpProxyServerIp().toString();
+
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
@@ -168,6 +178,7 @@ void tst_QSslSocket_onDemandCertificates_static::onDemandRootCertLoadingStaticMe
{
QString host("www.qt.io");
+#if QT_DEPRECATED_SINCE(5, 5)
// not using any root certs -> should not work
QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>());
QSslSocketPtr socket = newSocket();
@@ -190,6 +201,7 @@ void tst_QSslSocket_onDemandCertificates_static::onDemandRootCertLoadingStaticMe
QVERIFY(!socket3->waitForEncrypted());
QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+#endif
// setting empty default configuration -> should not work
QSslConfiguration conf;
diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST
index d3165a51e5..ec75ea16eb 100644
--- a/tests/auto/opengl/qgl/BLACKLIST
+++ b/tests/auto/opengl/qgl/BLACKLIST
@@ -1,25 +1,8 @@
-[glWidgetRendering]
-windows
-winrt
-[glFBORendering]
-windows
-winrt
-[multipleFBOInterleavedRendering]
-windows
-winrt
-[glPBufferRendering]
-windows
-winrt
-[replaceClipping]
-windows
-winrt
-[clipTest]
-windows
-winrt
[graphicsViewClipping]
-windows
-winrt
-linux ci
-[glFBOUseInGLWidget]
-windows
-winrt
+ubuntu-16.04
+rhel-7.6
+opensuse-leap
+ubuntu-18.04
+rhel-7.4
+opensuse-42.3
+
diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp
index 053c4b026b..3cc9592fb1 100644
--- a/tests/auto/opengl/qgl/tst_qgl.cpp
+++ b/tests/auto/opengl/qgl/tst_qgl.cpp
@@ -60,6 +60,8 @@ public:
tst_QGL();
virtual ~tst_QGL();
+ static void initMain();
+
private slots:
void initTestCase();
void getSetCheck();
@@ -101,6 +103,11 @@ tst_QGL::~tst_QGL()
{
}
+void tst_QGL::initMain()
+{
+ QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
+}
+
void tst_QGL::initTestCase()
{
QGLWidget glWidget;
diff --git a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
index b7b5b505a0..e12f6d9c18 100644
--- a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
+++ b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
@@ -33,6 +33,7 @@
#include <qpa/qplatformintegration.h>
#include <QtWidgets/QApplication>
#include <QtOpenGL/QtOpenGL>
+#include <qelapsedtimer.h>
#include "tst_qglthreads.h"
#ifndef QT_OPENGL_ES_2
@@ -74,9 +75,9 @@ public:
}
void run() {
- QTime time;
- time.start();
- while (time.elapsed() < RUNNING_TIME) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < RUNNING_TIME) {
lock();
waitForReadyToSwap();
@@ -291,11 +292,11 @@ public:
}
void run() {
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
failure = false;
- while (time.elapsed() < RUNNING_TIME && !failure) {
+ while (timer.elapsed() < RUNNING_TIME && !failure) {
m_widget->makeCurrent();
@@ -466,13 +467,13 @@ public:
public slots:
void draw() {
bool beginFailed = false;
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
int rotAngle = 10;
device->prepareDevice();
QPaintDevice *paintDevice = device->realPaintDevice();
QSize s(paintDevice->width(), paintDevice->height());
- while (time.elapsed() < RUNNING_TIME) {
+ while (timer.elapsed() < RUNNING_TIME) {
QPainter p;
if (!p.begin(paintDevice)) {
beginFailed = true;
@@ -605,9 +606,6 @@ void tst_QGLThreads::painterOnPixmapInThread()
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL)
|| !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps))
QSKIP("No platformsupport for ThreadedOpenGL or ThreadedPixmaps");
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- QSKIP("Drawing text in threads onto X11 drawables currently crashes on some X11 servers.");
-#endif
PaintThreadManager<PixmapWrapper> painterThreads(5);
painterThreads.start();
diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp
index b2b45bb237..de15f4c62d 100644
--- a/tests/auto/other/compiler/tst_compiler.cpp
+++ b/tests/auto/other/compiler/tst_compiler.cpp
@@ -842,7 +842,7 @@ void tst_Compiler::cxx11_constexpr()
static constexpr QBasicAtomicInt atomic = Q_BASIC_ATOMIC_INITIALIZER(1);
static constexpr int i = constexprValue();
QCOMPARE(i, constexprValue());
- QCOMPARE(atomic.load(), 1);
+ QCOMPARE(atomic.loadRelaxed(), 1);
#endif
}
diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST
index c465ff316e..2af5d40359 100644
--- a/tests/auto/other/gestures/BLACKLIST
+++ b/tests/auto/other/gestures/BLACKLIST
@@ -3,17 +3,25 @@ rhel-7.4
rhel-7.6
ubuntu-18.04
[customGesture]
-# QTBUG-67254
-ubuntu
-opensuse
opensuse-leap
+# QTBUG-67254
+opensuse-42.3
[graphicsItemGesture]
ubuntu-18.04
+rhel-7.4
+rhel-7.6
[graphicsItemTreeGesture]
ubuntu-18.04
[graphicsView]
ubuntu-18.04
+rhel-7.4
+rhel-7.6
[explicitGraphicsObjectTarget]
ubuntu-18.04
+rhel-7.4
+rhel-7.6
[autoCancelGestures2]
ubuntu-18.04
+rhel-7.4
+rhel-7.6
+
diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp
index 8fd22caa16..fbf906b55d 100644
--- a/tests/auto/other/lancelot/paintcommands.cpp
+++ b/tests/auto/other/lancelot/paintcommands.cpp
@@ -1208,7 +1208,7 @@ void PaintCommands::command_drawRoundRect(QRegularExpressionMatch re)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
- m_painter->drawRoundRect(x, y, w, h, xs, ys);
+ m_painter->drawRoundedRect(x, y, w, h, xs, ys, Qt::RelativeSize);
QT_WARNING_POP
}
@@ -2484,12 +2484,6 @@ void PaintCommands::command_surface_begin(QRegularExpressionMatch re)
m_painter->fillRect(QRect(0, 0, qRound(w), qRound(h)), Qt::transparent);
m_painter->restore();
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- } else if (m_type == WidgetType) {
- m_surface_pixmap = QPixmap(qRound(w), qRound(h));
- m_surface_pixmap.fill(Qt::transparent);
- m_painter = new QPainter(&m_surface_pixmap);
-#endif
} else {
QImage::Format surface_format;
if (QImage::toPixelFormat(m_format).alphaUsage() != QPixelFormat::UsesAlpha)
@@ -2541,11 +2535,6 @@ void PaintCommands::command_surface_end(QRegularExpressionMatch)
m_painter->beginNativePainting();
m_painter->endNativePainting();
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- } else if (m_type == WidgetType) {
- m_painter->drawPixmap(m_surface_rect.topLeft(), m_surface_pixmap);
- m_surface_pixmap = QPixmap();
-#endif
} else {
m_painter->drawImage(m_surface_rect, m_surface_image);
m_surface_image = QImage();
diff --git a/tests/auto/other/networkselftest/BLACKLIST b/tests/auto/other/networkselftest/BLACKLIST
index 4a958b43a5..55ebad985d 100644
--- a/tests/auto/other/networkselftest/BLACKLIST
+++ b/tests/auto/other/networkselftest/BLACKLIST
@@ -1,4 +1,5 @@
# QTBUG-27571
[ftpProxyServer]
-windows 32bit
-windows 64bit
+windows-7sp1
+windows-10
+
diff --git a/tests/auto/other/networkselftest/tst_networkselftest.cpp b/tests/auto/other/networkselftest/tst_networkselftest.cpp
index dc353d2090..1b125d8825 100644
--- a/tests/auto/other/networkselftest/tst_networkselftest.cpp
+++ b/tests/auto/other/networkselftest/tst_networkselftest.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <QtNetwork/QtNetwork>
#include <QtCore/QDateTime>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QTextStream>
#include <QtCore/QRandomGenerator>
#include <QtCore/QStandardPaths>
@@ -195,7 +196,7 @@ static bool doSocketFlush(QTcpSocket *socket, int timeout = 4000)
#ifndef QT_NO_SSL
QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
#endif
- QTime timer;
+ QElapsedTimer timer;
timer.start();
int t = timeout;
forever {
@@ -421,7 +422,7 @@ void tst_NetworkSelfTest::serverReachability()
QTcpSocket socket;
socket.connectToHost(QtNetworkSettings::serverName(), 12346);
- QTime timer;
+ QElapsedTimer timer;
timer.start();
socket.waitForConnected(10000);
QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
diff --git a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp
index fc979bce2d..ecc95d30b6 100644
--- a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp
+++ b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp
@@ -80,13 +80,9 @@ qint64 DynamicTreeModel::findParentId(qint64 searchId) const
if (searchId <= 0)
return -1;
- QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems);
- while (i.hasNext()) {
- i.next();
- QListIterator<QList<qint64> > j(i.value());
- while (j.hasNext()) {
- QList<qint64> l = j.next();
- if (l.contains(searchId))
+ for (auto i = m_childItems.cbegin(), end = m_childItems.cend(); i != end; ++i) {
+ for (const auto &list : i.value()) {
+ if (list.contains(searchId))
return i.key();
}
}
@@ -163,13 +159,12 @@ ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent)
{
}
-QModelIndex ModelChangeCommand::findIndex(QList<int> rows)
+QModelIndex ModelChangeCommand::findIndex(const QList<int> &rows) const
{
const int col = 0;
QModelIndex parent = QModelIndex();
- QListIterator<int> i(rows);
- while (i.hasNext()) {
- parent = m_model->index(i.next(), col, parent);
+ for (int row : rows) {
+ parent = m_model->index(row, col, parent);
if (!parent.isValid())
qFatal("%s: parent must be valid", Q_FUNC_INFO);
}
@@ -233,7 +228,7 @@ void ModelMoveCommand::doCommand()
if (srcParent == destParent)
d = m_destRow - (m_endRow - m_startRow + 1);
else
- d = m_destRow - (m_endRow - m_startRow) + 1;
+ d = m_destRow;
}
foreach (const qint64 id, l)
diff --git a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h
index 709751dd27..0807ffbe94 100644
--- a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h
+++ b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h
@@ -97,7 +97,7 @@ public:
m_rowNumbers = rowNumbers;
}
- QModelIndex findIndex(QList<int> rows);
+ QModelIndex findIndex(const QList<int> &rows) const;
void setStartRow(int row)
{
diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro
index 3587c38e76..6f3740a24f 100644
--- a/tests/auto/other/qaccessibility/qaccessibility.pro
+++ b/tests/auto/other/qaccessibility/qaccessibility.pro
@@ -11,5 +11,6 @@ win32 {
!winrt {
QT += windowsuiautomation_support-private
}
- LIBS += -luuid -loleacc -loleaut32 -lole32
+ LIBS += -loleacc -loleaut32
+ QMAKE_USE += ole32 uuid
}
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index bc45487599..7d7fa6403b 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -2580,6 +2580,7 @@ void tst_QAccessibility::dialogButtonBoxTest()
case QDialogButtonBox::GnomeLayout:
case QDialogButtonBox::KdeLayout:
case QDialogButtonBox::MacLayout:
+ case QDialogButtonBox::AndroidLayout:
expectedOrder << QDialogButtonBox::tr("Help")
<< QDialogButtonBox::tr("Reset")
<< QDialogButtonBox::tr("OK");
diff --git a/tests/auto/other/qaccessibilitymac/BLACKLIST b/tests/auto/other/qaccessibilitymac/BLACKLIST
deleted file mode 100644
index f53fa7e853..0000000000
--- a/tests/auto/other/qaccessibilitymac/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[hierarchyTest]
-osx-10.12 ci
diff --git a/tests/auto/other/qfocusevent/BLACKLIST b/tests/auto/other/qfocusevent/BLACKLIST
deleted file mode 100644
index 0b03472587..0000000000
--- a/tests/auto/other/qfocusevent/BLACKLIST
+++ /dev/null
@@ -1,6 +0,0 @@
-[checkReason_Shortcut]
-osx-10.12 ci
-[checkReason_ActiveWindow]
-osx-10.12 ci
-winrt
-
diff --git a/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST b/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST
index aea819fc2e..6173488c00 100644
--- a/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST
+++ b/tests/auto/other/qnetworkaccessmanager_and_qprogressdialog/BLACKLIST
@@ -1,2 +1,4 @@
+[downloadCheck]
+windows-10
[downloadCheck:with-zeroCopy]
windows
diff --git a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
index 0d656e223c..e09d304ff3 100644
--- a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
+++ b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
@@ -85,7 +85,7 @@ class RaceThread : public QThread
{
Q_OBJECT
RaceObject *object;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
public:
RaceThread()
@@ -378,6 +378,10 @@ public:
connect(timer, &QTimer::timeout, this, &DeleteReceiverRaceReceiver::onTimeout);
timer->start(1);
}
+ ~DeleteReceiverRaceReceiver()
+ {
+ delete receiver;
+ }
void onTimeout()
{
@@ -410,7 +414,7 @@ void tst_QObjectRace::disconnectRace()
{
enum { ThreadCount = 20, TimeLimit = 3000 };
- QCOMPARE(countedStructObjectsCount.load(), 0u);
+ QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
{
QScopedPointer<DisconnectRaceSenderObject> sender(new DisconnectRaceSenderObject());
@@ -428,15 +432,15 @@ void tst_QObjectRace::disconnectRace()
for (int i = 0; i < ThreadCount; ++i) {
threads[i]->requestInterruption();
- QVERIFY(threads[i]->wait(300));
+ QVERIFY(threads[i]->wait());
delete threads[i];
}
senderThread->quit();
- QVERIFY(senderThread->wait(300));
+ QVERIFY(senderThread->wait());
}
- QCOMPARE(countedStructObjectsCount.load(), 0u);
+ QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
{
QScopedPointer<DisconnectRaceSenderObject> sender(new DisconnectRaceSenderObject());
@@ -453,16 +457,16 @@ void tst_QObjectRace::disconnectRace()
QTest::qWait(TimeLimit);
senderThread->requestInterruption();
- QVERIFY(senderThread->wait(300));
+ QVERIFY(senderThread->wait());
for (int i = 0; i < ThreadCount; ++i) {
threads[i]->quit();
- QVERIFY(threads[i]->wait(300));
+ QVERIFY(threads[i]->wait());
delete threads[i];
}
}
- QCOMPARE(countedStructObjectsCount.load(), 0u);
+ QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
}
QTEST_MAIN(tst_QObjectRace)
diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp
index f31a755f9e..ab7bca8322 100644
--- a/tests/auto/other/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp
@@ -126,20 +126,20 @@ void tst_toolsupport::offsets_data()
#ifdef Q_PROCESSOR_X86
// x86 32-bit has weird alignment rules. Refer to QtPrivate::AlignOf in
// qglobal.h for more details.
- data << 168 << 248;
+ data << 152 << 224;
#else
- data << 172 << 248;
+ data << 156 << 224;
#endif
}
#endif
{
QTest::newRow("QDateTimePrivate::m_msecs")
- << pmm_to_offsetof(&QDateTimePrivate::m_msecs) << 0 << 0;
+ << pmm_to_offsetof(&QDateTimePrivate::m_msecs) << 8 << 8;
QTest::newRow("QDateTimePrivate::m_status")
- << pmm_to_offsetof(&QDateTimePrivate::m_status) << 8 << 8;
+ << pmm_to_offsetof(&QDateTimePrivate::m_status) << 4 << 4;
QTest::newRow("QDateTimePrivate::m_offsetFromUtc")
- << pmm_to_offsetof(&QDateTimePrivate::m_offsetFromUtc) << 12 << 12;
+ << pmm_to_offsetof(&QDateTimePrivate::m_offsetFromUtc) << 16 << 16;
QTest::newRow("QDateTimePrivate::m_timeZone")
<< pmm_to_offsetof(&QDateTimePrivate::m_timeZone) << 20 << 24;
}
diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
index abe4325278..7529bad833 100644
--- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
+++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
@@ -1315,7 +1315,9 @@ void tst_QPrinter::pageSize()
// Test set/get
QPrinter::PaperSize expected = QPrinter::A4;
QPrinterInfo info = QPrinterInfo::printerInfo(native.printerName());
- foreach (QPrinter::PaperSize supported, info.supportedPaperSizes()) {
+ const auto &pageSizes = info.supportedPageSizes();
+ for (const auto &pageSize : pageSizes) {
+ const QPrinter::PaperSize supported = QPrinter::PaperSize(pageSize.id());
if (supported != QPrinter::Custom && supported != native.paperSize()) {
expected = supported;
break;
@@ -1359,7 +1361,9 @@ void tst_QPrinter::paperSize()
// Test set/get
QPrinter::PaperSize expected = QPrinter::A4;
QPrinterInfo info = QPrinterInfo::printerInfo(native.printerName());
- foreach (QPrinter::PaperSize supported, info.supportedPaperSizes()) {
+ const auto &pageSizes = info.supportedPageSizes();
+ for (const auto &pageSize : pageSizes) {
+ const QPrinter::PaperSize supported = QPrinter::PaperSize(pageSize.id());
if (supported != QPrinter::Custom && supported != native.paperSize()) {
expected = supported;
break;
diff --git a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
index 92a06cda00..81b49a3a87 100644
--- a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
+++ b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
@@ -94,17 +94,16 @@ QString tst_QPrinterInfo::getDefaultPrinterFromSystem()
command << "lpstat" << "-d";
QString output = getOutputFromCommand(command);
- QRegExp noDefaultReg("[^:]*no .*default");
- int pos = noDefaultReg.indexIn(output);
- if (pos >= 0) {
+ QRegularExpression noDefaultReg("[^:]*no .*default");
+ QRegularExpressionMatch match;
+ match = noDefaultReg.match(output);
+ if (match.hasMatch())
return QString();
- }
- QRegExp defaultReg("default.*: *([a-zA-Z0-9_-]+)");
- defaultReg.indexIn(output);
- printer = defaultReg.cap(1);
+ QRegularExpression defaultReg("default.*: *([a-zA-Z0-9_-]+)");
+ match = defaultReg.match(output);
+ printer = match.captured(1);
#endif // Q_OS_UNIX
-
return printer;
}
@@ -121,10 +120,12 @@ QStringList tst_QPrinterInfo::getPrintersFromSystem()
QString output = getOutputFromCommand(command);
QStringList list = output.split(QChar::fromLatin1('\n'));
- QRegExp reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)");
+ QRegularExpression reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)");
+ QRegularExpressionMatch match;
for (int c = 0; c < list.size(); ++c) {
- if (reg.indexIn(list[c]) >= 0) {
- QString printer = reg.cap(1);
+ match = reg.match(list[c]);
+ if (match.hasMatch()) {
+ QString printer = match.captured(1);
ans << printer;
}
}
@@ -300,8 +301,13 @@ void tst_QPrinterInfo::testConstructors()
QCOMPARE(copy1.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
QCOMPARE(copy1.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
QCOMPARE(copy1.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
- QCOMPARE(copy1.supportedPaperSizes(), printers.at(i).supportedPaperSizes());
+ QCOMPARE(copy1.supportedPageSizes(), printers.at(i).supportedPageSizes());
+#if QT_DEPRECATED_SINCE(5, 3)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(copy1.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames());
+QT_WARNING_POP
+#endif
QCOMPARE(copy1.supportedResolutions(), printers.at(i).supportedResolutions());
QCOMPARE(copy1.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
QCOMPARE(copy1.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
@@ -321,8 +327,13 @@ void tst_QPrinterInfo::testConstructors()
QCOMPARE(copy2.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
QCOMPARE(copy2.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
QCOMPARE(copy2.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
- QCOMPARE(copy2.supportedPaperSizes(), printers.at(i).supportedPaperSizes());
+ QCOMPARE(copy2.supportedPageSizes(), printers.at(i).supportedPageSizes());
+#if QT_DEPRECATED_SINCE(5, 3)
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(copy2.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames());
+ QT_WARNING_POP
+#endif
QCOMPARE(copy2.supportedResolutions(), printers.at(i).supportedResolutions());
QCOMPARE(copy2.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
QCOMPARE(copy2.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
index 55875359ff..174db2863e 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
@@ -34,7 +34,8 @@
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlQuery>
-#include <QRegExp>
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
#include <QDir>
#include <QScopedPointer>
#include <QVariant>
@@ -511,13 +512,13 @@ public:
QSqlQuery q( "SELECT banner FROM v$version", db );
q.next();
- QRegExp vers( "([0-9]+)\\.[0-9\\.]+[0-9]" );
-
- if ( vers.indexIn( q.value( 0 ).toString() ) ) {
+ QRegularExpression vers("([0-9]+)\\.[0-9\\.]+[0-9]");
+ QRegularExpressionMatch match = vers.match(q.value(0).toString());
+ if (match.hasMatch()) {
bool ok;
- ver = vers.cap( 1 ).toInt( &ok );
+ ver = match.captured(1).toInt(&ok);
- if ( !ok )
+ if (!ok)
ver = -1;
}
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
index f309231b10..c59250e36e 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
@@ -34,7 +34,7 @@
#include <qsqlrecord.h>
#include <qsqlfield.h>
#include <qsqlindex.h>
-#include <qregexp.h>
+#include <qregularexpression.h>
#include <qvariant.h>
#include <qdatetime.h>
#include <qdebug.h>
@@ -228,7 +228,7 @@ struct FieldDef {
QString fieldName() const
{
QString rt = typeName;
- rt.replace(QRegExp("\\s"), QString("_"));
+ rt.replace(QRegularExpression("\\s"), QString("_"));
int i = rt.indexOf(QLatin1Char('('));
if (i == -1)
i = rt.length();
diff --git a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
index 08c6039e37..871ac24be4 100644
--- a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
+++ b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
@@ -42,10 +42,13 @@ public:
virtual ~tst_QSqlError();
private slots:
+#if QT_DEPRECATED_SINCE(5, 1)
void getSetCheck();
+#endif
void construction();
void moveOperator();
void operators();
+ void qtbug_74575();
};
tst_QSqlError::tst_QSqlError()
@@ -56,6 +59,7 @@ tst_QSqlError::~tst_QSqlError()
{
}
+#if QT_DEPRECATED_SINCE(5, 1)
// Testing get/set functions
void tst_QSqlError::getSetCheck()
{
@@ -82,14 +86,28 @@ void tst_QSqlError::getSetCheck()
obj1.setNumber(INT_MAX);
QCOMPARE(INT_MAX, obj1.number());
}
+#endif
void tst_QSqlError::construction()
{
- QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123);
+#if QT_DEPRECATED_SINCE(5, 3)
+ {
+ QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123);
+ QCOMPARE(obj1.driverText(), QString("drivertext"));
+ QCOMPARE(obj1.databaseText(), QString("databasetext"));
+ QCOMPARE(obj1.type(), QSqlError::UnknownError);
+ QCOMPARE(obj1.number(), 123);
+ QCOMPARE(obj1.nativeErrorCode(), QStringLiteral("123"));
+ QVERIFY(obj1.isValid());
+ }
+#endif
+ QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, QStringLiteral("123"));
QCOMPARE(obj1.driverText(), QString("drivertext"));
QCOMPARE(obj1.databaseText(), QString("databasetext"));
QCOMPARE(obj1.type(), QSqlError::UnknownError);
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj1.number(), 123);
+#endif
QCOMPARE(obj1.nativeErrorCode(), QStringLiteral("123"));
QVERIFY(obj1.isValid());
@@ -97,7 +115,9 @@ void tst_QSqlError::construction()
QCOMPARE(obj2.driverText(), obj1.driverText());
QCOMPARE(obj2.databaseText(), obj1.databaseText());
QCOMPARE(obj2.type(), obj1.type());
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj2.number(), obj1.number());
+#endif
QCOMPARE(obj2.nativeErrorCode(), obj1.nativeErrorCode());
QVERIFY(obj2.isValid());
@@ -105,7 +125,9 @@ void tst_QSqlError::construction()
QCOMPARE(obj3.driverText(), obj2.driverText());
QCOMPARE(obj3.databaseText(), obj2.databaseText());
QCOMPARE(obj3.type(), obj2.type());
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj3.number(), obj2.number());
+#endif
QCOMPARE(obj3.nativeErrorCode(), obj2.nativeErrorCode());
QVERIFY(obj3.isValid());
@@ -113,8 +135,11 @@ void tst_QSqlError::construction()
QVERIFY(!obj4.isValid());
QCOMPARE(obj4.driverText(), QString());
QCOMPARE(obj4.databaseText(), QString());
+ QCOMPARE(obj4.text(), QString());
QCOMPARE(obj4.type(), QSqlError::NoError);
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj4.number(), -1);
+#endif
QCOMPARE(obj4.nativeErrorCode(), QString());
QSqlError obj5(QStringLiteral("drivertext"), QStringLiteral("databasetext"),
@@ -122,7 +147,9 @@ void tst_QSqlError::construction()
QCOMPARE(obj5.driverText(), QString("drivertext"));
QCOMPARE(obj5.databaseText(), QString("databasetext"));
QCOMPARE(obj5.type(), QSqlError::UnknownError);
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj5.number(), 123);
+#endif
QCOMPARE(obj5.nativeErrorCode(), QStringLiteral("123"));
QVERIFY(obj5.isValid());
@@ -131,17 +158,31 @@ void tst_QSqlError::construction()
QCOMPARE(obj6.driverText(), QString("drivertext"));
QCOMPARE(obj6.databaseText(), QString("databasetext"));
QCOMPARE(obj6.type(), QSqlError::UnknownError);
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj6.number(), 0);
+#endif
QCOMPARE(obj6.nativeErrorCode(), QStringLiteral("Err123"));
QVERIFY(obj6.isValid());
- // Default constructed object as constructed before Qt 5.3
- QSqlError obj7(QString(), QString(), QSqlError::NoError, -1);
+#if QT_DEPRECATED_SINCE(5, 3)
+ {
+ // Default constructed object as constructed before Qt 5.3
+ QSqlError obj7(QString(), QString(), QSqlError::NoError, -1);
+ QVERIFY(!obj7.isValid());
+ QCOMPARE(obj7.driverText(), QString());
+ QCOMPARE(obj7.databaseText(), QString());
+ QCOMPARE(obj7.type(), QSqlError::NoError);
+ QCOMPARE(obj7.number(), -1);
+ QCOMPARE(obj7.nativeErrorCode(), QString());
+ }
+#endif
+
+ // Default constructed object
+ QSqlError obj7;
QVERIFY(!obj7.isValid());
QCOMPARE(obj7.driverText(), QString());
QCOMPARE(obj7.databaseText(), QString());
QCOMPARE(obj7.type(), QSqlError::NoError);
- QCOMPARE(obj7.number(), -1);
QCOMPARE(obj7.nativeErrorCode(), QString());
// Move constructor
@@ -149,37 +190,59 @@ void tst_QSqlError::construction()
QCOMPARE(obj8.driverText(), obj2.driverText());
QCOMPARE(obj8.databaseText(), obj2.databaseText());
QCOMPARE(obj8.type(), obj2.type());
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj8.number(), obj2.number());
+#endif
QCOMPARE(obj8.nativeErrorCode(), obj2.nativeErrorCode());
QVERIFY(obj8.isValid());
}
void tst_QSqlError::moveOperator()
{
- QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123), obj2;
+ QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, QStringLiteral("123")), obj2;
obj2 = std::move(obj1);
QCOMPARE(obj2.driverText(), QString("drivertext"));
QCOMPARE(obj2.databaseText(), QString("databasetext"));
QCOMPARE(obj2.type(), QSqlError::UnknownError);
+#if QT_DEPRECATED_SINCE(5, 3)
QCOMPARE(obj2.number(), 123);
+#endif
QCOMPARE(obj2.nativeErrorCode(), QStringLiteral("123"));
QVERIFY(obj2.isValid());
}
void tst_QSqlError::operators()
{
- QSqlError error1;
- QSqlError error2;
- QSqlError error3;
-
- error1.setType(QSqlError::NoError);
- error2.setType(QSqlError::NoError);
- error3.setType(QSqlError::UnknownError);
+ QSqlError error1(QString(), QString(), QSqlError::NoError);
+ QSqlError error2(QString(), QString(), QSqlError::NoError);
+ QSqlError error3(QString(), QString(), QSqlError::UnknownError);
QCOMPARE(error1, error2);
QVERIFY(error1 != error3);
}
+void tst_QSqlError::qtbug_74575()
+{
+ const QString driverText(QStringLiteral("drivertext"));
+ const QString databaseText(QStringLiteral("databasetext"));
+ const QString databaseTextNewline(QStringLiteral("databasetext\n"));
+
+ QSqlError error1(driverText, databaseText,
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error1.text(), databaseText + QLatin1Char(' ') + driverText);
+
+ QSqlError error2(QString(), databaseText,
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error2.text(), databaseText);
+
+ QSqlError error3(driverText, QString(),
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error3.text(), driverText);
+
+ QSqlError error4(driverText, databaseTextNewline,
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error4.text(), databaseTextNewline + driverText);
+}
QTEST_MAIN(tst_QSqlError)
#include "tst_qsqlerror.moc"
diff --git a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
index 09a842eb83..aa2cc05b56 100644
--- a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
+++ b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
@@ -345,7 +345,7 @@ void tst_QSqlThread::cleanupTestCase()
void tst_QSqlThread::init()
{
threadFinishedCount = 0;
- counter.store(4);
+ counter.storeRelaxed(4);
}
void tst_QSqlThread::cleanup()
diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
index b617151a36..44dd4a74cf 100644
--- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
+++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -32,6 +32,7 @@
#include <QtSql>
#include <QtSql/private/qsqltablemodel_p.h>
#include <QThread>
+#include <QElapsedTimer>
const QString test(qTableName("test", __FILE__, QSqlDatabase())),
test2(qTableName("test2", __FILE__, QSqlDatabase())),
@@ -1804,12 +1805,12 @@ void tst_QSqlTableModel::sqlite_bigTable()
QSqlQuery q(db);
QVERIFY_SQL( q, exec("create table "+bigtable+"(id int primary key, name varchar)"));
QVERIFY_SQL( q, prepare("insert into "+bigtable+"(id, name) values (?, ?)"));
- QTime startTime;
- startTime.start();
+ QElapsedTimer timing;
+ timing.start();
for (int i = 0; i < 10000; ++i) {
q.addBindValue(i);
q.addBindValue(QString::number(i));
- if(i%1000 == 0 && startTime.elapsed() > 5000)
+ if (i % 1000 == 0 && timing.elapsed() > 5000)
qDebug() << i << "records written";
QVERIFY_SQL( q, exec());
}
diff --git a/tests/auto/testlib/initmain/initmain.pro b/tests/auto/testlib/initmain/initmain.pro
new file mode 100644
index 0000000000..4c12aba08d
--- /dev/null
+++ b/tests/auto/testlib/initmain/initmain.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+SOURCES += tst_initmain.cpp
+QT = core testlib
+
+TARGET = tst_initmain
diff --git a/tests/auto/testlib/initmain/tst_initmain.cpp b/tests/auto/testlib/initmain/tst_initmain.cpp
new file mode 100644
index 0000000000..f08f82c5ec
--- /dev/null
+++ b/tests/auto/testlib/initmain/tst_initmain.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtCore/QCoreApplication>
+#include <QtTest/QtTest>
+
+class tst_InitMain : public QObject
+{
+ Q_OBJECT
+
+public:
+ static void initMain() { m_initMainCalled = true; }
+
+private slots:
+ void testcase();
+
+private:
+ static bool m_initMainCalled;
+};
+
+bool tst_InitMain::m_initMainCalled = false;
+
+void tst_InitMain::testcase()
+{
+ QVERIFY(m_initMainCalled);
+}
+
+QTEST_MAIN(tst_InitMain)
+
+#include "tst_initmain.moc"
diff --git a/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp b/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
index 60aa350145..b305eee0ec 100644
--- a/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
+++ b/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
@@ -63,7 +63,7 @@ void tst_QAbstractItemModelTester::stringListModel()
model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c");
proxy.setDynamicSortFilter(true);
- proxy.setFilterRegExp(QRegExp("[^b]"));
+ proxy.setFilterRegularExpression(QRegularExpression("[^b]"));
}
void tst_QAbstractItemModelTester::treeWidgetModel()
diff --git a/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp b/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
index df241c030e..9555c2a844 100644
--- a/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
+++ b/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
@@ -65,6 +65,11 @@ private slots:
void waitFunctionPointer_signalEmittedLater();
void waitFunctionPointer_signalEmittedTooLate();
void waitFunctionPointer_signalEmittedMultipleTimes();
+
+ void spyOnMetaMethod();
+
+ void spyOnMetaMethod_invalid();
+ void spyOnMetaMethod_invalid_data();
};
class QtTestObject: public QObject
@@ -432,5 +437,52 @@ void tst_QSignalSpy::waitFunctionPointer_signalEmittedMultipleTimes()
QCOMPARE(spy.count(), 3);
}
+void tst_QSignalSpy::spyOnMetaMethod()
+{
+ QObject obj;
+ auto mo = obj.metaObject();
+
+ auto signalIndex = mo->indexOfSignal("objectNameChanged(QString)");
+ QVERIFY(signalIndex != -1);
+
+ auto signal = mo->method(signalIndex);
+ QVERIFY(signal.isValid());
+ QCOMPARE(signal.methodType(), QMetaMethod::Signal);
+
+ QSignalSpy spy(&obj, signal);
+ QVERIFY(spy.isValid());
+
+ obj.setObjectName("A new object name");
+ QCOMPARE(spy.count(), 1);
+}
+
+Q_DECLARE_METATYPE(QMetaMethod);
+void tst_QSignalSpy::spyOnMetaMethod_invalid()
+{
+ QFETCH(QObject*, object);
+ QFETCH(QMetaMethod, signal);
+
+ QSignalSpy spy(object, signal);
+ QVERIFY(!spy.isValid());
+}
+
+void tst_QSignalSpy::spyOnMetaMethod_invalid_data()
+{
+ QTest::addColumn<QObject*>("object");
+ QTest::addColumn<QMetaMethod>("signal");
+
+ QTest::addRow("Invalid object")
+ << static_cast<QObject*>(nullptr)
+ << QMetaMethod();
+
+ QTest::addRow("Empty signal")
+ << new QObject(this)
+ << QMetaMethod();
+
+ QTest::addRow("Method is not a signal")
+ << new QObject(this)
+ << QObject::staticMetaObject.method(QObject::staticMetaObject.indexOfMethod("deleteLater()"));
+}
+
QTEST_MAIN(tst_QSignalSpy)
#include "tst_qsignalspy.moc"
diff --git a/tests/auto/testlib/selftests/alive/.gitignore b/tests/auto/testlib/selftests/alive/.gitignore
deleted file mode 100644
index 561285c5d0..0000000000
--- a/tests/auto/testlib/selftests/alive/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-tst_alive
diff --git a/tests/auto/testlib/selftests/alive/alive.pro b/tests/auto/testlib/selftests/alive/alive.pro
deleted file mode 100644
index bda0db2282..0000000000
--- a/tests/auto/testlib/selftests/alive/alive.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-SOURCES += tst_alive.cpp
-QT = core testlib
-
-mac:CONFIG -= app_bundle
-CONFIG -= debug_and_release_target
-
-
-TARGET = alive
-
-include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/alive/qtestalive.cpp b/tests/auto/testlib/selftests/alive/qtestalive.cpp
deleted file mode 100644
index 0200f2a563..0000000000
--- a/tests/auto/testlib/selftests/alive/qtestalive.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include <qcoreapplication.h>
-#include <qcoreevent.h>
-#include <qthread.h>
-
-class QTestAliveEvent: public QEvent
-{
-public:
-
- enum { AliveEventType = QEvent::User + 422 };
-
- explicit inline QTestAliveEvent(int aSequenceId)
- : QEvent(QEvent::Type(AliveEventType)), seqId(aSequenceId)
- {}
- inline int sequenceId() const { return seqId; }
-
-private:
- int seqId;
-};
-
-class QTestAlivePinger: public QObject
-{
-public:
- QTestAlivePinger(QObject *receiver, QObject *parent = 0);
- bool event(QEvent *e);
-
-protected:
- void timerEvent(QTimerEvent *event);
-
-private:
- QObject *rec;
- int timerId;
- int currentSequenceId;
- int lastSequenceId;
-};
-
-QTestAlivePinger::QTestAlivePinger(QObject *receiver, QObject *parent)
- : QObject(parent), rec(receiver), currentSequenceId(0), lastSequenceId(0)
-{
- if (!rec)
- qFatal("Null receiver object passed to QTestAlivePinger::QTestAlivePinger()");
- timerId = startTimer(850);
-}
-
-bool QTestAlivePinger::event(QEvent *event)
-{
- // pong received
- if (int(event->type()) == QTestAliveEvent::AliveEventType) {
- QTestAliveEvent *e = static_cast<QTestAliveEvent *>(event);
- //qDebug("PONG %d received", e->sequenceId());
- // if the events are not delivered in order, we don't care.
- if (e->sequenceId() > lastSequenceId)
- lastSequenceId = e->sequenceId();
- return true;
- }
- return QObject::event(event);
-}
-
-void QTestAlivePinger::timerEvent(QTimerEvent *event)
-{
- if (event->timerId() != timerId)
- return;
-
- if (lastSequenceId < currentSequenceId - 2) {
- qWarning("TEST LAGS %d PINGS behind!", currentSequenceId - lastSequenceId);
- }
- ++currentSequenceId;
- //qDebug("PING %d", currentSequenceId);
- QCoreApplication::postEvent(rec, new QTestAliveEvent(currentSequenceId));
-}
-
-class QTestAlive: public QThread
-{
-public:
- QTestAlive(QObject *parent = 0);
- ~QTestAlive();
- void run();
-
- bool event(QEvent *e);
-
-private:
- QTestAlivePinger *pinger;
-};
-
-QTestAlive::QTestAlive(QObject *parent)
- : QThread(parent), pinger(0)
-{
-}
-
-QTestAlive::~QTestAlive()
-{
- quit();
- while (isRunning());
-}
-
-bool QTestAlive::event(QEvent *e)
-{
- if (int(e->type()) == QTestAliveEvent::AliveEventType && pinger) {
- // ping received, send back the pong
- //qDebug("PONG %d", static_cast<QTestAliveEvent *>(e)->sequenceId());
- QCoreApplication::postEvent(pinger,
- new QTestAliveEvent(static_cast<QTestAliveEvent *>(e)->sequenceId()));
- return true;
- }
- return QThread::event(e);
-}
-
-void QTestAlive::run()
-{
- if (!QCoreApplication::instance())
- qFatal("QTestAlive::run(): Cannot start QTestAlive without a QCoreApplication instance.");
-
- QTestAlivePinger p(this);
- pinger = &p;
- exec();
- pinger = 0;
-}
-
-
diff --git a/tests/auto/testlib/selftests/alive/tst_alive.cpp b/tests/auto/testlib/selftests/alive/tst_alive.cpp
deleted file mode 100644
index eeb77b18c0..0000000000
--- a/tests/auto/testlib/selftests/alive/tst_alive.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include <QtTest/QtTest>
-#include <QWidget>
-
-#include "qtestalive.cpp"
-
-class tst_Alive: public QObject
-{
- Q_OBJECT
-
-private slots:
- void alive();
- void addMouseDClick() const;
-};
-
-void tst_Alive::alive()
-{
- QTestAlive a;
- a.start();
-
- sleep(5);
- QCoreApplication::processEvents();
- qDebug("CUT");
- sleep(5);
-}
-
-void tst_Alive::addMouseDClick() const
-{
- class DClickListener : public QWidget
- {
- public:
- DClickListener() : isTested(false)
- {
- }
-
- bool isTested;
- protected:
- virtual void mouseDoubleClickEvent(QMouseEvent * event)
- {
- isTested = true;
- QCOMPARE(event->type(), QEvent::MouseButtonDblClick);
- }
- };
-
- DClickListener listener;
-
- QTestEventList list;
- list.addMouseDClick(Qt::LeftButton);
-
- list.simulate(&listener);
- /* Check that we have been called at all. */
- QVERIFY(listener.isTested);
-}
-
-QTEST_MAIN(tst_Alive)
-#include "tst_alive.moc"
diff --git a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
index 2f6d633e9d..49c08982ad 100644
--- a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
+++ b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
@@ -75,6 +75,17 @@ void tst_Blacklisted::xpass()
QVERIFY2(true, "This test should BXPASS");
}
+#ifndef Q_OS_WIN
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf state;
+static void abort_handler(int signal)
+{
+ longjmp(state, 1);
+}
+#endif
+
void tst_Blacklisted::messages()
{
qWarning("This is a warning that should not appear in silent test output");
@@ -83,7 +94,15 @@ void tst_Blacklisted::messages()
qCritical("This is a critical message that should not appear in silent test output");
qInfo("This is an info message that should not appear in silent test output");
QTestLog::info("This is an internal testlib info message that should not appear in silent test output", __FILE__, __LINE__);
- qFatal("This is a fatal error message that should still appear in silent test output");
+
+#ifndef Q_OS_WIN
+ // We're testing qFatal, but we don't want to actually std::abort() !
+ auto prior = signal(SIGABRT, abort_handler);
+ if (setjmp(state))
+ signal(SIGABRT, prior);
+ else
+#endif
+ qFatal("This is a fatal error message that should still appear in silent test output");
}
QTEST_MAIN(tst_Blacklisted)
diff --git a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
index 8e2c7694a5..fb01b19d16 100644
--- a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+++ b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
@@ -256,7 +256,7 @@ void tst_Cmptest::compare_boolfuncs()
namespace {
template <typename T>
-T *null() Q_DECL_NOTHROW { return nullptr; }
+T *null() noexcept { return nullptr; }
}
void tst_Cmptest::compare_to_nullptr()
@@ -466,6 +466,8 @@ void tst_Cmptest::compareQPixmaps_data()
const QPixmap pixmap1(xpmPixmapData1);
const QPixmap pixmap2(xpmPixmapData2);
const QPixmap pixmap3(xpmPixmapData3);
+ QPixmap pixmapWrongDpr = pixmap1.scaled(2, 2);
+ pixmapWrongDpr.setDevicePixelRatio(2);
QTest::newRow("both null") << QPixmap() << QPixmap();
QTest::newRow("one null") << QPixmap() << pixmap1;
@@ -473,6 +475,7 @@ void tst_Cmptest::compareQPixmaps_data()
QTest::newRow("equal") << pixmap1 << pixmap1;
QTest::newRow("different size") << pixmap1 << pixmap3;
QTest::newRow("different pixels") << pixmap1 << pixmap2;
+ QTest::newRow("different dpr") << pixmap1 << pixmapWrongDpr;
}
void tst_Cmptest::compareQPixmaps()
@@ -492,6 +495,8 @@ void tst_Cmptest::compareQImages_data()
const QImage image2(QPixmap(xpmPixmapData2).toImage());
const QImage image1Indexed = image1.convertToFormat(QImage::Format_Indexed8);
const QImage image3(QPixmap(xpmPixmapData3).toImage());
+ QImage imageWrongDpr = image1.scaled(2, 2);
+ imageWrongDpr.setDevicePixelRatio(2);
QTest::newRow("both null") << QImage() << QImage();
QTest::newRow("one null") << QImage() << image1;
@@ -500,6 +505,7 @@ void tst_Cmptest::compareQImages_data()
QTest::newRow("different size") << image1 << image3;
QTest::newRow("different format") << image1 << image1Indexed;
QTest::newRow("different pixels") << image1 << image2;
+ QTest::newRow("different dpr") << image1 << imageWrongDpr;
}
void tst_Cmptest::compareQImages()
diff --git a/tests/auto/testlib/selftests/expected_cmptest.lightxml b/tests/auto/testlib/selftests/expected_cmptest.lightxml
index 58b5a5e530..f108933585 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.lightxml
+++ b/tests/auto/testlib/selftests/expected_cmptest.lightxml
@@ -209,6 +209,12 @@
<DataTag><![CDATA[different pixels]]></DataTag>
<Description><![CDATA[Compared values are not the same]]></Description>
</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[different dpr]]></DataTag>
+ <Description><![CDATA[Compared QPixmaps differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2]]></Description>
+</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="compareQImages">
@@ -246,6 +252,12 @@
<DataTag><![CDATA[different pixels]]></DataTag>
<Description><![CDATA[Compared values are not the same]]></Description>
</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[different dpr]]></DataTag>
+ <Description><![CDATA[Compared QImages differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2]]></Description>
+</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="compareQRegion">
diff --git a/tests/auto/testlib/selftests/expected_cmptest.tap b/tests/auto/testlib/selftests/expected_cmptest.tap
index 238db2fc2b..dc9cb5c950 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.tap
+++ b/tests/auto/testlib/selftests/expected_cmptest.tap
@@ -245,9 +245,9 @@ not ok 32 - compareQPixmaps(one null)
found: 1 (opA).isNull()
expected: 0 (opB).isNull()
actual: 1 (opA).isNull()
- at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 483
+ line: 486
...
not ok 33 - compareQPixmaps(other null)
---
@@ -257,9 +257,9 @@ not ok 33 - compareQPixmaps(other null)
found: 0 (opA).isNull()
expected: 1 (opB).isNull()
actual: 0 (opA).isNull()
- at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 483
+ line: 486
...
ok 34 - compareQPixmaps(equal)
not ok 35 - compareQPixmaps(different size)
@@ -270,19 +270,31 @@ not ok 35 - compareQPixmaps(different size)
found: 11x20 (opA)
expected: 20x20 (opB)
actual: 11x20 (opA)
- at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 483
+ line: 486
...
not ok 36 - compareQPixmaps(different pixels)
---
# Compared values are not the same
- at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 483
+ line: 486
...
-ok 37 - compareQImages(both null)
-not ok 38 - compareQImages(one null)
+not ok 37 - compareQPixmaps(different dpr)
+ ---
+ type: QCOMPARE
+ message: Compared QPixmaps differ in device pixel ratio.
+ wanted: 2 (opB)
+ found: 1 (opA)
+ expected: 2 (opB)
+ actual: 1 (opA)
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:486)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 486
+ ...
+ok 38 - compareQImages(both null)
+not ok 39 - compareQImages(one null)
---
type: QCOMPARE
message: Compared QImages differ.
@@ -290,11 +302,11 @@ not ok 38 - compareQImages(one null)
found: 1 (opA).isNull()
expected: 0 (opB).isNull()
actual: 1 (opA).isNull()
- at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 510
+ line: 516
...
-not ok 39 - compareQImages(other null)
+not ok 40 - compareQImages(other null)
---
type: QCOMPARE
message: Compared QImages differ.
@@ -302,12 +314,12 @@ not ok 39 - compareQImages(other null)
found: 0 (opA).isNull()
expected: 1 (opB).isNull()
actual: 0 (opA).isNull()
- at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 510
+ line: 516
...
-ok 40 - compareQImages(equal)
-not ok 41 - compareQImages(different size)
+ok 41 - compareQImages(equal)
+not ok 42 - compareQImages(different size)
---
type: QCOMPARE
message: Compared QImages differ in size.
@@ -315,11 +327,11 @@ not ok 41 - compareQImages(different size)
found: 11x20 (opA)
expected: 20x20 (opB)
actual: 11x20 (opA)
- at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 510
+ line: 516
...
-not ok 42 - compareQImages(different format)
+not ok 43 - compareQImages(different format)
---
type: QCOMPARE
message: Compared QImages differ in format.
@@ -327,19 +339,31 @@ not ok 42 - compareQImages(different format)
found: 6 (opA)
expected: 3 (opB)
actual: 6 (opA)
- at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 510
+ line: 516
...
-not ok 43 - compareQImages(different pixels)
+not ok 44 - compareQImages(different pixels)
---
# Compared values are not the same
- at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 516
+ ...
+not ok 45 - compareQImages(different dpr)
+ ---
+ type: QCOMPARE
+ message: Compared QImages differ in device pixel ratio.
+ wanted: 2 (opB)
+ found: 1 (opA)
+ expected: 2 (opB)
+ actual: 1 (opA)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:516)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 510
+ line: 516
...
-ok 44 - compareQRegion(equal-empty)
-not ok 45 - compareQRegion(1-empty)
+ok 46 - compareQRegion(equal-empty)
+not ok 47 - compareQRegion(1-empty)
---
type: QCOMPARE
message: Compared values are not the same
@@ -347,12 +371,12 @@ not ok 45 - compareQRegion(1-empty)
found: QRegion(200x50+10+10) (rA)
expected: QRegion(null) (rB)
actual: QRegion(200x50+10+10) (rA)
- at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:533)
+ at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:539)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 533
+ line: 539
...
-ok 46 - compareQRegion(equal)
-not ok 47 - compareQRegion(different lists)
+ok 48 - compareQRegion(equal)
+not ok 49 - compareQRegion(different lists)
---
type: QCOMPARE
message: Compared values are not the same
@@ -360,11 +384,11 @@ not ok 47 - compareQRegion(different lists)
found: QRegion(200x50+10+10) (rA)
expected: QRegion(2 rectangles, 50x200+100+200, 200x50+10+10) (rB)
actual: QRegion(200x50+10+10) (rA)
- at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:533)
+ at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:539)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 533
+ line: 539
...
-not ok 48 - compareQVector2D()
+not ok 50 - compareQVector2D()
---
type: QCOMPARE
message: Compared values are not the same
@@ -372,11 +396,11 @@ not ok 48 - compareQVector2D()
found: QVector2D(1, 2) (v2a)
expected: QVector2D(1, 3) (v2b)
actual: QVector2D(1, 2) (v2a)
- at: tst_Cmptest::compareQVector2D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:542)
+ at: tst_Cmptest::compareQVector2D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:548)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 542
+ line: 548
...
-not ok 49 - compareQVector3D()
+not ok 51 - compareQVector3D()
---
type: QCOMPARE
message: Compared values are not the same
@@ -384,11 +408,11 @@ not ok 49 - compareQVector3D()
found: QVector3D(1, 2, 3) (v3a)
expected: QVector3D(1, 3, 3) (v3b)
actual: QVector3D(1, 2, 3) (v3a)
- at: tst_Cmptest::compareQVector3D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:551)
+ at: tst_Cmptest::compareQVector3D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:557)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 551
+ line: 557
...
-not ok 50 - compareQVector4D()
+not ok 52 - compareQVector4D()
---
type: QCOMPARE
message: Compared values are not the same
@@ -396,11 +420,11 @@ not ok 50 - compareQVector4D()
found: QVector4D(1, 2, 3, 4) (v4a)
expected: QVector4D(1, 3, 3, 4) (v4b)
actual: QVector4D(1, 2, 3, 4) (v4a)
- at: tst_Cmptest::compareQVector4D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:560)
+ at: tst_Cmptest::compareQVector4D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:566)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 560
+ line: 566
...
-not ok 51 - verify()
+not ok 53 - verify()
---
type: QVERIFY
message: Verification failed
@@ -408,11 +432,11 @@ not ok 51 - verify()
found: false (opaqueFunc() < 2)
expected: true (opaqueFunc() < 2)
actual: false (opaqueFunc() < 2)
- at: tst_Cmptest::verify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:572)
+ at: tst_Cmptest::verify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:578)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 572
+ line: 578
...
-not ok 52 - verify2()
+not ok 54 - verify2()
---
type: QVERIFY
message: 42
@@ -420,11 +444,11 @@ not ok 52 - verify2()
found: false (opaqueFunc() < 2)
expected: true (opaqueFunc() < 2)
actual: false (opaqueFunc() < 2)
- at: tst_Cmptest::verify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:578)
+ at: tst_Cmptest::verify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:584)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 578
+ line: 584
...
-not ok 53 - tryVerify()
+not ok 55 - tryVerify()
---
type: QVERIFY
message: Verification failed
@@ -432,11 +456,11 @@ not ok 53 - tryVerify()
found: false (opaqueFunc() < 2)
expected: true (opaqueFunc() < 2)
actual: false (opaqueFunc() < 2)
- at: tst_Cmptest::tryVerify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:584)
+ at: tst_Cmptest::tryVerify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:590)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 584
+ line: 590
...
-not ok 54 - tryVerify2()
+not ok 56 - tryVerify2()
---
type: QVERIFY
message: 42
@@ -444,13 +468,13 @@ not ok 54 - tryVerify2()
found: false (opaqueFunc() < 2)
expected: true (opaqueFunc() < 2)
actual: false (opaqueFunc() < 2)
- at: tst_Cmptest::tryVerify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:590)
+ at: tst_Cmptest::tryVerify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:596)
file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
- line: 590
+ line: 596
...
-ok 55 - verifyExplicitOperatorBool()
-ok 56 - cleanupTestCase()
-1..56
-# tests 56
+ok 57 - verifyExplicitOperatorBool()
+ok 58 - cleanupTestCase()
+1..58
+# tests 58
# pass 18
-# fail 38
+# fail 40
diff --git a/tests/auto/testlib/selftests/expected_cmptest.teamcity b/tests/auto/testlib/selftests/expected_cmptest.teamcity
index 422d0cbfdf..426fddb20f 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.teamcity
+++ b/tests/auto/testlib/selftests/expected_cmptest.teamcity
@@ -95,6 +95,9 @@
##teamcity[testStarted name='compareQPixmaps(different pixels)' flowId='tst_Cmptest']
##teamcity[testFailed name='compareQPixmaps(different pixels)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same' flowId='tst_Cmptest']
##teamcity[testFinished name='compareQPixmaps(different pixels)' flowId='tst_Cmptest']
+##teamcity[testStarted name='compareQPixmaps(different dpr)' flowId='tst_Cmptest']
+##teamcity[testFailed name='compareQPixmaps(different dpr)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared QPixmaps differ in device pixel ratio.|n Actual (opA): 1|n Expected (opB): 2' flowId='tst_Cmptest']
+##teamcity[testFinished name='compareQPixmaps(different dpr)' flowId='tst_Cmptest']
##teamcity[testStarted name='compareQImages(both null)' flowId='tst_Cmptest']
##teamcity[testFinished name='compareQImages(both null)' flowId='tst_Cmptest']
##teamcity[testStarted name='compareQImages(one null)' flowId='tst_Cmptest']
@@ -114,6 +117,9 @@
##teamcity[testStarted name='compareQImages(different pixels)' flowId='tst_Cmptest']
##teamcity[testFailed name='compareQImages(different pixels)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same' flowId='tst_Cmptest']
##teamcity[testFinished name='compareQImages(different pixels)' flowId='tst_Cmptest']
+##teamcity[testStarted name='compareQImages(different dpr)' flowId='tst_Cmptest']
+##teamcity[testFailed name='compareQImages(different dpr)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared QImages differ in device pixel ratio.|n Actual (opA): 1|n Expected (opB): 2' flowId='tst_Cmptest']
+##teamcity[testFinished name='compareQImages(different dpr)' flowId='tst_Cmptest']
##teamcity[testStarted name='compareQRegion(equal-empty)' flowId='tst_Cmptest']
##teamcity[testFinished name='compareQRegion(equal-empty)' flowId='tst_Cmptest']
##teamcity[testStarted name='compareQRegion(1-empty)' flowId='tst_Cmptest']
diff --git a/tests/auto/testlib/selftests/expected_cmptest.txt b/tests/auto/testlib/selftests/expected_cmptest.txt
index e1aa81c1a1..08877ef74d 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.txt
+++ b/tests/auto/testlib/selftests/expected_cmptest.txt
@@ -104,6 +104,10 @@ FAIL! : tst_Cmptest::compareQPixmaps(different size) Compared QPixmaps differ i
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
FAIL! : tst_Cmptest::compareQPixmaps(different pixels) Compared values are not the same
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
+FAIL! : tst_Cmptest::compareQPixmaps(different dpr) Compared QPixmaps differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2
+ Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
PASS : tst_Cmptest::compareQImages(both null)
FAIL! : tst_Cmptest::compareQImages(one null) Compared QImages differ.
Actual (opA).isNull(): 1
@@ -124,6 +128,10 @@ FAIL! : tst_Cmptest::compareQImages(different format) Compared QImages differ i
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
FAIL! : tst_Cmptest::compareQImages(different pixels) Compared values are not the same
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
+FAIL! : tst_Cmptest::compareQImages(different dpr) Compared QImages differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2
+ Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
PASS : tst_Cmptest::compareQRegion(equal-empty)
FAIL! : tst_Cmptest::compareQRegion(1-empty) Compared values are not the same
Actual (rA): QRegion(200x50+10+10)
@@ -156,5 +164,5 @@ FAIL! : tst_Cmptest::tryVerify2() 'opaqueFunc() < 2' returned FALSE. (42)
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
PASS : tst_Cmptest::verifyExplicitOperatorBool()
PASS : tst_Cmptest::cleanupTestCase()
-Totals: 18 passed, 38 failed, 0 skipped, 0 blacklisted, 0ms
+Totals: 18 passed, 40 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_Cmptest *********
diff --git a/tests/auto/testlib/selftests/expected_cmptest.xml b/tests/auto/testlib/selftests/expected_cmptest.xml
index 1c5a17631a..daf2560f1b 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.xml
+++ b/tests/auto/testlib/selftests/expected_cmptest.xml
@@ -211,6 +211,12 @@
<DataTag><![CDATA[different pixels]]></DataTag>
<Description><![CDATA[Compared values are not the same]]></Description>
</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[different dpr]]></DataTag>
+ <Description><![CDATA[Compared QPixmaps differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2]]></Description>
+</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="compareQImages">
@@ -248,6 +254,12 @@
<DataTag><![CDATA[different pixels]]></DataTag>
<Description><![CDATA[Compared values are not the same]]></Description>
</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[different dpr]]></DataTag>
+ <Description><![CDATA[Compared QImages differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2]]></Description>
+</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="compareQRegion">
diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.xunitxml
index 99823d1c1c..397db4c3e4 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml
+++ b/tests/auto/testlib/selftests/expected_cmptest.xunitxml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<testsuite errors="0" failures="38" tests="26" name="tst_Cmptest">
+<testsuite errors="0" failures="40" tests="26" name="tst_Cmptest">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
@@ -98,6 +98,9 @@
Actual (opA): 11x20
Expected (opB): 20x20" result="fail"/>
<failure tag="different pixels" message="Compared values are not the same" result="fail"/>
+ <failure tag="different dpr" message="Compared QPixmaps differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2" result="fail"/>
</testcase>
<testcase result="fail" name="compareQImages">
<failure tag="one null" message="Compared QImages differ.
@@ -113,6 +116,9 @@
Actual (opA): 6
Expected (opB): 3" result="fail"/>
<failure tag="different pixels" message="Compared values are not the same" result="fail"/>
+ <failure tag="different dpr" message="Compared QImages differ in device pixel ratio.
+ Actual (opA): 1
+ Expected (opB): 2" result="fail"/>
</testcase>
<testcase result="fail" name="compareQRegion">
<failure tag="1&#x002D;empty" message="Compared values are not the same
diff --git a/tests/auto/testlib/selftests/expected_crashes_5.txt b/tests/auto/testlib/selftests/expected_crashes_5.txt
new file mode 100644
index 0000000000..088b9c5324
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_crashes_5.txt
@@ -0,0 +1,5 @@
+********* Start testing of tst_Crashes *********
+Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
+PASS : tst_Crashes::initTestCase()
+QFATAL : tst_Crashes::crash() Received signal 11
+ Function time: ms Total time: ms
diff --git a/tests/auto/testlib/selftests/expected_float.lightxml b/tests/auto/testlib/selftests/expected_float.lightxml
index 458f2277e6..5f5114bb2e 100644
--- a/tests/auto/testlib/selftests/expected_float.lightxml
+++ b/tests/auto/testlib/selftests/expected_float.lightxml
@@ -8,15 +8,15 @@
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="doubleComparisons">
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should PASS 1]]></DataTag>
-</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 1]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 2]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
@@ -428,21 +428,24 @@
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="float16Comparisons">
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should SUCCEED 1]]></DataTag>
-</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 1]]></DataTag>
<Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 2]]></DataTag>
<Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 0.0001
Expected (operandRight): 0.0003]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 2]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 3]]></DataTag>
<Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
@@ -450,7 +453,187 @@
Expected (operandRight): 99]]></Description>
</Incident>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should SUCCEED 2]]></DataTag>
+ <DataTag><![CDATA[should PASS 3]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 4]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e-05
+ Expected (operandRight): 5.87e-05]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 4]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 5]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: NaN == NaN]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: inf == inf]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: -inf == -inf]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): -inf]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_float.tap b/tests/auto/testlib/selftests/expected_float.tap
index 277dd2b1d4..9da51b93b3 100644
--- a/tests/auto/testlib/selftests/expected_float.tap
+++ b/tests/auto/testlib/selftests/expected_float.tap
@@ -1,8 +1,7 @@
TAP version 13
# tst_float
ok 1 - initTestCase()
-ok 2 - doubleComparisons(should PASS 1)
-not ok 3 - doubleComparisons(should FAIL 1)
+not ok 2 - doubleComparisons(should FAIL 1)
---
type: QCOMPARE
message: Compared doubles are not the same (fuzzy compare)
@@ -10,10 +9,11 @@ not ok 3 - doubleComparisons(should FAIL 1)
found: 1 (operandLeft)
expected: 3 (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
+ok 3 - doubleComparisons(should PASS 1)
not ok 4 - doubleComparisons(should FAIL 2)
---
type: QCOMPARE
@@ -22,9 +22,9 @@ not ok 4 - doubleComparisons(should FAIL 2)
found: 1e-07 (operandLeft)
expected: 3e-07 (operandRight)
actual: 1e-07 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
ok 5 - doubleComparisons(should PASS 2)
not ok 6 - doubleComparisons(should FAIL 3)
@@ -35,9 +35,9 @@ not ok 6 - doubleComparisons(should FAIL 3)
found: 999999999999 (operandLeft)
expected: 999999999998 (operandRight)
actual: 999999999999 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
ok 7 - doubleComparisons(should PASS 3)
not ok 8 - doubleComparisons(should FAIL 4)
@@ -48,9 +48,9 @@ not ok 8 - doubleComparisons(should FAIL 4)
found: 9.99999999999e-311 (operandLeft)
expected: 9.99999999997e-311 (operandRight)
actual: 9.99999999999e-311 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
ok 9 - doubleComparisons(should PASS 4)
not ok 10 - doubleComparisons(should FAIL 5)
@@ -61,9 +61,9 @@ not ok 10 - doubleComparisons(should FAIL 5)
found: 9.99999999999e+306 (operandLeft)
expected: 9.99999999997e+306 (operandRight)
actual: 9.99999999999e+306 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
ok 11 - doubleComparisons(should PASS: NaN == NaN)
not ok 12 - doubleComparisons(should FAIL: NaN != 0)
@@ -74,9 +74,9 @@ not ok 12 - doubleComparisons(should FAIL: NaN != 0)
found: nan (operandLeft)
expected: 0 (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 13 - doubleComparisons(should FAIL: 0 != NaN)
---
@@ -86,9 +86,9 @@ not ok 13 - doubleComparisons(should FAIL: 0 != NaN)
found: 0 (operandLeft)
expected: nan (operandRight)
actual: 0 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 14 - doubleComparisons(should FAIL: NaN != 1)
---
@@ -98,9 +98,9 @@ not ok 14 - doubleComparisons(should FAIL: NaN != 1)
found: nan (operandLeft)
expected: 1 (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 15 - doubleComparisons(should FAIL: 1 != NaN)
---
@@ -110,9 +110,9 @@ not ok 15 - doubleComparisons(should FAIL: 1 != NaN)
found: 1 (operandLeft)
expected: nan (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
ok 16 - doubleComparisons(should PASS: inf == inf)
ok 17 - doubleComparisons(should PASS: -inf == -inf)
@@ -124,9 +124,9 @@ not ok 18 - doubleComparisons(should FAIL: inf != -inf)
found: inf (operandLeft)
expected: -inf (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 19 - doubleComparisons(should FAIL: -inf != inf)
---
@@ -136,9 +136,9 @@ not ok 19 - doubleComparisons(should FAIL: -inf != inf)
found: -inf (operandLeft)
expected: inf (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 20 - doubleComparisons(should FAIL: inf != nan)
---
@@ -148,9 +148,9 @@ not ok 20 - doubleComparisons(should FAIL: inf != nan)
found: inf (operandLeft)
expected: nan (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 21 - doubleComparisons(should FAIL: nan != inf)
---
@@ -160,9 +160,9 @@ not ok 21 - doubleComparisons(should FAIL: nan != inf)
found: nan (operandLeft)
expected: inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 22 - doubleComparisons(should FAIL: -inf != nan)
---
@@ -172,9 +172,9 @@ not ok 22 - doubleComparisons(should FAIL: -inf != nan)
found: -inf (operandLeft)
expected: nan (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 23 - doubleComparisons(should FAIL: nan != -inf)
---
@@ -184,9 +184,9 @@ not ok 23 - doubleComparisons(should FAIL: nan != -inf)
found: nan (operandLeft)
expected: -inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 24 - doubleComparisons(should FAIL: inf != 0)
---
@@ -196,9 +196,9 @@ not ok 24 - doubleComparisons(should FAIL: inf != 0)
found: inf (operandLeft)
expected: 0 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 25 - doubleComparisons(should FAIL: 0 != inf)
---
@@ -208,9 +208,9 @@ not ok 25 - doubleComparisons(should FAIL: 0 != inf)
found: 0 (operandLeft)
expected: inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 26 - doubleComparisons(should FAIL: -inf != 0)
---
@@ -220,9 +220,9 @@ not ok 26 - doubleComparisons(should FAIL: -inf != 0)
found: -inf (operandLeft)
expected: 0 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 27 - doubleComparisons(should FAIL: 0 != -inf)
---
@@ -232,9 +232,9 @@ not ok 27 - doubleComparisons(should FAIL: 0 != -inf)
found: 0 (operandLeft)
expected: -inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 28 - doubleComparisons(should FAIL: inf != 1)
---
@@ -244,9 +244,9 @@ not ok 28 - doubleComparisons(should FAIL: inf != 1)
found: inf (operandLeft)
expected: 1 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 29 - doubleComparisons(should FAIL: 1 != inf)
---
@@ -256,9 +256,9 @@ not ok 29 - doubleComparisons(should FAIL: 1 != inf)
found: 1 (operandLeft)
expected: inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 30 - doubleComparisons(should FAIL: -inf != 1)
---
@@ -268,9 +268,9 @@ not ok 30 - doubleComparisons(should FAIL: -inf != 1)
found: -inf (operandLeft)
expected: 1 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 31 - doubleComparisons(should FAIL: 1 != -inf)
---
@@ -280,9 +280,9 @@ not ok 31 - doubleComparisons(should FAIL: 1 != -inf)
found: 1 (operandLeft)
expected: -inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 32 - doubleComparisons(should FAIL: inf != max)
---
@@ -292,9 +292,9 @@ not ok 32 - doubleComparisons(should FAIL: inf != max)
found: inf (operandLeft)
expected: 1.79769313486e+308 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 33 - doubleComparisons(should FAIL: inf != -max)
---
@@ -304,9 +304,9 @@ not ok 33 - doubleComparisons(should FAIL: inf != -max)
found: inf (operandLeft)
expected: -1.79769313486e+308 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 34 - doubleComparisons(should FAIL: max != inf)
---
@@ -316,9 +316,9 @@ not ok 34 - doubleComparisons(should FAIL: max != inf)
found: 1.79769313486e+308 (operandLeft)
expected: inf (operandRight)
actual: 1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 35 - doubleComparisons(should FAIL: -max != inf)
---
@@ -328,9 +328,9 @@ not ok 35 - doubleComparisons(should FAIL: -max != inf)
found: -1.79769313486e+308 (operandLeft)
expected: inf (operandRight)
actual: -1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 36 - doubleComparisons(should FAIL: -inf != max)
---
@@ -340,9 +340,9 @@ not ok 36 - doubleComparisons(should FAIL: -inf != max)
found: -inf (operandLeft)
expected: 1.79769313486e+308 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 37 - doubleComparisons(should FAIL: -inf != -max)
---
@@ -352,9 +352,9 @@ not ok 37 - doubleComparisons(should FAIL: -inf != -max)
found: -inf (operandLeft)
expected: -1.79769313486e+308 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 38 - doubleComparisons(should FAIL: max != -inf)
---
@@ -364,9 +364,9 @@ not ok 38 - doubleComparisons(should FAIL: max != -inf)
found: 1.79769313486e+308 (operandLeft)
expected: -inf (operandRight)
actual: 1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 39 - doubleComparisons(should FAIL: -max != -inf)
---
@@ -376,9 +376,9 @@ not ok 39 - doubleComparisons(should FAIL: -max != -inf)
found: -1.79769313486e+308 (operandLeft)
expected: -inf (operandRight)
actual: -1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:54)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 54
+ line: 103
...
not ok 40 - floatComparisons(should FAIL 1)
---
@@ -388,9 +388,9 @@ not ok 40 - floatComparisons(should FAIL 1)
found: 1 (operandLeft)
expected: 3 (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
ok 41 - floatComparisons(should PASS 1)
not ok 42 - floatComparisons(should FAIL 2)
@@ -401,9 +401,9 @@ not ok 42 - floatComparisons(should FAIL 2)
found: 1e-07 (operandLeft)
expected: 3e-07 (operandRight)
actual: 1e-07 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
ok 43 - floatComparisons(should PASS 2)
not ok 44 - floatComparisons(should FAIL 3)
@@ -414,9 +414,9 @@ not ok 44 - floatComparisons(should FAIL 3)
found: 99999 (operandLeft)
expected: 99998 (operandRight)
actual: 99999 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
ok 45 - floatComparisons(should PASS 3)
not ok 46 - floatComparisons(should FAIL 4)
@@ -427,9 +427,9 @@ not ok 46 - floatComparisons(should FAIL 4)
found: 9.9999e-40 (operandLeft)
expected: 9.99971e-40 (operandRight)
actual: 9.9999e-40 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
ok 47 - floatComparisons(should PASS 4)
not ok 48 - floatComparisons(should FAIL 5)
@@ -440,9 +440,9 @@ not ok 48 - floatComparisons(should FAIL 5)
found: 9.9999e+37 (operandLeft)
expected: 9.9997e+37 (operandRight)
actual: 9.9999e+37 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
ok 49 - floatComparisons(should PASS: NaN == NaN)
not ok 50 - floatComparisons(should FAIL: NaN != 0)
@@ -453,9 +453,9 @@ not ok 50 - floatComparisons(should FAIL: NaN != 0)
found: nan (operandLeft)
expected: 0 (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 51 - floatComparisons(should FAIL: 0 != NaN)
---
@@ -465,9 +465,9 @@ not ok 51 - floatComparisons(should FAIL: 0 != NaN)
found: 0 (operandLeft)
expected: nan (operandRight)
actual: 0 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 52 - floatComparisons(should FAIL: NaN != 1)
---
@@ -477,9 +477,9 @@ not ok 52 - floatComparisons(should FAIL: NaN != 1)
found: nan (operandLeft)
expected: 1 (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 53 - floatComparisons(should FAIL: 1 != NaN)
---
@@ -489,9 +489,9 @@ not ok 53 - floatComparisons(should FAIL: 1 != NaN)
found: 1 (operandLeft)
expected: nan (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
ok 54 - floatComparisons(should PASS: inf == inf)
ok 55 - floatComparisons(should PASS: -inf == -inf)
@@ -503,9 +503,9 @@ not ok 56 - floatComparisons(should FAIL: inf != -inf)
found: inf (operandLeft)
expected: -inf (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 57 - floatComparisons(should FAIL: -inf != inf)
---
@@ -515,9 +515,9 @@ not ok 57 - floatComparisons(should FAIL: -inf != inf)
found: -inf (operandLeft)
expected: inf (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 58 - floatComparisons(should FAIL: inf != nan)
---
@@ -527,9 +527,9 @@ not ok 58 - floatComparisons(should FAIL: inf != nan)
found: inf (operandLeft)
expected: nan (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 59 - floatComparisons(should FAIL: nan != inf)
---
@@ -539,9 +539,9 @@ not ok 59 - floatComparisons(should FAIL: nan != inf)
found: nan (operandLeft)
expected: inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 60 - floatComparisons(should FAIL: -inf != nan)
---
@@ -551,9 +551,9 @@ not ok 60 - floatComparisons(should FAIL: -inf != nan)
found: -inf (operandLeft)
expected: nan (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 61 - floatComparisons(should FAIL: nan != -inf)
---
@@ -563,9 +563,9 @@ not ok 61 - floatComparisons(should FAIL: nan != -inf)
found: nan (operandLeft)
expected: -inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 62 - floatComparisons(should FAIL: inf != 0)
---
@@ -575,9 +575,9 @@ not ok 62 - floatComparisons(should FAIL: inf != 0)
found: inf (operandLeft)
expected: 0 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 63 - floatComparisons(should FAIL: 0 != inf)
---
@@ -587,9 +587,9 @@ not ok 63 - floatComparisons(should FAIL: 0 != inf)
found: 0 (operandLeft)
expected: inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 64 - floatComparisons(should FAIL: -inf != 0)
---
@@ -599,9 +599,9 @@ not ok 64 - floatComparisons(should FAIL: -inf != 0)
found: -inf (operandLeft)
expected: 0 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 65 - floatComparisons(should FAIL: 0 != -inf)
---
@@ -611,9 +611,9 @@ not ok 65 - floatComparisons(should FAIL: 0 != -inf)
found: 0 (operandLeft)
expected: -inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 66 - floatComparisons(should FAIL: inf != 1)
---
@@ -623,9 +623,9 @@ not ok 66 - floatComparisons(should FAIL: inf != 1)
found: inf (operandLeft)
expected: 1 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 67 - floatComparisons(should FAIL: 1 != inf)
---
@@ -635,9 +635,9 @@ not ok 67 - floatComparisons(should FAIL: 1 != inf)
found: 1 (operandLeft)
expected: inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 68 - floatComparisons(should FAIL: -inf != 1)
---
@@ -647,9 +647,9 @@ not ok 68 - floatComparisons(should FAIL: -inf != 1)
found: -inf (operandLeft)
expected: 1 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 69 - floatComparisons(should FAIL: 1 != -inf)
---
@@ -659,9 +659,9 @@ not ok 69 - floatComparisons(should FAIL: 1 != -inf)
found: 1 (operandLeft)
expected: -inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 70 - floatComparisons(should FAIL: inf != max)
---
@@ -671,9 +671,9 @@ not ok 70 - floatComparisons(should FAIL: inf != max)
found: inf (operandLeft)
expected: 3.40282e+38 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 71 - floatComparisons(should FAIL: inf != -max)
---
@@ -683,9 +683,9 @@ not ok 71 - floatComparisons(should FAIL: inf != -max)
found: inf (operandLeft)
expected: -3.40282e+38 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 72 - floatComparisons(should FAIL: max != inf)
---
@@ -695,9 +695,9 @@ not ok 72 - floatComparisons(should FAIL: max != inf)
found: 3.40282e+38 (operandLeft)
expected: inf (operandRight)
actual: 3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 73 - floatComparisons(should FAIL: -max != inf)
---
@@ -707,9 +707,9 @@ not ok 73 - floatComparisons(should FAIL: -max != inf)
found: -3.40282e+38 (operandLeft)
expected: inf (operandRight)
actual: -3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 74 - floatComparisons(should FAIL: -inf != max)
---
@@ -719,9 +719,9 @@ not ok 74 - floatComparisons(should FAIL: -inf != max)
found: -inf (operandLeft)
expected: 3.40282e+38 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 75 - floatComparisons(should FAIL: -inf != -max)
---
@@ -731,9 +731,9 @@ not ok 75 - floatComparisons(should FAIL: -inf != -max)
found: -inf (operandLeft)
expected: -3.40282e+38 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 76 - floatComparisons(should FAIL: max != -inf)
---
@@ -743,9 +743,9 @@ not ok 76 - floatComparisons(should FAIL: max != -inf)
found: 3.40282e+38 (operandLeft)
expected: -inf (operandRight)
actual: 3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
not ok 77 - floatComparisons(should FAIL: -max != -inf)
---
@@ -755,12 +755,11 @@ not ok 77 - floatComparisons(should FAIL: -max != -inf)
found: -3.40282e+38 (operandLeft)
expected: -inf (operandRight)
actual: -3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:127)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 127
+ line: 137
...
-ok 78 - float16Comparisons(should SUCCEED 1)
-not ok 79 - float16Comparisons(should FAIL 1)
+not ok 78 - float16Comparisons(should FAIL 1)
---
type: QCOMPARE
message: Compared qfloat16s are not the same (fuzzy compare)
@@ -768,10 +767,11 @@ not ok 79 - float16Comparisons(should FAIL 1)
found: 1 (operandLeft)
expected: 3 (operandRight)
actual: 1 (operandLeft)
- at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:200)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 200
+ line: 171
...
+ok 79 - float16Comparisons(should PASS 1)
not ok 80 - float16Comparisons(should FAIL 2)
---
type: QCOMPARE
@@ -780,11 +780,12 @@ not ok 80 - float16Comparisons(should FAIL 2)
found: 0.0001 (operandLeft)
expected: 0.0003 (operandRight)
actual: 0.0001 (operandLeft)
- at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:200)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 200
+ line: 171
...
-not ok 81 - float16Comparisons(should FAIL 3)
+ok 81 - float16Comparisons(should PASS 2)
+not ok 82 - float16Comparisons(should FAIL 3)
---
type: QCOMPARE
message: Compared qfloat16s are not the same (fuzzy compare)
@@ -792,12 +793,352 @@ not ok 81 - float16Comparisons(should FAIL 3)
found: 98 (operandLeft)
expected: 99 (operandRight)
actual: 98 (operandLeft)
- at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:200)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 200
+ line: 171
...
-ok 82 - float16Comparisons(should SUCCEED 2)
-not ok 83 - compareFloatTests(1e0)
+ok 83 - float16Comparisons(should PASS 3)
+not ok 84 - float16Comparisons(should FAIL 4)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 5.87e-05 (operandRight)
+ found: 5.93e-05 (operandLeft)
+ expected: 5.87e-05 (operandRight)
+ actual: 5.93e-05 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 85 - float16Comparisons(should PASS 4)
+not ok 86 - float16Comparisons(should FAIL 5)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 5.88e+04 (operandRight)
+ found: 5.94e+04 (operandLeft)
+ expected: 5.88e+04 (operandRight)
+ actual: 5.94e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 87 - float16Comparisons(should PASS: NaN == NaN)
+not ok 88 - float16Comparisons(should FAIL: NaN != 0)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0 (operandRight)
+ found: nan (operandLeft)
+ expected: 0 (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 89 - float16Comparisons(should FAIL: 0 != NaN)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: 0 (operandLeft)
+ expected: nan (operandRight)
+ actual: 0 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 90 - float16Comparisons(should FAIL: NaN != 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 1 (operandRight)
+ found: nan (operandLeft)
+ expected: 1 (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 91 - float16Comparisons(should FAIL: 1 != NaN)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: 1 (operandLeft)
+ expected: nan (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 92 - float16Comparisons(should PASS: inf == inf)
+ok 93 - float16Comparisons(should PASS: -inf == -inf)
+not ok 94 - float16Comparisons(should FAIL: inf != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: inf (operandLeft)
+ expected: -inf (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 95 - float16Comparisons(should FAIL: -inf != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: -inf (operandLeft)
+ expected: inf (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 96 - float16Comparisons(should FAIL: inf != nan)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: inf (operandLeft)
+ expected: nan (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 97 - float16Comparisons(should FAIL: nan != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: nan (operandLeft)
+ expected: inf (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 98 - float16Comparisons(should FAIL: -inf != nan)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: -inf (operandLeft)
+ expected: nan (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 99 - float16Comparisons(should FAIL: nan != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: nan (operandLeft)
+ expected: -inf (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 100 - float16Comparisons(should FAIL: inf != 0)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0 (operandRight)
+ found: inf (operandLeft)
+ expected: 0 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 101 - float16Comparisons(should FAIL: 0 != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: 0 (operandLeft)
+ expected: inf (operandRight)
+ actual: 0 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 102 - float16Comparisons(should FAIL: -inf != 0)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0 (operandRight)
+ found: -inf (operandLeft)
+ expected: 0 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 103 - float16Comparisons(should FAIL: 0 != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: 0 (operandLeft)
+ expected: -inf (operandRight)
+ actual: 0 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 104 - float16Comparisons(should FAIL: inf != 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 1 (operandRight)
+ found: inf (operandLeft)
+ expected: 1 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 105 - float16Comparisons(should FAIL: 1 != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: 1 (operandLeft)
+ expected: inf (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 106 - float16Comparisons(should FAIL: -inf != 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 1 (operandRight)
+ found: -inf (operandLeft)
+ expected: 1 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 107 - float16Comparisons(should FAIL: 1 != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: 1 (operandLeft)
+ expected: -inf (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 108 - float16Comparisons(should FAIL: inf != max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 6.55e+04 (operandRight)
+ found: inf (operandLeft)
+ expected: 6.55e+04 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 109 - float16Comparisons(should FAIL: inf != -max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -6.55e+04 (operandRight)
+ found: inf (operandLeft)
+ expected: -6.55e+04 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 110 - float16Comparisons(should FAIL: max != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: 6.55e+04 (operandLeft)
+ expected: inf (operandRight)
+ actual: 6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 111 - float16Comparisons(should FAIL: -max != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: -6.55e+04 (operandLeft)
+ expected: inf (operandRight)
+ actual: -6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 112 - float16Comparisons(should FAIL: -inf != max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 6.55e+04 (operandRight)
+ found: -inf (operandLeft)
+ expected: 6.55e+04 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 113 - float16Comparisons(should FAIL: -inf != -max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -6.55e+04 (operandRight)
+ found: -inf (operandLeft)
+ expected: -6.55e+04 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 114 - float16Comparisons(should FAIL: max != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: 6.55e+04 (operandLeft)
+ expected: -inf (operandRight)
+ actual: 6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 115 - float16Comparisons(should FAIL: -max != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: -6.55e+04 (operandLeft)
+ expected: -inf (operandRight)
+ actual: -6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 116 - compareFloatTests(1e0)
---
type: QCOMPARE
message: Compared floats are not the same (fuzzy compare)
@@ -805,11 +1146,11 @@ not ok 83 - compareFloatTests(1e0)
found: 1 (t1)
expected: 3 (t3)
actual: 1 (t1)
- at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:245)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 245
+ line: 210
...
-not ok 84 - compareFloatTests(1e-7)
+not ok 117 - compareFloatTests(1e-7)
---
type: QCOMPARE
message: Compared floats are not the same (fuzzy compare)
@@ -817,11 +1158,11 @@ not ok 84 - compareFloatTests(1e-7)
found: 1e-07 (t1)
expected: 3e-07 (t3)
actual: 1e-07 (t1)
- at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:245)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 245
+ line: 210
...
-not ok 85 - compareFloatTests(1e+7)
+not ok 118 - compareFloatTests(1e+7)
---
type: QCOMPARE
message: Compared floats are not the same (fuzzy compare)
@@ -829,12 +1170,12 @@ not ok 85 - compareFloatTests(1e+7)
found: 1e+07 (t1)
expected: 3e+07 (t3)
actual: 1e+07 (t1)
- at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:245)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 245
+ line: 210
...
-ok 86 - cleanupTestCase()
-1..86
-# tests 86
-# pass 18
-# fail 68
+ok 119 - cleanupTestCase()
+1..119
+# tests 119
+# pass 23
+# fail 96
diff --git a/tests/auto/testlib/selftests/expected_float.teamcity b/tests/auto/testlib/selftests/expected_float.teamcity
index e23bc722b1..af81296c42 100644
--- a/tests/auto/testlib/selftests/expected_float.teamcity
+++ b/tests/auto/testlib/selftests/expected_float.teamcity
@@ -1,11 +1,11 @@
##teamcity[testSuiteStarted name='tst_float' flowId='tst_float']
##teamcity[testStarted name='initTestCase()' flowId='tst_float']
##teamcity[testFinished name='initTestCase()' flowId='tst_float']
-##teamcity[testStarted name='doubleComparisons(should PASS 1)' flowId='tst_float']
-##teamcity[testFinished name='doubleComparisons(should PASS 1)' flowId='tst_float']
##teamcity[testStarted name='doubleComparisons(should FAIL 1)' flowId='tst_float']
##teamcity[testFailed name='doubleComparisons(should FAIL 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared doubles are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): 3' flowId='tst_float']
##teamcity[testFinished name='doubleComparisons(should FAIL 1)' flowId='tst_float']
+##teamcity[testStarted name='doubleComparisons(should PASS 1)' flowId='tst_float']
+##teamcity[testFinished name='doubleComparisons(should PASS 1)' flowId='tst_float']
##teamcity[testStarted name='doubleComparisons(should FAIL 2)' flowId='tst_float']
##teamcity[testFailed name='doubleComparisons(should FAIL 2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared doubles are not the same (fuzzy compare)|n Actual (operandLeft) : 1e-07|n Expected (operandRight): 3e-07' flowId='tst_float']
##teamcity[testFinished name='doubleComparisons(should FAIL 2)' flowId='tst_float']
@@ -215,19 +215,113 @@
##teamcity[testStarted name='floatComparisons(should FAIL: -max != -inf)' flowId='tst_float']
##teamcity[testFailed name='floatComparisons(should FAIL: -max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared floats are not the same (fuzzy compare)|n Actual (operandLeft) : -3.40282e+38|n Expected (operandRight): -inf' flowId='tst_float']
##teamcity[testFinished name='floatComparisons(should FAIL: -max != -inf)' flowId='tst_float']
-##teamcity[testStarted name='float16Comparisons(should SUCCEED 1)' flowId='tst_float']
-##teamcity[testFinished name='float16Comparisons(should SUCCEED 1)' flowId='tst_float']
##teamcity[testStarted name='float16Comparisons(should FAIL 1)' flowId='tst_float']
##teamcity[testFailed name='float16Comparisons(should FAIL 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): 3' flowId='tst_float']
##teamcity[testFinished name='float16Comparisons(should FAIL 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 1)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 1)' flowId='tst_float']
##teamcity[testStarted name='float16Comparisons(should FAIL 2)' flowId='tst_float']
##teamcity[testFailed name='float16Comparisons(should FAIL 2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0.0001|n Expected (operandRight): 0.0003' flowId='tst_float']
##teamcity[testFinished name='float16Comparisons(should FAIL 2)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 2)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 2)' flowId='tst_float']
##teamcity[testStarted name='float16Comparisons(should FAIL 3)' flowId='tst_float']
##teamcity[testFailed name='float16Comparisons(should FAIL 3)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 98|n Expected (operandRight): 99' flowId='tst_float']
##teamcity[testFinished name='float16Comparisons(should FAIL 3)' flowId='tst_float']
-##teamcity[testStarted name='float16Comparisons(should SUCCEED 2)' flowId='tst_float']
-##teamcity[testFinished name='float16Comparisons(should SUCCEED 2)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 3)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 3)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 4)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 4)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 5.93e-05|n Expected (operandRight): 5.87e-05' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 4)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 4)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 4)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 5)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 5)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 5.94e+04|n Expected (operandRight): 5.88e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 5)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS: NaN == NaN)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS: NaN == NaN)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: NaN != 0)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: NaN != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): 0' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: NaN != 0)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != NaN)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != NaN)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != NaN)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: NaN != 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: NaN != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): 1' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: NaN != 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != NaN)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != NaN)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != NaN)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS: inf == inf)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS: inf == inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS: -inf == -inf)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS: -inf == -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != nan)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != nan)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != nan)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: nan != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: nan != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: nan != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != nan)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != nan)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != nan)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: nan != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: nan != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: nan != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != 0)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 0' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != 0)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != 0)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 0' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != 0)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 1' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 1' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != -max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != -max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): -6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != -max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: max != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: max != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 6.55e+04|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: max != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -max != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -max != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -6.55e+04|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -max != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != -max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != -max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): -6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != -max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: max != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 6.55e+04|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: max != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -max != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -6.55e+04|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -max != -inf)' flowId='tst_float']
##teamcity[testStarted name='compareFloatTests(1e0)' flowId='tst_float']
##teamcity[testFailed name='compareFloatTests(1e0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared floats are not the same (fuzzy compare)|n Actual (t1): 1|n Expected (t3): 3' flowId='tst_float']
##teamcity[testFinished name='compareFloatTests(1e0)' flowId='tst_float']
diff --git a/tests/auto/testlib/selftests/expected_float.txt b/tests/auto/testlib/selftests/expected_float.txt
index 6419a13f86..d22a52a63d 100644
--- a/tests/auto/testlib/selftests/expected_float.txt
+++ b/tests/auto/testlib/selftests/expected_float.txt
@@ -1,11 +1,11 @@
********* Start testing of tst_float *********
Config: Using QtTest library
PASS : tst_float::initTestCase()
-PASS : tst_float::doubleComparisons(should PASS 1)
FAIL! : tst_float::doubleComparisons(should FAIL 1) Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::doubleComparisons(should PASS 1)
FAIL! : tst_float::doubleComparisons(should FAIL 2) Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1e-07
Expected (operandRight): 3e-07
@@ -263,20 +263,137 @@ FAIL! : tst_float::floatComparisons(should FAIL: -max != -inf) Compared floats
Actual (operandLeft) : -3.40282e+38
Expected (operandRight): -inf
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
-PASS : tst_float::float16Comparisons(should SUCCEED 1)
FAIL! : tst_float::float16Comparisons(should FAIL 1) Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 1)
FAIL! : tst_float::float16Comparisons(should FAIL 2) Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 0.0001
Expected (operandRight): 0.0003
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 2)
FAIL! : tst_float::float16Comparisons(should FAIL 3) Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 98
Expected (operandRight): 99
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
-PASS : tst_float::float16Comparisons(should SUCCEED 2)
+PASS : tst_float::float16Comparisons(should PASS 3)
+FAIL! : tst_float::float16Comparisons(should FAIL 4) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e-05
+ Expected (operandRight): 5.87e-05
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 4)
+FAIL! : tst_float::float16Comparisons(should FAIL 5) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS: NaN == NaN)
+FAIL! : tst_float::float16Comparisons(should FAIL: NaN != 0) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 0 != NaN) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: NaN != 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 1 != NaN) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS: inf == inf)
+PASS : tst_float::float16Comparisons(should PASS: -inf == -inf)
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != nan) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: nan != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != nan) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: nan != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != 0) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 0 != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != 0) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 0
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 0 != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 1 != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 1
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 1 != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != -max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: max != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -max != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != -max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): -6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: max != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -max != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
FAIL! : tst_float::compareFloatTests(1e0) Compared floats are not the same (fuzzy compare)
Actual (t1): 1
Expected (t3): 3
@@ -290,5 +407,5 @@ FAIL! : tst_float::compareFloatTests(1e+7) Compared floats are not the same (fu
Expected (t3): 3e+07
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
PASS : tst_float::cleanupTestCase()
-Totals: 18 passed, 68 failed, 0 skipped, 0 blacklisted, 0ms
+Totals: 23 passed, 96 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_float *********
diff --git a/tests/auto/testlib/selftests/expected_float.xml b/tests/auto/testlib/selftests/expected_float.xml
index 65d2c5ad96..247bce9577 100644
--- a/tests/auto/testlib/selftests/expected_float.xml
+++ b/tests/auto/testlib/selftests/expected_float.xml
@@ -10,15 +10,15 @@
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="doubleComparisons">
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should PASS 1]]></DataTag>
-</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 1]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 2]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
@@ -430,21 +430,24 @@
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="float16Comparisons">
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should SUCCEED 1]]></DataTag>
-</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 1]]></DataTag>
<Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 2]]></DataTag>
<Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 0.0001
Expected (operandRight): 0.0003]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 2]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 3]]></DataTag>
<Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
@@ -452,7 +455,187 @@
Expected (operandRight): 99]]></Description>
</Incident>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should SUCCEED 2]]></DataTag>
+ <DataTag><![CDATA[should PASS 3]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 4]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e-05
+ Expected (operandRight): 5.87e-05]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 4]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 5]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: NaN == NaN]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: inf == inf]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: -inf == -inf]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): -inf]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_float.xunitxml b/tests/auto/testlib/selftests/expected_float.xunitxml
index 9b2af9b616..602f9252a4 100644
--- a/tests/auto/testlib/selftests/expected_float.xunitxml
+++ b/tests/auto/testlib/selftests/expected_float.xunitxml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<testsuite errors="0" failures="68" tests="6" name="tst_float">
+<testsuite errors="0" failures="96" tests="6" name="tst_float">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
@@ -206,6 +206,90 @@
<failure tag="should FAIL 3" message="Compared qfloat16s are not the same (fuzzy compare)
Actual (operandLeft) : 98
Expected (operandRight): 99" result="fail"/>
+ <failure tag="should FAIL 4" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e&#x002D;05
+ Expected (operandRight): 5.87e&#x002D;05" result="fail"/>
+ <failure tag="should FAIL 5" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04" result="fail"/>
+ <failure tag="should FAIL: NaN != 0" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0" result="fail"/>
+ <failure tag="should FAIL: 0 != NaN" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: NaN != 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1" result="fail"/>
+ <failure tag="should FAIL: 1 != NaN" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: inf != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: inf != nan" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: nan != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != nan" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: nan != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: inf != 0" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0" result="fail"/>
+ <failure tag="should FAIL: 0 != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != 0" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): 0" result="fail"/>
+ <failure tag="should FAIL: 0 != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: inf != 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1" result="fail"/>
+ <failure tag="should FAIL: 1 != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): 1" result="fail"/>
+ <failure tag="should FAIL: 1 != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: inf != max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04" result="fail"/>
+ <failure tag="should FAIL: inf != &#x002D;max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): &#x002D;6.55e+04" result="fail"/>
+ <failure tag="should FAIL: max != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;max != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;6.55e+04
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): 6.55e+04" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != &#x002D;max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): &#x002D;6.55e+04" result="fail"/>
+ <failure tag="should FAIL: max != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;max != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;6.55e+04
+ Expected (operandRight): &#x002D;inf" result="fail"/>
</testcase>
<testcase result="fail" name="compareFloatTests">
<failure tag="1e0" message="Compared floats are not the same (fuzzy compare)
diff --git a/tests/auto/testlib/selftests/expected_globaldata.lightxml b/tests/auto/testlib/selftests/expected_globaldata.lightxml
index f66c4c552d..1212e4b364 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.lightxml
+++ b/tests/auto/testlib/selftests/expected_globaldata.lightxml
@@ -12,174 +12,195 @@
</TestFunction>
<TestFunction name="testGlobal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skip">
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1]]></DataTag>
+ <DataTag><![CDATA[global=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipLocal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipSingle">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
-<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[global: false local: true]]></Description>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
-</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[skipping]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_globaldata.tap b/tests/auto/testlib/selftests/expected_globaldata.tap
index 580cf3a7a8..4d61b7437b 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.tap
+++ b/tests/auto/testlib/selftests/expected_globaldata.tap
@@ -2,51 +2,56 @@ TAP version 13
# tst_globaldata
# initTestCase initTestCase (null)
ok 1 - initTestCase()
-# init testGlobal local 1
+# init testGlobal local=false
# global: false
# local: false
-# cleanup testGlobal local 1
-ok 2 - testGlobal(1:local 1)
-# init testGlobal local 2
+# cleanup testGlobal local=false
+ok 2 - testGlobal(global=false:local=false)
+# init testGlobal local=true
# global: false
# local: true
-# cleanup testGlobal local 2
-ok 3 - testGlobal(1:local 2)
-# init testGlobal local 1
+# cleanup testGlobal local=true
+ok 3 - testGlobal(global=false:local=true)
+# init testGlobal local=false
# global: true
# local: false
-# cleanup testGlobal local 1
-ok 4 - testGlobal(2:local 1)
-# init testGlobal local 2
+# cleanup testGlobal local=false
+ok 4 - testGlobal(global=true:local=false)
+# init testGlobal local=true
# global: true
# local: true
-# cleanup testGlobal local 2
-ok 5 - testGlobal(2:local 2)
-ok 6 - skip(1) # SKIP skipping
-# init skipLocal local 1
-ok 7 - skipLocal(1:local 1) # SKIP skipping
-# cleanup skipLocal local 1
-# init skipLocal local 2
-ok 8 - skipLocal(1:local 2) # SKIP skipping
-# cleanup skipLocal local 2
-# init skipSingle local 1
+# cleanup testGlobal local=true
+ok 5 - testGlobal(global=true:local=true)
+ok 6 - skip(global=false) # SKIP skipping
+# init skipLocal local=false
+ok 7 - skipLocal(global=false:local=false) # SKIP skipping
+# cleanup skipLocal local=false
+# init skipLocal local=true
+ok 8 - skipLocal(global=false:local=true) # SKIP skipping
+# cleanup skipLocal local=true
+# init skipLocal local=false
+ok 9 - skipLocal(global=true:local=false) # SKIP skipping
+# cleanup skipLocal local=false
+# init skipLocal local=true
+ok 10 - skipLocal(global=true:local=true) # SKIP skipping
+# cleanup skipLocal local=true
+# init skipSingle local=false
# global: false local: false
-# cleanup skipSingle local 1
-ok 9 - skipSingle(1:local 1)
-# init skipSingle local 2
-# global: false local: true
-# cleanup skipSingle local 2
-ok 10 - skipSingle(1:local 2)
-# init skipSingle local 1
-ok 11 - skipSingle(2:local 1) # SKIP skipping
-# cleanup skipSingle local 1
-# init skipSingle local 2
+# cleanup skipSingle local=false
+ok 11 - skipSingle(global=false:local=false)
+# init skipSingle local=true
+ok 12 - skipSingle(global=false:local=true) # SKIP Skipping
+# cleanup skipSingle local=true
+# init skipSingle local=false
+ok 13 - skipSingle(global=true:local=false) # SKIP Skipping
+# cleanup skipSingle local=false
+# init skipSingle local=true
# global: true local: true
-# cleanup skipSingle local 2
-ok 12 - skipSingle(2:local 2)
+# cleanup skipSingle local=true
+ok 14 - skipSingle(global=true:local=true)
# cleanupTestCase cleanupTestCase (null)
-ok 13 - cleanupTestCase()
-1..13
-# tests 13
-# pass 9
+ok 15 - cleanupTestCase()
+1..15
+# tests 15
+# pass 8
# fail 0
diff --git a/tests/auto/testlib/selftests/expected_globaldata.teamcity b/tests/auto/testlib/selftests/expected_globaldata.teamcity
index 5d623a3285..f76f6090ba 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.teamcity
+++ b/tests/auto/testlib/selftests/expected_globaldata.teamcity
@@ -2,30 +2,31 @@
##teamcity[testStarted name='initTestCase()' flowId='tst_globaldata']
##teamcity[testStdOut name='initTestCase()' out='QDEBUG: initTestCase initTestCase (null)' flowId='tst_globaldata']
##teamcity[testFinished name='initTestCase()' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 1)' out='QDEBUG: init testGlobal local 1|nQDEBUG: global: false|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local 1' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 2)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 2)' out='QDEBUG: init testGlobal local 2|nQDEBUG: global: false|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 2)' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 1)' out='QDEBUG: init testGlobal local 1|nQDEBUG: global: true|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local 1' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 2)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 2)' out='QDEBUG: init testGlobal local 2|nQDEBUG: global: true|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 2)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=false)' out='QDEBUG: init testGlobal local=false|nQDEBUG: global: false|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local=false' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=true)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=true)' out='QDEBUG: init testGlobal local=true|nQDEBUG: global: false|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local=true' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=true)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=false)' out='QDEBUG: init testGlobal local=false|nQDEBUG: global: true|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local=false' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=true)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=true)' out='QDEBUG: init testGlobal local=true|nQDEBUG: global: true|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local=true' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=true)' flowId='tst_globaldata']
##teamcity[testIgnored name='skip()' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testIgnored name='skipLocal(local 1)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testIgnored name='skipLocal(local 2)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testStarted name='skipSingle(local 1)' flowId='tst_globaldata']
-##teamcity[testStdOut name='skipSingle(local 1)' out='QDEBUG: init skipLocal local 1|nQDEBUG: cleanup skipLocal local 1|nQDEBUG: init skipLocal local 2|nQDEBUG: cleanup skipLocal local 2|nQDEBUG: init skipSingle local 1|nQDEBUG: global: false local: false|nQDEBUG: cleanup skipSingle local 1' flowId='tst_globaldata']
-##teamcity[testFinished name='skipSingle(local 1)' flowId='tst_globaldata']
-##teamcity[testStarted name='skipSingle(local 2)' flowId='tst_globaldata']
-##teamcity[testStdOut name='skipSingle(local 2)' out='QDEBUG: init skipSingle local 2|nQDEBUG: global: false local: true|nQDEBUG: cleanup skipSingle local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='skipSingle(local 2)' flowId='tst_globaldata']
-##teamcity[testIgnored name='skipSingle(local 1)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testStdOut name='skipSingle(local 2)' out='QDEBUG: init skipSingle local 1|nQDEBUG: cleanup skipSingle local 1|nQDEBUG: init skipSingle local 2|nQDEBUG: global: true local: true|nQDEBUG: cleanup skipSingle local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='skipSingle(local 2)' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=false)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=true)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=false)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=true)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testStarted name='skipSingle(local=false)' flowId='tst_globaldata']
+##teamcity[testStdOut name='skipSingle(local=false)' out='QDEBUG: init skipLocal local=false|nQDEBUG: cleanup skipLocal local=false|nQDEBUG: init skipLocal local=true|nQDEBUG: cleanup skipLocal local=true|nQDEBUG: init skipLocal local=false|nQDEBUG: cleanup skipLocal local=false|nQDEBUG: init skipLocal local=true|nQDEBUG: cleanup skipLocal local=true|nQDEBUG: init skipSingle local=false|nQDEBUG: global: false local: false|nQDEBUG: cleanup skipSingle local=false' flowId='tst_globaldata']
+##teamcity[testFinished name='skipSingle(local=false)' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipSingle(local=true)' message='Skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipSingle(local=false)' message='Skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testStarted name='skipSingle(local=true)' flowId='tst_globaldata']
+##teamcity[testStdOut name='skipSingle(local=true)' out='QDEBUG: init skipSingle local=true|nQDEBUG: cleanup skipSingle local=true|nQDEBUG: init skipSingle local=false|nQDEBUG: cleanup skipSingle local=false|nQDEBUG: init skipSingle local=true|nQDEBUG: global: true local: true|nQDEBUG: cleanup skipSingle local=true' flowId='tst_globaldata']
+##teamcity[testFinished name='skipSingle(local=true)' flowId='tst_globaldata']
##teamcity[testStarted name='cleanupTestCase()' flowId='tst_globaldata']
##teamcity[testStdOut name='cleanupTestCase()' out='QDEBUG: cleanupTestCase cleanupTestCase (null)' flowId='tst_globaldata']
##teamcity[testFinished name='cleanupTestCase()' flowId='tst_globaldata']
diff --git a/tests/auto/testlib/selftests/expected_globaldata.txt b/tests/auto/testlib/selftests/expected_globaldata.txt
index b12f4a2a69..016b5e8299 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.txt
+++ b/tests/auto/testlib/selftests/expected_globaldata.txt
@@ -2,53 +2,61 @@
Config: Using QtTest library
QDEBUG : tst_globaldata::initTestCase() initTestCase initTestCase (null)
PASS : tst_globaldata::initTestCase()
-QDEBUG : tst_globaldata::testGlobal(1:local 1) init testGlobal local 1
-QDEBUG : tst_globaldata::testGlobal(1:local 1) global: false
-QDEBUG : tst_globaldata::testGlobal(1:local 1) local: false
-QDEBUG : tst_globaldata::testGlobal(1:local 1) cleanup testGlobal local 1
-PASS : tst_globaldata::testGlobal(1:local 1)
-QDEBUG : tst_globaldata::testGlobal(1:local 2) init testGlobal local 2
-QDEBUG : tst_globaldata::testGlobal(1:local 2) global: false
-QDEBUG : tst_globaldata::testGlobal(1:local 2) local: true
-QDEBUG : tst_globaldata::testGlobal(1:local 2) cleanup testGlobal local 2
-PASS : tst_globaldata::testGlobal(1:local 2)
-QDEBUG : tst_globaldata::testGlobal(2:local 1) init testGlobal local 1
-QDEBUG : tst_globaldata::testGlobal(2:local 1) global: true
-QDEBUG : tst_globaldata::testGlobal(2:local 1) local: false
-QDEBUG : tst_globaldata::testGlobal(2:local 1) cleanup testGlobal local 1
-PASS : tst_globaldata::testGlobal(2:local 1)
-QDEBUG : tst_globaldata::testGlobal(2:local 2) init testGlobal local 2
-QDEBUG : tst_globaldata::testGlobal(2:local 2) global: true
-QDEBUG : tst_globaldata::testGlobal(2:local 2) local: true
-QDEBUG : tst_globaldata::testGlobal(2:local 2) cleanup testGlobal local 2
-PASS : tst_globaldata::testGlobal(2:local 2)
-SKIP : tst_globaldata::skip(1) skipping
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) init testGlobal local=false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) global: false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) local: false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) cleanup testGlobal local=false
+PASS : tst_globaldata::testGlobal(global=false:local=false)
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) init testGlobal local=true
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) global: false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) local: true
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) cleanup testGlobal local=true
+PASS : tst_globaldata::testGlobal(global=false:local=true)
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) init testGlobal local=false
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) global: true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) local: false
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) cleanup testGlobal local=false
+PASS : tst_globaldata::testGlobal(global=true:local=false)
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) init testGlobal local=true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) global: true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) local: true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) cleanup testGlobal local=true
+PASS : tst_globaldata::testGlobal(global=true:local=true)
+SKIP : tst_globaldata::skip(global=false) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipLocal(1:local 1) init skipLocal local 1
-SKIP : tst_globaldata::skipLocal(1:local 1) skipping
+QDEBUG : tst_globaldata::skipLocal(global=false:local=false) init skipLocal local=false
+SKIP : tst_globaldata::skipLocal(global=false:local=false) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipLocal(1:local 1) cleanup skipLocal local 1
-QDEBUG : tst_globaldata::skipLocal(1:local 2) init skipLocal local 2
-SKIP : tst_globaldata::skipLocal(1:local 2) skipping
+QDEBUG : tst_globaldata::skipLocal(global=false:local=false) cleanup skipLocal local=false
+QDEBUG : tst_globaldata::skipLocal(global=false:local=true) init skipLocal local=true
+SKIP : tst_globaldata::skipLocal(global=false:local=true) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipLocal(1:local 2) cleanup skipLocal local 2
-QDEBUG : tst_globaldata::skipSingle(1:local 1) init skipSingle local 1
-QDEBUG : tst_globaldata::skipSingle(1:local 1) global: false local: false
-QDEBUG : tst_globaldata::skipSingle(1:local 1) cleanup skipSingle local 1
-PASS : tst_globaldata::skipSingle(1:local 1)
-QDEBUG : tst_globaldata::skipSingle(1:local 2) init skipSingle local 2
-QDEBUG : tst_globaldata::skipSingle(1:local 2) global: false local: true
-QDEBUG : tst_globaldata::skipSingle(1:local 2) cleanup skipSingle local 2
-PASS : tst_globaldata::skipSingle(1:local 2)
-QDEBUG : tst_globaldata::skipSingle(2:local 1) init skipSingle local 1
-SKIP : tst_globaldata::skipSingle(2:local 1) skipping
+QDEBUG : tst_globaldata::skipLocal(global=false:local=true) cleanup skipLocal local=true
+QDEBUG : tst_globaldata::skipLocal(global=true:local=false) init skipLocal local=false
+SKIP : tst_globaldata::skipLocal(global=true:local=false) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipSingle(2:local 1) cleanup skipSingle local 1
-QDEBUG : tst_globaldata::skipSingle(2:local 2) init skipSingle local 2
-QDEBUG : tst_globaldata::skipSingle(2:local 2) global: true local: true
-QDEBUG : tst_globaldata::skipSingle(2:local 2) cleanup skipSingle local 2
-PASS : tst_globaldata::skipSingle(2:local 2)
+QDEBUG : tst_globaldata::skipLocal(global=true:local=false) cleanup skipLocal local=false
+QDEBUG : tst_globaldata::skipLocal(global=true:local=true) init skipLocal local=true
+SKIP : tst_globaldata::skipLocal(global=true:local=true) skipping
+ Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
+QDEBUG : tst_globaldata::skipLocal(global=true:local=true) cleanup skipLocal local=true
+QDEBUG : tst_globaldata::skipSingle(global=false:local=false) init skipSingle local=false
+QDEBUG : tst_globaldata::skipSingle(global=false:local=false) global: false local: false
+QDEBUG : tst_globaldata::skipSingle(global=false:local=false) cleanup skipSingle local=false
+PASS : tst_globaldata::skipSingle(global=false:local=false)
+QDEBUG : tst_globaldata::skipSingle(global=false:local=true) init skipSingle local=true
+SKIP : tst_globaldata::skipSingle(global=false:local=true) Skipping
+ Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
+QDEBUG : tst_globaldata::skipSingle(global=false:local=true) cleanup skipSingle local=true
+QDEBUG : tst_globaldata::skipSingle(global=true:local=false) init skipSingle local=false
+SKIP : tst_globaldata::skipSingle(global=true:local=false) Skipping
+ Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
+QDEBUG : tst_globaldata::skipSingle(global=true:local=false) cleanup skipSingle local=false
+QDEBUG : tst_globaldata::skipSingle(global=true:local=true) init skipSingle local=true
+QDEBUG : tst_globaldata::skipSingle(global=true:local=true) global: true local: true
+QDEBUG : tst_globaldata::skipSingle(global=true:local=true) cleanup skipSingle local=true
+PASS : tst_globaldata::skipSingle(global=true:local=true)
QDEBUG : tst_globaldata::cleanupTestCase() cleanupTestCase cleanupTestCase (null)
PASS : tst_globaldata::cleanupTestCase()
-Totals: 9 passed, 0 failed, 4 skipped, 0 blacklisted, 0ms
+Totals: 8 passed, 0 failed, 7 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_globaldata *********
diff --git a/tests/auto/testlib/selftests/expected_globaldata.xml b/tests/auto/testlib/selftests/expected_globaldata.xml
index 0f705ef352..9aa48c8f16 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.xml
+++ b/tests/auto/testlib/selftests/expected_globaldata.xml
@@ -14,174 +14,195 @@
</TestFunction>
<TestFunction name="testGlobal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skip">
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1]]></DataTag>
+ <DataTag><![CDATA[global=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipLocal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipSingle">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
-<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[global: false local: true]]></Description>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
-</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[skipping]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_globaldata.xunitxml b/tests/auto/testlib/selftests/expected_globaldata.xunitxml
index bdd7e3f00a..de184c2fdd 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.xunitxml
+++ b/tests/auto/testlib/selftests/expected_globaldata.xunitxml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<testsuite errors="37" failures="0" tests="6" name="tst_globaldata">
+<testsuite errors="43" failures="0" tests="6" name="tst_globaldata">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
@@ -9,88 +9,100 @@
<!-- message="initTestCase initTestCase (null)" type="qdebug" -->
</testcase>
<testcase result="pass" name="testGlobal">
- <!-- tag="1:local 1" message="init testGlobal local 1" type="qdebug" -->
- <!-- tag="1:local 1" message="global: false" type="qdebug" -->
- <!-- tag="1:local 1" message="local: false" type="qdebug" -->
- <!-- tag="1:local 1" message="cleanup testGlobal local 1" type="qdebug" -->
- <!-- tag="1:local 2" message="init testGlobal local 2" type="qdebug" -->
- <!-- tag="1:local 2" message="global: false" type="qdebug" -->
- <!-- tag="1:local 2" message="local: true" type="qdebug" -->
- <!-- tag="1:local 2" message="cleanup testGlobal local 2" type="qdebug" -->
- <!-- tag="2:local 1" message="init testGlobal local 1" type="qdebug" -->
- <!-- tag="2:local 1" message="global: true" type="qdebug" -->
- <!-- tag="2:local 1" message="local: false" type="qdebug" -->
- <!-- tag="2:local 1" message="cleanup testGlobal local 1" type="qdebug" -->
- <!-- tag="2:local 2" message="init testGlobal local 2" type="qdebug" -->
- <!-- tag="2:local 2" message="global: true" type="qdebug" -->
- <!-- tag="2:local 2" message="local: true" type="qdebug" -->
- <!-- tag="2:local 2" message="cleanup testGlobal local 2" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="init testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="global: false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="local: false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="cleanup testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="init testGlobal local=true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="global: false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="local: true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="cleanup testGlobal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="init testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="global: true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="local: false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="cleanup testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="init testGlobal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="global: true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="local: true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="cleanup testGlobal local=true" type="qdebug" -->
</testcase>
<testcase name="skip">
- <!-- tag="1" message="skipping" type="skip" -->
+ <!-- tag="global=false" message="skipping" type="skip" -->
</testcase>
<testcase name="skipLocal">
- <!-- tag="1:local 1" message="init skipLocal local 1" type="qdebug" -->
- <!-- tag="1:local 1" message="skipping" type="skip" -->
- <!-- tag="1:local 1" message="cleanup skipLocal local 1" type="qdebug" -->
- <!-- tag="1:local 2" message="init skipLocal local 2" type="qdebug" -->
- <!-- tag="1:local 2" message="skipping" type="skip" -->
- <!-- tag="1:local 2" message="cleanup skipLocal local 2" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="init skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="skipping" type="skip" -->
+ <!-- tag="global=false:local=false" message="cleanup skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="init skipLocal local=true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="skipping" type="skip" -->
+ <!-- tag="global=false:local=true" message="cleanup skipLocal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="init skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="skipping" type="skip" -->
+ <!-- tag="global=true:local=false" message="cleanup skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="init skipLocal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="skipping" type="skip" -->
+ <!-- tag="global=true:local=true" message="cleanup skipLocal local=true" type="qdebug" -->
</testcase>
<testcase result="pass" name="skipSingle">
- <!-- tag="1:local 1" message="init skipSingle local 1" type="qdebug" -->
- <!-- tag="1:local 1" message="global: false local: false" type="qdebug" -->
- <!-- tag="1:local 1" message="cleanup skipSingle local 1" type="qdebug" -->
- <!-- tag="1:local 2" message="init skipSingle local 2" type="qdebug" -->
- <!-- tag="1:local 2" message="global: false local: true" type="qdebug" -->
- <!-- tag="1:local 2" message="cleanup skipSingle local 2" type="qdebug" -->
- <!-- tag="2:local 1" message="init skipSingle local 1" type="qdebug" -->
- <!-- tag="2:local 1" message="skipping" type="skip" -->
- <!-- tag="2:local 1" message="cleanup skipSingle local 1" type="qdebug" -->
- <!-- tag="2:local 2" message="init skipSingle local 2" type="qdebug" -->
- <!-- tag="2:local 2" message="global: true local: true" type="qdebug" -->
- <!-- tag="2:local 2" message="cleanup skipSingle local 2" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="init skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="global: false local: false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="cleanup skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="init skipSingle local=true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="Skipping" type="skip" -->
+ <!-- tag="global=false:local=true" message="cleanup skipSingle local=true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="init skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="Skipping" type="skip" -->
+ <!-- tag="global=true:local=false" message="cleanup skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="init skipSingle local=true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="global: true local: true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="cleanup skipSingle local=true" type="qdebug" -->
</testcase>
<testcase result="pass" name="cleanupTestCase">
<!-- message="cleanupTestCase cleanupTestCase (null)" type="qdebug" -->
</testcase>
<system-err>
<![CDATA[initTestCase initTestCase (null)]]>
-<![CDATA[init testGlobal local 1]]>
+<![CDATA[init testGlobal local=false]]>
<![CDATA[global: false]]>
<![CDATA[local: false]]>
-<![CDATA[cleanup testGlobal local 1]]>
-<![CDATA[init testGlobal local 2]]>
+<![CDATA[cleanup testGlobal local=false]]>
+<![CDATA[init testGlobal local=true]]>
<![CDATA[global: false]]>
<![CDATA[local: true]]>
-<![CDATA[cleanup testGlobal local 2]]>
-<![CDATA[init testGlobal local 1]]>
+<![CDATA[cleanup testGlobal local=true]]>
+<![CDATA[init testGlobal local=false]]>
<![CDATA[global: true]]>
<![CDATA[local: false]]>
-<![CDATA[cleanup testGlobal local 1]]>
-<![CDATA[init testGlobal local 2]]>
+<![CDATA[cleanup testGlobal local=false]]>
+<![CDATA[init testGlobal local=true]]>
<![CDATA[global: true]]>
<![CDATA[local: true]]>
-<![CDATA[cleanup testGlobal local 2]]>
+<![CDATA[cleanup testGlobal local=true]]>
<![CDATA[skipping]]>
-<![CDATA[init skipLocal local 1]]>
+<![CDATA[init skipLocal local=false]]>
<![CDATA[skipping]]>
-<![CDATA[cleanup skipLocal local 1]]>
-<![CDATA[init skipLocal local 2]]>
+<![CDATA[cleanup skipLocal local=false]]>
+<![CDATA[init skipLocal local=true]]>
<![CDATA[skipping]]>
-<![CDATA[cleanup skipLocal local 2]]>
-<![CDATA[init skipSingle local 1]]>
-<![CDATA[global: false local: false]]>
-<![CDATA[cleanup skipSingle local 1]]>
-<![CDATA[init skipSingle local 2]]>
-<![CDATA[global: false local: true]]>
-<![CDATA[cleanup skipSingle local 2]]>
-<![CDATA[init skipSingle local 1]]>
+<![CDATA[cleanup skipLocal local=true]]>
+<![CDATA[init skipLocal local=false]]>
+<![CDATA[skipping]]>
+<![CDATA[cleanup skipLocal local=false]]>
+<![CDATA[init skipLocal local=true]]>
<![CDATA[skipping]]>
-<![CDATA[cleanup skipSingle local 1]]>
-<![CDATA[init skipSingle local 2]]>
+<![CDATA[cleanup skipLocal local=true]]>
+<![CDATA[init skipSingle local=false]]>
+<![CDATA[global: false local: false]]>
+<![CDATA[cleanup skipSingle local=false]]>
+<![CDATA[init skipSingle local=true]]>
+<![CDATA[Skipping]]>
+<![CDATA[cleanup skipSingle local=true]]>
+<![CDATA[init skipSingle local=false]]>
+<![CDATA[Skipping]]>
+<![CDATA[cleanup skipSingle local=false]]>
+<![CDATA[init skipSingle local=true]]>
<![CDATA[global: true local: true]]>
-<![CDATA[cleanup skipSingle local 2]]>
+<![CDATA[cleanup skipSingle local=true]]>
<![CDATA[cleanupTestCase cleanupTestCase (null)]]>
</system-err>
</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.lightxml b/tests/auto/testlib/selftests/expected_signaldumper.lightxml
new file mode 100644
index 0000000000..f68834e1a2
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.lightxml
@@ -0,0 +1,578 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) started ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="noConnections">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlot">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlotOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlots">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlotsOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwarding">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwardingOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignal">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignalOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) emitSecondSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="variousTypes">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) finished ()]]></Description>
+</Message>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.tap b/tests/auto/testlib/selftests/expected_signaldumper.tap
new file mode 100644
index 0000000000..04d7d94745
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.tap
@@ -0,0 +1,151 @@
+TAP version 13
+# tst_Signaldumper
+# Signal: QThread(_POINTER_) started ()
+ok 1 - initTestCase()
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+ok 2 - noConnections()
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 3 - oneSlot(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 4 - oneSlot(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 5 - oneSlotOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 6 - oneSlotOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 7 - twoSlots(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 8 - twoSlots(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+# Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 9 - twoSlotsOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 10 - twoSlotsOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 11 - signalForwarding(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 12 - signalForwarding(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) nestedSignal()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) nestedSignal()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 13 - signalForwardingOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 14 - signalForwardingOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 15 - slotEmittingSignal(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 16 - slotEmittingSignal(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) emitSecondSignal()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 17 - slotEmittingSignalOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 18 - slotEmittingSignalOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))
+# Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)
+# Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))
+# Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))
+# Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())
+# Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())
+# Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)
+# Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())
+# Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)
+# Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()
+# Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+# Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+ok 19 - variousTypes()
+ok 20 - cleanupTestCase()
+# Signal: QThread(_POINTER_) finished ()
+1..20
+# tests 20
+# pass 20
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.teamcity b/tests/auto/testlib/selftests/expected_signaldumper.teamcity
new file mode 100644
index 0000000000..3b8cf8c54f
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.teamcity
@@ -0,0 +1,61 @@
+##teamcity[testSuiteStarted name='tst_Signaldumper' flowId='tst_Signaldumper']
+##teamcity[testStarted name='initTestCase()' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='initTestCase()' out='INFO: Signal: QThread(_POINTER_) started ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='initTestCase()' flowId='tst_Signaldumper']
+##teamcity[testStarted name='noConnections()' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='noConnections()' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))' flowId='tst_Signaldumper']
+##teamcity[testFinished name='noConnections()' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlot(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlot(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlot(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlot(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlot(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlot(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlotOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlotOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlotOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlotOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlotOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlotOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlots(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlots(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlots(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlots(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlots(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlots(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlotsOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlotsOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlotsOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlotsOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlotsOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlotsOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwarding(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwarding(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwarding(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwarding(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwarding(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwarding(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwardingOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwardingOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) nestedSignal()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) nestedSignal()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwardingOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwardingOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwardingOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwardingOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignal(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignal(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignal(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignal(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignal(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignal(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignalOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignalOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) emitSecondSignal()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignalOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignalOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignalOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignalOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='variousTypes()' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='variousTypes()' out='INFO: Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))|nINFO: Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))|nINFO: Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))|nINFO: Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())|nINFO: Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())' flowId='tst_Signaldumper']
+##teamcity[testFinished name='variousTypes()' flowId='tst_Signaldumper']
+##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Signaldumper']
+##teamcity[testSuiteFinished name='tst_Signaldumper' flowId='tst_Signaldumper']
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.txt b/tests/auto/testlib/selftests/expected_signaldumper.txt
new file mode 100644
index 0000000000..f89c31afe5
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.txt
@@ -0,0 +1,149 @@
+********* Start testing of tst_Signaldumper *********
+Config: Using QtTest library
+INFO : tst_Signaldumper::initTestCase() Signal: QThread(_POINTER_) started ()
+PASS : tst_Signaldumper::initTestCase()
+INFO : tst_Signaldumper::noConnections() Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::noConnections() Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+PASS : tst_Signaldumper::noConnections()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlot(direct)
+INFO : tst_Signaldumper::oneSlot(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlot(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlot(queued)
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlotOldSyntax(direct)
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlotOldSyntax(queued)
+INFO : tst_Signaldumper::twoSlots(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlots(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlots(direct)
+INFO : tst_Signaldumper::twoSlots(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlots(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlots(queued)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlotsOldSyntax(direct)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlotsOldSyntax(queued)
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::signalForwarding(direct)
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::signalForwarding(queued)
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) nestedSignal()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) nestedSignal()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::signalForwardingOldSyntax(direct)
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::signalForwardingOldSyntax(queued)
+INFO : tst_Signaldumper::slotEmittingSignal(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignal(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::slotEmittingSignal(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::slotEmittingSignal(direct)
+INFO : tst_Signaldumper::slotEmittingSignal(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignal(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::slotEmittingSignal(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::slotEmittingSignal(queued)
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) emitSecondSignal()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::slotEmittingSignalOldSyntax(direct)
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::slotEmittingSignalOldSyntax(queued)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+PASS : tst_Signaldumper::variousTypes()
+PASS : tst_Signaldumper::cleanupTestCase()
+INFO : tst_Signaldumper::UnknownTestFunc() Signal: QThread(_POINTER_) finished ()
+Totals: 20 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_Signaldumper *********
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xml b/tests/auto/testlib/selftests/expected_signaldumper.xml
new file mode 100644
index 0000000000..82959c62df
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.xml
@@ -0,0 +1,581 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_Signaldumper">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) started ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="noConnections">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlot">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlotOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlots">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlotsOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwarding">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwardingOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignal">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignalOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) emitSecondSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="variousTypes">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) finished ()]]></Description>
+</Message>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xunitxml b/tests/auto/testlib/selftests/expected_signaldumper.xunitxml
new file mode 100644
index 0000000000..930dc97262
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.xunitxml
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="125" failures="0" tests="12" name="tst_Signaldumper">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase">
+ <!-- message="Signal: QThread(_POINTER_) started ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="noConnections">
+ <!-- message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ </testcase>
+ <testcase result="pass" name="oneSlot">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="oneSlotOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="twoSlots">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="twoSlotsOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="signalForwarding">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="signalForwardingOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) nestedSignal()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) nestedSignal()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="slotEmittingSignal">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="slotEmittingSignalOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) emitSecondSignal()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="variousTypes">
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&amp;)@_POINTER_)" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qListSignal (QList&lt;int&gt;())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector&lt;int&gt;())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector&lt;int&gt;&amp;)@_POINTER_)" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector&lt;int&gt;())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector&lt;int&gt;*)_POINTER_)" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())" type="info" -->
+ </testcase>
+ <testcase result="pass" name="cleanupTestCase">
+ <!-- message="Signal: QThread(_POINTER_) finished ()" type="info" -->
+ </testcase>
+ <system-err>
+<![CDATA[Signal: QThread(_POINTER_) started ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) emitSecondSignal()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]>
+<![CDATA[Signal: QThread(_POINTER_) finished ()]]>
+ </system-err>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/float/tst_float.cpp b/tests/auto/testlib/selftests/float/tst_float.cpp
index 49d00ac0e0..cefd8a57c4 100644
--- a/tests/auto/testlib/selftests/float/tst_float.cpp
+++ b/tests/auto/testlib/selftests/float/tst_float.cpp
@@ -46,6 +46,55 @@ private slots:
void compareFloatTests_data() const;
};
+template<typename F>
+static void nonFinite_data(F zero, F one)
+{
+ using Bounds = std::numeric_limits<F>;
+
+ // QCOMPARE special-cases non-finite values
+ if (Bounds::has_quiet_NaN) {
+ const F nan = Bounds::quiet_NaN();
+ QTest::newRow("should PASS: NaN == NaN") << nan << nan;
+ QTest::newRow("should FAIL: NaN != 0") << nan << zero;
+ QTest::newRow("should FAIL: 0 != NaN") << zero << nan;
+ QTest::newRow("should FAIL: NaN != 1") << nan << one;
+ QTest::newRow("should FAIL: 1 != NaN") << one << nan;
+ }
+
+ if (Bounds::has_infinity) {
+ const F uge = Bounds::infinity();
+ QTest::newRow("should PASS: inf == inf") << uge << uge;
+ QTest::newRow("should PASS: -inf == -inf") << -uge << -uge;
+ QTest::newRow("should FAIL: inf != -inf") << uge << -uge;
+ QTest::newRow("should FAIL: -inf != inf") << -uge << uge;
+ if (Bounds::has_quiet_NaN) {
+ const F nan = Bounds::quiet_NaN();
+ QTest::newRow("should FAIL: inf != nan") << uge << nan;
+ QTest::newRow("should FAIL: nan != inf") << nan << uge;
+ QTest::newRow("should FAIL: -inf != nan") << -uge << nan;
+ QTest::newRow("should FAIL: nan != -inf") << nan << -uge;
+ }
+ QTest::newRow("should FAIL: inf != 0") << uge << zero;
+ QTest::newRow("should FAIL: 0 != inf") << zero << uge;
+ QTest::newRow("should FAIL: -inf != 0") << -uge << zero;
+ QTest::newRow("should FAIL: 0 != -inf") << zero << -uge;
+ QTest::newRow("should FAIL: inf != 1") << uge << one;
+ QTest::newRow("should FAIL: 1 != inf") << one << uge;
+ QTest::newRow("should FAIL: -inf != 1") << -uge << one;
+ QTest::newRow("should FAIL: 1 != -inf") << one << -uge;
+
+ const F big = Bounds::max();
+ QTest::newRow("should FAIL: inf != max") << uge << big;
+ QTest::newRow("should FAIL: inf != -max") << uge << -big;
+ QTest::newRow("should FAIL: max != inf") << big << uge;
+ QTest::newRow("should FAIL: -max != inf") << -big << uge;
+ QTest::newRow("should FAIL: -inf != max") << -uge << big;
+ QTest::newRow("should FAIL: -inf != -max") << -uge << -big;
+ QTest::newRow("should FAIL: max != -inf") << big << -uge;
+ QTest::newRow("should FAIL: -max != -inf") << -big << -uge;
+ }
+}
+
void tst_float::doubleComparisons() const
{
QFETCH(double, operandLeft);
@@ -58,65 +107,26 @@ void tst_float::doubleComparisons_data() const
{
QTest::addColumn<double>("operandLeft");
QTest::addColumn<double>("operandRight");
+ double zero(0.), one(1.);
- QTest::newRow("should PASS 1") << 0. << 0.;
- QTest::newRow("should FAIL 1") << 1.00000 << 3.00000;
- QTest::newRow("should FAIL 2") << 1.00000e-7 << 3.00000e-7;
+ QTest::newRow("should FAIL 1") << one << 3.;
+ QTest::newRow("should PASS 1") << zero << zero;
+ QTest::newRow("should FAIL 2") << 1.e-7 << 3.e-7;
// QCOMPARE for doubles uses qFuzzyCompare(), which succeeds if the numbers
// differ by no more than 1e-12 times the smaller value. Thus
// QCOMPARE(1e12-2, 1e12-1) should fail, while QCOMPARE(1e12+1, 1e12+2)
// should pass.
- QTest::newRow("should PASS 2") << 1e12 + 1. << 1e12 + 2.;
- QTest::newRow("should FAIL 3") << 1e12 - 1. << 1e12 - 2.;
+ QTest::newRow("should PASS 2") << 1e12 + one << 1e12 + 2.;
+ QTest::newRow("should FAIL 3") << 1e12 - one << 1e12 - 2.;
// ... but rounding makes that a bit unrelaible when scaled close to the bounds.
QTest::newRow("should PASS 3") << 1e-310 + 1e-322 << 1e-310 + 2e-322;
QTest::newRow("should FAIL 4") << 1e-310 - 1e-322 << 1e-310 - 3e-322;
QTest::newRow("should PASS 4") << 1e307 + 1e295 << 1e307 + 2e295;
QTest::newRow("should FAIL 5") << 1e307 - 1e295 << 1e307 - 3e295;
- // QCOMPARE special-cases non-finite values
- if (std::numeric_limits<double>::has_quiet_NaN) {
- const double nan = std::numeric_limits<double>::quiet_NaN();
- QTest::newRow("should PASS: NaN == NaN") << nan << nan;
- QTest::newRow("should FAIL: NaN != 0") << nan << 0.;
- QTest::newRow("should FAIL: 0 != NaN") << 0. << nan;
- QTest::newRow("should FAIL: NaN != 1") << nan << 1.;
- QTest::newRow("should FAIL: 1 != NaN") << 1. << nan;
- }
- if (std::numeric_limits<double>::has_infinity) {
- const double uge = std::numeric_limits<double>::infinity();
- QTest::newRow("should PASS: inf == inf") << uge << uge;
- QTest::newRow("should PASS: -inf == -inf") << -uge << -uge;
- QTest::newRow("should FAIL: inf != -inf") << uge << -uge;
- QTest::newRow("should FAIL: -inf != inf") << -uge << uge;
- if (std::numeric_limits<double>::has_quiet_NaN) {
- const double nan = std::numeric_limits<double>::quiet_NaN();
- QTest::newRow("should FAIL: inf != nan") << uge << nan;
- QTest::newRow("should FAIL: nan != inf") << nan << uge;
- QTest::newRow("should FAIL: -inf != nan") << -uge << nan;
- QTest::newRow("should FAIL: nan != -inf") << nan << -uge;
- }
- QTest::newRow("should FAIL: inf != 0") << uge << 0.;
- QTest::newRow("should FAIL: 0 != inf") << 0. << uge;
- QTest::newRow("should FAIL: -inf != 0") << -uge << 0.;
- QTest::newRow("should FAIL: 0 != -inf") << 0. << -uge;
- QTest::newRow("should FAIL: inf != 1") << uge << 1.;
- QTest::newRow("should FAIL: 1 != inf") << 1. << uge;
- QTest::newRow("should FAIL: -inf != 1") << -uge << 1.;
- QTest::newRow("should FAIL: 1 != -inf") << 1. << -uge;
-
- const double big = std::numeric_limits<double>::max();
- QTest::newRow("should FAIL: inf != max") << uge << big;
- QTest::newRow("should FAIL: inf != -max") << uge << -big;
- QTest::newRow("should FAIL: max != inf") << big << uge;
- QTest::newRow("should FAIL: -max != inf") << -big << uge;
- QTest::newRow("should FAIL: -inf != max") << -uge << big;
- QTest::newRow("should FAIL: -inf != -max") << -uge << -big;
- QTest::newRow("should FAIL: max != -inf") << big << -uge;
- QTest::newRow("should FAIL: -max != -inf") << -big << -uge;
- }
+ nonFinite_data(zero, one);
}
void tst_float::floatComparisons() const
@@ -131,65 +141,26 @@ void tst_float::floatComparisons_data() const
{
QTest::addColumn<float>("operandLeft");
QTest::addColumn<float>("operandRight");
+ float zero(0.f), one(1.f);
- QTest::newRow("should FAIL 1") << 1.00000f << 3.00000f;
- QTest::newRow("should PASS 1") << 0.f << 0.f;
- QTest::newRow("should FAIL 2") << 1.00000e-7f << 3.00000e-7f;
+ QTest::newRow("should FAIL 1") << one << 3.f;
+ QTest::newRow("should PASS 1") << zero << zero;
+ QTest::newRow("should FAIL 2") << 1.e-7f << 3.e-7f;
// QCOMPARE for floats uses qFuzzyCompare(), which succeeds if the numbers
// differ by no more than 1e-5 times the smaller value. Thus
// QCOMPARE(1e5-2, 1e5-1) should fail, while QCOMPARE(1e5+1, 1e5+2)
// should pass.
- QTest::newRow("should PASS 2") << 1e5f + 1.f << 1e5f + 2.f;
- QTest::newRow("should FAIL 3") << 1e5f - 1.f << 1e5f - 2.f;
+ QTest::newRow("should PASS 2") << 1e5f + one << 1e5f + 2.f;
+ QTest::newRow("should FAIL 3") << 1e5f - one << 1e5f - 2.f;
// ... but rounding makes that a bit unrelaible when scaled close to the bounds.
QTest::newRow("should PASS 3") << 1e-39f + 1e-44f << 1e-39f + 2e-44f;
QTest::newRow("should FAIL 4") << 1e-39f - 1e-44f << 1e-39f - 3e-44f;
QTest::newRow("should PASS 4") << 1e38f + 1e33f << 1e38f + 2e33f;
QTest::newRow("should FAIL 5") << 1e38f - 1e33f << 1e38f - 3e33f;
- // QCOMPARE special-cases non-finite values
- if (std::numeric_limits<float>::has_quiet_NaN) {
- const float nan = std::numeric_limits<float>::quiet_NaN();
- QTest::newRow("should PASS: NaN == NaN") << nan << nan;
- QTest::newRow("should FAIL: NaN != 0") << nan << 0.f;
- QTest::newRow("should FAIL: 0 != NaN") << 0.f << nan;
- QTest::newRow("should FAIL: NaN != 1") << nan << 1.f;
- QTest::newRow("should FAIL: 1 != NaN") << 1.f << nan;
- }
- if (std::numeric_limits<float>::has_infinity) {
- const float uge = std::numeric_limits<float>::infinity();
- QTest::newRow("should PASS: inf == inf") << uge << uge;
- QTest::newRow("should PASS: -inf == -inf") << -uge << -uge;
- QTest::newRow("should FAIL: inf != -inf") << uge << -uge;
- QTest::newRow("should FAIL: -inf != inf") << -uge << uge;
- if (std::numeric_limits<float>::has_quiet_NaN) {
- const float nan = std::numeric_limits<float>::quiet_NaN();
- QTest::newRow("should FAIL: inf != nan") << uge << nan;
- QTest::newRow("should FAIL: nan != inf") << nan << uge;
- QTest::newRow("should FAIL: -inf != nan") << -uge << nan;
- QTest::newRow("should FAIL: nan != -inf") << nan << -uge;
- }
- QTest::newRow("should FAIL: inf != 0") << uge << 0.f;
- QTest::newRow("should FAIL: 0 != inf") << 0.f << uge;
- QTest::newRow("should FAIL: -inf != 0") << -uge << 0.f;
- QTest::newRow("should FAIL: 0 != -inf") << 0.f << -uge;
- QTest::newRow("should FAIL: inf != 1") << uge << 1.f;
- QTest::newRow("should FAIL: 1 != inf") << 1.f << uge;
- QTest::newRow("should FAIL: -inf != 1") << -uge << 1.f;
- QTest::newRow("should FAIL: 1 != -inf") << 1.f << -uge;
-
- const float big = std::numeric_limits<float>::max();
- QTest::newRow("should FAIL: inf != max") << uge << big;
- QTest::newRow("should FAIL: inf != -max") << uge << -big;
- QTest::newRow("should FAIL: max != inf") << big << uge;
- QTest::newRow("should FAIL: -max != inf") << -big << uge;
- QTest::newRow("should FAIL: -inf != max") << -uge << big;
- QTest::newRow("should FAIL: -inf != -max") << -uge << -big;
- QTest::newRow("should FAIL: max != -inf") << big << -uge;
- QTest::newRow("should FAIL: -max != -inf") << -big << -uge;
- }
+ nonFinite_data(zero, one);
}
void tst_float::float16Comparisons() const
@@ -204,28 +175,22 @@ void tst_float::float16Comparisons_data() const
{
QTest::addColumn<qfloat16>("operandLeft");
QTest::addColumn<qfloat16>("operandRight");
+ qfloat16 zero(0), one(1);
- QTest::newRow("should SUCCEED 1")
- << qfloat16(0)
- << qfloat16(0);
-
- QTest::newRow("should FAIL 1")
- << qfloat16(1.000)
- << qfloat16(3.000);
-
- QTest::newRow("should FAIL 2")
- << qfloat16(1.000e-4f)
- << qfloat16(3.000e-4f);
+ QTest::newRow("should FAIL 1") << one << qfloat16(3);
+ QTest::newRow("should PASS 1") << zero << zero;
+ QTest::newRow("should FAIL 2") << qfloat16(1e-4f) << qfloat16(3e-4f);
// QCOMPARE for qfloat16s uses qFuzzyCompare()
-
- QTest::newRow("should FAIL 3")
- << qfloat16(98)
- << qfloat16(99);
-
- QTest::newRow("should SUCCEED 2")
- << qfloat16(1001)
- << qfloat16(1002);
+ QTest::newRow("should PASS 2") << qfloat16(1001) << qfloat16(1002);
+ QTest::newRow("should FAIL 3") << qfloat16(98) << qfloat16(99);
+ // ... which gets a bit unreliable near to the type's bounds
+ QTest::newRow("should PASS 3") << qfloat16(6e-5f) + qfloat16(6e-7f) << qfloat16(6e-5f) + qfloat16(11e-7f);
+ QTest::newRow("should FAIL 4") << qfloat16(6e-5f) - qfloat16(7e-7f) << qfloat16(6e-5f) - qfloat16(13e-7f);
+ QTest::newRow("should PASS 4") << qfloat16(6e4) + qfloat16(700) << qfloat16(6e4) + qfloat16(1200);
+ QTest::newRow("should FAIL 5") << qfloat16(6e4) - qfloat16(600) << qfloat16(6e4) - qfloat16(1200);
+
+ nonFinite_data(zero, one);
}
void tst_float::compareFloatTests() const
diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py
index 9ec87c8fc6..48ecbf0289 100755
--- a/tests/auto/testlib/selftests/generate_expected_output.py
+++ b/tests/auto/testlib/selftests/generate_expected_output.py
@@ -92,6 +92,17 @@ class Cleaner (object):
(r'(Loc: \[[^[\]()]+)\(\d+\)', r'\1(0)'), # txt
(r'(\[Loc: [^[\]()]+)\(\d+\)', r'\1(0)'), # teamcity
(r'(<(?:Incident|Message)\b.*\bfile=.*\bline=)"\d+"', r'\1"0"'), # lightxml, xml
+ # Pointers printed by signal dumper:
+ (r'\(\b[a-f0-9]{8,}\b\)', r'(_POINTER_)'),
+ # Example/for reference:
+ # ((QString&)@55f5fbb8dd40)
+ # ((const QVector<int>*)7ffd671d4558)
+ (r'\((\((?:const )?\w+(?:<[^>]+>)?[*&]*\)@?)\b[a-f\d]{8,}\b\)', r'(\1_POINTER_)'),
+ # For xml output there is no '<', '>' or '&', so we need an alternate version for that:
+ # ((QVector&lt;int&gt;&amp;)@5608b455e640)
+ (r'\((\((?:const )?\w+(?:&lt;(?:[^&]|&(?!gt;))*&gt;)?(?:\*|&amp;)?\)@?)[a-z\d]+\b\)', r'(\1_POINTER_)'),
+ # QEventDispatcher{Glib,Win32,etc.}
+ (r'\bQEventDispatcher\w+\b', r'QEventDispatcherPlatform'),
),
precook = re.compile):
"""Private implementation details of __init__()."""
@@ -296,6 +307,7 @@ def generateTestData(testname, clean,
"benchlibcounting": "-eventcounter",
"printdatatags": "-datatags",
"printdatatagswithglobaltags": "-datatags",
+ "signaldumper": "-vs",
"silent": "-silent",
"verbose1": "-v1",
"verbose2": "-v2",
diff --git a/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp b/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp
index 6c0ae1f43c..3c5c2c8f37 100644
--- a/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp
+++ b/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp
@@ -66,9 +66,10 @@ void tst_globaldata::initTestCase()
void tst_globaldata::initTestCase_data()
{
- QTest::addColumn<bool>("booli");
- QTest::newRow("1") << false;
- QTest::newRow("2") << true;
+ // QFETCH_GLOBAL shall iterate these, for every test:
+ QTest::addColumn<bool>("global");
+ QTest::newRow("global=false") << false;
+ QTest::newRow("global=true") << true;
}
void tst_globaldata::cleanupTestCase()
@@ -94,41 +95,42 @@ void tst_globaldata::cleanup()
void tst_globaldata::testGlobal_data()
{
- QTest::addColumn<bool>("booll");
- QTest::newRow("local 1") << false;
- QTest::newRow("local 2") << true;
+ QTest::addColumn<bool>("local");
+ QTest::newRow("local=false") << false;
+ QTest::newRow("local=true") << true;
}
void tst_globaldata::testGlobal()
{
- QFETCH_GLOBAL(bool, booli);
- qDebug() << "global:" << booli;
- QFETCH(bool, booll);
- qDebug() << "local:" << booll;
+ QFETCH_GLOBAL(bool, global);
+ qDebug() << "global:" << global;
+ QFETCH(bool, local);
+ qDebug() << "local:" << local;
}
void tst_globaldata::skip_data()
{
- QTest::addColumn<bool>("booll");
- QTest::newRow("local 1") << false;
- QTest::newRow("local 2") << true;
-
+ testGlobal_data();
QSKIP("skipping");
}
void tst_globaldata::skip()
{
- qDebug() << "this line should never be reached";
+ // A skip in _data() causes the whole test to be skipped, for all global rows.
+ QVERIFY(!"This line should never be reached.");
}
void tst_globaldata::skipSingle()
{
- QFETCH_GLOBAL(bool, booli);
- QFETCH(bool, booll);
-
- if (booli && !booll)
- QSKIP("skipping");
- qDebug() << "global:" << booli << "local:" << booll;
+ QFETCH_GLOBAL(bool, global);
+ QFETCH(bool, local);
+
+ // A skip in the last run of one global row used to suppress the test in the
+ // next global row (where a skip in an earlier run of the first row did not).
+ if (global ^ local)
+ QSKIP("Skipping");
+ qDebug() << "global:" << global << "local:" << local;
+ QCOMPARE(global, local);
}
void tst_globaldata::skipLocal()
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index b4568dd3e1..2cad0b7e17 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -1,5 +1,4 @@
SUBPROGRAMS = \
- #alive \
assert \
badxml \
benchlibcallgrind \
@@ -37,6 +36,7 @@ SUBPROGRAMS = \
printdatatagswithglobaltags \
qexecstringlist \
silent \
+ signaldumper \
singleskip \
skip \
skipcleanup \
diff --git a/tests/auto/testlib/selftests/signaldumper/signaldumper.pro b/tests/auto/testlib/selftests/signaldumper/signaldumper.pro
new file mode 100644
index 0000000000..8780b18419
--- /dev/null
+++ b/tests/auto/testlib/selftests/signaldumper/signaldumper.pro
@@ -0,0 +1,9 @@
+SOURCES += tst_signaldumper.cpp
+QT = core testlib-private
+
+macos:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = signaldumper
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp
new file mode 100644
index 0000000000..f6cd0d510e
--- /dev/null
+++ b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp
@@ -0,0 +1,417 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtTest/QtTest>
+#include <private/qtestlog_p.h>
+
+class tst_Signaldumper : public QObject
+{
+ Q_OBJECT
+
+ void addConnectionTypeData();
+
+private slots:
+ void noConnections();
+ void oneSlot_data();
+ void oneSlot();
+ void oneSlotOldSyntax_data();
+ void oneSlotOldSyntax();
+ void twoSlots_data();
+ void twoSlots();
+ void twoSlotsOldSyntax_data();
+ void twoSlotsOldSyntax();
+ void signalForwarding_data();
+ void signalForwarding();
+ void signalForwardingOldSyntax_data();
+ void signalForwardingOldSyntax();
+ void slotEmittingSignal_data();
+ void slotEmittingSignal();
+ void slotEmittingSignalOldSyntax_data();
+ void slotEmittingSignalOldSyntax();
+
+ void variousTypes();
+};
+
+void tst_Signaldumper::addConnectionTypeData()
+{
+ QTest::addColumn<Qt::ConnectionType>("connectionType");
+ QTest::newRow("direct") << Qt::ConnectionType::DirectConnection;
+ QTest::newRow("queued") << Qt::ConnectionType::QueuedConnection;
+}
+
+/*
+ Simple class to keep the slots and signals separate from the test
+*/
+class SignalSlotClass : public QObject
+{
+ Q_OBJECT
+
+public:
+ SignalSlotClass();
+
+public slots:
+ void slotWithoutParameters() {}
+ void slotWithParameters(int i, char c) { Q_UNUSED(i); Q_UNUSED(c); }
+ void emitSecondSignal() { emit nestedSignal(); }
+
+signals:
+ void signalWithoutParameters();
+ void signalWithParameters(int i, char c);
+
+ void nestedSignal();
+ void nestedSignalWithParameters(int i, char c);
+
+ // For the "variousTypes" test
+ void qStringSignal(QString string);
+ void qStringRefSignal(QString &string);
+ void qStringConstRefSignal(const QString &string);
+ void qByteArraySignal(QByteArray byteArray);
+ void qListSignal(QList<int> list);
+ void qVectorSignal(QVector<int> vector);
+ void qVectorRefSignal(QVector<int> &vector);
+ void qVectorConstRefSignal(const QVector<int> &vector);
+ void qVectorConstPointerSignal(const QVector<int> *vector);
+ void qVectorPointerConstSignal(QVector<int> *const vector);
+ void qVariantSignal(QVariant variant);
+};
+
+SignalSlotClass::SignalSlotClass()
+{
+ // For printing signal argument in "variousTypes" test
+ qRegisterMetaType<QVector<int>>();
+ qRegisterMetaType<QList<int>>();
+}
+
+void tst_Signaldumper::noConnections()
+{
+ SignalSlotClass signalSlotOwner;
+
+ emit signalSlotOwner.signalWithoutParameters();
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+}
+
+void tst_Signaldumper::oneSlot_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::oneSlot()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::oneSlotOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::oneSlotOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::twoSlots_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::twoSlots()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ // Now, instead of creating two slots or two objects, we will just do the same connection twice.
+ // The same slot will then be invoked twice.
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ auto connection2 = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithParameters, connectionType);
+ connection2 = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ connection2 = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+}
+
+void tst_Signaldumper::twoSlotsOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::twoSlotsOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ // Now, instead of creating two slots or two objects, we will just do the same connection twice.
+ // The same slot will then be invoked twice.
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ auto connection2 = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
+ connection2 = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ connection2 = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+}
+
+void tst_Signaldumper::signalForwarding_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::signalForwarding()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ // parameterless signal to parameterless signal
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::nestedSignal, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameter(full) signal
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::nestedSignalWithParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameterless signal
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::nestedSignal, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::signalForwardingOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::signalForwardingOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ // parameterless signal to parameterless signal
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SIGNAL(nestedSignal()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameter(full) signal
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SIGNAL(nestedSignalWithParameters(int, char)), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameterless signal
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SIGNAL(nestedSignal()), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::slotEmittingSignal_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::slotEmittingSignal()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::emitSecondSignal, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::slotEmittingSignalOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::slotEmittingSignalOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(emitSecondSignal()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::variousTypes()
+{
+ SignalSlotClass signalSlotOwner;
+ QString string = QString::fromLatin1("Test string");
+ emit signalSlotOwner.qStringSignal(string);
+ emit signalSlotOwner.qStringRefSignal(string);
+ emit signalSlotOwner.qStringConstRefSignal(string);
+ emit signalSlotOwner.qByteArraySignal(QByteArray("Test bytearray"));
+
+ QList<int> list{1, 2, 3, 242};
+ emit signalSlotOwner.qListSignal(list);
+
+ QVector<int> vector{1, 2, 3, 242};
+ emit signalSlotOwner.qVectorSignal(vector);
+ emit signalSlotOwner.qVectorRefSignal(vector);
+ emit signalSlotOwner.qVectorConstRefSignal(vector);
+ emit signalSlotOwner.qVectorConstPointerSignal(&vector);
+ emit signalSlotOwner.qVectorPointerConstSignal(&vector);
+
+ QVariant variant = 24;
+ emit signalSlotOwner.qVariantSignal(variant);
+ variant = QVariant(string);
+ emit signalSlotOwner.qVariantSignal(variant);
+}
+
+QTEST_MAIN(tst_Signaldumper)
+#include "tst_signaldumper.moc"
diff --git a/tests/auto/testlib/selftests/silent/tst_silent.cpp b/tests/auto/testlib/selftests/silent/tst_silent.cpp
index 97fbbfd30a..cf3c35dec4 100644
--- a/tests/auto/testlib/selftests/silent/tst_silent.cpp
+++ b/tests/auto/testlib/selftests/silent/tst_silent.cpp
@@ -72,6 +72,17 @@ void tst_Silent::xpass()
QVERIFY2(true, "This test should XPASS");
}
+#ifndef Q_OS_WIN
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf state;
+static void abort_handler(int signal)
+{
+ longjmp(state, 1);
+}
+#endif
+
void tst_Silent::messages()
{
qWarning("This is a warning that should not appear in silent test output");
@@ -80,7 +91,15 @@ void tst_Silent::messages()
qCritical("This is a critical message that should not appear in silent test output");
qInfo("This is an info message that should not appear in silent test output");
QTestLog::info("This is an internal testlib info message that should not appear in silent test output", __FILE__, __LINE__);
- qFatal("This is a fatal error message that should still appear in silent test output");
+
+#ifndef Q_OS_WIN
+ // We're testing qFatal, but we don't want to actually std::abort() !
+ auto prior = signal(SIGABRT, abort_handler);
+ if (setjmp(state))
+ signal(SIGABRT, prior);
+ else
+#endif
+ qFatal("This is a fatal error message that should still appear in silent test output");
}
QTEST_MAIN(tst_Silent)
diff --git a/tests/auto/testlib/selftests/sleep/tst_sleep.cpp b/tests/auto/testlib/selftests/sleep/tst_sleep.cpp
index b7b141afd0..95cb68521d 100644
--- a/tests/auto/testlib/selftests/sleep/tst_sleep.cpp
+++ b/tests/auto/testlib/selftests/sleep/tst_sleep.cpp
@@ -28,6 +28,7 @@
#include <QtCore/QCoreApplication>
+#include <QtCore/QElapsedTimer>
#include <QtTest/QtTest>
class tst_Sleep: public QObject
@@ -41,7 +42,7 @@ private slots:
void tst_Sleep::sleep()
{
- QTime t;
+ QElapsedTimer t;
t.start();
QTest::qSleep(100);
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index e8d6fe228b..331ae48135 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -439,7 +439,6 @@ void tst_Selftests::runSubTest_data()
QTest::addColumn<bool>("crashes");
QStringList tests = QStringList()
-// << "alive" // timer dependent
#if !defined(Q_OS_WIN)
// On windows, assert does nothing in release mode and blocks execution
// with a popup window in debug mode.
@@ -488,6 +487,7 @@ void tst_Selftests::runSubTest_data()
<< "printdatatags"
<< "printdatatagswithglobaltags"
<< "qexecstringlist"
+ << "signaldumper"
<< "silent"
<< "singleskip"
<< "skip"
@@ -553,6 +553,9 @@ void tst_Selftests::runSubTest_data()
else if (subtest == "printdatatagswithglobaltags") {
arguments << "-datatags";
}
+ else if (subtest == "signaldumper") {
+ arguments << "-vs";
+ }
else if (subtest == "silent") {
arguments << "-silent";
}
@@ -950,6 +953,29 @@ bool tst_Selftests::compareLine(const QString &logger, const QString &subdir,
if (actualLine.startsWith(QLatin1String("Totals:")) && expectedLine.startsWith(QLatin1String("Totals:")))
return true;
+ const QLatin1String pointerPlaceholder("_POINTER_");
+ if (expectedLine.contains(pointerPlaceholder)
+ && (expectedLine.contains(QLatin1String("Signal: "))
+ || expectedLine.contains(QLatin1String("Slot: ")))) {
+ QString actual = actualLine;
+ // We don't care about the pointer of the object to whom the signal belongs, so we
+ // replace it with _POINTER_, e.g.:
+ // Signal: SignalSlotClass(7ffd72245410) signalWithoutParameters ()
+ // Signal: QThread(7ffd72245410) started ()
+ // After this instance pointer we may have further pointers and
+ // references (with an @ prefix) as parameters of the signal or
+ // slot being invoked.
+ // Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@55f5fbb8dd40)
+ actual.replace(QRegularExpression("\\b[a-f0-9]{8,}\\b"), pointerPlaceholder);
+ // Also change QEventDispatcher{Glib,Win32,etc.} to QEventDispatcherPlatform
+ actual.replace(QRegularExpression("\\b(QEventDispatcher)\\w+\\b"), QLatin1String("\\1Platform"));
+ if (actual != expectedLine) {
+ *errorMessage = msgMismatch(actual, expectedLine);
+ return false;
+ }
+ return true;
+ }
+
*errorMessage = msgMismatch(actualLine, expectedLine);
return false;
}
diff --git a/tests/auto/testlib/testlib.pro b/tests/auto/testlib/testlib.pro
index 587c76a189..55f1f9b87b 100644
--- a/tests/auto/testlib/testlib.pro
+++ b/tests/auto/testlib/testlib.pro
@@ -1,5 +1,6 @@
TEMPLATE = subdirs
SUBDIRS = \
+ initmain \
outformat \
qsignalspy \
selftests \
diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri
deleted file mode 100644
index 26e7f6ab8a..0000000000
--- a/tests/auto/testserver.pri
+++ /dev/null
@@ -1,216 +0,0 @@
-# Integrating docker-based test servers into Qt Test framework
-#
-# This file adds support for docker-based test servers built by testcase
-# projects that need them. To enable this feature, any automated test can
-# include testserver.pri in its project file. This instructs qmake to insert
-# additional targets into the generated Makefile. The 'check' target then brings
-# up test servers before running the testcase, and shuts them down afterwards.
-#
-# TESTSERVER_COMPOSE_FILE
-# - Contains the path of docker-compose file
-# This configuration file defines the services used for autotests. It tells the
-# docker engine how to build up the docker images and containers. In qtbase, a
-# shared docker-compose file is located in the tests folder.
-# Example: TESTSERVER_COMPOSE_FILE = \
-# $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
-#
-# The user must run the provisioning scripts in advance before attempting to
-# build the test servers. The docker_testserver.sh script is used to build up
-# the docker images into the docker-cache. It handles the immutable parts of the
-# server installation that rarely need adjustment, such as downloading packages.
-# Example: qt5/coin/provisioning/.../testserver/docker_testserver.sh
-#
-# QT_TEST_SERVER_LIST
-# - A list of test servers to bring up for this testcase
-# These test servers should be defined in $$TESTSERVER_COMPOSE_FILE. Each
-# testcase can define the test servers it depends on.
-# Example: QT_TEST_SERVER_LIST = apache2 squid vsftpd ftp-proxy danted
-#
-# Pre-processor defines needed for the application:
-# QT_TEST_SERVER
-# - A preprocessor macro used for testcase to change testing parameters at
-# compile time
-# This macro is predefined for docker-based test servers and is passed as a
-# compiler option (-DQT_TEST_SERVER). The testcase can then check whether
-# docker-based servers are in use and change the testing parameters, such as
-# host name or port number, at compile time. An example can be found in
-# network-settings.h.
-#
-# Example:
-# #if defined(QT_TEST_SERVER)
-# Change the testing parameters at compile time
-# #endif
-#
-# QT_TEST_SERVER_DOMAIN
-# - A preprocessor macro that holds the server domain name
-# Provided for the helper functions in network-settings.h. Use function
-# serverDomainName() in your application instead.
-#
-# Additional make targets:
-# 1. check_network - A renamed target from the check target of testcase feature.
-# 2. testserver_clean - Clean up server containers/images and tidy away related
-# files.
-
-# The docker test server should only be integrated in the leaf Makefile.
-# If debug_and_release option is in use, skip the meta-Makefile except for
-# Makefile.Debug and Makefile.Release.
-debug_and_release:!build_pass: return()
-
-DOCKER_ENABLED = 1
-
-equals(QMAKE_HOST.os, Darwin) {
- DOCKER_ENABLED = 0
- message("Not using docker network test server on macOS, see QTQAINFRA-2717 and QTQAINFRA-2750")
-}
-
-TESTSERVER_VERSION = ""
-
-equals(DOCKER_ENABLED, 1) {
- TESTSERVER_VERSION = $$system(docker-compose --version)
-}
-
-isEmpty(TESTSERVER_VERSION) {
- # Make check with server "qt-test-server.qt-test-net" as a fallback
-} else {
- # Make check with docker test servers
- equals(QMAKE_HOST.os, Linux) {
- # For the platform supporting docker bridge network, each container is
- # assigned a unique hostname and connected to the same network domain
- # to communicate with the others.
- DEFINES += QT_TEST_SERVER_NAME
- DNSDOMAIN = test-net.qt.local
- } else {
- # For the others, the containers are deployed into a virtual machine
- # using the host network. All the containers share the same hostname of
- # the virtual machine, and they are connected to the same network domain.
- # NOTE: In Windows, Apple Bonjour only works within a single local domain.
- DNSDOMAIN = local
- }
-
- equals(QMAKE_HOST.os, Darwin) {
- # There is no docker bridge on macOS. It is impossible to ping a container.
- # Docker docs recommends using port mapping to connect to a container;
- # but it causes a port conflict if the user is running a service that
- # binds the same port on the host. An alternative solution is to deploy
- # the docker environment into VirtualBox using docker-machine.
- TESTSERVER_COMPOSE_FILE = \
- $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-for-macOS.yml
-
- # The connection configuration for the target machine
- MACHINE_CONFIG = $(shell docker-machine config qt-test-server)
-
- # The environment variables passed to the docker-compose file
- TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)'
- TEST_ENV += 'TEST_DOMAIN=$$DNSDOMAIN'
- TEST_CMD = env
- } else:equals(QMAKE_HOST.os, Windows) {
- # There is no docker bridge on Windows. It is impossible to ping a container.
- # Use docker-machine to deploy the docker environment into VirtualBox.
- TESTSERVER_COMPOSE_FILE = \
- $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-for-windows.yml
-
- # The connection configuration for the target machine
- MACHINE_CONFIG = (docker-machine config qt-test-server)
-
- # The environment variables passed to the docker-compose file
- TEST_ENV = '\$\$env:MACHINE_IP = docker-machine ip qt-test-server;'
- TEST_ENV += '\$\$env:TEST_DOMAIN = $$shell_quote(\"$$DNSDOMAIN\");'
-
- # Docker-compose CLI environment variables:
- # Enable path conversion from Windows-style to Unix-style in volume definitions.
- TEST_ENV += '\$\$env:COMPOSE_CONVERT_WINDOWS_PATHS = $$shell_quote(\"true\");'
-
- TEST_CMD = 'PowerShell -noprofile'
- CONFIG += PowerShell
- } else {
- TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
-
- # The environment variables passed to the docker-compose file
- TEST_ENV = 'TEST_DOMAIN=$$DNSDOMAIN'
- TEST_CMD = env
- }
-
- # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem).
- DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\")
-
- # Ensure that the docker-compose file is provided. It is a configuration
- # file which is mandatory for all docker-compose commands. You can get more
- # detail from the description of TESTSERVER_COMPOSE_FILE above. There is
- # also an example showing how to configure it manually.
- FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set"
- PowerShell {
- testserver_pretest.commands = echo $$TESTSERVER_VERSION &&
- testserver_pretest.commands += \
- $$TEST_CMD if ([String]::IsNullOrEmpty($$shell_quote(\"$$TESTSERVER_COMPOSE_FILE\"))) \
- {Write-Error $$shell_quote(\"$$FILE_PRETEST_MSG\")} &&
- } else {
- testserver_pretest.commands = $(info "testserver:" $$TESTSERVER_VERSION)
- testserver_pretest.commands += $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG))
- }
-
- # Make sure docker-machine is both created and running. The docker_machine
- # script is used to deploy the docker environment into VirtualBox.
- # Example: qt5/coin/provisioning/common/shared/testserver/docker_machine.sh
- !isEmpty(MACHINE_CONFIG) {
- MACHINE_LIST_CMD = docker-machine ls -q --filter "Name=^qt-test-server\$\$"
- MACHINE_LIST_MSG = "Docker machine qt-test-server not found"
- PowerShell {
- testserver_pretest.commands += $$TEST_CMD if (!($$MACHINE_LIST_CMD)) \
- {Write-Error $$shell_quote(\"$$MACHINE_LIST_MSG\")} &&
- } else {
- testserver_pretest.commands += \
- $(if $(shell $$MACHINE_LIST_CMD),,$(error $$MACHINE_LIST_MSG))
- }
-
- MACHINE_STATE_CMD = \
- docker-machine ls -q --filter "State=Running" --filter "Name=^qt-test-server\$\$"
- MACHINE_START_CMD = docker-machine start qt-test-server
- MACHINE_RECERT = docker-machine regenerate-certs -f qt-test-server
- PowerShell {
- testserver_pretest.commands += \
- $$TEST_CMD if (!($$MACHINE_STATE_CMD)) {$$MACHINE_START_CMD; $$MACHINE_RECERT} &&
- } else {
- testserver_pretest.commands += \
- $(if $(shell $$MACHINE_STATE_CMD),,\
- $(shell $$MACHINE_START_CMD > /dev/null && $$MACHINE_RECERT > /dev/null))
- }
- }
-
- # Before starting the test servers, it requires the user to run the setup
- # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance.
- IMAGE_PRETEST_CMD = docker $$MACHINE_CONFIG images -aq "qt-test-server-*"
- IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found"
- PowerShell {
- testserver_pretest.commands += $$TEST_CMD if (!($$IMAGE_PRETEST_CMD)) \
- {Write-Error $$shell_quote(\"$$IMAGE_PRETEST_MSG\")}
- } else {
- testserver_pretest.commands += \
- $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG))
- }
-
- # Rename the check target of testcase feature
- check.target = check_network
- testserver_test.target = check
-
- # Pretesting test servers environment
- testserver_test.depends = testserver_pretest
-
- # Bring up test servers and make sure the services are ready.
- !isEmpty(TEST_CMD): testserver_test.commands = $$TEST_CMD $$TEST_ENV
- testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE up \
- --detach --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} &&
-
- # Check test cases with docker-based test servers.
- testserver_test.commands += $(MAKE) -f $(MAKEFILE) check_network &&
-
- # Stop and remove test servers after testing.
- !isEmpty(TEST_CMD): testserver_test.commands += $$TEST_CMD $$TEST_ENV
- testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \
- --timeout 1
-
- # Destroy test servers and tidy away related files.
- testserver_clean.commands = docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \
- --rmi all
-
- QMAKE_EXTRA_TARGETS += testserver_pretest testserver_test testserver_clean
-}
diff --git a/tests/auto/tools/moc/cxx-attributes.h b/tests/auto/tools/moc/cxx-attributes.h
new file mode 100644
index 0000000000..eff6a3ec41
--- /dev/null
+++ b/tests/auto/tools/moc/cxx-attributes.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 CXXATTRIBUTE_H
+#define CXXATTRIBUTE_H
+
+#include <QtCore/QObject>
+
+class CppAttribute : public QObject
+{
+ Q_OBJECT
+signals:
+ [[deprecated]] void deprecatedSignal();
+
+public slots:
+ [[deprecated]] void deprecatedSlot() {}
+ [[deprecated]] [[tst_moc::maybe_unused]] int deprecatedSlot2() { return 42; }
+ [[deprecated("reason")]] void deprecatedReason() {}
+ [[deprecated("reason[")]] void deprecatedReasonWithLBRACK() {}
+ [[deprecated("reason[[")]] void deprecatedReasonWith2LBRACK() {}
+ [[deprecated("reason]")]] void deprecatedReasonWithRBRACK() {}
+ [[deprecated("reason]]")]] void deprecatedReasonWith2RBRACK() {}
+ void slotWithArguments([[tst_moc::maybe_unused]] int) {}
+#if !defined(_MSC_VER) || _MSC_VER >= 1912
+ // On MSVC it causes:
+ // moc_cxx-attributes.cpp(133): fatal error C1001: An internal error has occurred in the compiler.
+ Q_INVOKABLE [[tst_moc::noreturn]] void noreturnSlot() { throw "unused"; }
+ [[tst_moc::noreturn]] Q_SCRIPTABLE void noreturnSlot2() { throw "unused"; }
+ [[deprecated]] int returnInt() { return 0; }
+ Q_SLOT [[tst_moc::noreturn]] [[deprecated]] void noreturnDeprecatedSlot() { throw "unused"; }
+ Q_INVOKABLE void noreturnSlot3() [[tst_moc::noreturn]] { throw "unused"; }
+#endif
+};
+
+#ifdef Q_MOC_RUN
+# define TEST_COMPILER_DEPRECATION [[deprecated]]
+# define TEST_COMPILER_DEPRECATION_X(x) [[deprecated(x)]]
+#else
+# define TEST_COMPILER_DEPRECATION Q_DECL_ENUMERATOR_DEPRECATED
+# define TEST_COMPILER_DEPRECATION_X(x) Q_DECL_ENUMERATOR_DEPRECATED_X(x)
+#endif
+
+namespace TestQNamespaceDeprecated {
+ Q_NAMESPACE
+ enum class TestEnum1 {
+ Key1 = 11,
+ Key2 TEST_COMPILER_DEPRECATION,
+ Key3 TEST_COMPILER_DEPRECATION_X("reason"),
+ Key4 TEST_COMPILER_DEPRECATION_X("reason["),
+ Key5 TEST_COMPILER_DEPRECATION_X("reason[["),
+ Key6 TEST_COMPILER_DEPRECATION_X("reason]"),
+ Key7 TEST_COMPILER_DEPRECATION_X("reason]]"),
+ };
+ Q_ENUM_NS(TestEnum1)
+
+ // try to dizzy moc by adding a struct in between
+ struct TestGadget {
+ Q_GADGET
+ public:
+ enum class TestGEnum1 {
+ Key1 = 13,
+ Key2 TEST_COMPILER_DEPRECATION,
+ Key3 TEST_COMPILER_DEPRECATION_X("reason")
+ };
+ Q_ENUM(TestGEnum1)
+ };
+
+ enum class TestFlag1 {
+ None = 0,
+ Flag1 = 1,
+ Flag2 TEST_COMPILER_DEPRECATION = 2,
+ Flag3 TEST_COMPILER_DEPRECATION_X("reason") = 3,
+ Any = Flag1 | Flag2 | Flag3
+ };
+ Q_FLAG_NS(TestFlag1)
+}
+
+#endif // CXXATTRIBUTE_H
diff --git a/tests/auto/tools/moc/cxx11-enums.h b/tests/auto/tools/moc/cxx11-enums.h
index cc14c0acda..d5bd228f12 100644
--- a/tests/auto/tools/moc/cxx11-enums.h
+++ b/tests/auto/tools/moc/cxx11-enums.h
@@ -30,7 +30,6 @@
#define CXX11_ENUMS_H
#include <QtCore/QObject>
-#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_MOC_RUN)
class CXX11Enums
{
Q_GADGET
@@ -73,21 +72,4 @@ public:
Q_FLAGS(ClassFlags)
};
-#else
-//workaround to get the moc compiled code to compile
-class CXX11Enums
-{
- Q_GADGET
-public:
- struct EnumClass { enum { A0, A1, A2, A3 }; };
- struct TypedEnumClass { enum { C0, C1, C2, C3 }; };
- enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
- enum TypedEnum { B0, B1 , B2, B3 };
-};
-
-class CXX11Enums2 : public CXX11Enums
-{
- Q_GADGET
-};
-#endif
#endif // CXX11_ENUMS_H
diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro
index 3cbc9ebb5e..ad8c093add 100644
--- a/tests/auto/tools/moc/moc.pro
+++ b/tests/auto/tools/moc/moc.pro
@@ -29,7 +29,8 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n
non-gadget-parent-class.h grand-parent-gadget-class.h \
related-metaobjects-in-gadget.h \
related-metaobjects-name-conflict.h \
- namespace.h cxx17-namespaces.h
+ namespace.h cxx17-namespaces.h \
+ cxx-attributes.h
if(*-g++*|*-icc*|*-clang*|*-llvm):!win32-*: HEADERS += os9-newlines.h win-newlines.h
diff --git a/tests/auto/tools/moc/parse-defines.h b/tests/auto/tools/moc/parse-defines.h
index 7b0fa29d7c..bd22b0b9af 100644
--- a/tests/auto/tools/moc/parse-defines.h
+++ b/tests/auto/tools/moc/parse-defines.h
@@ -51,7 +51,6 @@
#define PD_CLASSINFO Q_CLASSINFO
-#if defined(Q_COMPILER_VARIADIC_MACROS) || defined (Q_MOC_RUN)
#define PD_VARARG(x, ...) x(__VA_ARGS__)
#if defined(Q_CC_GNU) || defined(Q_MOC_RUN)
@@ -61,7 +60,6 @@
#define PD_VARARGEXT(x, ...) x(__VA_ARGS__)
#endif
-#endif
#define PD_ADD_SUFFIX(x) PD_DEFINE1(x,_SUFFIX)
#define PD_DEFINE_ITSELF PD_ADD_SUFFIX(PD_DEFINE_ITSELF)
@@ -100,7 +98,6 @@ public slots:
PD_TEST_IDENTIFIER_ARG(void, combined6()) {}
-#if defined(Q_COMPILER_VARIADIC_MACROS) || defined (Q_MOC_RUN)
PD_VARARG(void vararg1) {}
PD_VARARG(void vararg2, int) {}
PD_VARARG(void vararg3, int, int) {}
@@ -108,14 +105,6 @@ public slots:
PD_VARARGEXT(void vararg4) {}
PD_VARARGEXT(void vararg5, int) {}
PD_VARARGEXT(void vararg6, int, int) {}
-#else
- void vararg1() {}
- void vararg2(int) {}
- void vararg3(int,int) {}
- void vararg4() {}
- void vararg5(int) {}
- void vararg6(int,int) {}
-#endif
#define OUTERFUNCTION(x) x
#define INNERFUNCTION(x) OUTERFUNCTION(x)
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 50321c322b..89f563f11d 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -71,6 +71,7 @@
#include "grand-parent-gadget-class.h"
#include "namespace.h"
#include "cxx17-namespaces.h"
+#include "cxx-attributes.h"
#ifdef Q_MOC_RUN
// check that moc can parse these constructs, they are being used in Windows winsock2.h header
@@ -148,6 +149,17 @@ namespace TestQNamespace {
Q_FLAG_NS(TestFlag2)
}
+
+#define TESTEXPORTMACRO Q_DECL_EXPORT
+
+namespace TestExportNamespace {
+ Q_NAMESPACE_EXPORT(TESTEXPORTMACRO)
+ enum class MyEnum {
+ Key1, Key2
+ };
+ Q_ENUM_NS(MyEnum)
+}
+
QT_USE_NAMESPACE
template <bool b> struct QTBUG_31218 {};
@@ -704,6 +716,7 @@ private slots:
void optionsFileError();
void testQNamespace();
void cxx17Namespaces();
+ void cxxAttributes();
signals:
void sigWithUnsignedArg(unsigned foo);
@@ -1040,7 +1053,7 @@ void tst_Moc::testExtraDataForEnum()
const QMetaObject *mobjUser = &EnumUserClass::staticMetaObject;
QCOMPARE(mobjUser->enumeratorCount(), 0);
- const QMetaObject * const *objects = mobjUser->d.relatedMetaObjects;
+ const auto *objects = mobjUser->d.relatedMetaObjects;
QVERIFY(objects);
QCOMPARE(objects[0], mobjSource);
QVERIFY(!objects[1]);
@@ -1424,6 +1437,16 @@ void tst_Moc::environmentIncludePaths()
// plugin_metadata.h contains a plugin which we register here. Since we're not building this
// application as a plugin, we need top copy some of the initializer code found in qplugin.h:
extern "C" QObject *qt_plugin_instance();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+extern "C" QPluginMetaData qt_plugin_query_metadata();
+class StaticPluginInstance{
+public:
+ StaticPluginInstance() {
+ QStaticPlugin plugin(qt_plugin_instance, qt_plugin_query_metadata);
+ qRegisterStaticPluginFunction(plugin);
+ }
+};
+#else
extern "C" const char *qt_plugin_query_metadata();
class StaticPluginInstance{
public:
@@ -1432,6 +1455,7 @@ public:
qRegisterStaticPluginFunction(plugin);
}
};
+#endif
static StaticPluginInstance staticInstance;
void tst_Moc::specifyMetaTagsFromCmdline() {
@@ -3555,10 +3579,9 @@ namespace QTBUG32933_relatedObjectsDontIncludeItself {
void tst_Moc::QTBUG32933_relatedObjectsDontIncludeItself()
{
const QMetaObject *mo = &QTBUG32933_relatedObjectsDontIncludeItself::NS::Obj::staticMetaObject;
- const QMetaObject * const *objects = mo->d.relatedMetaObjects;
+ const auto *objects = mo->d.relatedMetaObjects;
// the related objects should be empty because the enums is in the same object.
QVERIFY(!objects);
-
}
class UnrelatedClass : public QObject
@@ -3664,7 +3687,7 @@ void tst_Moc::relatedMetaObjectsNameConflict()
// load all specified metaobjects int a set
QSet<const QMetaObject*> dependency;
- const QMetaObject *const *i = dependingObject->d.relatedMetaObjects;
+ const auto *i = dependingObject->d.relatedMetaObjects;
while (*i) {
dependency.insert(*i);
++i;
@@ -3848,6 +3871,14 @@ static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name, const
}
}
+class EnumFromNamespaceClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(FooNamespace::Enum1 prop READ prop CONSTANT)
+public:
+ FooNamespace::Enum1 prop() { return FooNamespace::Enum1::Key2; }
+};
+
void tst_Moc::testQNamespace()
{
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 4);
@@ -3872,9 +3903,18 @@ void tst_Moc::testQNamespace()
QCOMPARE(meta.enclosingMetaObject(), &TestQNamespace::staticMetaObject);
QCOMPARE(meta.keyCount(), 2);
+ QCOMPARE(TestExportNamespace::staticMetaObject.enumeratorCount(), 1);
+ checkEnum(TestExportNamespace::staticMetaObject.enumerator(0), "MyEnum",
+ {{"Key1", 0}, {"Key2", 1}});
+
QCOMPARE(FooNamespace::staticMetaObject.enumeratorCount(), 1);
QCOMPARE(FooNamespace::FooNestedNamespace::staticMetaObject.enumeratorCount(), 2);
QCOMPARE(FooNamespace::FooNestedNamespace::FooMoreNestedNamespace::staticMetaObject.enumeratorCount(), 1);
+
+ EnumFromNamespaceClass obj;
+ const QVariant prop = obj.property("prop");
+ QCOMPARE(prop.type(), QMetaType::Int);
+ QCOMPARE(prop.toInt(), int(FooNamespace::Enum1::Key2));
}
void tst_Moc::cxx17Namespaces()
@@ -3896,6 +3936,41 @@ void tst_Moc::cxx17Namespaces()
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().value(0), 3);
}
+void tst_Moc::cxxAttributes()
+{
+ auto so = CppAttribute::staticMetaObject;
+ QCOMPARE(so.className(), "CppAttribute");
+ QCOMPARE(so.enumeratorCount(), 0);
+ QVERIFY(so.indexOfSignal("deprecatedSignal") != 1);
+ for (auto a: {"deprecatedSlot", "deprecatedSlot2", "deprecatedReason", "deprecatedReasonWithLBRACK",
+ "deprecatedReasonWith2LBRACK", "deprecatedReasonWithRBRACK", "deprecatedReasonWith2RBRACK",
+ "slotWithArguments"
+#if !defined(_MSC_VER) || _MSC_VER >= 1912
+ , "noreturnSlot", "noreturnSlot2", "returnInt", "noreturnDeprecatedSlot",
+ "noreturnSlot3"
+#endif
+ }) {
+ QVERIFY(so.indexOfSlot(a) != 1);
+ }
+
+ QCOMPARE(TestQNamespaceDeprecated::staticMetaObject.enumeratorCount(), 2);
+ checkEnum(TestQNamespaceDeprecated::staticMetaObject.enumerator(0), "TestEnum1",
+ {{"Key1", 11}, {"Key2", 12}, {"Key3", 13}, {"Key4", 14}, {"Key5", 15}, {"Key6", 16},
+ {"Key7", 17}});
+ checkEnum(TestQNamespaceDeprecated::staticMetaObject.enumerator(1), "TestFlag1",
+ {{"None", 0}, {"Flag1", 1}, {"Flag2", 2}, {"Flag3", 3}, {"Any", 1 | 2 | 3}});
+
+ QCOMPARE(TestQNamespaceDeprecated::TestGadget::staticMetaObject.enumeratorCount(), 1);
+ checkEnum(TestQNamespaceDeprecated::TestGadget::staticMetaObject.enumerator(0), "TestGEnum1",
+ {{"Key1", 13}, {"Key2", 14}, {"Key3", 15}});
+
+ QMetaEnum meta = QMetaEnum::fromType<TestQNamespaceDeprecated::TestEnum1>();
+ QVERIFY(meta.isValid());
+ QCOMPARE(meta.name(), "TestEnum1");
+ QCOMPARE(meta.enclosingMetaObject(), &TestQNamespaceDeprecated::staticMetaObject);
+ QCOMPARE(meta.keyCount(), 7);
+}
+
QTEST_MAIN(tst_Moc)
// the generated code must compile with QT_NO_KEYWORDS
diff --git a/tests/auto/tools/qmake/testcompiler.cpp b/tests/auto/tools/qmake/testcompiler.cpp
index e769f955c4..8ab8d5d721 100644
--- a/tests/auto/tools/qmake/testcompiler.cpp
+++ b/tests/auto/tools/qmake/testcompiler.cpp
@@ -164,15 +164,17 @@ bool TestCompiler::runCommand(const QString &cmd, const QStringList &args, bool
return errorOut();
}
- child.setReadChannel(QProcess::StandardError);
child.waitForFinished(-1);
bool ok = child.exitStatus() == QProcess::NormalExit && (expectFail ^ (child.exitCode() == 0));
- foreach (const QByteArray &output, child.readAllStandardError().split('\n')) {
- testOutput_.append(QString::fromLocal8Bit(output));
-
- if (output.startsWith("Project MESSAGE: FAILED"))
- ok = false;
+ for (auto channel : { QProcess::StandardOutput, QProcess::StandardError }) {
+ child.setReadChannel(channel);
+ while (!child.atEnd()) {
+ const QString output = QString::fromLocal8Bit(child.readLine());
+ if (output.startsWith("Project MESSAGE: FAILED"))
+ ok = false;
+ testOutput_.append(output);
+ }
}
return ok ? true : errorOut();
@@ -292,8 +294,10 @@ bool TestCompiler::make( const QString &workPath, const QString &target, bool ex
D.setCurrent( workPath );
QStringList args = makeArgs_;
- if (makeCmd_.contains("nmake", Qt::CaseInsensitive))
+ if (makeCmd_.contains("nmake", Qt::CaseInsensitive) ||
+ makeCmd_.contains("jom", Qt::CaseInsensitive)) {
args << "/NOLOGO";
+ }
if (!target.isEmpty())
args << target;
diff --git a/tests/auto/tools/qmake/testcompiler.h b/tests/auto/tools/qmake/testcompiler.h
index e22a2c6c3d..d80cd8d53a 100644
--- a/tests/auto/tools/qmake/testcompiler.h
+++ b/tests/auto/tools/qmake/testcompiler.h
@@ -73,13 +73,17 @@ public:
bool removeProject( const QString &workPath, const QString &project );
// removes the file specified by 'fileName' on the 'workPath'
bool removeFile( const QString &workPath, const QString &fileName );
- // returns each line of stdout of the last command append with a "new line" character(s) to suit the platform
+
+ // Returns each line of stdout/stderr of the last commands
+ // separated by platform-specific line endings.
QString commandOutput() const;
+
// clear the results of storage of stdout for running previous commands
void clearCommandOutput();
-private:
bool runCommand(const QString &cmd, const QStringList &args, bool expectFail = false);
+
+private:
bool errorOut();
QString makeCmd_;
diff --git a/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro b/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro
new file mode 100644
index 0000000000..c3e8034e35
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+CONFIG += debug_and_release
+TARGET = bah
+DESTDIR = shu
+SOURCES += main.cpp
diff --git a/tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp b/tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp
new file mode 100644
index 0000000000..39de28135a
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp
@@ -0,0 +1,4 @@
+int main(int, char **)
+{
+ return 0;
+}
diff --git a/tests/auto/tools/qmake/testdata/windows_resources/inter.inc b/tests/auto/tools/qmake/testdata/windows_resources/inter.inc
new file mode 100644
index 0000000000..0c2594214e
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/windows_resources/inter.inc
@@ -0,0 +1 @@
+#include "version.inc"
diff --git a/tests/auto/tools/qmake/testdata/windows_resources/main.cpp b/tests/auto/tools/qmake/testdata/windows_resources/main.cpp
new file mode 100644
index 0000000000..237c8ce181
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/windows_resources/main.cpp
@@ -0,0 +1 @@
+int main() {}
diff --git a/tests/auto/tools/qmake/testdata/windows_resources/version.inc b/tests/auto/tools/qmake/testdata/windows_resources/version.inc
new file mode 100644
index 0000000000..b797c9acce
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/windows_resources/version.inc
@@ -0,0 +1,28 @@
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
+ FILEFLAGS 0x0L
+ FILEFLAGSMASK 0x3fL
+ FILEOS 0x00040004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "The Qt Company Ltd"
+ VALUE "FileDescription", "A Good File"
+ VALUE "FileVersion", "1.0.0.0"
+ VALUE "LegalCopyright", "Copyright (C) 2019 The Qt Company Ltd."
+ VALUE "InternalName", "foo"
+ VALUE "OriginalFilename", "foo.exe"
+ VALUE "ProductName", "A Good Product"
+ VALUE "ProductVersion", "1.0.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/tests/auto/tools/qmake/testdata/windows_resources/windows_resources.pro b/tests/auto/tools/qmake/testdata/windows_resources/windows_resources.pro
new file mode 100644
index 0000000000..80a5e5c19a
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/windows_resources/windows_resources.pro
@@ -0,0 +1,4 @@
+QT = core
+SOURCES = main.cpp
+RC_FILE = windows_resources.rc
+TEMPLATE = app
diff --git a/tests/auto/tools/qmake/testdata/windows_resources/windows_resources.rc b/tests/auto/tools/qmake/testdata/windows_resources/windows_resources.rc
new file mode 100644
index 0000000000..4df652de35
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/windows_resources/windows_resources.rc
@@ -0,0 +1,2 @@
+#include "winver.h"
+#include "inter.inc"
diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp
index 09e725f98a..9b434a7b5b 100644
--- a/tests/auto/tools/qmake/tst_qmake.cpp
+++ b/tests/auto/tools/qmake/tst_qmake.cpp
@@ -33,6 +33,7 @@
#include <QDir>
#include <QDirIterator>
#include <QObject>
+#include <QRegularExpression>
#include <QStandardPaths>
#include <QTemporaryDir>
@@ -75,14 +76,17 @@ private slots:
void findMocs();
void findDeps();
void rawString();
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
void bundle_spaces();
+#elif defined(Q_OS_WIN)
+ void windowsResources();
#endif
void substitutes();
void project();
void proFileCache();
void qinstall();
void resources();
+ void conflictingTargets();
private:
TestCompiler test_compiler;
@@ -423,7 +427,7 @@ void tst_qmake::prompt()
{
#if 0
QProcess qmake;
- qmake.setReadChannelMode(QProcess::MergedChannels);
+ qmake.setProcessChannelMode(QProcess::MergedChannels);
qmake.setWorkingDirectory(QLatin1String("testdata/prompt"));
qmake.start(QLatin1String("qmake CONFIG-=debug_and_release CONFIG-=debug CONFIG+=release"),
QIODevice::Text | QIODevice::ReadWrite);
@@ -511,7 +515,8 @@ struct TempFile
}
};
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
+
void tst_qmake::bundle_spaces()
{
QString workDir = base_path + "/testdata/bundle-spaces";
@@ -542,7 +547,34 @@ void tst_qmake::bundle_spaces()
QVERIFY( !non_existing_file.exists() );
QVERIFY( test_compiler.removeMakefile(workDir) );
}
-#endif // defined(Q_OS_MAC)
+
+#elif defined(Q_OS_WIN) // defined(Q_OS_DARWIN)
+
+void tst_qmake::windowsResources()
+{
+ QString workDir = base_path + "/testdata/windows_resources";
+ QVERIFY(test_compiler.qmake(workDir, "windows_resources"));
+ QVERIFY(test_compiler.make(workDir));
+
+ // Another "make" must not rebuild the .res file
+ test_compiler.clearCommandOutput();
+ QVERIFY(test_compiler.make(workDir));
+ QVERIFY(!test_compiler.commandOutput().contains("windows_resources.rc"));
+ test_compiler.clearCommandOutput();
+
+ // Wait a second to make sure we get a new timestamp in the touch below
+ QTest::qWait(1000);
+
+ // Touch the deepest include of the .rc file
+ QVERIFY(test_compiler.runCommand("cmd", QStringList{"/c",
+ "echo.>>" + QDir::toNativeSeparators(workDir + "/version.inc")}));
+
+ // The next "make" must rebuild the .res file
+ QVERIFY(test_compiler.make(workDir));
+ QVERIFY(test_compiler.commandOutput().contains("windows_resources.rc"));
+}
+
+#endif // defined(Q_OS_WIN)
void tst_qmake::substitutes()
{
@@ -717,5 +749,18 @@ void tst_qmake::resources()
QVERIFY(test_compiler.make(workDir));
}
+void tst_qmake::conflictingTargets()
+{
+ QString workDir = base_path + "/testdata/conflicting_targets";
+ QVERIFY(test_compiler.qmake(workDir, "conflicting_targets"));
+ const QRegularExpression rex("Targets of builds '([^']+)' and '([^']+)' conflict");
+ auto match = rex.match(test_compiler.commandOutput());
+ QVERIFY(match.hasMatch());
+ QStringList builds = { match.captured(1), match.captured(2) };
+ std::sort(builds.begin(), builds.end());
+ const QStringList expectedBuilds{"Debug", "Release"};
+ QCOMPARE(builds, expectedBuilds);
+}
+
QTEST_MAIN(tst_qmake)
#include "tst_qmake.moc"
diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro
index 29f17f6a14..5e9e9fe637 100644
--- a/tests/auto/tools/qmakelib/qmakelib.pro
+++ b/tests/auto/tools/qmakelib/qmakelib.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qmakelib
QT = core testlib
-win32: LIBS += -ladvapi32
+win32: QMAKE_USE += advapi32
INCLUDEPATH += ../../../../qmake/library
VPATH += ../../../../qmake/library
diff --git a/tests/auto/tools/rcc/data/depfile/simple.d.expected b/tests/auto/tools/rcc/data/depfile/simple.d.expected
new file mode 100644
index 0000000000..a89b61bdc7
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/simple.d.expected
@@ -0,0 +1 @@
+simple.qrc.cpp: ../images/images/circle.png ../images/images/square.png
diff --git a/tests/auto/tools/rcc/data/depfile/simple.qrc b/tests/auto/tools/rcc/data/depfile/simple.qrc
new file mode 100644
index 0000000000..521dc4d4a0
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/simple.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>../images/images/circle.png</file>
+ <file>../images/images/square.png</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/depfile/specialchar$file.txt b/tests/auto/tools/rcc/data/depfile/specialchar$file.txt
new file mode 100644
index 0000000000..5da849b5c6
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/specialchar$file.txt
@@ -0,0 +1 @@
+ABC
diff --git a/tests/auto/tools/rcc/data/depfile/specialchar.d.expected b/tests/auto/tools/rcc/data/depfile/specialchar.d.expected
new file mode 100644
index 0000000000..9dd1af0958
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/specialchar.d.expected
@@ -0,0 +1 @@
+specialchar.qrc.cpp: specialchar$$file.txt ../images/images/subdir/triangle.png
diff --git a/tests/auto/tools/rcc/data/depfile/specialchar.qrc b/tests/auto/tools/rcc/data/depfile/specialchar.qrc
new file mode 100644
index 0000000000..133cbc7655
--- /dev/null
+++ b/tests/auto/tools/rcc/data/depfile/specialchar.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>../images/images/subdir/triangle.png</file>
+ <file>specialchar$file.txt</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected
new file mode 100644
index 0000000000..9dcd131af5
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected
@@ -0,0 +1,68 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 5.14.0
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x00\x02\
+0\
+1\
+\x00\x00\x00#\
+0\
+123456789 012345\
+6789 0123456789 \
+12\
+\x00\x00\x00\x01\
+@\
+\
+\x00\x00\x00\x00\
+\
+"
+
+qt_resource_name = b"\
+\x00\x04\
+\x00\x06\xa8\xa1\
+\x00d\
+\x00a\x00t\x00a\
+\x00\x0a\
+\x04\x08\x0a\xb4\
+\x00d\
+\x00a\x00t\x00a\x00-\x002\x00.\x00t\x00x\x00t\
+\x00\x0b\
+\x00\xb5Ot\
+\x00d\
+\x00a\x00t\x00a\x00-\x003\x005\x00.\x00t\x00x\x00t\
+\x00\x0a\
+\x04\x11\x0a\xb4\
+\x00d\
+\x00a\x00t\x00a\x00-\x001\x00.\x00t\x00x\x00t\
+\x00\x0a\
+\x04\x0e\x0a\xb4\
+\x00d\
+\x00a\x00t\x00a\x00-\x000\x00.\x00t\x00x\x00t\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\
+IGNORE: (time stamp)
+\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+IGNORE: (time stamp)
+\x00\x00\x00^\x00\x00\x00\x00\x00\x01\x00\x00\x002\
+IGNORE: (time stamp)
+\x00\x00\x00D\x00\x00\x00\x00\x00\x01\x00\x00\x00-\
+IGNORE: (time stamp)
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp
index c810c6e364..42a4134e5f 100644
--- a/tests/auto/tools/rcc/tst_rcc.cpp
+++ b/tests/auto/tools/rcc/tst_rcc.cpp
@@ -46,6 +46,33 @@
typedef QMap<QString, QString> QStringMap;
Q_DECLARE_METATYPE(QStringMap)
+static QByteArray msgProcessStartFailed(const QProcess &p)
+{
+ const QString result = QLatin1String("Could not start \"")
+ + QDir::toNativeSeparators(p.program()) + QLatin1String("\": ")
+ + p.errorString();
+ return result.toLocal8Bit();
+}
+
+static QByteArray msgProcessTimeout(const QProcess &p)
+{
+ return '"' + QDir::toNativeSeparators(p.program()).toLocal8Bit()
+ + "\" timed out.";
+}
+
+static QByteArray msgProcessCrashed(QProcess &p)
+{
+ return '"' + QDir::toNativeSeparators(p.program()).toLocal8Bit()
+ + "\" crashed.\n" + p.readAllStandardError();
+}
+
+static QByteArray msgProcessFailed(QProcess &p)
+{
+ return '"' + QDir::toNativeSeparators(p.program()).toLocal8Bit()
+ + "\" returned " + QByteArray::number(p.exitCode()) + ":\n"
+ + p.readAllStandardError();
+}
+
class tst_rcc : public QObject
{
Q_OBJECT
@@ -62,10 +89,16 @@ private slots:
void readback_data();
void readback();
+ void depFileGeneration_data();
+ void depFileGeneration();
+
+ void python();
+
void cleanupTestCase();
private:
QString m_rcc;
+ QString m_dataPath;
};
void tst_rcc::initTestCase()
@@ -74,20 +107,19 @@ void tst_rcc::initTestCase()
// we must force a certain hash order when testing or tst_rcc will fail, see QTBUG-25078
QVERIFY(qputenv("QT_RCC_TEST", "1"));
m_rcc = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/rcc");
-}
-QString findExpectedFile(const QString &base)
-{
- QString expectedrccfile = base;
+ m_dataPath = QFINDTESTDATA("data");
+ QVERIFY(!m_dataPath.isEmpty());
+}
- // Must be updated with each minor release.
- if (QFileInfo(expectedrccfile + QLatin1String(".450")).exists())
- expectedrccfile += QLatin1String(".450");
- return expectedrccfile;
+static inline bool isPythonComment(const QString &line)
+{
+ return line.startsWith(QLatin1Char('#'));
}
-static QString doCompare(const QStringList &actual, const QStringList &expected)
+static QString doCompare(const QStringList &actual, const QStringList &expected,
+ const QString &timeStampPath)
{
if (actual.size() != expected.size()) {
return QString("Length count different: actual: %1, expected: %2")
@@ -95,13 +127,21 @@ static QString doCompare(const QStringList &actual, const QStringList &expected)
}
QByteArray ba;
+ const bool isPython = isPythonComment(expected.constFirst());
for (int i = 0, n = expected.size(); i != n; ++i) {
QString expectedLine = expected.at(i);
if (expectedLine.startsWith("IGNORE:"))
continue;
+ if (isPython && isPythonComment(expectedLine) && isPythonComment(actual.at(i)))
+ continue;
if (expectedLine.startsWith("TIMESTAMP:")) {
const QString relativePath = expectedLine.mid(strlen("TIMESTAMP:"));
- const quint64 timeStamp = QFileInfo(relativePath).lastModified().toMSecsSinceEpoch();
+ const QFileInfo fi(timeStampPath + QLatin1Char('/') + relativePath);
+ if (!fi.isFile()) {
+ ba.append("File " + fi.absoluteFilePath().toUtf8() + " does not exist!");
+ break;
+ }
+ const quint64 timeStamp = quint64(fi.lastModified().toMSecsSinceEpoch());
expectedLine.clear();
for (int shift = 56; shift >= 0; shift -= 8) {
expectedLine.append(QLatin1String("0x"));
@@ -110,7 +150,7 @@ static QString doCompare(const QStringList &actual, const QStringList &expected)
}
}
if (expectedLine != actual.at(i)) {
- qDebug() << "LINES" << i << "DIFFER";
+ qDebug() << "LINES" << (i + 1) << "DIFFER";
ba.append(
"\n<<<<<< actual\n" + actual.at(i) + "\n======\n" + expectedLine
+ "\n>>>>>> expected\n"
@@ -126,49 +166,53 @@ void tst_rcc::rcc_data()
QTest::addColumn<QString>("qrcfile");
QTest::addColumn<QString>("expected");
- QString dataPath = QFINDTESTDATA("data/images/");
- if (dataPath.isEmpty())
- QFAIL("data path not found");
- QTest::newRow("images") << dataPath << "images.qrc" << "images.expected";
+ const QString imagesPath = m_dataPath + QLatin1String("/images");
+ QTest::newRow("images") << imagesPath << "images.qrc" << "images.expected";
- QString sizesPath = QFINDTESTDATA("data/sizes/");
- if (sizesPath.isEmpty())
- QFAIL("data path not found");
+ const QString sizesPath = m_dataPath + QLatin1String("/sizes");
QTest::newRow("size-0") << sizesPath << "size-0.qrc" << "size-0.expected";
QTest::newRow("size-1") << sizesPath << "size-1.qrc" << "size-1.expected";
QTest::newRow("size-2-0-35-1") << sizesPath << "size-2-0-35-1.qrc" << "size-2-0-35-1.expected";
}
+static QStringList readLinesFromFile(const QString &fileName,
+ QString::SplitBehavior splitBehavior)
+{
+ QFile file(fileName);
+
+ bool ok = file.open(QIODevice::ReadOnly | QIODevice::Text);
+ if (!ok) {
+ QWARN(qPrintable(QString::fromLatin1("Could not open testdata file %1: %2")
+ .arg(fileName, file.errorString())));
+ }
+
+ return QString::fromUtf8(file.readAll()).split(QLatin1Char('\n'), splitBehavior);
+}
+
void tst_rcc::rcc()
{
QFETCH(QString, directory);
QFETCH(QString, qrcfile);
QFETCH(QString, expected);
- if (!QDir::setCurrent(directory)) {
- QString message = QString::fromLatin1("Unable to cd from '%1' to '%2'").arg(QDir::currentPath(), directory);
- QFAIL(qPrintable(message));
- }
-
// If the file expectedoutput.txt exists, compare the
// console output with the content of that file
- const QString expected2 = findExpectedFile(expected);
- QFile expectedFile(expected2);
- if (!expectedFile.exists()) {
- qDebug() << "NO EXPECTATIONS? " << expected2;
- return;
- }
// Launch; force no compression, otherwise the output would be different
// depending on the compression algorithm we're using
QProcess process;
+ process.setWorkingDirectory(directory);
process.start(m_rcc, { "-no-compress", qrcfile });
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(process).constData());
if (!process.waitForFinished()) {
- const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
- QString message = QString::fromLatin1("'%1' could not be found when run from '%2'. Path: '%3' ").
- arg(m_rcc, QDir::currentPath(), path);
- QFAIL(qPrintable(message));
+ process.kill();
+ QFAIL(msgProcessTimeout(process).constData());
}
+ QVERIFY2(process.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(process).constData());
+ QVERIFY2(process.exitCode() == 0,
+ msgProcessFailed(process).constData());
+
const QChar cr = QLatin1Char('\r');
const QString err = QString::fromLocal8Bit(process.readAllStandardError()).remove(cr);
const QString out = QString::fromLatin1(process.readAllStandardOutput()).remove(cr);
@@ -181,63 +225,20 @@ void tst_rcc::rcc()
const QChar nl = QLatin1Char('\n');
const QStringList actualLines = out.split(nl);
- QVERIFY(expectedFile.open(QIODevice::ReadOnly|QIODevice::Text));
- const QStringList expectedLines = QString::fromLatin1(expectedFile.readAll()).split(nl);
+ const QStringList expectedLines =
+ readLinesFromFile(directory + QLatin1Char('/') + expected, QString::KeepEmptyParts);
+ QVERIFY(!expectedLines.isEmpty());
- const QString diff = doCompare(actualLines, expectedLines);
+ const QString diff = doCompare(actualLines, expectedLines, directory);
if (diff.size())
QFAIL(qPrintable(diff));
}
-
-
-static void createRccBinaryData(const QString &rcc, const QString &baseDir,
- const QString &qrcFileName, const QString &rccFileName)
-{
- QString currentDir = QDir::currentPath();
- QDir::setCurrent(baseDir);
-
- // same as above: force no compression
- QProcess rccProcess;
- rccProcess.start(rcc, { "-binary", "-no-compress", "-o", rccFileName, qrcFileName });
- bool ok = rccProcess.waitForFinished();
- if (!ok) {
- QString errorString = QString::fromLatin1("Could not start rcc (is it in PATH?): %1").arg(rccProcess.errorString());
- QFAIL(qPrintable(errorString));
- }
-
- QByteArray output = rccProcess.readAllStandardOutput();
- if (!output.isEmpty()) {
- QString errorMessage = QString::fromLatin1("rcc stdout: %1").arg(QString::fromLocal8Bit(output));
- QWARN(qPrintable(errorMessage));
- }
-
- output = rccProcess.readAllStandardError();
- if (!output.isEmpty()) {
- QString errorMessage = QString::fromLatin1("rcc stderr: %1").arg(QString::fromLocal8Bit(output));
- QWARN(qPrintable(errorMessage));
- }
-
- QDir::setCurrent(currentDir);
-}
-
-static QStringList readLinesFromFile(const QString &fileName)
-{
- QFile file(fileName);
-
- bool ok = file.open(QIODevice::ReadOnly | QIODevice::Text);
- if (!ok)
- QWARN(qPrintable(QString::fromLatin1("Could not open testdata file %1: %2").arg(fileName, file.errorString())));
-
- QStringList lines = QString::fromUtf8(file.readAll()).split(QLatin1Char('\n'), QString::SkipEmptyParts);
- return lines;
-}
-
static QStringMap readExpectedFiles(const QString &fileName)
{
QStringMap expectedFiles;
- QStringList lines = readLinesFromFile(fileName);
+ QStringList lines = readLinesFromFile(fileName, QString::SkipEmptyParts);
foreach (const QString &line, lines) {
QString resourceFileName = line.section(QLatin1Char(' '), 0, 0, QString::SectionSkipEmpty);
QString actualFileName = line.section(QLatin1Char(' '), 1, 1, QString::SectionSkipEmpty);
@@ -268,9 +269,7 @@ void tst_rcc::binary_data()
QTest::addColumn<QString>("baseDirectory");
QTest::addColumn<QStringMap>("expectedFiles");
- QString dataPath = QFINDTESTDATA("data/binary/");
- if (dataPath.isEmpty())
- QFAIL("data path not found");
+ QString dataPath = m_dataPath + QLatin1String("/binary/");
QDirIterator iter(dataPath, QStringList() << QLatin1String("*.qrc"));
while (iter.hasNext())
@@ -279,12 +278,33 @@ void tst_rcc::binary_data()
QFileInfo qrcFileInfo = iter.fileInfo();
QString absoluteBaseName = QFileInfo(qrcFileInfo.absolutePath(), qrcFileInfo.baseName()).absoluteFilePath();
QString rccFileName = absoluteBaseName + QLatin1String(".rcc");
- createRccBinaryData(m_rcc, dataPath, qrcFileInfo.absoluteFilePath(), rccFileName);
+
+ // same as above: force no compression
+ QProcess rccProcess;
+ rccProcess.setWorkingDirectory(dataPath);
+ rccProcess.start(m_rcc, { "-binary", "-no-compress", "-o", rccFileName, qrcFileInfo.absoluteFilePath() });
+ QVERIFY2(rccProcess.waitForStarted(), msgProcessStartFailed(rccProcess).constData());
+ if (!rccProcess.waitForFinished()) {
+ rccProcess.kill();
+ QFAIL(msgProcessTimeout(rccProcess).constData());
+ }
+ QVERIFY2(rccProcess.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(rccProcess).constData());
+ QVERIFY2(rccProcess.exitCode() == 0,
+ msgProcessFailed(rccProcess).constData());
+
+ QByteArray output = rccProcess.readAllStandardOutput();
+ if (!output.isEmpty())
+ qWarning("rcc stdout: %s", output.constData());
+
+ output = rccProcess.readAllStandardError();
+ if (!output.isEmpty())
+ qWarning("rcc stderr: %s", output.constData());
QString localeFileName = absoluteBaseName + QLatin1String(".locale");
QFile localeFile(localeFileName);
if (localeFile.exists()) {
- QStringList locales = readLinesFromFile(localeFileName);
+ QStringList locales = readLinesFromFile(localeFileName, QString::SkipEmptyParts);
foreach (const QString &locale, locales) {
QString expectedFileName = QString::fromLatin1("%1.%2.%3").arg(absoluteBaseName, locale, QLatin1String("expected"));
QStringMap expectedFiles = readExpectedFiles(expectedFileName);
@@ -386,16 +406,12 @@ void tst_rcc::readback()
QFETCH(QString, resourceName);
QFETCH(QString, fileSystemName);
- QString dataPath = QFINDTESTDATA("data/");
- if (dataPath.isEmpty())
- QFAIL("data path not found");
-
QFile resourceFile(resourceName);
QVERIFY(resourceFile.open(QIODevice::ReadOnly));
QByteArray resourceData = resourceFile.readAll();
resourceFile.close();
- QFile fileSystemFile(dataPath + fileSystemName);
+ QFile fileSystemFile(m_dataPath + QLatin1Char('/') + fileSystemName);
QVERIFY(fileSystemFile.open(QIODevice::ReadOnly));
QByteArray fileSystemData = fileSystemFile.readAll();
fileSystemFile.close();
@@ -403,13 +419,85 @@ void tst_rcc::readback()
QCOMPARE(resourceData, fileSystemData);
}
+void tst_rcc::depFileGeneration_data()
+{
+ QTest::addColumn<QString>("qrcfile");
+ QTest::addColumn<QString>("depfile");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("simple") << "simple.qrc" << "simple.d" << "simple.d.expected";
+ QTest::newRow("specialchar") << "specialchar.qrc" << "specialchar.d" << "specialchar.d.expected";
+}
+
+void tst_rcc::depFileGeneration()
+{
+ QFETCH(QString, qrcfile);
+ QFETCH(QString, depfile);
+ QFETCH(QString, expected);
+ const QString directory = m_dataPath + QLatin1String("/depfile");
+
+ QProcess process;
+ process.setWorkingDirectory(directory);
+ process.start(m_rcc, { "-d", depfile, "-o", qrcfile + ".cpp", qrcfile });
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(process).constData());
+ if (!process.waitForFinished()) {
+ process.kill();
+ QFAIL(msgProcessTimeout(process).constData());
+ }
+ QVERIFY2(process.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(process).constData());
+ QVERIFY2(process.exitCode() == 0,
+ msgProcessFailed(process).constData());
+
+ QFile depFileOutput(directory + QLatin1String("/") + depfile);
+ QVERIFY(depFileOutput.open(QIODevice::ReadOnly | QIODevice::Text));
+ QByteArray depFileData = depFileOutput.readAll();
+ depFileOutput.close();
+
+ QFile depFileExpected(directory + QLatin1String("/") + expected);
+ QVERIFY(depFileExpected.open(QIODevice::ReadOnly | QIODevice::Text));
+ QByteArray expectedData = depFileExpected.readAll();
+ depFileExpected.close();
+
+ QCOMPARE(depFileData, expectedData);
+}
+
+void tst_rcc::python()
+{
+ const QString path = m_dataPath + QLatin1String("/sizes");
+ const QString testFileRoot = path + QLatin1String("/size-2-0-35-1");
+ const QString qrcFile = testFileRoot + QLatin1String(".qrc");
+ const QString expectedFile = testFileRoot + QLatin1String("_python.expected");
+ const QString actualFile = testFileRoot + QLatin1String(".rcc");
+
+ QProcess process;
+ process.setWorkingDirectory(path);
+ process.start(m_rcc, { "-g", "python", "-o", actualFile, qrcFile});
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(process).constData());
+ if (!process.waitForFinished()) {
+ process.kill();
+ QFAIL(msgProcessTimeout(process).constData());
+ }
+ QVERIFY2(process.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(process).constData());
+ QVERIFY2(process.exitCode() == 0,
+ msgProcessFailed(process).constData());
+
+ const auto actualLines = readLinesFromFile(actualFile, QString::KeepEmptyParts);
+ QVERIFY(!actualLines.isEmpty());
+ const auto expectedLines = readLinesFromFile(expectedFile, QString::KeepEmptyParts);
+ QVERIFY(!expectedLines.isEmpty());
+ const QString diff = doCompare(actualLines, expectedLines, path);
+ if (!diff.isEmpty())
+ QFAIL(qPrintable(diff));
+}
+
void tst_rcc::cleanupTestCase()
{
- QString dataPath = QFINDTESTDATA("data/binary/");
- if (dataPath.isEmpty())
- return;
- QDir dataDir(dataPath);
+ QDir dataDir(m_dataPath + QLatin1String("/binary"));
QFileInfoList entries = dataDir.entryInfoList(QStringList() << QLatin1String("*.rcc"));
+ QDir dataDepDir(m_dataPath + QLatin1String("/depfile"));
+ entries += dataDepDir.entryInfoList({QLatin1String("*.d"), QLatin1String("*.qrc.cpp")});
foreach (const QFileInfo &entry, entries)
QFile::remove(entry.absoluteFilePath());
}
diff --git a/tests/auto/tools/uic/baseline/dialog.ui b/tests/auto/tools/uic/baseline/dialog.ui
index e99d6fb3c4..936cc2eee8 100644
--- a/tests/auto/tools/uic/baseline/dialog.ui
+++ b/tests/auto/tools/uic/baseline/dialog.ui
@@ -1,4 +1,4 @@
-<ui version="4.0" >
+<ui version="4.0" connectslotsbyname="false">
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
diff --git a/tests/auto/tools/uic/baseline/dialog.ui.h b/tests/auto/tools/uic/baseline/dialog.ui.h
index aeed71d058..cd6449873e 100644
--- a/tests/auto/tools/uic/baseline/dialog.ui.h
+++ b/tests/auto/tools/uic/baseline/dialog.ui.h
@@ -52,8 +52,6 @@ public:
retranslateUi(Dialog);
-
- QMetaObject::connectSlotsByName(Dialog);
} // setupUi
void retranslateUi(QDialog *Dialog)
diff --git a/tests/auto/tools/uic/baseline/qfiledialog.ui.h b/tests/auto/tools/uic/baseline/qfiledialog.ui.h
index 9e51ee6a7c..52f8d25c75 100644
--- a/tests/auto/tools/uic/baseline/qfiledialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qfiledialog.ui.h
@@ -291,7 +291,7 @@ public:
detailModeButton->setToolTip(QCoreApplication::translate("QFileDialog", "Detail View", nullptr));
#endif // QT_CONFIG(tooltip)
fileTypeLabel->setText(QCoreApplication::translate("QFileDialog", "Files of type:", nullptr));
- Q_UNUSED(QFileDialog);
+ (void)QFileDialog;
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp
index f9553028fe..5b2f1f008b 100644
--- a/tests/auto/tools/uic/tst_uic.cpp
+++ b/tests/auto/tools/uic/tst_uic.cpp
@@ -36,17 +36,27 @@
#include <QtCore/QTemporaryDir>
#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
+#include <QtCore/QVector>
#include <cstdio>
static const char keepEnvVar[] = "UIC_KEEP_GENERATED_FILES";
static const char diffToStderrEnvVar[] = "UIC_STDERR_DIFF";
+struct TestEntry
+{
+ QByteArray name;
+ QString baselineBaseName;
+ QString generatedFileName;
+};
+
class tst_uic : public QObject
{
Q_OBJECT
public:
+ using TestEntries = QVector<TestEntry>;
+
tst_uic();
private Q_SLOTS:
@@ -63,13 +73,20 @@ private Q_SLOTS:
void compare();
void compare_data() const;
+ void python();
+ void python_data() const;
+
void runCompare();
private:
+ void populateTestEntries();
+
const QString m_command;
QString m_baseline;
QTemporaryDir m_generated;
+ TestEntries m_testEntries;
QRegularExpression m_versionRegexp;
+ QString m_python;
};
tst_uic::tst_uic()
@@ -85,6 +102,32 @@ static QByteArray msgProcessStartFailed(const QString &command, const QString &w
return result.toLocal8Bit();
}
+// Locate Python and check whether PySide2 is installed
+static QString locatePython(QTemporaryDir &generatedDir)
+{
+ QString python = QStandardPaths::findExecutable(QLatin1String("python"));
+ if (python.isEmpty()) {
+ qWarning("Cannot locate python, skipping tests");
+ return QString();
+ }
+ QFile importTestFile(generatedDir.filePath(QLatin1String("import_test.py")));
+ if (!importTestFile.open(QIODevice::WriteOnly| QIODevice::Text))
+ return QString();
+ importTestFile.write("import PySide2.QtCore\n");
+ importTestFile.close();
+ QProcess process;
+ process.start(python, {importTestFile.fileName()});
+ if (!process.waitForStarted() || !process.waitForFinished())
+ return QString();
+ if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) {
+ const QString stdErr = QString::fromLocal8Bit(process.readAllStandardError()).simplified();
+ qWarning("PySide2 is not installed (%s)", qPrintable(stdErr));
+ return QString();
+ }
+ importTestFile.remove();
+ return python;
+}
+
void tst_uic::initTestCase()
{
QVERIFY2(m_generated.isValid(), qPrintable(m_generated.errorString()));
@@ -105,7 +148,28 @@ void tst_uic::initTestCase()
arg(QDir::currentPath());
if (!outLines.empty())
msg += outLines.front();
+ populateTestEntries();
+ QVERIFY(!m_testEntries.isEmpty());
qDebug("%s", qPrintable(msg));
+
+ m_python = locatePython(m_generated);
+}
+
+void tst_uic::populateTestEntries()
+{
+ const QString generatedPrefix = m_generated.path() + QLatin1Char('/');
+ QDir baseline(m_baseline);
+ const QString baseLinePrefix = baseline.path() + QLatin1Char('/');
+ const QFileInfoList baselineFiles =
+ baseline.entryInfoList(QStringList(QString::fromLatin1("*.ui")), QDir::Files);
+ m_testEntries.reserve(baselineFiles.size());
+ for (const QFileInfo &baselineFile : baselineFiles) {
+ const QString baseName = baselineFile.baseName();
+ const QString baselineBaseName = baseLinePrefix + baseName;
+ const QString generatedFile = generatedPrefix + baselineFile.fileName()
+ + QLatin1String(".h");
+ m_testEntries.append(TestEntry{baseName.toLocal8Bit(), baselineBaseName, generatedFile});
+ }
}
static const char helpFormat[] = R"(
@@ -171,22 +235,12 @@ void tst_uic::run_data() const
QTest::addColumn<QString>("generatedFile");
QTest::addColumn<QStringList>("options");
- QDir generated(m_generated.path());
- QDir baseline(m_baseline);
- const QFileInfoList baselineFiles = baseline.entryInfoList(QStringList("*.ui"), QDir::Files);
- foreach (const QFileInfo &baselineFile, baselineFiles) {
- const QString generatedFile = generated.absolutePath()
- + QLatin1Char('/') + baselineFile.fileName()
- + QLatin1String(".h");
-
+ for (const TestEntry &te : m_testEntries) {
QStringList options;
- if (baselineFile.fileName() == QLatin1String("qttrid.ui"))
+ if (te.name == QByteArrayLiteral("qttrid"))
options << QStringList(QLatin1String("-idbased"));
-
- QTest::newRow(qPrintable(baselineFile.baseName()))
- << baselineFile.absoluteFilePath()
- << generatedFile
- << options;
+ QTest::newRow(te.name.constData()) << (te.baselineBaseName + QLatin1String(".ui"))
+ << te.generatedFileName << options;
}
}
@@ -264,15 +318,9 @@ void tst_uic::compare_data() const
QTest::addColumn<QString>("originalFile");
QTest::addColumn<QString>("generatedFile");
- QDir generated(m_generated.path());
- QDir baseline(m_baseline);
- const QFileInfoList baselineFiles = baseline.entryInfoList(QStringList("*.h"), QDir::Files);
- foreach (const QFileInfo &baselineFile, baselineFiles) {
- const QString generatedFile = generated.absolutePath()
- + QLatin1Char('/') + baselineFile.fileName();
- QTest::newRow(qPrintable(baselineFile.baseName()))
- << baselineFile.absoluteFilePath()
- << generatedFile;
+ for (const TestEntry &te : m_testEntries) {
+ QTest::newRow(te.name.constData()) << (te.baselineBaseName + QLatin1String(".ui.h"))
+ << te.generatedFileName;
}
}
@@ -280,7 +328,7 @@ void tst_uic::runTranslation()
{
QProcess process;
- QDir baseline(m_baseline);
+ const QDir baseline(m_baseline);
QDir generated(m_generated.path());
generated.mkdir(QLatin1String("translation"));
@@ -327,5 +375,75 @@ void tst_uic::runCompare()
QCOMPARE(generatedFileContents, originalFileContents);
}
+// Let uic generate Python code and verify that it is syntactically
+// correct by compiling it into .pyc. This test is executed only
+// when python with an installed Qt for Python is detected (see locatePython()).
+
+static inline QByteArray msgCompilePythonFailed(const QByteArray &error)
+{
+ // If there is a line with blanks and caret indicating an error in the line
+ // above, insert the cursor into the offending line and remove the caret.
+ QByteArrayList lines = error.trimmed().split('\n');
+ for (int i = lines.size() - 1; i > 0; --i) {
+ const auto &line = lines.at(i);
+ const int caret = line.indexOf('^');
+ if (caret == 0 || (caret > 0 && line.at(caret - 1) == ' ')) {
+ lines.removeAt(i);
+ lines[i - 1].insert(caret, '|');
+ break;
+ }
+ }
+ return lines.join('\n');
+}
+
+void tst_uic::python_data() const
+{
+ QTest::addColumn<QString>("originalFile");
+ QTest::addColumn<QString>("generatedFile");
+
+ const int size = m_python.isEmpty()
+ ? qMin(1, m_testEntries.size()) : m_testEntries.size();
+ for (int i = 0; i < size; ++i) {
+ const TestEntry &te = m_testEntries.at(i);
+ // qprintsettingsoutput: variable named 'from' clashes with Python
+ if (!te.baselineBaseName.endsWith(QLatin1String("/qprintsettingsoutput"))) {
+ QString generatedFile = te.generatedFileName;
+ generatedFile.chop(1); // foo.h -> foo.py
+ generatedFile.append(QLatin1String("py"));
+ QTest::newRow(te.name.constData())
+ << (te.baselineBaseName + QLatin1String(".ui"))
+ << generatedFile;
+ }
+ }
+}
+
+void tst_uic::python()
+{
+ QFETCH(QString, originalFile);
+ QFETCH(QString, generatedFile);
+ if (m_python.isEmpty())
+ QSKIP("Python was not found");
+
+ QStringList uicArguments{QLatin1String("-g"), QLatin1String("python"),
+ originalFile, QLatin1String("-o"), generatedFile};
+ QProcess process;
+ process.setWorkingDirectory(m_generated.path());
+ process.start(m_command, uicArguments);
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString()));
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+ QVERIFY(QFileInfo::exists(generatedFile));
+
+ // Test Python code generation by compiling the file
+ QStringList compileArguments{QLatin1String("-m"), QLatin1String("py_compile"), generatedFile};
+ process.start(m_python, compileArguments);
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString()));
+ QVERIFY(process.waitForFinished());
+ const bool compiled = process.exitStatus() == QProcess::NormalExit
+ && process.exitCode() == 0;
+ QVERIFY2(compiled, msgCompilePythonFailed(process.readAllStandardError()).constData());
+}
+
QTEST_MAIN(tst_uic)
#include "tst_uic.moc"
diff --git a/tests/auto/widgets/dialogs/qdialog/BLACKLIST b/tests/auto/widgets/dialogs/qdialog/BLACKLIST
index dd6a8bfff9..72e3dff6dd 100644
--- a/tests/auto/widgets/dialogs/qdialog/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qdialog/BLACKLIST
@@ -1,4 +1,4 @@
[snapToDefaultButton]
-osx
+osx-10.14
[showFullScreen]
osx-10.13 ci
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
index c840dabc1a..a494d7119a 100644
--- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -52,7 +52,9 @@ class DummyDialog : public QDialog
{
public:
DummyDialog(): QDialog() {}
+#if QT_DEPRECATED_SINCE(5, 13)
using QDialog::showExtension;
+#endif
};
class tst_QDialog : public QObject
@@ -64,8 +66,10 @@ public:
private slots:
void cleanup();
void getSetCheck();
+#if QT_DEPRECATED_SINCE(5, 13)
void showExtension_data();
void showExtension();
+#endif
void defaultButtons();
void showMaximized();
void showMinimized();
@@ -76,6 +80,9 @@ private slots:
void deleteInExec();
#if QT_CONFIG(sizegrip)
void showSizeGrip();
+#if QT_DEPRECATED_SINCE(5, 13)
+ void showSizeGrip_deprecated();
+#endif
#endif
void setVisible();
void reject();
@@ -89,6 +96,7 @@ private slots:
void tst_QDialog::getSetCheck()
{
QDialog obj1;
+#if QT_DEPRECATED_SINCE(5, 13)
// QWidget* QDialog::extension()
// void QDialog::setExtension(QWidget*)
QWidget *var1 = new QWidget;
@@ -97,6 +105,7 @@ void tst_QDialog::getSetCheck()
obj1.setExtension((QWidget *)0);
QCOMPARE((QWidget *)0, obj1.extension());
// No delete var1, since setExtension takes ownership
+#endif
// int QDialog::result()
// void QDialog::setResult(int)
@@ -146,6 +155,7 @@ void tst_QDialog::cleanup()
QVERIFY(QApplication::topLevelWidgets().isEmpty());
}
+#if QT_DEPRECATED_SINCE(5, 13)
void tst_QDialog::showExtension_data()
{
QTest::addColumn<QSize>("dlgSize");
@@ -197,6 +207,7 @@ void tst_QDialog::showExtension()
testWidget.setExtension( 0 );
}
+#endif
void tst_QDialog::defaultButtons()
{
@@ -422,9 +433,37 @@ void tst_QDialog::deleteInExec()
}
#if QT_CONFIG(sizegrip)
+
// From Task 124269
void tst_QDialog::showSizeGrip()
{
+ QDialog dialog(nullptr);
+ dialog.show();
+ QWidget *ext = new QWidget(&dialog);
+ QVERIFY(!dialog.isSizeGripEnabled());
+
+ dialog.setSizeGripEnabled(true);
+ QPointer<QSizeGrip> sizeGrip = dialog.findChild<QSizeGrip *>();
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+ QVERIFY(dialog.isSizeGripEnabled());
+
+ dialog.setSizeGripEnabled(false);
+ QVERIFY(!dialog.isSizeGripEnabled());
+
+ dialog.setSizeGripEnabled(true);
+ sizeGrip = dialog.findChild<QSizeGrip *>();
+ QVERIFY(sizeGrip);
+ QVERIFY(sizeGrip->isVisible());
+ sizeGrip->hide();
+ dialog.hide();
+ dialog.show();
+ QVERIFY(!sizeGrip->isVisible());
+}
+
+#if QT_DEPRECATED_SINCE(5, 13)
+void tst_QDialog::showSizeGrip_deprecated()
+{
QDialog dialog(0);
dialog.show();
QWidget *ext = new QWidget(&dialog);
@@ -476,7 +515,9 @@ void tst_QDialog::showSizeGrip()
dialog.show();
QVERIFY(!sizeGrip->isVisible());
}
-#endif
+#endif // QT_DEPRECATED_SINCE(5, 13)
+
+#endif // QT_CONFIG(sizegrip)
void tst_QDialog::setVisible()
{
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 748c8aaa84..2131e45f29 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -800,7 +800,10 @@ void tst_QFiledialog::isReadOnly()
QAction* renameAction = fd.findChild<QAction*>("qt_rename_action");
QAction* deleteAction = fd.findChild<QAction*>("qt_delete_action");
+#if QT_DEPRECATED_SINCE(5, 13)
QCOMPARE(fd.isReadOnly(), false);
+#endif
+ QCOMPARE(fd.testOption(QFileDialog::ReadOnly), false);
// This is dependent upon the file/dir, find cross platform way to test
//fd.setDirectory(QDir::home());
@@ -1421,6 +1424,16 @@ void tst_QFiledialog::clearLineEdit()
QTRY_VERIFY(fd.directory().absolutePath() != workDirPath);
QVERIFY(lineEdit->text().isEmpty());
+
+ // QTBUG-71415: When pressing back, the selection (activated
+ // directory) should be restored.
+ QToolButton *backButton = fd.findChild<QToolButton*>("backButton");
+ QVERIFY(backButton);
+ QTreeView *treeView = fd.findChildren<QTreeView*>("treeView").value(0);
+ QVERIFY(treeView);
+ backButton->click();
+ QTRY_COMPARE(treeView->selectionModel()->selectedIndexes().value(0).data().toString(),
+ dirName);
}
void tst_QFiledialog::enableChooseButton()
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST
index e0887d8ad1..875855b59e 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST
@@ -1,2 +1,4 @@
[QTBUG4419_lineEditSelectAll]
-osx
+osx-10.12
+osx-10.14
+osx-10.13
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index 869418371c..40eff1e4c3 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -378,24 +378,24 @@ void tst_QFileDialog2::task143519_deleteAndRenameActionBehavior()
// defaults
QVERIFY(openContextMenu(fd));
QCOMPARE(fd.selectedFiles(), QStringList(ctx.file.fileName()));
- QCOMPARE(rm->isEnabled(), !fd.isReadOnly());
- QCOMPARE(mv->isEnabled(), !fd.isReadOnly());
+ QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
+ QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
// change to non-defaults:
- fd.setReadOnly(!fd.isReadOnly());
+ fd.setOption(QFileDialog::ReadOnly, !fd.testOption(QFileDialog::ReadOnly));
QVERIFY(openContextMenu(fd));
QCOMPARE(fd.selectedFiles().size(), 1);
- QCOMPARE(rm->isEnabled(), !fd.isReadOnly());
- QCOMPARE(mv->isEnabled(), !fd.isReadOnly());
+ QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
+ QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
// and changed back to defaults:
- fd.setReadOnly(!fd.isReadOnly());
+ fd.setOption(QFileDialog::ReadOnly, !fd.testOption(QFileDialog::ReadOnly));
QVERIFY(openContextMenu(fd));
QCOMPARE(fd.selectedFiles().size(), 1);
- QCOMPARE(rm->isEnabled(), !fd.isReadOnly());
- QCOMPARE(mv->isEnabled(), !fd.isReadOnly());
+ QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
+ QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
}
#endif // !QT_NO_CONTEXTMENU && !QT_NO_MENU
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST
index f78d23c6b1..aae2cacc3b 100644
--- a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST
@@ -1,13 +1,16 @@
winrt
+[sort]
+winrt
[sort:QFileDialog usage]
ubuntu
b2qt
[specialFiles]
-ubuntu
b2qt
[dirsBeforeFiles]
-ubuntu
+winrt
b2qt
-windows
+ubuntu
+windows-10
rhel
-suse-leap
+[drives]
+winrt
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
index 665a116a3a..f8f40e8488 100644
--- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -65,18 +65,18 @@
} \
} while(0)
-class tst_QFileSystemModel : public QObject {
- Q_OBJECT
+Q_DECLARE_METATYPE(QDir::Filters)
+Q_DECLARE_METATYPE(QFileDevice::Permissions)
-public:
- tst_QFileSystemModel();
+Q_LOGGING_CATEGORY(lcFileSystemModel, "qt.widgets.tests.qfilesystemmodel")
-public Q_SLOTS:
- void init();
- void cleanup();
+class tst_QFileSystemModel : public QObject {
+ Q_OBJECT
private slots:
void initTestCase();
+ void cleanup();
+
void indexPath();
void rootPath();
@@ -128,48 +128,33 @@ private slots:
void fileInfo();
protected:
- bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList());
- QModelIndex prepareTestModelRoot(const QString &test_path, QSignalSpy **spy2 = nullptr,
- QSignalSpy **spy3 = nullptr);
+ bool createFiles(QFileSystemModel *model, const QString &test_path,
+ const QStringList &initial_files, int existingFileCount = 0,
+ const QStringList &initial_dirs = QStringList());
+ QModelIndex prepareTestModelRoot(QFileSystemModel *model, const QString &test_path,
+ QSignalSpy **spy2 = nullptr, QSignalSpy **spy3 = nullptr);
private:
- QFileSystemModel *model;
QString flatDirTestPath;
QTemporaryDir m_tempDir;
};
-tst_QFileSystemModel::tst_QFileSystemModel() : model(0)
-{
-}
-
-void tst_QFileSystemModel::init()
-{
- cleanup();
- QCOMPARE(model, nullptr);
- model = new QFileSystemModel;
-}
-
void tst_QFileSystemModel::cleanup()
{
- delete model;
- model = 0;
- QString tmp = flatDirTestPath;
- QDir dir(tmp);
- if (dir.exists(tmp)) {
- QStringList list = dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot);
- for (int i = 0; i < list.count(); ++i) {
- QFileInfo fi(dir.path() + '/' + list.at(i));
- if (fi.exists() && fi.isFile()) {
- QFile p(fi.absoluteFilePath());
- p.setPermissions(QFile::ReadUser | QFile::ReadOwner | QFile::ExeOwner | QFile::ExeUser | QFile::WriteUser | QFile::WriteOwner | QFile::WriteOther);
- QFile dead(dir.path() + '/' + list.at(i));
- dead.remove();
+ QDir dir(flatDirTestPath);
+ if (dir.exists()) {
+ const QDir::Filters filters = QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot;
+ const QFileInfoList list = dir.entryInfoList(filters);
+ for (const QFileInfo &fi : list) {
+ if (fi.isDir()) {
+ QVERIFY(dir.rmdir(fi.fileName()));
+ } else {
+ QFile dead(fi.absoluteFilePath());
+ dead.setPermissions(QFile::ReadUser | QFile::ReadOwner | QFile::ExeOwner | QFile::ExeUser | QFile::WriteUser | QFile::WriteOwner | QFile::WriteOther);
+ QVERIFY(dead.remove());
}
- if (fi.exists() && fi.isDir())
- QVERIFY(dir.rmdir(list.at(i)));
}
- list = dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot);
- QCOMPARE(list.count(), 0);
+ QVERIFY(dir.entryInfoList(filters).isEmpty());
}
}
@@ -182,6 +167,7 @@ void tst_QFileSystemModel::initTestCase()
void tst_QFileSystemModel::indexPath()
{
#if !defined(Q_OS_WIN)
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
int depth = QDir::currentPath().count('/');
model->setRootPath(QDir::currentPath());
QString backPath;
@@ -195,9 +181,10 @@ void tst_QFileSystemModel::indexPath()
void tst_QFileSystemModel::rootPath()
{
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QCOMPARE(model->rootPath(), QString(QDir().path()));
- QSignalSpy rootChanged(model, SIGNAL(rootPathChanged(QString)));
+ QSignalSpy rootChanged(model.data(), &QFileSystemModel::rootPathChanged);
QModelIndex root = model->setRootPath(model->rootPath());
root = model->setRootPath("this directory shouldn't exist");
QCOMPARE(rootChanged.count(), 0);
@@ -243,6 +230,7 @@ void tst_QFileSystemModel::rootPath()
void tst_QFileSystemModel::readOnly()
{
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QCOMPARE(model->isReadOnly(), true);
QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat"));
QVERIFY2(file.open(), qPrintable(file.errorString()));
@@ -263,19 +251,21 @@ void tst_QFileSystemModel::readOnly()
class CustomFileIconProvider : public QFileIconProvider
{
public:
- CustomFileIconProvider() : QFileIconProvider() {
- mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical);
- dvd = qApp->style()->standardIcon(QStyle::SP_DriveDVDIcon);
+ CustomFileIconProvider() : QFileIconProvider()
+ {
+ auto style = QApplication::style();
+ mb = style->standardIcon(QStyle::SP_MessageBoxCritical);
+ dvd = style->standardIcon(QStyle::SP_DriveDVDIcon);
}
- virtual QIcon icon(const QFileInfo &info) const
+ QIcon icon(const QFileInfo &info) const override
{
if (info.isDir())
return mb;
return QFileIconProvider::icon(info);
}
- virtual QIcon icon(IconType type) const
+ QIcon icon(IconType type) const override
{
if (type == QFileIconProvider::Folder)
return dvd;
@@ -289,69 +279,67 @@ private:
void tst_QFileSystemModel::iconProvider()
{
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QVERIFY(model->iconProvider());
- QFileIconProvider *p = new QFileIconProvider();
- model->setIconProvider(p);
- QCOMPARE(model->iconProvider(), p);
- model->setIconProvider(0);
- delete p;
+ QScopedPointer<QFileIconProvider> provider(new QFileIconProvider);
+ model->setIconProvider(provider.data());
+ QCOMPARE(model->iconProvider(), provider.data());
+ model->setIconProvider(nullptr);
+ provider.reset();
- QFileSystemModel *myModel = new QFileSystemModel();
+ QScopedPointer<QFileSystemModel> myModel(new QFileSystemModel);
const QStringList documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
QVERIFY(!documentPaths.isEmpty());
- const QString documentPath = documentPaths.front();
- myModel->setRootPath(documentPath);
+ myModel->setRootPath(documentPaths.constFirst());
//We change the provider, icons must be updated
- CustomFileIconProvider *custom = new CustomFileIconProvider();
- myModel->setIconProvider(custom);
+ provider.reset(new CustomFileIconProvider);
+ myModel->setIconProvider(provider.data());
- QPixmap mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50);
+ QPixmap mb = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50);
QCOMPARE(myModel->fileIcon(myModel->index(QDir::homePath())).pixmap(50, 50), mb);
- delete myModel;
- delete custom;
}
-bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs)
+bool tst_QFileSystemModel::createFiles(QFileSystemModel *model, const QString &test_path,
+ const QStringList &initial_files, int existingFileCount,
+ const QStringList &initial_dirs)
{
- //qDebug() << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files;
+ qCDebug(lcFileSystemModel) << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files;
bool timedOut = false;
TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount), &timedOut);
if (timedOut)
return false;
- for (int i = 0; i < initial_dirs.count(); ++i) {
- QDir dir(test_path);
- if (!dir.exists()) {
- qWarning() << "error" << test_path << "doesn't exists";
- return false;
- }
- if(!dir.mkdir(initial_dirs.at(i))) {
- qWarning() << "error" << "failed to make" << initial_dirs.at(i);
+ QDir dir(test_path);
+ if (!dir.exists()) {
+ qWarning() << "error" << test_path << "doesn't exist";
+ return false;
+ }
+ for (const auto &initial_dir : initial_dirs) {
+ if (!dir.mkdir(initial_dir)) {
+ qWarning() << "error" << "failed to make" << initial_dir;
return false;
}
- //qDebug() << test_path + '/' + initial_dirs.at(i) << (QFile::exists(test_path + '/' + initial_dirs.at(i)));
+ qCDebug(lcFileSystemModel) << test_path + '/' + initial_dir << (QFile::exists(test_path + '/' + initial_dir));
}
- for (int i = 0; i < initial_files.count(); ++i) {
- QFile file(test_path + '/' + initial_files.at(i));
+ for (const auto &initial_file : initial_files) {
+ QFile file(test_path + '/' + initial_file);
if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {
- qDebug() << "failed to open file" << initial_files.at(i);
+ qDebug() << "failed to open file" << initial_file;
return false;
}
if (!file.resize(1024 + file.size())) {
- qDebug() << "failed to resize file" << initial_files.at(i);
+ qDebug() << "failed to resize file" << initial_file;
return false;
}
if (!file.flush()) {
- qDebug() << "failed to flush file" << initial_files.at(i);
+ qDebug() << "failed to flush file" << initial_file;
return false;
}
file.close();
#if defined(Q_OS_WIN)
- if (initial_files.at(i)[0] == '.') {
- QString hiddenFile = QDir::toNativeSeparators(file.fileName());
- wchar_t nativeHiddenFile[MAX_PATH];
- memset(nativeHiddenFile, 0, sizeof(nativeHiddenFile));
- hiddenFile.toWCharArray(nativeHiddenFile);
+ if (initial_file[0] == '.') {
+ const QString hiddenFile = QDir::toNativeSeparators(file.fileName());
+ const auto nativeHiddenFile = reinterpret_cast<const wchar_t *>(hiddenFile.utf16());
#ifndef Q_OS_WINRT
DWORD currentAttributes = ::GetFileAttributes(nativeHiddenFile);
#else // !Q_OS_WINRT
@@ -370,13 +358,13 @@ bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringLi
}
}
#endif
- //qDebug() << test_path + '/' + initial_files.at(i) << (QFile::exists(test_path + '/' + initial_files.at(i)));
+ qCDebug(lcFileSystemModel) << test_path + '/' + initial_file << (QFile::exists(test_path + '/' + initial_file));
}
return true;
}
-QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path, QSignalSpy **spy2,
- QSignalSpy **spy3)
+QModelIndex tst_QFileSystemModel::prepareTestModelRoot(QFileSystemModel *model, const QString &test_path,
+ QSignalSpy **spy2, QSignalSpy **spy3)
{
if (model->rowCount(model->index(test_path)) != 0)
return QModelIndex();
@@ -387,9 +375,8 @@ QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path,
*spy3 = new QSignalSpy(model, &QFileSystemModel::rowsAboutToBeInserted);
QStringList files = { "b", "d", "f", "h", "j", ".a", ".c", ".e", ".g" };
- QString l = "b,d,f,h,j,.a,.c,.e,.g";
- if (!createFiles(test_path, files))
+ if (!createFiles(model, test_path, files))
return QModelIndex();
QModelIndex root = model->setRootPath(test_path);
@@ -406,10 +393,10 @@ QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path,
void tst_QFileSystemModel::rowCount()
{
- const QString tmp = flatDirTestPath;
QSignalSpy *spy2 = nullptr;
QSignalSpy *spy3 = nullptr;
- QModelIndex root = prepareTestModelRoot(flatDirTestPath, &spy2, &spy3);
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QModelIndex root = prepareTestModelRoot(model.data(), flatDirTestPath, &spy2, &spy3);
QVERIFY(root.isValid());
QVERIFY(spy2 && spy2->count() > 0);
@@ -419,11 +406,11 @@ void tst_QFileSystemModel::rowCount()
void tst_QFileSystemModel::rowsInserted_data()
{
QTest::addColumn<int>("count");
- QTest::addColumn<int>("ascending");
+ QTest::addColumn<Qt::SortOrder>("ascending");
for (int i = 0; i < 4; ++i) {
const QByteArray iB = QByteArray::number(i);
- QTest::newRow(("Qt::AscendingOrder " + iB).constData()) << i << (int)Qt::AscendingOrder;
- QTest::newRow(("Qt::DescendingOrder " + iB).constData()) << i << (int)Qt::DescendingOrder;
+ QTest::newRow(("Qt::AscendingOrder " + iB).constData()) << i << Qt::AscendingOrder;
+ QTest::newRow(("Qt::DescendingOrder " + iB).constData()) << i << Qt::DescendingOrder;
}
}
@@ -436,20 +423,21 @@ static inline QString lastEntry(const QModelIndex &root)
void tst_QFileSystemModel::rowsInserted()
{
const QString tmp = flatDirTestPath;
- QModelIndex root = prepareTestModelRoot(tmp);
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QModelIndex root = prepareTestModelRoot(model.data(), tmp);
QVERIFY(root.isValid());
- QFETCH(int, ascending);
+ QFETCH(Qt::SortOrder, ascending);
QFETCH(int, count);
- model->sort(0, (Qt::SortOrder)ascending);
+ model->sort(0, ascending);
- QSignalSpy spy0(model, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QSignalSpy spy1(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy spy0(model.data(), &QAbstractItemModel::rowsInserted);
+ QSignalSpy spy1(model.data(), &QAbstractItemModel::rowsAboutToBeInserted);
int oldCount = model->rowCount(root);
QStringList files;
for (int i = 0; i < count; ++i)
files.append(QLatin1Char('c') + QString::number(i));
- QVERIFY(createFiles(tmp, files, 5));
+ QVERIFY(createFiles(model.data(), tmp, files, 5));
QTRY_COMPARE(model->rowCount(root), oldCount + count);
int totalRowsInserted = 0;
for (int i = 0; i < spy0.count(); ++i) {
@@ -469,7 +457,7 @@ void tst_QFileSystemModel::rowsInserted()
}
if (count == 0) QCOMPARE(spy1.count(), 0); else QVERIFY(spy1.count() >= 1);
- QVERIFY(createFiles(tmp, QStringList(".hidden_file"), 5 + count));
+ QVERIFY(createFiles(model.data(), tmp, QStringList(".hidden_file"), 5 + count));
if (count != 0)
QTRY_VERIFY(spy0.count() >= 1);
@@ -489,19 +477,21 @@ void tst_QFileSystemModel::rowsRemoved_data()
void tst_QFileSystemModel::rowsRemoved()
{
const QString tmp = flatDirTestPath;
- QModelIndex root = prepareTestModelRoot(tmp);
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QModelIndex root = prepareTestModelRoot(model.data(), tmp);
QVERIFY(root.isValid());
QFETCH(int, count);
- QFETCH(int, ascending);
- model->sort(0, (Qt::SortOrder)ascending);
+ QFETCH(Qt::SortOrder, ascending);
+ model->sort(0, ascending);
- QSignalSpy spy0(model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QSignalSpy spy1(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy spy0(model.data(), &QAbstractItemModel::rowsRemoved);
+ QSignalSpy spy1(model.data(), &QAbstractItemModel::rowsAboutToBeRemoved);
int oldCount = model->rowCount(root);
for (int i = count - 1; i >= 0; --i) {
- //qDebug() << "removing" << model->index(i, 0, root).data().toString();
- QVERIFY(QFile::remove(tmp + '/' + model->index(i, 0, root).data().toString()));
+ const QString fileName = model->index(i, 0, root).data().toString();
+ qCDebug(lcFileSystemModel) << "removing" << fileName;
+ QVERIFY(QFile::remove(tmp + QLatin1Char('/') + fileName));
}
for (int i = 0 ; i < 10; ++i) {
if (count != 0) {
@@ -520,18 +510,23 @@ void tst_QFileSystemModel::rowsRemoved()
lst.append(model->index(i, 0, root).data().toString());
if (model->rowCount(root) == oldCount - count)
break;
- qDebug() << "still have:" << lst << QFile::exists(tmp + '/' + QString(".a"));
+ qCDebug(lcFileSystemModel) << "still have:" << lst << QFile::exists(tmp + QLatin1String("/.a"));
QDir tmpLister(tmp);
- qDebug() << tmpLister.entryList();
+ qCDebug(lcFileSystemModel) << tmpLister.entryList();
}
QTRY_COMPARE(model->rowCount(root), oldCount - count);
- QVERIFY(QFile::exists(tmp + '/' + QString(".a")));
- QVERIFY(QFile::remove(tmp + '/' + QString(".a")));
- QVERIFY(QFile::remove(tmp + '/' + QString(".c")));
+ QVERIFY(QFile::exists(tmp + QLatin1String("/.a")));
+ QVERIFY(QFile::remove(tmp + QLatin1String("/.a")));
+ QVERIFY(QFile::remove(tmp + QLatin1String("/.c")));
- if (count != 0) QVERIFY(spy0.count() >= 1); else QCOMPARE(spy0.count(), 0);
- if (count != 0) QVERIFY(spy1.count() >= 1); else QCOMPARE(spy1.count(), 0);
+ if (count != 0) {
+ QVERIFY(spy0.count() >= 1);
+ QVERIFY(spy1.count() >= 1);
+ } else {
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+ }
}
void tst_QFileSystemModel::dataChanged_data()
@@ -544,18 +539,19 @@ void tst_QFileSystemModel::dataChanged()
QSKIP("This can't be tested right now since we don't watch files, only directories.");
const QString tmp = flatDirTestPath;
- QModelIndex root = prepareTestModelRoot(tmp);
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QModelIndex root = prepareTestModelRoot(model.data(), tmp);
QVERIFY(root.isValid());
QFETCH(int, count);
- QFETCH(int, assending);
- model->sort(0, (Qt::SortOrder)assending);
+ QFETCH(Qt::SortOrder, ascending);
+ model->sort(0, ascending);
- QSignalSpy spy(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+ QSignalSpy spy(model.data(), &QAbstractItemModel::dataChanged);
QStringList files;
for (int i = 0; i < count; ++i)
files.append(model->index(i, 0, root).data().toString());
- createFiles(tmp, files);
+ createFiles(model.data(), tmp, files);
QTest::qWait(WAITTIME);
@@ -566,64 +562,68 @@ void tst_QFileSystemModel::filters_data()
{
QTest::addColumn<QStringList>("files");
QTest::addColumn<QStringList>("dirs");
- QTest::addColumn<int>("dirFilters");
+ QTest::addColumn<QDir::Filters>("dirFilters");
QTest::addColumn<QStringList>("nameFilters");
QTest::addColumn<int>("rowCount");
- QTest::newRow("no dirs") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs) << QStringList() << 2;
- QTest::newRow("no dirs - dot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 1;
- QTest::newRow("no dirs - dotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 1;
- QTest::newRow("no dirs - dotanddotdot") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0;
- QTest::newRow("one dir - dot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDot) << QStringList() << 2;
- QTest::newRow("one dir - dotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotDot) << QStringList() << 2;
- QTest::newRow("one dir - dotanddotdot") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1;
- QTest::newRow("one dir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") << (int)(QDir::Dirs) << QStringList() << 3;
- QTest::newRow("no dir + hidden") << (QStringList() << "a" << "b" << "c") << QStringList() << (int)(QDir::Dirs | QDir::Hidden) << QStringList() << 2;
- QTest::newRow("dir+hid+files") << (QStringList() << "a" << "b" << "c") << QStringList() <<
- (int)(QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 5;
- QTest::newRow("dir+file+hid-dot .A") << (QStringList() << "a" << "b" << "c") << (QStringList() << ".A") <<
- (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4;
- QTest::newRow("dir+files+hid+dot A") << (QStringList() << "a" << "b" << "c") << (QStringList() << "AFolder") <<
- (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << (QStringList() << "A*") << 2;
- QTest::newRow("dir+files+hid+dot+cas1") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
- (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "Z") << 1;
- QTest::newRow("dir+files+hid+dot+cas2") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
- (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << (QStringList() << "a") << 1;
- QTest::newRow("dir+files+hid+dot+cas+alldir") << (QStringList() << "a" << "b" << "c") << (QStringList() << "Z") <<
- (int)(QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << (QStringList() << "Z") << 1;
-
- QTest::newRow("case sensitive") << (QStringList() << "Antiguagdb" << "Antiguamtd"
- << "Antiguamtp" << "afghanistangdb" << "afghanistanmtd")
- << QStringList() << (int)(QDir::Files) << QStringList() << 5;
+
+ const QStringList abcList{QLatin1String("a"), QLatin1String("b"), QLatin1String("c")};
+ const QStringList zList{QLatin1String("Z")};
+
+ QTest::newRow("no dirs") << abcList << QStringList() << QDir::Filters(QDir::Dirs) << QStringList() << 2;
+ QTest::newRow("no dirs - dot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDot) << QStringList() << 1;
+ QTest::newRow("no dirs - dotdot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDotDot) << QStringList() << 1;
+ QTest::newRow("no dirs - dotanddotdot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0;
+ QTest::newRow("one dir - dot") << abcList << zList << (QDir::Dirs | QDir::NoDot) << QStringList() << 2;
+ QTest::newRow("one dir - dotdot") << abcList << zList << (QDir::Dirs | QDir::NoDotDot) << QStringList() << 2;
+ QTest::newRow("one dir - dotanddotdot") << abcList << zList << (QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1;
+ QTest::newRow("one dir") << abcList << zList << QDir::Filters(QDir::Dirs) << QStringList() << 3;
+ QTest::newRow("no dir + hidden") << abcList << QStringList() << (QDir::Dirs | QDir::Hidden) << QStringList() << 2;
+ QTest::newRow("dir+hid+files") << abcList << QStringList() <<
+ (QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 5;
+ QTest::newRow("dir+file+hid-dot .A") << abcList << QStringList{QLatin1String(".A")} <<
+ (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4;
+ QTest::newRow("dir+files+hid+dot A") << abcList << QStringList{QLatin1String("AFolder")} <<
+ (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList{QLatin1String("A*")} << 2;
+ QTest::newRow("dir+files+hid+dot+cas1") << abcList << zList <<
+ (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << zList << 1;
+ QTest::newRow("dir+files+hid+dot+cas2") << abcList << zList <<
+ (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << QStringList{QLatin1String("a")} << 1;
+ QTest::newRow("dir+files+hid+dot+cas+alldir") << abcList << zList <<
+ (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << zList << 1;
+
+ QTest::newRow("case sensitive") << QStringList{QLatin1String("Antiguagdb"), QLatin1String("Antiguamtd"),
+ QLatin1String("Antiguamtp"), QLatin1String("afghanistangdb"), QLatin1String("afghanistanmtd")}
+ << QStringList() << QDir::Filters(QDir::Files) << QStringList() << 5;
}
void tst_QFileSystemModel::filters()
{
QString tmp = flatDirTestPath;
- QVERIFY(createFiles(tmp, QStringList()));
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QVERIFY(createFiles(model.data(), tmp, QStringList()));
QModelIndex root = model->setRootPath(tmp);
QFETCH(QStringList, files);
QFETCH(QStringList, dirs);
- QFETCH(int, dirFilters);
+ QFETCH(QDir::Filters, dirFilters);
QFETCH(QStringList, nameFilters);
QFETCH(int, rowCount);
if (nameFilters.count() > 0)
model->setNameFilters(nameFilters);
model->setNameFilterDisables(false);
- model->setFilter((QDir::Filters)dirFilters);
+ model->setFilter(dirFilters);
- QVERIFY(createFiles(tmp, files, 0, dirs));
+ QVERIFY(createFiles(model.data(), tmp, files, 0, dirs));
QTRY_COMPARE(model->rowCount(root), rowCount);
// Make sure that we do what QDir does
QDir xFactor(tmp);
- QDir::Filters filters = (QDir::Filters)dirFilters;
QStringList dirEntries;
if (nameFilters.count() > 0)
- dirEntries = xFactor.entryList(nameFilters, filters);
+ dirEntries = xFactor.entryList(nameFilters, dirFilters);
else
- dirEntries = xFactor.entryList(filters);
+ dirEntries = xFactor.entryList(dirFilters);
QCOMPARE(dirEntries.count(), rowCount);
@@ -667,12 +667,13 @@ void tst_QFileSystemModel::nameFilters()
{
QStringList list;
list << "a" << "b" << "c";
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
model->setNameFilters(list);
model->setNameFilterDisables(false);
QCOMPARE(model->nameFilters(), list);
QString tmp = flatDirTestPath;
- QVERIFY(createFiles(tmp, list));
+ QVERIFY(createFiles(model.data(), tmp, list));
QModelIndex root = model->setRootPath(tmp);
QTRY_COMPARE(model->rowCount(root), 3);
@@ -693,15 +694,17 @@ void tst_QFileSystemModel::setData_data()
<< QDir::temp().absolutePath() + '/' + "a"
<< false;
*/
+
+ const QStringList abcList{QLatin1String("a"), QLatin1String("b"), QLatin1String("c")};
QTest::newRow("in current dir")
<< QString()
- << (QStringList() << "a" << "b" << "c")
+ << abcList
<< "a"
<< "d"
<< true;
QTest::newRow("in subdir")
<< "s"
- << (QStringList() << "a" << "b" << "c")
+ << abcList
<< "a"
<< "d"
<< true;
@@ -709,7 +712,8 @@ void tst_QFileSystemModel::setData_data()
void tst_QFileSystemModel::setData()
{
- QSignalSpy spy(model, SIGNAL(fileRenamed(QString,QString,QString)));
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QSignalSpy spy(model.data(), &QFileSystemModel::fileRenamed);
QFETCH(QString, subdirName);
QFETCH(QStringList, files);
QFETCH(QString, oldFileName);
@@ -722,7 +726,7 @@ void tst_QFileSystemModel::setData()
QVERIFY(dir.mkdir(subdirName));
tmp.append('/' + subdirName);
}
- QVERIFY(createFiles(tmp, files));
+ QVERIFY(createFiles(model.data(), tmp, files));
QModelIndex tmpIdx = model->setRootPath(flatDirTestPath);
if (!subdirName.isEmpty()) {
tmpIdx = model->index(tmp);
@@ -760,6 +764,7 @@ void tst_QFileSystemModel::sortPersistentIndex()
const QFileInfo fileInfo(file.fileName());
file.close();
QTRY_VERIFY(QDir(flatDirTestPath).entryInfoList().contains(fileInfo));
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QModelIndex root = model->setRootPath(flatDirTestPath);
QTRY_VERIFY(model->rowCount(root) > 0);
@@ -786,8 +791,9 @@ void tst_QFileSystemModel::sort()
{
QFETCH(bool, fileDialogMode);
- MyFriendFileSystemModel *myModel = new MyFriendFileSystemModel();
- QTreeView *tree = new QTreeView();
+ QScopedPointer<MyFriendFileSystemModel> myModel(new MyFriendFileSystemModel);
+ QTreeView tree;
+ tree.setWindowTitle(QTest::currentTestFunction());
if (fileDialogMode && EmulationDetector::isRunningArmOnX86())
QSKIP("Crashes in QEMU. QTBUG-70572");
@@ -816,24 +822,23 @@ void tst_QFileSystemModel::sort()
myModel->setRootPath("");
myModel->setFilter(QDir::AllEntries | QDir::System | QDir::Hidden);
- tree->setSortingEnabled(true);
- tree->setModel(myModel);
- tree->show();
- tree->resize(800, 800);
- QVERIFY(QTest::qWaitForWindowActive(tree));
- tree->header()->setSortIndicator(1,Qt::DescendingOrder);
- tree->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
+ tree.setSortingEnabled(true);
+ tree.setModel(myModel.data());
+ tree.show();
+ tree.resize(800, 800);
+ QVERIFY(QTest::qWaitForWindowActive(&tree));
+ tree.header()->setSortIndicator(1, Qt::DescendingOrder);
+ tree.header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
QStringList dirsToOpen;
- do
- {
- dirsToOpen<<dir.absolutePath();
+ do {
+ dirsToOpen << dir.absolutePath();
} while (dir.cdUp());
for (int i = dirsToOpen.size() -1 ; i > 0 ; --i) {
QString path = dirsToOpen[i];
- tree->expand(myModel->index(path, 0));
+ tree.expand(myModel->index(path, 0));
}
- tree->expand(myModel->index(dirPath, 0));
+ tree.expand(myModel->index(dirPath, 0));
QModelIndex parent = myModel->index(dirPath, 0);
QList<QString> expectedOrder;
expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + ".." << dirPath + QChar('/') + ".";
@@ -859,15 +864,13 @@ void tst_QFileSystemModel::sort()
QTRY_COMPARE(dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString(), expectedOrder.at(i));
}
}
-
- delete tree;
- delete myModel;
}
void tst_QFileSystemModel::mkdir()
{
QString tmp = flatDirTestPath;
QString newFolderPath = QDir::toNativeSeparators(tmp + '/' + "NewFoldermkdirtest4");
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QModelIndex tmpDir = model->index(tmp);
QVERIFY(tmpDir.isValid());
QDir bestatic(newFolderPath);
@@ -902,6 +905,7 @@ void tst_QFileSystemModel::deleteFile()
qWarning() << "unable to create" << newFilePath;
}
newFile.close();
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QModelIndex idx = model->index(newFilePath);
QVERIFY(idx.isValid());
QVERIFY(model->remove(idx));
@@ -963,7 +967,8 @@ void tst_QFileSystemModel::caseSensitivity()
QString tmp = flatDirTestPath;
QStringList files;
files << "a" << "c" << "C";
- QVERIFY(createFiles(tmp, files));
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QVERIFY(createFiles(model.data(), tmp, files));
QModelIndex root = model->index(tmp);
QStringList paths;
QModelIndexList indexes;
@@ -1013,13 +1018,14 @@ void tst_QFileSystemModel::dirsBeforeFiles()
const int itemCount = 3;
for (int i = 0; i < itemCount; ++i) {
- QLatin1Char c('a' + i);
- dir.mkdir(c + QLatin1String("-dir"));
+ QLatin1Char c('a' + char(i));
+ QVERIFY(dir.mkdir(c + QLatin1String("-dir")));
QFile file(flatDirTestPath + QLatin1Char('/') + c + QLatin1String("-file"));
- file.open(QIODevice::ReadWrite);
+ QVERIFY(file.open(QIODevice::ReadWrite));
file.close();
}
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
QModelIndex root = model->setRootPath(flatDirTestPath);
// Wait for model to be notified by the file system watcher
QTRY_COMPARE(model->rowCount(root), 2 * itemCount);
@@ -1073,7 +1079,7 @@ static inline QByteArray permissionRowName(bool readOnly, int permission)
void tst_QFileSystemModel::permissions_data()
{
- QTest::addColumn<int>("permissions");
+ QTest::addColumn<QFileDevice::Permissions>("permissions");
QTest::addColumn<bool>("readOnly");
static const int permissions[] = {
@@ -1081,22 +1087,23 @@ void tst_QFileSystemModel::permissions_data()
QFile::ReadOwner,
QFile::WriteOwner|QFile::ReadOwner,
};
- for (size_t i = 0; i < sizeof permissions / sizeof *permissions; ++i) {
- QTest::newRow(permissionRowName(false, permissions[i]).constData()) << permissions[i] << false;
- QTest::newRow(permissionRowName(true, permissions[i]).constData()) << permissions[i] << true;
+ for (int permission : permissions) {
+ QTest::newRow(permissionRowName(false, permission).constData()) << QFileDevice::Permissions(permission) << false;
+ QTest::newRow(permissionRowName(true, permission).constData()) << QFileDevice::Permissions(permission) << true;
}
}
void tst_QFileSystemModel::permissions() // checks QTBUG-20503
{
- QFETCH(int, permissions);
+ QFETCH(QFileDevice::Permissions, permissions);
QFETCH(bool, readOnly);
const QString tmp = flatDirTestPath;
const QString file = tmp + QLatin1String("/f");
- QVERIFY(createFiles(tmp, QStringList() << "f"));
+ QScopedPointer<QFileSystemModel> model(new QFileSystemModel);
+ QVERIFY(createFiles(model.data(), tmp, QStringList{QLatin1String("f")}));
- QVERIFY(QFile::setPermissions(file, QFile::Permissions(permissions)));
+ QVERIFY(QFile::setPermissions(file, permissions));
const QModelIndex root = model->setRootPath(tmp);
diff --git a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST
index da52809aad..8d8a7c2105 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST
@@ -1,2 +1,4 @@
[defaultButton]
-*
+opensuse-leap
+rhel-7.6
+ubuntu
diff --git a/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST b/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST
index 1789f51507..2b784414cd 100644
--- a/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qprogressdialog/BLACKLIST
@@ -1,2 +1,2 @@
[autoShow]
-osx ci
+osx-10.13
diff --git a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
index 2ada4fedb6..6f527e7b6b 100644
--- a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
+++ b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
@@ -252,7 +252,7 @@ class QTestTranslator : public QTranslator
{
const QString m_str;
public:
- explicit QTestTranslator(QString str) : m_str(qMove(str)) {}
+ explicit QTestTranslator(QString str) : m_str(std::move(str)) {}
QString translate(const char *, const char *sourceText, const char *, int) const override
{ return m_str + sourceText + m_str; }
@@ -265,7 +265,7 @@ class QTranslatorGuard {
Translator t;
public:
template <typename Arg>
- explicit QTranslatorGuard(Arg a) : t(qMove(a))
+ explicit QTranslatorGuard(Arg a) : t(std::move(a))
{ qApp->installTranslator(&t); }
~QTranslatorGuard()
{ qApp->removeTranslator(&t); }
diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
index da75e64d1e..243cb6483e 100644
--- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
+++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
@@ -417,7 +417,7 @@ void tst_QWizard::setPixmap()
QVERIFY(wizard.pixmap(QWizard::BannerPixmap).isNull());
QVERIFY(wizard.pixmap(QWizard::LogoPixmap).isNull());
QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).isNull());
- if (QSysInfo::macVersion() <= Q_MV_OSX(10, 13))
+ if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::MacOSHighSierra)
QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull());
else
QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull());
@@ -425,7 +425,7 @@ void tst_QWizard::setPixmap()
QVERIFY(page->pixmap(QWizard::BannerPixmap).isNull());
QVERIFY(page->pixmap(QWizard::LogoPixmap).isNull());
QVERIFY(page->pixmap(QWizard::WatermarkPixmap).isNull());
- if (QSysInfo::macVersion() <= Q_MV_OSX(10, 13))
+ if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::MacOSHighSierra)
QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull());
else
QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
diff --git a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST
index 4833af527f..64a92d18aa 100644
--- a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST
+++ b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST
@@ -1,3 +1,2 @@
[prepareGeometryChangeInvalidateCache]
-opensuse
-opensuse-leap
+opensuse-42.3
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
index ae6de48195..16818a98f9 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
@@ -5,4 +5,4 @@ QT += core-private gui-private
SOURCES += tst_qgraphicsitem.cpp
DEFINES += QT_NO_CAST_TO_ASCII
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index 670dc0b808..0b08586f7d 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -272,6 +272,9 @@ class tst_QGraphicsItem : public QObject
{
Q_OBJECT
+public:
+ static void initMain();
+
private slots:
void construction();
void constructionWithParent();
@@ -474,6 +477,14 @@ private:
QTouchDevice *m_touchDevice = nullptr;
};
+void tst_QGraphicsItem::initMain()
+{
+#ifdef Q_OS_WIN
+ // Ensure minimum size constraints of framed windows on High DPI screens
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+}
+
void tst_QGraphicsItem::construction()
{
for (int i = 0; i < 7; ++i) {
@@ -4440,15 +4451,19 @@ protected:
break;
case QGraphicsItem::ItemPositionHasChanged:
break;
+#if QT_DEPRECATED_SINCE(5, 14)
case QGraphicsItem::ItemMatrixChange: {
+#if QT_DEPRECATED_SINCE(5, 13)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
QVariant variant;
variant.setValue<QMatrix>(matrix());
oldValues << variant;
QT_WARNING_POP
+#endif
}
break;
+#endif
case QGraphicsItem::ItemTransformChange: {
QVariant variant;
variant.setValue<QTransform>(transform());
@@ -4566,6 +4581,7 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.oldValues.last(), QVariant(true));
QCOMPARE(tester.isEnabled(), true);
}
+#if QT_DEPRECATED_SINCE(5, 13)
{
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED // QDesktopWidget::screen()
@@ -4585,6 +4601,7 @@ QT_WARNING_DISABLE_DEPRECATED // QDesktopWidget::screen()
QCOMPARE(tester.matrix(), QMatrix().rotate(90));
QT_WARNING_POP
}
+#endif
{
tester.resetTransform();
++changeCount;
@@ -8397,7 +8414,7 @@ void tst_QGraphicsItem::focusProxy()
QString err;
QTextStream stream(&err);
stream << "QGraphicsItem::setFocusProxy: "
- << (void*)item << " is already in the focus proxy chain" << flush;
+ << (void*)item << " is already in the focus proxy chain" << Qt::flush;
QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
item2->setFocusProxy(item); // fails
QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
index dfb2752ee0..ed79904ed8 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
@@ -54,9 +54,9 @@ void tst_QGraphicsItemAnimation::construction()
QCOMPARE(animation.posAt(0), QPointF());
QCOMPARE(animation.posAt(0.5), QPointF());
QCOMPARE(animation.posAt(1), QPointF());
- QCOMPARE(animation.matrixAt(0), QMatrix());
- QCOMPARE(animation.matrixAt(0.5), QMatrix());
- QCOMPARE(animation.matrixAt(1), QMatrix());
+ QCOMPARE(animation.transformAt(0), QTransform());
+ QCOMPARE(animation.transformAt(0.5), QTransform());
+ QCOMPARE(animation.transformAt(1), QTransform());
QCOMPARE(animation.rotationAt(0), qreal(0.0));
QCOMPARE(animation.rotationAt(0.5), qreal(0.0));
QCOMPARE(animation.rotationAt(1), qreal(0.0));
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index 4a301337ef..a437b05479 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -330,7 +330,7 @@ public:
{
// Make sure QGraphicsProxyWidget::paint does not modify the render hints set on the painter.
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
- | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
+ | QPainter::TextAntialiasing);
const QPainter::RenderHints oldRenderHints = painter->renderHints();
QGraphicsProxyWidget::paint(painter, option, widget);
QCOMPARE(painter->renderHints(), oldRenderHints);
@@ -463,14 +463,13 @@ void tst_QGraphicsProxyWidget::setWidget()
QCOMPARE(proxy->focusPolicy(), Qt::WheelFocus);
QVERIFY(proxy->acceptDrops());
QCOMPARE(proxy->acceptHoverEvents(), true); // to get widget enter events
- int left, top, right, bottom;
- widget->getContentsMargins(&left, &top, &right, &bottom);
+ const QMarginsF margins = QMarginsF{widget->contentsMargins()};
qreal rleft, rtop, rright, rbottom;
proxy->getContentsMargins(&rleft, &rtop, &rright, &rbottom);
- QCOMPARE((qreal)left, rleft);
- QCOMPARE((qreal)top, rtop);
- QCOMPARE((qreal)right, rright);
- QCOMPARE((qreal)bottom, rbottom);
+ QCOMPARE(margins.left(), rleft);
+ QCOMPARE(margins.top(), rtop);
+ QCOMPARE(margins.right(), rright);
+ QCOMPARE(margins.bottom(), rbottom);
} else {
// proxy shouldn't mess with the widget if it can't insert it.
QCOMPARE(proxy->widget(), nullptr);
@@ -2769,9 +2768,6 @@ void tst_QGraphicsProxyWidget::windowOpacity()
// disabled on platforms without alpha channel support in QPixmap (e.g.,
// X11 without XRender).
int paints = 0;
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- paints = !X11->use_xrender;
-#endif
QTRY_COMPARE(eventSpy.counts[QEvent::UpdateRequest], 0);
QTRY_COMPARE(eventSpy.counts[QEvent::Paint], paints);
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST
index b8b427b3dd..c3797c9d57 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST
@@ -1,13 +1,5 @@
[isActive]
opensuse-42.3 ci
-[removeFullyTransparentItem]
-osx-10.12
[tabFocus_sceneWithNestedFocusWidgets]
-opensuse
-opensuse-leap
-[inputMethod]
-opensuse
-opensuse-leap
-[hoverEvents_parentChild]
-ubuntu
+opensuse-42.3
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
index 351cecd92e..2f648a2212 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
@@ -4,7 +4,7 @@ QT += widgets widgets-private testlib
QT += core-private gui-private
SOURCES += tst_qgraphicsscene.cpp
RESOURCES += images.qrc
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
DEFINES += SRCDIR=\\\"$$PWD\\\"
DEFINES += QT_NO_CAST_TO_ASCII
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
index 46f1d5df5c..950f3ef670 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -26,11 +26,24 @@
**
****************************************************************************/
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QDial>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QGraphicsScene>
+#include <QtWidgets/QGraphicsPixmapItem>
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleFactory>
+#include <QtWidgets/QVBoxLayout>
+
+#include <QtGui/QScreen>
#include <QtTest/QtTest>
-#include <QtGui>
-#include <QtWidgets>
+#include <QtCore/QDebug>
+#include <QtCore/QLoggingCategory>
+
#include <private/qgraphicsscene_p.h>
#include <private/qgraphicssceneindex_p.h>
#include <math.h>
@@ -39,7 +52,7 @@
#include <private/qinputmethod_p.h>
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-#include <windows.h>
+#include <QtCore/qt_windows.h>
#define Q_CHECK_PAINTEVENTS \
if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
QSKIP("The Graphics View doesn't get the paint events");
@@ -51,6 +64,7 @@ Q_DECLARE_METATYPE(Qt::FocusReason)
Q_DECLARE_METATYPE(QPainterPath)
Q_DECLARE_METATYPE(Qt::AspectRatioMode)
Q_DECLARE_METATYPE(Qt::ItemSelectionMode)
+Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlags)
static const int randomX[] = {276, 40, 250, 864, -56, 426, 855, 825, 184, 955, -798, -804, 773,
282, 489, 686, 780, -220, 50, 749, -856, -205, 81, 492, -819, 518,
@@ -95,14 +109,16 @@ static const int randomY[] = {603, 70, -318, 843, 450, -637, 199, -527, 407, 964
-588, 864, 234, 225, -303, 493, 246, 153, 338, -378, 377, -819, 140, 136,
467, -849, -326, -533, 166, 252, -994, -699, 904, -566, 621, -752};
+Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests")
+
class HoverItem : public QGraphicsRectItem
{
public:
HoverItem()
- : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), isHovered(false)
+ : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
{ setAcceptHoverEvents(true); }
- bool isHovered;
+ bool isHovered = false;
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
@@ -128,13 +144,13 @@ class EventSpy : public QGraphicsWidget
Q_OBJECT
public:
EventSpy(QObject *watched, QEvent::Type type)
- : _count(0), spied(type)
+ : spied(type)
{
watched->installEventFilter(this);
}
EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
- : _count(0), spied(type)
+ : spied(type)
{
scene->addItem(this);
watched->installSceneEventFilter(this);
@@ -143,7 +159,7 @@ public:
int count() const { return _count; }
protected:
- bool eventFilter(QObject *watched, QEvent *event)
+ bool eventFilter(QObject *watched, QEvent *event) override
{
Q_UNUSED(watched);
if (event->type() == spied)
@@ -151,7 +167,7 @@ protected:
return false;
}
- bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override
{
Q_UNUSED(watched);
if (event->type() == spied)
@@ -159,13 +175,17 @@ protected:
return false;
}
- int _count;
- QEvent::Type spied;
+ int _count = 0;
+ const QEvent::Type spied;
};
class tst_QGraphicsScene : public QObject
{
Q_OBJECT
+public:
+ tst_QGraphicsScene();
+ static void initMain() { QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); }
+
public slots:
void cleanup();
@@ -268,13 +288,26 @@ private slots:
void taskQTBUG_15977_renderWithDeviceCoordinateCache();
void taskQTBUG_16401_focusItem();
void taskQTBUG_42915_focusNextPrevChild();
+
+private:
+ QRect m_availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
+ QSize m_testSize;
};
+tst_QGraphicsScene::tst_QGraphicsScene()
+{
+ const int testSize = qMax(200, m_availableGeometry.width() / 10);
+ m_testSize.setWidth(testSize);
+ m_testSize.setHeight(testSize);
+}
+
void tst_QGraphicsScene::cleanup()
{
// ensure not even skipped tests with custom input context leave it dangling
- QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
- inputMethodPrivate->testContext = 0;
+ QInputMethodPrivate *inputMethodPrivate =
+ QInputMethodPrivate::get(QGuiApplication::inputMethod());
+ inputMethodPrivate->testContext = nullptr;
+ QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
}
void tst_QGraphicsScene::construction()
@@ -287,7 +320,7 @@ void tst_QGraphicsScene::construction()
QVERIFY(scene.items(QPolygonF()).isEmpty());
QVERIFY(scene.items(QPainterPath()).isEmpty());
QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::collidingItems: cannot find collisions for null item");
- QVERIFY(scene.collidingItems(0).isEmpty());
+ QVERIFY(scene.collidingItems(nullptr).isEmpty());
QVERIFY(scene.items(QPointF()).isEmpty());
QVERIFY(scene.selectedItems().isEmpty());
QVERIFY(!scene.focusItem());
@@ -301,7 +334,7 @@ static inline const QGraphicsItem *itemAt(const QGraphicsScene &scene, qreal x,
void tst_QGraphicsScene::sceneRect()
{
QGraphicsScene scene;
- QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF)));
+ QSignalSpy sceneRectChanged(&scene, &QGraphicsScene::sceneRectChanged);
QCOMPARE(scene.sceneRect(), QRectF());
QCOMPARE(sceneRectChanged.count(), 0);
@@ -435,9 +468,9 @@ void tst_QGraphicsScene::items()
scene.removeItem(items.at(5));
delete items.at(5);
- QVERIFY(!scene.items().contains(0));
+ QVERIFY(!scene.items().contains(nullptr));
delete items.at(7);
- QVERIFY(!scene.items().contains(0));
+ QVERIFY(!scene.items().contains(nullptr));
}
{
QGraphicsScene scene;
@@ -516,7 +549,7 @@ void tst_QGraphicsScene::itemsBoundingRect()
QGraphicsScene scene;
- foreach (QRectF rect, rects) {
+ for (const auto &rect : qAsConst(rects)) {
QPainterPath path;
path.addRect(rect);
QGraphicsPathItem *item = scene.addPath(path);
@@ -581,7 +614,7 @@ void tst_QGraphicsScene::items_QPointF()
int n = 0;
QList<QGraphicsItem *> addedItems;
- foreach(QRectF rect, items) {
+ for (const auto &rect : qAsConst(items)) {
QPainterPath path;
path.addRect(0, 0, rect.width(), rect.height());
@@ -593,7 +626,8 @@ void tst_QGraphicsScene::items_QPointF()
}
QList<int> itemIndexes;
- foreach (QGraphicsItem *item, scene.items(point))
+ const auto &actualItemsAtPoint = scene.items(point);
+ for (QGraphicsItem *item : actualItemsAtPoint)
itemIndexes << addedItems.indexOf(item);
QCOMPARE(itemIndexes, itemsAtPoint);
@@ -912,12 +946,11 @@ void tst_QGraphicsScene::items_QPainterPath_2()
class CustomView : public QGraphicsView
{
public:
- CustomView() : repaints(0)
- { }
+ using QGraphicsView::QGraphicsView;
- int repaints;
+ int repaints = 0;
protected:
- void paintEvent(QPaintEvent *event)
+ void paintEvent(QPaintEvent *event) override
{
++repaints;
QGraphicsView::paintEvent(event);
@@ -927,7 +960,7 @@ protected:
void tst_QGraphicsScene::selectionChanged()
{
QGraphicsScene scene(0, 0, 1000, 1000);
- QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QSignalSpy spy(&scene, &QGraphicsScene::selectionChanged);
QCOMPARE(spy.count(), 0);
QPainterPath path;
@@ -997,7 +1030,7 @@ void tst_QGraphicsScene::selectionChanged()
void tst_QGraphicsScene::selectionChanged2()
{
QGraphicsScene scene;
- QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QSignalSpy spy(&scene, &QGraphicsScene::selectionChanged);
QGraphicsItem *item1 = scene.addRect(0, 0, 100, 100);
QGraphicsItem *item2 = scene.addRect(100, 100, 100, 100);
@@ -1009,13 +1042,13 @@ void tst_QGraphicsScene::selectionChanged2()
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.setScenePos(QPointF(50, 50));
event.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
}
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.setScenePos(QPointF(50, 50));
event.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
}
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
@@ -1024,13 +1057,13 @@ void tst_QGraphicsScene::selectionChanged2()
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.setScenePos(QPointF(150, 150));
event.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
}
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.setScenePos(QPointF(150, 150));
event.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
}
QVERIFY(!item1->isSelected());
QVERIFY(item2->isSelected());
@@ -1040,7 +1073,7 @@ void tst_QGraphicsScene::selectionChanged2()
event.setScenePos(QPointF(50, 50));
event.setButton(Qt::LeftButton);
event.setModifiers(Qt::ControlModifier);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
}
QVERIFY(!item1->isSelected());
QVERIFY(item2->isSelected());
@@ -1049,7 +1082,7 @@ void tst_QGraphicsScene::selectionChanged2()
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.setScenePos(QPointF(50, 50));
event.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
}
QVERIFY(item1->isSelected());
QVERIFY(!item2->isSelected());
@@ -1065,10 +1098,12 @@ void tst_QGraphicsScene::addItem()
QGraphicsScene scene;
CustomView view;
+ view.setWindowTitle(QTest::currentTestFunction());
view.setScene(&scene);
+ view.resize(m_testSize);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- qApp->processEvents();
+ QCoreApplication::processEvents();
view.repaints = 0;
scene.addItem(path);
@@ -1115,14 +1150,14 @@ void tst_QGraphicsScene::addEllipse()
QCOMPARE(ellipse->pen(), QPen(Qt::red));
QCOMPARE(ellipse->brush(), QBrush(Qt::blue));
QCOMPARE(ellipse->rect(), QRectF(-10, -10, 20, 20));
- QCOMPARE(itemAt(scene, 0, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(itemAt(scene, 0, 0), ellipse);
QVERIFY(scene.items(QPointF(-10, -10)).isEmpty());
- QCOMPARE(itemAt(scene, -9.9, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(itemAt(scene, -9.9, 0), ellipse);
QVERIFY(scene.items(QPointF(-10, 10)).isEmpty());
- QCOMPARE(itemAt(scene, 0, -9.9), (QGraphicsItem *)ellipse);
- QCOMPARE(itemAt(scene, 0, 9.9), (QGraphicsItem *)ellipse);
+ QCOMPARE(itemAt(scene, 0, -9.9), ellipse);
+ QCOMPARE(itemAt(scene, 0, 9.9), ellipse);
QVERIFY(scene.items(QPointF(10, -10)).isEmpty());
- QCOMPARE(itemAt(scene, 9.9, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(itemAt(scene, 9.9, 0), ellipse);
QVERIFY(scene.items(QPointF(10, 10)).isEmpty());
}
@@ -1136,15 +1171,15 @@ void tst_QGraphicsScene::addLine()
QCOMPARE(line->pos(), QPointF());
QCOMPARE(line->pen(), pen);
QCOMPARE(line->line(), QLineF(-10, -10, 20, 20));
- QCOMPARE(itemAt(scene, 0, 0), (QGraphicsItem *)line);
- QCOMPARE(itemAt(scene, -10, -10), (QGraphicsItem *)line);
+ QCOMPARE(itemAt(scene, 0, 0), line);
+ QCOMPARE(itemAt(scene, -10, -10), line);
QVERIFY(scene.items(QPointF(-9.9, 0)).isEmpty());
QVERIFY(scene.items(QPointF(-10, 10)).isEmpty());
QVERIFY(scene.items(QPointF(0, -9.9)).isEmpty());
QVERIFY(scene.items(QPointF(0, 9.9)).isEmpty());
QVERIFY(scene.items(QPointF(10, -10)).isEmpty());
QVERIFY(scene.items(QPointF(9.9, 0)).isEmpty());
- QCOMPARE(itemAt(scene, 10, 10), (QGraphicsItem *)line);
+ QCOMPARE(itemAt(scene, 10, 10), line);
}
void tst_QGraphicsScene::addPath()
@@ -1162,16 +1197,16 @@ void tst_QGraphicsScene::addPath()
path->setPen(QPen(Qt::red, 0));
- QCOMPARE(itemAt(scene, 0, 0), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, -9.9, 0), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 9.9, 0), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 0, -9.9), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 0, 9.9), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 0, 30), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, -9.9, 30), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 9.9, 30), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 0, 20.1), (QGraphicsItem *)path);
- QCOMPARE(itemAt(scene, 0, 39.9), (QGraphicsItem *)path);
+ QCOMPARE(itemAt(scene, 0, 0), path);
+ QCOMPARE(itemAt(scene, -9.9, 0), path);
+ QCOMPARE(itemAt(scene, 9.9, 0), path);
+ QCOMPARE(itemAt(scene, 0, -9.9), path);
+ QCOMPARE(itemAt(scene, 0, 9.9), path);
+ QCOMPARE(itemAt(scene, 0, 30), path);
+ QCOMPARE(itemAt(scene, -9.9, 30), path);
+ QCOMPARE(itemAt(scene, 9.9, 30), path);
+ QCOMPARE(itemAt(scene, 0, 20.1), path);
+ QCOMPARE(itemAt(scene, 0, 39.9), path);
QVERIFY(scene.items(QPointF(-10, -10)).isEmpty());
QVERIFY(scene.items(QPointF(10, -10)).isEmpty());
QVERIFY(scene.items(QPointF(-10, 10)).isEmpty());
@@ -1193,10 +1228,10 @@ void tst_QGraphicsScene::addPixmap()
QCOMPARE(pixmap->pos(), QPointF());
QCOMPARE(pixmap->pixmap(), pix);
- QCOMPARE(itemAt(scene, 0, 0), (QGraphicsItem *)pixmap);
- QCOMPARE(itemAt(scene, pix.width() - 1, 0), (QGraphicsItem *)pixmap);
- QCOMPARE(itemAt(scene, 0, pix.height() - 1), (QGraphicsItem *)pixmap);
- QCOMPARE(itemAt(scene, pix.width() - 1, pix.height() - 1), (QGraphicsItem *)pixmap);
+ QCOMPARE(itemAt(scene, 0, 0), pixmap);
+ QCOMPARE(itemAt(scene, pix.width() - 1, 0), pixmap);
+ QCOMPARE(itemAt(scene, 0, pix.height() - 1), pixmap);
+ QCOMPARE(itemAt(scene, pix.width() - 1, pix.height() - 1), pixmap);
QVERIFY(scene.items(QPointF(-1, -1)).isEmpty());
QVERIFY(scene.items(QPointF(pix.width() - 1, -1)).isEmpty());
@@ -1218,14 +1253,14 @@ void tst_QGraphicsScene::addRect()
rect->setPen(QPen(Qt::red, 0));
- QCOMPARE(itemAt(scene, 0, 0), (QGraphicsItem *)rect);
- QCOMPARE(itemAt(scene, -10, -10), (QGraphicsItem *)rect);
- QCOMPARE(itemAt(scene, -9.9, 0), (QGraphicsItem *)rect);
+ QCOMPARE(itemAt(scene, 0, 0),rect);
+ QCOMPARE(itemAt(scene, -10, -10), rect);
+ QCOMPARE(itemAt(scene, -9.9, 0), rect);
QVERIFY(scene.items(QPointF(-10, 10)).isEmpty());
- QCOMPARE(itemAt(scene, 0, -9.9), (QGraphicsItem *)rect);
- QCOMPARE(itemAt(scene, 0, 9.9), (QGraphicsItem *)rect);
+ QCOMPARE(itemAt(scene, 0, -9.9), rect);
+ QCOMPARE(itemAt(scene, 0, 9.9), rect);
QVERIFY(scene.items(QPointF(10, -10)).isEmpty());
- QCOMPARE(itemAt(scene, 9.9, 0), (QGraphicsItem *)rect);
+ QCOMPARE(itemAt(scene, 9.9, 0), rect);
QVERIFY(scene.items(QPointF(10, 10)).isEmpty());
}
@@ -1271,6 +1306,7 @@ void tst_QGraphicsScene::removeItem()
scene.setSceneRect(-50, -50, 100, 100);
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
view.setFixedSize(150, 150);
view.show();
QApplication::setActiveWindow(&view);
@@ -1342,7 +1378,7 @@ void tst_QGraphicsScene::focusItem()
class FocusItem : public QGraphicsTextItem
{
protected:
- void focusOutEvent(QFocusEvent *)
+ void focusOutEvent(QFocusEvent *) override
{
QVERIFY(!scene()->focusItem());
}
@@ -1359,14 +1395,14 @@ void tst_QGraphicsScene::focusItemLostFocus()
scene.addItem(item);
item->setFocus();
- QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
+ QCOMPARE(scene.focusItem(), item);
item->clearFocus();
}
class ClearTestItem : public QGraphicsRectItem
{
public:
- ClearTestItem(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
+ using QGraphicsRectItem::QGraphicsRectItem;
~ClearTestItem() { qDeleteAll(items); }
QList<QGraphicsItem *> items;
};
@@ -1389,7 +1425,7 @@ void tst_QGraphicsScene::clear()
scene.setItemIndexMethod(QGraphicsScene::NoIndex);
scene.addItem(firstItem);
scene.addItem(secondItem);
- QCOMPARE(scene.items().at(0), (QGraphicsItem*)firstItem);
+ QCOMPARE(scene.items().at(0), firstItem);
QCOMPARE(scene.items().at(1), secondItem);
ClearTestItem *thirdItem = new ClearTestItem(firstItem);
@@ -1441,7 +1477,7 @@ void tst_QGraphicsScene::setFocusItem()
QVERIFY(item->hasFocus());
QVERIFY(!item2->hasFocus());
- scene.setFocusItem(0);
+ scene.setFocusItem(nullptr);
QVERIFY(!item->hasFocus());
QVERIFY(!item2->hasFocus());
@@ -1562,26 +1598,26 @@ void tst_QGraphicsScene::hoverEvents_siblings()
Q_CHECK_PAINTEVENTS
QGraphicsScene scene;
- QGraphicsItem *lastItem = 0;
+ QGraphicsItem *lastItem = nullptr;
QList<HoverItem *> items;
for (int i = 0; i < 15; ++i) {
- QGraphicsItem *item = new HoverItem;
+ auto item = new HoverItem;
scene.addItem(item);
- items << (HoverItem *)item;
- if (lastItem) {
+ items << item;
+ if (lastItem)
item->setPos(lastItem->pos() + QPointF(sin(i / 3.0) * 17, cos(i / 3.0) * 17));
- }
item->setZValue(i);
lastItem = item;
}
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
view.setRenderHint(QPainter::Antialiasing, true);
view.setMinimumSize(400, 300);
view.rotate(10);
view.scale(1.7, 1.7);
view.show();
- qApp->setActiveWindow(&view);
+ QApplication::setActiveWindow(&view);
view.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&view));
@@ -1604,8 +1640,8 @@ void tst_QGraphicsScene::hoverEvents_siblings()
mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
QApplication::sendEvent(&scene, &mouseEvent);
- qApp->processEvents(); // this posts updates from the scene to the view
- qApp->processEvents(); // which trigger a repaint here
+ QCoreApplication::processEvents(); // this posts updates from the scene to the view
+ QCoreApplication::processEvents(); // which trigger a repaint here
QTRY_VERIFY(items.at(i)->isHovered);
if (j && i > 0)
@@ -1621,8 +1657,8 @@ void tst_QGraphicsScene::hoverEvents_siblings()
mouseEvent.setScenePos(QPointF(-1000, -1000));
QApplication::sendEvent(&scene, &mouseEvent);
- qApp->processEvents(); // this posts updates from the scene to the view
- qApp->processEvents(); // which trigger a repaint here
+ QCoreApplication::processEvents(); // this posts updates from the scene to the view
+ QCoreApplication::processEvents(); // which trigger a repaint here
}
}
@@ -1631,12 +1667,12 @@ void tst_QGraphicsScene::hoverEvents_parentChild()
Q_CHECK_PAINTEVENTS
QGraphicsScene scene;
- QGraphicsItem *lastItem = 0;
+ QGraphicsItem *lastItem = nullptr;
QList<HoverItem *> items;
for (int i = 0; i < 15; ++i) {
- QGraphicsItem *item = new HoverItem;
+ auto item = new HoverItem;
scene.addItem(item);
- items << (HoverItem *)item;
+ items << item;
if (lastItem) {
item->setParentItem(lastItem);
item->setPos(sin(i / 3.0) * 17, cos(i / 3.0) * 17);
@@ -1645,12 +1681,13 @@ void tst_QGraphicsScene::hoverEvents_parentChild()
}
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
view.setRenderHint(QPainter::Antialiasing, true);
view.setMinimumSize(400, 300);
view.rotate(10);
view.scale(1.7, 1.7);
view.show();
- qApp->setActiveWindow(&view);
+ QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
@@ -1669,8 +1706,8 @@ void tst_QGraphicsScene::hoverEvents_parentChild()
mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
QApplication::sendEvent(&scene, &mouseEvent);
- qApp->processEvents(); // this posts updates from the scene to the view
- qApp->processEvents(); // which trigger a repaint here
+ QCoreApplication::processEvents(); // this posts updates from the scene to the view
+ QCoreApplication::processEvents(); // which trigger a repaint here
QTRY_VERIFY(items.at(i)->isHovered);
if (i < 14)
@@ -1683,8 +1720,8 @@ void tst_QGraphicsScene::hoverEvents_parentChild()
mouseEvent.setScenePos(QPointF(-1000, -1000));
QApplication::sendEvent(&scene, &mouseEvent);
- qApp->processEvents(); // this posts updates from the scene to the view
- qApp->processEvents(); // which trigger a repaint here
+ QCoreApplication::processEvents(); // this posts updates from the scene to the view
+ QCoreApplication::processEvents(); // which trigger a repaint here
}
}
@@ -1712,23 +1749,23 @@ void tst_QGraphicsScene::createItemGroup()
// All items in children1 are children of parent1
QGraphicsItem *parent1 = scene.addRect(QRectF(-10, -10, 20, 20));
- foreach (QGraphicsItem *item, children1)
+ for (QGraphicsItem *item : qAsConst(children1))
item->setParentItem(parent1);
QGraphicsItemGroup *group = scene.createItemGroup(children1);
QCOMPARE(group->parentItem(), parent1);
- QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(children1.first()->parentItem(), group);
scene.destroyItemGroup(group);
QCOMPARE(children1.first()->parentItem(), parent1);
group = scene.createItemGroup(children1);
QCOMPARE(group->parentItem(), parent1);
- QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(children1.first()->parentItem(), group);
scene.destroyItemGroup(group);
QCOMPARE(children1.first()->parentItem(), parent1);
// All items in children2 are children of parent2
QGraphicsItem *parent2 = scene.addRect(QRectF(-10, -10, 20, 20));
- foreach (QGraphicsItem *item, children2)
+ for (QGraphicsItem *item : qAsConst(children2))
item->setParentItem(parent2);
// Now make parent2 a child of parent1, so all children2 are also children
@@ -1738,21 +1775,21 @@ void tst_QGraphicsScene::createItemGroup()
// The children2 group should still have parent2 as their common ancestor.
group = scene.createItemGroup(children2);
QCOMPARE(group->parentItem(), parent2);
- QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(children2.first()->parentItem(), group);
scene.destroyItemGroup(group);
QCOMPARE(children2.first()->parentItem(), parent2);
// But the set of both children2 and children1 share only parent1.
group = scene.createItemGroup(children2 + children1);
QCOMPARE(group->parentItem(), parent1);
- QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
- QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(children1.first()->parentItem(), group);
+ QCOMPARE(children2.first()->parentItem(), group);
scene.destroyItemGroup(group);
QCOMPARE(children1.first()->parentItem(), parent1);
QCOMPARE(children2.first()->parentItem(), parent1);
// Fixup the parent-child chain
- foreach (QGraphicsItem *item, children2)
+ for (QGraphicsItem *item : qAsConst(children2))
item->setParentItem(parent2);
// These share no common parent
@@ -1762,7 +1799,7 @@ void tst_QGraphicsScene::createItemGroup()
// Make children3 children of parent3
QGraphicsItem *parent3 = scene.addRect(QRectF(-10, -10, 20, 20));
- foreach (QGraphicsItem *item, children3)
+ for (QGraphicsItem *item : qAsConst(children3))
item->setParentItem(parent3);
// These should have parent3 as a parent
@@ -1794,15 +1831,14 @@ void tst_QGraphicsScene::createItemGroup()
class EventTester : public QGraphicsEllipseItem
{
public:
- EventTester()
- : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false)
+ EventTester() : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20))
{ }
- bool ignoreMouse;
- QList<QEvent::Type> eventTypes;
+ bool ignoreMouse = false;
+ QVector<QEvent::Type> eventTypes;
protected:
- bool sceneEvent(QEvent *event)
+ bool sceneEvent(QEvent *event) override
{
eventTypes << QEvent::Type(event->type());
switch (event->type()) {
@@ -1813,6 +1849,7 @@ protected:
event->ignore();
return true;
}
+ break;
default:
break;
}
@@ -1867,7 +1904,7 @@ void tst_QGraphicsScene::mouseEventPropagation()
QCOMPARE(c->eventTypes.size(), 0);
QCOMPARE(b->eventTypes.size(), 0);
QCOMPARE(a->eventTypes.size(), 0);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
+ QCOMPARE(scene.mouseGrabberItem(), d);
// Send a move
QApplication::sendEvent(&scene, &moveEvent);
@@ -1876,7 +1913,7 @@ void tst_QGraphicsScene::mouseEventPropagation()
QCOMPARE(c->eventTypes.size(), 0);
QCOMPARE(b->eventTypes.size(), 0);
QCOMPARE(a->eventTypes.size(), 0);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
+ QCOMPARE(scene.mouseGrabberItem(), d);
// Send a release
QApplication::sendEvent(&scene, &releaseEvent);
@@ -1898,7 +1935,7 @@ void tst_QGraphicsScene::mouseEventPropagation()
QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
QCOMPARE(b->eventTypes.size(), 0);
QCOMPARE(a->eventTypes.size(), 0);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+ QCOMPARE(scene.mouseGrabberItem(), c);
// Send another press, with a button that isn't actually accepted
QApplication::sendEvent(&scene, &pressEvent);
@@ -1908,7 +1945,7 @@ void tst_QGraphicsScene::mouseEventPropagation()
QCOMPARE(c->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
QCOMPARE(b->eventTypes.size(), 0);
QCOMPARE(a->eventTypes.size(), 0);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+ QCOMPARE(scene.mouseGrabberItem(), c);
// Send a move
QApplication::sendEvent(&scene, &moveEvent);
@@ -1917,7 +1954,7 @@ void tst_QGraphicsScene::mouseEventPropagation()
QCOMPARE(c->eventTypes.at(3), QEvent::GraphicsSceneMouseMove);
QCOMPARE(b->eventTypes.size(), 0);
QCOMPARE(a->eventTypes.size(), 0);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+ QCOMPARE(scene.mouseGrabberItem(), c);
// Send a release
QApplication::sendEvent(&scene, &releaseEvent);
@@ -1950,7 +1987,7 @@ void tst_QGraphicsScene::mouseEventPropagation()
QCOMPARE(c->eventTypes.at(7), QEvent::GraphicsSceneMousePress);
QCOMPARE(b->eventTypes.size(), 0);
QCOMPARE(a->eventTypes.size(), 0);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+ QCOMPARE(scene.mouseGrabberItem(), c);
// Clicking outside the items removes the mouse grabber
}
@@ -1999,7 +2036,7 @@ void tst_QGraphicsScene::mouseEventPropagation_ignore()
QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
QCOMPARE(d->eventTypes.at(2), QEvent::UngrabMouse);
- QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)a);
+ QCOMPARE(scene.mouseGrabberItem(), a);
a->ignoreMouse = true;
@@ -2115,7 +2152,7 @@ public:
QVector<QPointF> mouseMovePoints;
protected:
- void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
{
mouseMovePoints << event->scenePos();
}
@@ -2140,22 +2177,17 @@ void tst_QGraphicsScene::mouseEventPropagation_mouseMove()
class DndTester : public QGraphicsEllipseItem
{
public:
- DndTester(const QRectF &rect)
- : QGraphicsEllipseItem(rect), lastEvent(0),
- ignoresDragEnter(false), ignoresDragMove(false)
-
- {
- }
+ using QGraphicsEllipseItem::QGraphicsEllipseItem;
~DndTester()
{
delete lastEvent;
}
- QGraphicsSceneDragDropEvent *lastEvent;
+ QGraphicsSceneDragDropEvent *lastEvent = nullptr;
QList<QEvent::Type> eventList;
- bool ignoresDragEnter;
- bool ignoresDragMove;
+ bool ignoresDragEnter = false;
+ bool ignoresDragMove = false;
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
@@ -2218,21 +2250,21 @@ void tst_QGraphicsScene::dragAndDrop_simple()
QMimeData mimeData;
// Initial drag enter for the scene
- QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragEnter);
QVERIFY(dragEnter.isAccepted());
QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
{
// Move outside the item
- QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
}
{
// Move inside the item without setAcceptDrops
- QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2241,7 +2273,7 @@ void tst_QGraphicsScene::dragAndDrop_simple()
item->setAcceptDrops(true);
{
// Move inside the item with setAcceptDrops
- QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2255,7 +2287,7 @@ void tst_QGraphicsScene::dragAndDrop_simple()
}
{
// Another move inside the item
- QDragMoveEvent dragMove(view.mapFromScene(item->mapToScene(5, 5)), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->mapToScene(5, 5)), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2268,7 +2300,7 @@ void tst_QGraphicsScene::dragAndDrop_simple()
}
{
// Move outside the item
- QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2281,7 +2313,7 @@ void tst_QGraphicsScene::dragAndDrop_simple()
}
{
// Move inside the item again
- QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2295,7 +2327,7 @@ void tst_QGraphicsScene::dragAndDrop_simple()
}
{
// Drop inside the item
- QDropEvent drop(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDropEvent drop(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &drop);
QVERIFY(drop.isAccepted());
QCOMPARE(drop.dropAction(), Qt::CopyAction);
@@ -2322,13 +2354,13 @@ void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
QMimeData mimeData;
// Initial drag enter for the scene
- QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragEnter);
QVERIFY(dragEnter.isAccepted());
QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
{
// Move inside the item
- QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2338,7 +2370,7 @@ void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
}
{
// Move outside the item
- QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2353,7 +2385,7 @@ void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
{
// Move inside the item
- QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2369,7 +2401,7 @@ void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
{
// Move inside the item
- QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2378,7 +2410,7 @@ void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
}
// Dummy drop event to keep the Mac from crashing.
- QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dropEvent);
}
@@ -2405,14 +2437,14 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
QMimeData mimeData;
// Initial drag enter for the scene
- QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragEnter);
QVERIFY(dragEnter.isAccepted());
QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
{
// Move outside the items
- QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2421,7 +2453,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
}
{
// Move inside item1
- QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2432,7 +2464,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
{
// Move into the intersection item1-item2
- QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted()); // move does not propagate, (ignoresDragMove = true)
QCOMPARE(item1->eventList.size(), 3);
@@ -2443,7 +2475,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
}
{
// Move into the item2
- QDragMoveEvent dragMove(view.mapFromScene(15, 15), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(15, 15), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(!dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
@@ -2453,7 +2485,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
}
{
// Move inside item1
- QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted());
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2467,7 +2499,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
{
item2->ignoresDragEnter = true;
// Move into the intersection item1-item2
- QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dragMove);
QVERIFY(dragMove.isAccepted()); // dragEnter propagates down to item1, which then accepts the move event.
QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
@@ -2480,7 +2512,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
{
item2->ignoresDragEnter = false;
// Drop on the intersection item1-item2
- QDropEvent drop(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDropEvent drop(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &drop);
QVERIFY(drop.isAccepted());
QCOMPARE(drop.dropAction(), Qt::CopyAction);
@@ -2491,7 +2523,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate()
}
// Dummy drop event to keep the Mac from crashing.
- QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, {});
QApplication::sendEvent(view.viewport(), &dropEvent);
}
#endif
@@ -2580,6 +2612,8 @@ void tst_QGraphicsScene::render()
pix.fill(Qt::blue);
QGraphicsView view;
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
QGraphicsScene scene(&view);
scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black, 0), QBrush(Qt::white));
scene.addEllipse(QRectF(-2, -7, 4, 4), QPen(Qt::black, 0), QBrush(Qt::yellow))->setZValue(1);
@@ -2642,6 +2676,7 @@ void tst_QGraphicsScene::render()
gridLayout->addWidget(newLabel, 2, 0);
QWidget widget;
+ widget.setWindowTitle(QTest::currentTestFunction());
widget.setLayout(gridLayout);
widget.show();
@@ -2660,33 +2695,32 @@ void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight()
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) || defined(Q_OS_WINRT)
QSKIP("Test only works on platforms with resizable windows");
#endif
-
- QGraphicsScene scene(0, 0, 150, 150);
+ QGraphicsScene scene(0, 0, m_testSize.width(), m_testSize.height());
// Add item with negative width.
- QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, -150, 50);
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, -m_testSize.width(), 50);
item1->setBrush(Qt::red);
- item1->setPos(150, 50);
+ item1->setPos(m_testSize.width(), 50);
scene.addItem(item1);
// Add item with negative height.
- QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 50, -150);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 50, -m_testSize.height());
item2->setBrush(Qt::blue);
- item2->setPos(50, 150);
+ item2->setPos(50, m_testSize.height());
scene.addItem(item2);
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
view.setFrameStyle(QFrame::NoFrame);
- view.resize(150, 150);
view.show();
- QCOMPARE(view.viewport()->size(), QSize(150, 150));
+ QTRY_COMPARE(view.viewport()->size(), m_testSize);
QImage expected(view.viewport()->size(), QImage::Format_RGB32);
view.viewport()->render(&expected);
// Make sure the scene background is the same as the viewport background.
scene.setBackgroundBrush(view.viewport()->palette().brush(view.viewport()->backgroundRole()));
- QImage actual(150, 150, QImage::Format_RGB32);
+ QImage actual(m_testSize, QImage::Format_RGB32);
QPainter painter(&actual);
scene.render(&painter);
painter.end();
@@ -2710,6 +2744,8 @@ void tst_QGraphicsScene::contextMenuEvent()
QVERIFY(scene.hasFocus());
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
view.show();
view.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&view));
@@ -2726,11 +2762,11 @@ void tst_QGraphicsScene::contextMenuEvent()
class ContextMenuItem : public QGraphicsRectItem
{
public:
- ContextMenuItem() : QGraphicsRectItem(0, 0, 100, 100)
+ ContextMenuItem(const QSize &s) : QGraphicsRectItem(0, 0, s.width(), s.height())
{ setBrush(Qt::red); }
protected:
- void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *) override
{ /* just accept */ }
};
@@ -2740,26 +2776,30 @@ void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
QSKIP("Test fails on some Android devices (QTBUG-44430)");
#endif
- QGraphicsScene scene(0, 0, 200, 200);
- ContextMenuItem *item = new ContextMenuItem;
+ QGraphicsScene scene(0, 0, m_testSize.width(), m_testSize.height());
+ const QSize itemSize = m_testSize / 2;
+ ContextMenuItem *item = new ContextMenuItem(itemSize);
item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
scene.addItem(item);
QWidget topLevel;
+ topLevel.setWindowTitle(QTest::currentTestFunction());
+ topLevel.resize(m_testSize);
QGraphicsView view(&scene, &topLevel);
- view.resize(200, 200);
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+
{
- QPoint pos(50, 50);
+ QPoint pos(itemSize.width() / 2, itemSize.height() / 2);
QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
event.ignore();
QApplication::sendEvent(view.viewport(), &event);
QVERIFY(event.isAccepted());
}
{
- QPoint pos(150, 150);
+ QPoint pos(itemSize.width() * 3 / 2, itemSize.height() * 3 / 2);
QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
event.ignore();
QApplication::sendEvent(view.viewport(), &event);
@@ -2767,14 +2807,14 @@ void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
}
view.scale(1.5, 1.5);
{
- QPoint pos(25, 25);
+ QPoint pos(itemSize.width() / 4, itemSize.height() / 4);
QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
event.ignore();
QApplication::sendEvent(view.viewport(), &event);
QVERIFY(event.isAccepted());
}
{
- QPoint pos(55, 55);
+ QPoint pos(itemSize.width() / 2 + 5, itemSize.height() / 2 + 5);
QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
event.ignore();
QApplication::sendEvent(view.viewport(), &event);
@@ -2790,14 +2830,14 @@ void tst_QGraphicsScene::update()
QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
rect->setPen(QPen(Qt::black, 0));
scene.addItem(rect);
- qApp->processEvents();
+ QCoreApplication::processEvents();
rect->setPos(-100, -100);
// This function forces indexing
itemAt(scene, 0, 0);
qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
- QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
+ QSignalSpy spy(&scene, &QGraphicsScene::changed);
// We update the scene.
scene.update();
@@ -2806,12 +2846,13 @@ void tst_QGraphicsScene::update()
itemAt(scene, 0, 0);
// This will process the pending update
- QApplication::instance()->processEvents();
+ QCoreApplication::processEvents();
// Check that the update region is correct
QCOMPARE(spy.count(), 1);
QRectF region;
- foreach (QRectF rectF, qvariant_cast<QList<QRectF> >(spy.at(0).at(0)))
+ const auto &rects = qvariant_cast<QList<QRectF> >(spy.at(0).at(0));
+ for (const auto &rectF : rects)
region |= rectF;
QCOMPARE(region, QRectF(-100, -100, 200, 200));
}
@@ -2821,9 +2862,11 @@ void tst_QGraphicsScene::update2()
QGraphicsScene scene;
scene.setSceneRect(-200, -200, 200, 200);
CustomView view;
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
view.setScene(&scene);
view.show();
- qApp->setActiveWindow(&view);
+ QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.repaints >= 1);
view.repaints = 0;
@@ -2831,13 +2874,13 @@ void tst_QGraphicsScene::update2()
// Make sure QGraphicsScene::update only requires one event-loop iteration
// before the view is updated.
scene.update();
- qApp->processEvents();
+ QCoreApplication::processEvents();
QTRY_COMPARE(view.repaints, 1);
view.repaints = 0;
// The same for partial scene updates.
scene.update(QRectF(-100, -100, 100, 100));
- qApp->processEvents();
+ QCoreApplication::processEvents();
QCOMPARE(view.repaints, 1);
}
@@ -2853,7 +2896,7 @@ void tst_QGraphicsScene::views()
QCOMPARE(scene.views().size(), 2);
QVERIFY(scene.views().contains(&view1));
- view.setScene(0);
+ view.setScene(nullptr);
QCOMPARE(scene.views().size(), 1);
QCOMPARE(scene.views().at(0), &view1);
@@ -2871,12 +2914,12 @@ void tst_QGraphicsScene::views()
class CustomScene : public QGraphicsScene
{
public:
- CustomScene() : gotTimerEvent(false)
+ CustomScene()
{ startTimer(10); }
- bool gotTimerEvent;
+ bool gotTimerEvent = false;
protected:
- void timerEvent(QTimerEvent *)
+ void timerEvent(QTimerEvent *) override
{
gotTimerEvent = true;
}
@@ -2893,7 +2936,7 @@ void tst_QGraphicsScene::testEvent()
class DisabledItemTester : public QGraphicsRectItem
{
public:
- DisabledItemTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ DisabledItemTester(const QRectF &rect, QGraphicsItem *parent = nullptr)
: QGraphicsRectItem(rect, parent)
{ }
@@ -2901,13 +2944,13 @@ public:
QList<QEvent::Type> receivedSceneEventFilters;
protected:
- bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override
{
receivedSceneEventFilters << event->type();
return QGraphicsRectItem::sceneEventFilter(watched, event);
}
- bool sceneEvent(QEvent *event)
+ bool sceneEvent(QEvent *event) override
{
receivedSceneEvents << event->type();
return QGraphicsRectItem::sceneEvent(event);
@@ -2965,11 +3008,9 @@ void tst_QGraphicsScene::eventsToDisabledItems()
class ExposedPixmapItem : public QGraphicsPixmapItem
{
public:
- ExposedPixmapItem(QGraphicsItem *item = 0)
- : QGraphicsPixmapItem(item)
- { }
+ using QGraphicsPixmapItem::QGraphicsPixmapItem;
- void paint(QPainter *, const QStyleOptionGraphicsItem *option, QWidget *)
+ void paint(QPainter *, const QStyleOptionGraphicsItem *option, QWidget *) override
{
exposed = option->exposedRect;
}
@@ -3013,8 +3054,9 @@ void tst_QGraphicsScene::tabFocus_emptyScene()
QWidget widget;
widget.setLayout(layout);
+ widget.setWindowTitle(QTest::currentTestFunction());
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
@@ -3060,9 +3102,10 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems()
layout->addWidget(dial2);
QWidget widget;
+ widget.setWindowTitle(QTest::currentTestFunction());
widget.setLayout(layout);
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
@@ -3112,18 +3155,18 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems()
QVERIFY(!view->viewport()->hasFocus());
QVERIFY(!scene.hasFocus());
QVERIFY(!item->hasFocus());
- QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+ QCOMPARE(scene.focusItem(), item);
// Check that the correct item regains focus.
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
QVERIFY(view->hasFocus());
QTRY_VERIFY(scene.isActive());
QVERIFY(view->viewport()->hasFocus());
QVERIFY(scene.hasFocus());
- QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+ QCOMPARE(scene.focusItem(), item);
QVERIFY(item->hasFocus());
}
@@ -3131,14 +3174,13 @@ class FocusWidget : public QGraphicsWidget
{
Q_OBJECT
public:
- FocusWidget(QGraphicsItem *parent = 0)
- : QGraphicsWidget(parent), tabs(0), backTabs(0)
+ FocusWidget(QGraphicsItem *parent = nullptr) : QGraphicsWidget(parent)
{
setFocusPolicy(Qt::StrongFocus);
resize(100, 100);
}
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) override
{
if (option->state & QStyle::State_HasFocus) {
painter->fillRect(rect(), Qt::blue);
@@ -3152,11 +3194,11 @@ public:
}
}
- int tabs;
- int backTabs;
+ int tabs = 0;
+ int backTabs = 0;
protected:
- bool sceneEvent(QEvent *event)
+ bool sceneEvent(QEvent *event) override
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *k = static_cast<QKeyEvent *>(event);
@@ -3168,9 +3210,9 @@ protected:
return QGraphicsWidget::sceneEvent(event);
}
- void focusInEvent(QFocusEvent *)
+ void focusInEvent(QFocusEvent *) override
{ update(); }
- void focusOutEvent(QFocusEvent *)
+ void focusOutEvent(QFocusEvent *) override
{ update(); }
};
@@ -3195,9 +3237,10 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets()
layout->addWidget(dial2);
QWidget widget;
+ widget.setWindowTitle(QTest::currentTestFunction());
widget.setLayout(layout);
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
@@ -3236,7 +3279,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets()
widget.hide();
QTest::qWait(15);
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
QTRY_VERIFY(widget1->hasFocus());
@@ -3279,9 +3322,10 @@ void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets()
layout->addWidget(dial2);
QWidget widget;
+ widget.setWindowTitle(QTest::currentTestFunction());
widget.setLayout(layout);
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
@@ -3366,7 +3410,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets()
widget.hide();
QTest::qWait(12);
widget.show();
- qApp->setActiveWindow(&widget);
+ QApplication::setActiveWindow(&widget);
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget));
QTRY_VERIFY(widget1->hasFocus());
@@ -3390,11 +3434,11 @@ void tst_QGraphicsScene::style()
QCOMPARE(sceneSpy.count(), 1);
QCOMPARE(proxySpy.count(), 1);
QCOMPARE(editSpy.count(), 1);
- QCOMPARE(scene.style(), (QStyle *)windowsStyle);
- QCOMPARE(proxy->style(), (QStyle *)windowsStyle);
- QCOMPARE(edit->style(), (QStyle *)windowsStyle);
+ QCOMPARE(scene.style(), windowsStyle.data());
+ QCOMPARE(proxy->style(), windowsStyle.data());
+ QCOMPARE(edit->style(), windowsStyle.data());
- scene.setStyle(0);
+ scene.setStyle(nullptr);
QCOMPARE(sceneSpy.count(), 2);
QCOMPARE(proxySpy.count(), 2);
QCOMPARE(editSpy.count(), 2);
@@ -3411,11 +3455,12 @@ void tst_QGraphicsScene::task139710_bspTreeCrash()
for (int i = 0; i < 2; ++i) {
// trigger delayed item indexing
- qApp->processEvents();
+ QCoreApplication::processEvents();
scene.setSceneRect(0, 0, 10000, 10000);
// delete all items in the scene - pointers are now likely to be recycled
- foreach (QGraphicsItem *item, scene.items()) {
+ const auto &items = scene.items();
+ for (QGraphicsItem *item : items) {
scene.removeItem(item);
delete item;
}
@@ -3427,7 +3472,7 @@ void tst_QGraphicsScene::task139710_bspTreeCrash()
}
// trigger delayed item indexing for the first 1000 items
- qApp->processEvents();
+ QCoreApplication::processEvents();
// add 1000 more items - the BSP tree is now resized
for (int i = 0; i < 1000; ++i) {
@@ -3437,7 +3482,8 @@ void tst_QGraphicsScene::task139710_bspTreeCrash()
// get items from the BSP tree and use them. there was junk in the tree
// the second time this happened.
- foreach (QGraphicsItem *item, scene.items(QRectF(0, 0, 1000, 1000)))
+ const auto &itemsWithin = scene.items(QRectF(0, 0, 1000, 1000));
+ for (QGraphicsItem *item : itemsWithin)
item->moveBy(0, 0);
}
}
@@ -3446,7 +3492,7 @@ void tst_QGraphicsScene::task139782_containsItemBoundingRect()
{
// The item in question has a scene bounding rect of (10, 10, 50, 50)
QGraphicsScene scene(0.0, 0.0, 200.0, 200.0);
- QGraphicsRectItem *item = new QGraphicsRectItem(0.0, 0.0, 50.0, 50.0, 0);
+ QGraphicsRectItem *item = new QGraphicsRectItem(0.0, 0.0, 50.0, 50.0, nullptr);
scene.addItem(item);
item->setPos(10.0, 10.0);
@@ -3476,7 +3522,8 @@ void tst_QGraphicsScene::task160653_selectionChanged()
QGraphicsScene scene(0, 0, 100, 100);
scene.addItem(new QGraphicsRectItem(0, 0, 20, 20));
scene.addItem(new QGraphicsRectItem(30, 30, 20, 20));
- foreach (QGraphicsItem *item, scene.items()) {
+ const auto &items = scene.items();
+ for (QGraphicsItem *item : items) {
item->setFlags(
item->flags() | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
item->setSelected(true);
@@ -3484,12 +3531,14 @@ void tst_QGraphicsScene::task160653_selectionChanged()
QVERIFY(scene.items().size() > 1);
QCOMPARE(scene.items().size(), scene.selectedItems().size());
- QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QSignalSpy spy(&scene, &QGraphicsScene::selectionChanged);
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
QTest::mouseClick(
- view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.items().first()->scenePos()));
+ view.viewport(), Qt::LeftButton, {}, view.mapFromScene(scene.items().first()->scenePos()));
QCOMPARE(spy.count(), 1);
}
@@ -3574,17 +3623,21 @@ void tst_QGraphicsScene::sorting()
scene.addItem(t_1);
- foreach (QGraphicsItem *item, scene.items())
+ const auto &items = scene.items();
+ for (QGraphicsItem *item : items)
item->setFlag(QGraphicsItem::ItemIsSelectable);
// QGraphicsView view(&scene);
// view.setDragMode(QGraphicsView::RubberBandDrag);
// view.show();
- qDebug() << "items: {";
- foreach (QGraphicsItem *item, scene.items(QRectF(32, 31, 4, 55)))
- qDebug() << "\t" << item->data(0).toString();
- qDebug() << "}";
+ if (lcTests().isDebugEnabled()) {
+ qCDebug(lcTests) << "items: {";
+ const auto &itemsWithin = scene.items(QRectF(32, 31, 4, 55));
+ for (QGraphicsItem *item : itemsWithin)
+ qCDebug(lcTests).nospace() << '\t' << item->data(0).toString();
+ qCDebug(lcTests) << '}';
+ }
QCOMPARE(scene.items(QRectF(32, 31, 4, 55)),
QList<QGraphicsItem *>()
@@ -3664,11 +3717,11 @@ void tst_QGraphicsScene::changedSignal()
QFETCH(bool, withView);
QGraphicsScene scene;
ChangedListener cl;
- connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
+ connect(&scene, &QGraphicsScene::changed, &cl, &ChangedListener::changed);
- QGraphicsView *view = 0;
+ QScopedPointer<QGraphicsView> view;
if (withView)
- view = new QGraphicsView(&scene);
+ view.reset(new QGraphicsView(&scene));
QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 10, 10);
rect->setPen(QPen(Qt::black, 0));
@@ -3682,16 +3735,13 @@ void tst_QGraphicsScene::changedSignal()
rect->setPos(20, 0);
QCOMPARE(cl.changes.size(), 1);
- qApp->processEvents();
+ QCoreApplication::processEvents();
QCOMPARE(cl.changes.size(), 2);
QCOMPARE(cl.changes.at(1).size(), 2);
QCOMPARE(cl.changes.at(1).first(), QRectF(0, 0, 10, 10));
QCOMPARE(cl.changes.at(1).last(), QRectF(20, 0, 10, 10));
QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
-
- if (withView)
- delete view;
}
void tst_QGraphicsScene::stickyFocus_data()
@@ -3718,7 +3768,7 @@ void tst_QGraphicsScene::stickyFocus()
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.setScenePos(QPointF(-10, -10)); // outside item
event.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
QCOMPARE(text->hasFocus(), sticky);
}
@@ -3736,43 +3786,51 @@ void tst_QGraphicsScene::sendEvent()
void tst_QGraphicsScene::inputMethod_data()
{
- QTest::addColumn<int>("flags");
+ QTest::addColumn<QGraphicsItem::GraphicsItemFlags>("flags");
QTest::addColumn<bool>("callFocusItem");
- QTest::newRow("0") << 0 << false;
- QTest::newRow("1") << (int)QGraphicsItem::ItemAcceptsInputMethod << false;
- QTest::newRow("2") << (int)QGraphicsItem::ItemIsFocusable << false;
+ QTest::newRow("0") << QGraphicsItem::GraphicsItemFlags() << false;
+ QTest::newRow("1") << QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemAcceptsInputMethod) << false;
+ QTest::newRow("2") << QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsFocusable) << false;
QTest::newRow("3") <<
- (int)(QGraphicsItem::ItemAcceptsInputMethod|QGraphicsItem::ItemIsFocusable) << true;
+ (QGraphicsItem::ItemAcceptsInputMethod|QGraphicsItem::ItemIsFocusable) << true;
}
class InputMethodTester : public QGraphicsRectItem
{
- void inputMethodEvent(QInputMethodEvent *) { ++eventCalls; }
- QVariant inputMethodQuery(Qt::InputMethodQuery) const { ++queryCalls; return QVariant(); }
+ void inputMethodEvent(QInputMethodEvent *) override { ++eventCalls; }
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const override
+ {
+ ++queryCalls;
+ return QVariant();
+ }
+
public:
- int eventCalls;
- mutable int queryCalls;
+ int eventCalls = 0;
+ mutable int queryCalls = 0;
};
void tst_QGraphicsScene::inputMethod()
{
PlatformInputContext inputContext;
- QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
+ QInputMethodPrivate *inputMethodPrivate =
+ QInputMethodPrivate::get(QGuiApplication::inputMethod());
inputMethodPrivate->testContext = &inputContext;
- QFETCH(int, flags);
+ QFETCH(QGraphicsItem::GraphicsItemFlags, flags);
QFETCH(bool, callFocusItem);
InputMethodTester *item = new InputMethodTester;
- item->setFlags((QGraphicsItem::GraphicsItemFlags)flags);
+ item->setFlags(flags);
QGraphicsScene scene;
QGraphicsView view(&scene);
+ view.resize(m_testSize);
view.show();
+ view.setWindowTitle(QTest::currentTestFunction());
QApplication::setActiveWindow(&view);
view.setFocus();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+ QCOMPARE(QApplication::activeWindow(), &view);
inputContext.m_resetCallCount = 0;
inputContext.m_commitCallCount = 0;
@@ -3784,25 +3842,25 @@ void tst_QGraphicsScene::inputMethod()
QCOMPARE(inputContext.m_resetCallCount, 0);
item->eventCalls = 0;
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
QCOMPARE(item->eventCalls, callFocusItem ? 1 : 0);
item->queryCalls = 0;
- scene.inputMethodQuery((Qt::InputMethodQuery)0);
+ scene.inputMethodQuery(Qt::InputMethodQuery(0));
QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0);
- scene.setFocusItem(0);
+ scene.setFocusItem(nullptr);
// the input context is reset twice, once because an item has lost focus and again because
// the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
QCOMPARE(inputContext.m_resetCallCount + inputContext.m_commitCallCount, callFocusItem ? 2 : 0);
QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected
item->eventCalls = 0;
- qApp->sendEvent(&scene, &event);
+ QCoreApplication::sendEvent(&scene, &event);
QCOMPARE(item->eventCalls, 0);
item->queryCalls = 0;
- scene.inputMethodQuery((Qt::InputMethodQuery)0);
+ scene.inputMethodQuery(Qt::InputMethodQuery(0));
QCOMPARE(item->queryCalls, 0);
}
@@ -3826,18 +3884,18 @@ void tst_QGraphicsScene::dispatchHoverOnPress()
me.setButtons(Qt::LeftButton);
QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
me2.setButton(Qt::LeftButton);
- qApp->sendEvent(&scene, &me);
- qApp->sendEvent(&scene, &me2);
- QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ QCoreApplication::sendEvent(&scene, &me);
+ QCoreApplication::sendEvent(&scene, &me2);
+ QCOMPARE(tester1->eventTypes, QVector<QEvent::Type>()
<< QEvent::GraphicsSceneHoverEnter
<< QEvent::GraphicsSceneHoverMove
<< QEvent::GrabMouse
<< QEvent::GraphicsSceneMousePress
<< QEvent::UngrabMouse);
tester1->eventTypes.clear();
- qApp->sendEvent(&scene, &me);
- qApp->sendEvent(&scene, &me2);
- QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ QCoreApplication::sendEvent(&scene, &me);
+ QCoreApplication::sendEvent(&scene, &me2);
+ QCOMPARE(tester1->eventTypes, QVector<QEvent::Type>()
<< QEvent::GraphicsSceneHoverMove
<< QEvent::GrabMouse
<< QEvent::GraphicsSceneMousePress
@@ -3852,21 +3910,21 @@ void tst_QGraphicsScene::dispatchHoverOnPress()
me2.setScenePos(QPointF(30, 30));
me2.setButton(Qt::LeftButton);
tester1->eventTypes.clear();
- qApp->sendEvent(&scene, &me);
- qApp->sendEvent(&scene, &me2);
- qDebug() << tester1->eventTypes;
- QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ QCoreApplication::sendEvent(&scene, &me);
+ QCoreApplication::sendEvent(&scene, &me2);
+ qCDebug(lcTests) << tester1->eventTypes;
+ QCOMPARE(tester1->eventTypes, QVector<QEvent::Type>()
<< QEvent::GraphicsSceneHoverLeave);
- QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
+ QCOMPARE(tester2->eventTypes, QVector<QEvent::Type>()
<< QEvent::GraphicsSceneHoverEnter
<< QEvent::GraphicsSceneHoverMove
<< QEvent::GrabMouse
<< QEvent::GraphicsSceneMousePress
<< QEvent::UngrabMouse);
tester2->eventTypes.clear();
- qApp->sendEvent(&scene, &me);
- qApp->sendEvent(&scene, &me2);
- QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
+ QCoreApplication::sendEvent(&scene, &me);
+ QCoreApplication::sendEvent(&scene, &me2);
+ QCOMPARE(tester2->eventTypes, QVector<QEvent::Type>()
<< QEvent::GraphicsSceneHoverMove
<< QEvent::GrabMouse
<< QEvent::GraphicsSceneMousePress
@@ -3915,7 +3973,7 @@ void tst_QGraphicsScene::initialFocus()
if (activeScene) {
QEvent windowActivate(QEvent::WindowActivate);
- qApp->sendEvent(&scene, &windowActivate);
+ QCoreApplication::sendEvent(&scene, &windowActivate);
scene.setFocus();
}
@@ -3923,7 +3981,7 @@ void tst_QGraphicsScene::initialFocus()
if (!activeScene) {
QEvent windowActivate(QEvent::WindowActivate);
- qApp->sendEvent(&scene, &windowActivate);
+ QCoreApplication::sendEvent(&scene, &windowActivate);
scene.setFocus();
}
@@ -3933,14 +3991,13 @@ void tst_QGraphicsScene::initialFocus()
class PolishItem : public QGraphicsTextItem
{
public:
- PolishItem(QGraphicsItem *parent = 0)
- : QGraphicsTextItem(parent), polished(false), deleteChildrenInPolish(true), addChildrenInPolish(false) { }
+ using QGraphicsTextItem::QGraphicsTextItem;
- bool polished;
- bool deleteChildrenInPolish;
- bool addChildrenInPolish;
+ bool polished = false;
+ bool deleteChildrenInPolish = true;
+ bool addChildrenInPolish = false;
protected:
- QVariant itemChange(GraphicsItemChange change, const QVariant& value)
+ QVariant itemChange(GraphicsItemChange change, const QVariant& value) override
{
if (change == ItemVisibleChange) {
polished = true;
@@ -3979,19 +4036,19 @@ void tst_QGraphicsScene::polishItems2()
// Wait for the polish event to be delivered.
QVERIFY(!item->polished);
- QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
+ QCoreApplication::sendPostedEvents(&scene, QEvent::MetaCall);
QVERIFY(item->polished);
// We deleted the children we added above, but we also
// added 10 new children. These should be polished in the next
// event loop iteration.
- QList<QGraphicsItem *> children = item->childItems();
+ const QList<QGraphicsItem *> children = item->childItems();
QCOMPARE(children.count(), 10);
- foreach (QGraphicsItem *child, children)
+ for (QGraphicsItem *child : children)
QVERIFY(!static_cast<PolishItem *>(child)->polished);
- QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
- foreach (QGraphicsItem *child, children)
+ QCoreApplication::sendPostedEvents(&scene, QEvent::MetaCall);
+ for (QGraphicsItem *child : children)
QVERIFY(static_cast<PolishItem *>(child)->polished);
}
@@ -4008,6 +4065,8 @@ void tst_QGraphicsScene::isActive()
{
QWidget toplevel1;
+ toplevel1.setWindowTitle(QTest::currentTestFunction());
+ toplevel1.resize(m_testSize);
QHBoxLayout *layout = new QHBoxLayout;
toplevel1.setLayout(layout);
QGraphicsView *view1 = new QGraphicsView(&scene1);
@@ -4073,8 +4132,9 @@ void tst_QGraphicsScene::isActive()
{
- const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
QWidget toplevel2;
+ toplevel2.setWindowTitle(QTest::currentTestFunction());
+ toplevel2.resize(m_testSize);
QHBoxLayout *layout = new QHBoxLayout;
toplevel2.setLayout(layout);
QGraphicsView *view1 = new QGraphicsView(&scene1);
@@ -4087,7 +4147,7 @@ void tst_QGraphicsScene::isActive()
QVERIFY(!scene1.hasFocus());
QVERIFY(!scene2.hasFocus());
- toplevel2.move(availableGeometry.topLeft() + QPoint(50, 50));
+ toplevel2.move(m_availableGeometry.topLeft() + QPoint(50, 50));
toplevel2.show();
QApplication::setActiveWindow(&toplevel2);
QVERIFY(QTest::qWaitForWindowActive(&toplevel2));
@@ -4136,12 +4196,13 @@ void tst_QGraphicsScene::isActive()
QVERIFY(!scene2.hasFocus());
QGraphicsView topLevelView;
- topLevelView.move(availableGeometry.topLeft() + QPoint(500, 50));
+ topLevelView.move(toplevel2.geometry().topRight() + QPoint(100, 50));
+ topLevelView.resize(m_testSize);
topLevelView.show();
QApplication::setActiveWindow(&topLevelView);
topLevelView.setFocus();
QVERIFY(QTest::qWaitForWindowActive(&topLevelView));
- QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&topLevelView));
+ QCOMPARE(QApplication::activeWindow(), &topLevelView);
QVERIFY(!scene1.isActive());
QVERIFY(!scene2.isActive());
@@ -4182,6 +4243,7 @@ void tst_QGraphicsScene::isActive()
{
QWidget toplevel3;
+ toplevel3.resize(m_testSize);
QHBoxLayout *layout = new QHBoxLayout;
toplevel3.setLayout(layout);
QGraphicsView *view1 = new QGraphicsView(&scene1);
@@ -4211,7 +4273,7 @@ void tst_QGraphicsScene::isActive()
QVERIFY(scene1.hasFocus());
QVERIFY(!scene2.hasFocus());
- view1->setParent(0);
+ view1->setParent(nullptr);
QVERIFY(!scene1.isActive());
QVERIFY(scene2.isActive());
QVERIFY(!scene1.hasFocus());
@@ -4243,7 +4305,7 @@ void tst_QGraphicsScene::siblingIndexAlwaysValid()
scene.addItem(parent2);
//Then we make the child a top level
- child->setParentItem(0);
+ child->setParentItem(nullptr);
//This is trigerred by a repaint...
QGraphicsScenePrivate::get(&scene)->index->estimateTopLevelItems(QRectF(), Qt::AscendingOrder);
@@ -4259,6 +4321,8 @@ void tst_QGraphicsScene::siblingIndexAlwaysValid()
scene2.setItemIndexMethod(QGraphicsScene::NoIndex);
QGraphicsView view2(&scene2);
+ view2.setWindowTitle(QTest::currentTestFunction());
+ view2.resize(m_testSize);
// first add the blue rect
QGraphicsRectItem* const item1 = new QGraphicsRectItem(QRect( 10, 10, 10, 10 ));
@@ -4302,9 +4366,11 @@ void tst_QGraphicsScene::removeFullyTransparentItem()
child->setParentItem(parent);
CustomView view;
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
view.setScene(&scene);
view.show();
- qApp->setActiveWindow(&view);
+ QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QCoreApplication::processEvents(); // Process all queued paint events
@@ -4353,33 +4419,35 @@ void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache()
void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts()
{
// Test using DeviceCoordinateCache and opaque item
- QWidget *w = new QWidget();
+ QScopedPointer<QWidget> w(new QWidget);
w->setPalette(QColor(0, 0, 255));
w->setGeometry(0, 0, 50, 50);
QGraphicsScene *scene = new QGraphicsScene();
- CustomView *view = new CustomView;
- view->setScene(scene);
+ CustomView view;
+ view.resize(m_testSize);
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.setScene(scene);
- QGraphicsProxyWidget *proxy = scene->addWidget(w);
+ QGraphicsProxyWidget *proxy = scene->addWidget(w.data());
proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
proxy->setTransform(QTransform().rotate(15), true);
- view->show();
- QVERIFY(QTest::qWaitForWindowExposed(view));
- view->repaints = 0;
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ view.repaints = 0;
proxy->update(10, 10, 10, 10);
- QTRY_VERIFY(view->repaints > 0);
+ QTRY_VERIFY(view.repaints > 0);
QPixmap pix;
QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy);
- QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view.viewport()).key, &pix));
QTransform t = proxy->sceneTransform();
// Map from scene coordinates to pixmap coordinates.
// X origin in the pixmap is the most-left point
// of the item's boundingRect in the scene.
- qreal adjust = t.mapRect(proxy->boundingRect().toRect()).left();
+ const int adjust = t.mapRect(proxy->boundingRect().toRect()).left();
QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
QPixmap subpix = pix.copy(rect);
@@ -4388,8 +4456,6 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts()
for(int j = 0; j < im.height(); j++)
QCOMPARE(qAlpha(im.pixel(i, j)), 255);
}
-
- delete w;
}
void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
@@ -4403,28 +4469,30 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
rectItem->setParentItem(backItem);
QGraphicsScene *scene = new QGraphicsScene();
- CustomView *view = new CustomView;
- view->setScene(scene);
+ CustomView view;
+ view.resize(m_testSize);
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.setScene(scene);
scene->addItem(backItem);
rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
backItem->setTransform(QTransform().rotate(15), true);
- view->show();
- QVERIFY(QTest::qWaitForWindowExposed(view));
- view->repaints = 0;
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ view.repaints = 0;
rectItem->update(10, 10, 10, 10);
- QTRY_VERIFY(view->repaints > 0);
+ QTRY_VERIFY(view.repaints > 0);
QPixmap pix;
QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
- QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view.viewport()).key, &pix));
QTransform t = rectItem->sceneTransform();
// Map from scene coordinates to pixmap coordinates.
// X origin in the pixmap is the most-left point
// of the item's boundingRect in the scene.
- qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ const int adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
QPixmap subpix = pix.copy(rect);
@@ -4434,8 +4502,6 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
QCOMPARE(qAlpha(im.pixel(i, j)), 125);
}
}
-
- delete view;
}
// Test using ItemCoordinateCache and opaque item
@@ -4444,18 +4510,20 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
rectItem->setBrush(QColor(0, 0, 255));
QGraphicsScene *scene = new QGraphicsScene();
- CustomView *view = new CustomView;
- view->setScene(scene);
+ CustomView view;
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
+ view.setScene(scene);
scene->addItem(rectItem);
rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
rectItem->setTransform(QTransform().rotate(15), true);
- view->show();
- QVERIFY(QTest::qWaitForWindowExposed(view));
- view->repaints = 0;
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ view.repaints = 0;
rectItem->update(10, 10, 10, 10);
- QTRY_VERIFY(view->repaints > 0);
+ QTRY_VERIFY(view.repaints > 0);
QPixmap pix;
QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
@@ -4465,7 +4533,7 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
// Map from scene coordinates to pixmap coordinates.
// X origin in the pixmap is the most-left point
// of the item's boundingRect in the scene.
- qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ const int adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
QPixmap subpix = pix.copy(rect);
@@ -4474,8 +4542,6 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
for(int j = 0; j < im.height(); j++)
QCOMPARE(qAlpha(im.pixel(i, j)), 255);
}
-
- delete view;
}
// Test using ItemCoordinateCache and semi-transparent item
@@ -4484,18 +4550,20 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
rectItem->setBrush(QColor(0, 0, 255, 125));
QGraphicsScene *scene = new QGraphicsScene();
- CustomView *view = new CustomView;
- view->setScene(scene);
+ CustomView view;
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
+ view.setScene(scene);
scene->addItem(rectItem);
rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
rectItem->setTransform(QTransform().rotate(15), true);
- view->show();
- QVERIFY(QTest::qWaitForWindowExposed(view));
- view->repaints = 0;
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ view.repaints = 0;
rectItem->update(10, 10, 10, 10);
- QTRY_VERIFY(view->repaints > 0);
+ QTRY_VERIFY(view.repaints > 0);
QPixmap pix;
QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
@@ -4505,7 +4573,7 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
// Map from scene coordinates to pixmap coordinates.
// X origin in the pixmap is the most-left point
// of the item's boundingRect in the scene.
- qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ const int adjust = int(t.mapRect(rectItem->boundingRect().toRect()).left());
QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
QPixmap subpix = pix.copy(rect);
@@ -4514,8 +4582,6 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
for(int j = 0; j < im.height(); j++)
QCOMPARE(qAlpha(im.pixel(i, j)), 125);
}
-
- delete view;
}
}
@@ -4546,7 +4612,7 @@ void tst_QGraphicsScene::zeroScale()
QGraphicsView view(&scene);
ChangedListener cl;
- connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
+ connect(&scene, &QGraphicsScene::changed, &cl, &ChangedListener::changed);
QGraphicsRectItem *rect1 = new QGraphicsRectItem(0, 0, 0.0000001, 0.00000001);
scene.addItem(rect1);
@@ -4569,13 +4635,13 @@ void tst_QGraphicsScene::focusItemChangedSignal()
qRegisterMetaType<Qt::FocusReason>("Qt::FocusReason");
QGraphicsScene scene;
- QSignalSpy spy(&scene, SIGNAL(focusItemChanged(QGraphicsItem *, QGraphicsItem *, Qt::FocusReason)));
+ QSignalSpy spy(&scene, &QGraphicsScene::focusItemChanged);
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 0);
scene.setFocus();
QCOMPARE(spy.count(), 0);
QEvent activateEvent(QEvent::WindowActivate);
- qApp->sendEvent(&scene, &activateEvent);
+ QCoreApplication::sendEvent(&scene, &activateEvent);
QCOMPARE(spy.count(), 0);
QGraphicsRectItem *topLevelItem1 = new QGraphicsRectItem;
@@ -4592,7 +4658,7 @@ void tst_QGraphicsScene::focusItemChangedSignal()
QCOMPARE(spy.count(), 1);
QList<QVariant> arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), topLevelItem2);
QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), nullptr);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::OtherFocusReason);
QVERIFY(topLevelItem2->hasFocus());
@@ -4602,14 +4668,14 @@ void tst_QGraphicsScene::focusItemChangedSignal()
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), nullptr);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), topLevelItem2);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::OtherFocusReason);
scene.setFocus(Qt::MenuBarFocusReason);
QCOMPARE(spy.count(), 1);
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), topLevelItem2);
QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), nullptr);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::MenuBarFocusReason);
@@ -4617,15 +4683,15 @@ void tst_QGraphicsScene::focusItemChangedSignal()
topLevelItem1->setFocus(Qt::TabFocusReason);
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem1);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), topLevelItem1);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), topLevelItem2);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::TabFocusReason);
topLevelItem2->setFocus(Qt::TabFocusReason);
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem2);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem1);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), topLevelItem2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), topLevelItem1);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::TabFocusReason);
}
@@ -4633,10 +4699,10 @@ void tst_QGraphicsScene::focusItemChangedSignal()
// when the scene activation changes) breaks quite a few tests so leave this fix
// for some future release. See QTBUG-28346.
QEvent deactivateEvent(QEvent::WindowDeactivate);
- qApp->sendEvent(&scene, &deactivateEvent);
+ QCoreApplication::sendEvent(&scene, &deactivateEvent);
QEXPECT_FAIL("", "QTBUG-28346", Continue);
QCOMPARE(spy.count(), 1);
- qApp->sendEvent(&scene, &activateEvent);
+ QCoreApplication::sendEvent(&scene, &activateEvent);
QEXPECT_FAIL("", "QTBUG-28346", Continue);
QCOMPARE(spy.count(), 1);
@@ -4647,8 +4713,8 @@ void tst_QGraphicsScene::focusItemChangedSignal()
QCOMPARE(spy.count(), 1);
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)panel1);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), panel1);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), topLevelItem2);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason);
QGraphicsRectItem *panel2 = new QGraphicsRectItem;
@@ -4661,16 +4727,16 @@ void tst_QGraphicsScene::focusItemChangedSignal()
QCOMPARE(spy.count(), 1);
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)panel2);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)panel1);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), panel2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), panel1);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason);
scene.setActivePanel(panel1);
QCOMPARE(spy.count(), 1);
arguments = spy.takeFirst();
QCOMPARE(arguments.size(), 3);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)panel1);
- QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)panel2);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), panel1);
+ QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(1)), panel2);
QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason);
}
@@ -4679,14 +4745,15 @@ void tst_QGraphicsScene::focusItemChangedSignal()
class ItemCountsPaintCalls : public QGraphicsRectItem
{
public:
- ItemCountsPaintCalls(const QRectF & rect, QGraphicsItem *parent = 0)
- : QGraphicsRectItem(rect, parent), repaints(0) {}
- void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 )
+ using QGraphicsRectItem::QGraphicsRectItem;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget = nullptr) override
{
QGraphicsRectItem::paint(painter, option, widget);
++repaints;
}
- int repaints;
+ int repaints = 0;
};
void tst_QGraphicsScene::minimumRenderSize()
@@ -4700,10 +4767,12 @@ void tst_QGraphicsScene::minimumRenderSize()
scene.addItem(bigParent);
CustomView view;
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
view.setScene(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- qApp->processEvents();
+ QCoreApplication::processEvents();
// Initially, everything should be repainted the same number of times
int viewRepaints = 0;
@@ -4716,7 +4785,7 @@ void tst_QGraphicsScene::minimumRenderSize()
// Setting a minimum render size should cause a repaint
scene.setMinimumRenderSize(0.5);
- qApp->processEvents();
+ QCoreApplication::processEvents();
QTRY_VERIFY(view.repaints > viewRepaints);
viewRepaints = view.repaints;
@@ -4727,7 +4796,7 @@ void tst_QGraphicsScene::minimumRenderSize()
// Scaling should cause a repaint of big items only.
view.scale(0.1, 0.1);
- qApp->processEvents();
+ QCoreApplication::processEvents();
QTRY_VERIFY(view.repaints > viewRepaints);
viewRepaints = view.repaints;
@@ -4738,7 +4807,7 @@ void tst_QGraphicsScene::minimumRenderSize()
// Scaling further should cause even fewer items to be repainted
view.scale(0.1, 0.1); // Stacks with previous scale
- qApp->processEvents();
+ QCoreApplication::processEvents();
QTRY_VERIFY(view.repaints > viewRepaints);
viewRepaints = view.repaints;
@@ -4752,6 +4821,8 @@ void tst_QGraphicsScene::focusOnTouch()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
scene.setSceneRect(0, 0, 100, 100);
QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
rect->setFlag(QGraphicsItem::ItemIsFocusable, true);
@@ -4809,6 +4880,7 @@ void tst_QGraphicsScene::taskQTBUG_16401_focusItem()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
+ view.resize(m_testSize);
QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
rect->setFlag(QGraphicsItem::ItemIsFocusable);
@@ -4839,6 +4911,8 @@ void tst_QGraphicsScene::taskQTBUG_42915_focusNextPrevChild()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
+ view.setWindowTitle(QTest::currentTestFunction());
+ view.resize(m_testSize);
scene.setSceneRect(1, 1, 198, 198);
view.setFocus();
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST
index ee13a37212..9b76ea02ff 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST
@@ -1,20 +1,16 @@
[task255529_transformationAnchorMouseAndViewportMargins]
-xcb
+opensuse-leap
[cursor]
-xcb
+opensuse-leap
[cursor2]
-xcb
-windows
-[rubberBandExtendSelection]
-xcb
-[rotated_rubberBand]
-xcb
+ubuntu-16.04
[sendEvent]
-xcb
-[forwardMousePress]
-xcb
+ubuntu-16.04
+opensuse-42.3
[resizeAnchor]
-xcb
+opensuse-leap
+rhel-7.6
+ubuntu
[update2]
opensuse-42.3
[itemsInRect_cosmeticAdjust]
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 1442219bea..e21b1b889a 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -352,8 +352,8 @@ void tst_QGraphicsView::renderHints()
view.setScene(&scene);
- view.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
- QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+ view.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing);
QCOMPARE(item->hints, 0);
view.show();
@@ -361,8 +361,8 @@ void tst_QGraphicsView::renderHints()
view.repaint();
QTRY_COMPARE(item->hints, view.renderHints());
- view.setRenderHints(QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
- QCOMPARE(view.renderHints(), QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+ view.setRenderHints(QPainter::Antialiasing);
+ QCOMPARE(view.renderHints(), QPainter::Antialiasing);
view.repaint();
QTRY_COMPARE(item->hints, view.renderHints());
@@ -2219,7 +2219,7 @@ void tst_QGraphicsView::wheelEvent()
{
QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
- 120, 0, 0, Qt::Horizontal);
+ QPoint(), QPoint(120, 0), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QApplication::sendEvent(view.viewport(), &event);
QCOMPARE(scene.orientation, Qt::Horizontal);
}
@@ -2228,7 +2228,7 @@ void tst_QGraphicsView::wheelEvent()
{
QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
- 120, 0, 0, Qt::Vertical);
+ QPoint(), QPoint(0, 120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QApplication::sendEvent(view.viewport(), &event);
QCOMPARE(scene.orientation, Qt::Vertical);
}
@@ -2526,9 +2526,8 @@ void tst_QGraphicsView::viewportUpdateMode2()
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.setScene(&dummyScene);
view.ensurePolished(); // make sure we get the right content margins
- int left, top, right, bottom;
- view.getContentsMargins(&left, &top, &right, &bottom);
- view.resize(200 + left + right, 200 + top + bottom);
+ const QMargins margins = view.contentsMargins();
+ view.resize(200 + margins.left() + margins.right(), 200 + margins.top() + margins.bottom());
toplevel.show();
qApp->setActiveWindow(&toplevel);
QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
@@ -2611,11 +2610,6 @@ void tst_QGraphicsView::optimizationFlags()
QGraphicsView view;
QVERIFY(!view.optimizationFlags());
- view.setOptimizationFlag(QGraphicsView::DontClipPainter);
- QVERIFY(view.optimizationFlags() & QGraphicsView::DontClipPainter);
- view.setOptimizationFlag(QGraphicsView::DontClipPainter, false);
- QVERIFY(!view.optimizationFlags());
-
view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
QVERIFY(view.optimizationFlags() & QGraphicsView::DontSavePainterState);
view.setOptimizationFlag(QGraphicsView::DontSavePainterState, false);
@@ -2626,10 +2620,8 @@ void tst_QGraphicsView::optimizationFlags()
view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, false);
QVERIFY(!view.optimizationFlags());
- view.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
- | QGraphicsView::DontClipPainter);
- QCOMPARE(view.optimizationFlags(), QGraphicsView::OptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
- | QGraphicsView::DontClipPainter));
+ view.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing);
+ QCOMPARE(view.optimizationFlags(), QGraphicsView::OptimizationFlags(QGraphicsView::DontAdjustForAntialiasing));
}
class MessUpPainterItem : public QGraphicsRectItem
@@ -4043,9 +4035,8 @@ void tst_QGraphicsView::update()
CustomView view(0, &toplevel);
view.setScene(&dummyScene);
view.ensurePolished(); // must ensure polished to get content margins right
- int left, top, right, bottom;
- view.getContentsMargins(&left, &top, &right, &bottom);
- view.resize(200 + left + right, 200 + top + bottom);
+ const QMargins margins = view.contentsMargins();
+ view.resize(200 + margins.left() + margins.right(), 200 + margins.top() + margins.bottom());
toplevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
@@ -4857,7 +4848,7 @@ void tst_QGraphicsView::QTBUG_16063_microFocusRect()
scene.setFocusItem(item);
view.setFocus();
- QRectF mfv = view.inputMethodQuery(Qt::ImMicroFocus).toRectF();
+ QRectF mfv = view.inputMethodQuery(Qt::ImCursorRectangle).toRectF();
QCOMPARE(mfv, IMItem::mf.translated(-view.mapToScene(view.sceneRect().toRect()).boundingRect().topLeft()));
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index 85b42e54fe..d3477be986 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -2905,7 +2905,7 @@ public:
Q_UNUSED(widget);
qreal w = rect().width();
QRectF box(0, 0, w, 2400/w);
- painter->drawRoundRect(box);
+ painter->drawRoundedRect(box, 25, 25, Qt::RelativeSize);
painter->drawLine(box.topLeft(), box.bottomRight());
painter->drawLine(box.bottomLeft(), box.topRight());
}
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 6f7dca86eb..bcfc477733 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -1024,9 +1024,6 @@ void tst_QAbstractItemView::setItemDelegate()
centerOnScreen(&v);
moveCursorAway(&v);
v.show();
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- QCursor::setPos(v.geometry().center());
-#endif
QApplication::setActiveWindow(&v);
QVERIFY(QTest::qWaitForWindowActive(&v));
diff --git a/tests/auto/widgets/itemviews/qcolumnview/BLACKLIST b/tests/auto/widgets/itemviews/qcolumnview/BLACKLIST
deleted file mode 100644
index bda01c700c..0000000000
--- a/tests/auto/widgets/itemviews/qcolumnview/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[scrollTo:reverse]
-osx
diff --git a/tests/auto/widgets/itemviews/qheaderview/BLACKLIST b/tests/auto/widgets/itemviews/qheaderview/BLACKLIST
index efb813f7d2..4eceaae0d3 100644
--- a/tests/auto/widgets/itemviews/qheaderview/BLACKLIST
+++ b/tests/auto/widgets/itemviews/qheaderview/BLACKLIST
@@ -1,3 +1,2 @@
[stretchAndRestoreLastSection]
-opensuse
opensuse-leap
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 1b3e1e1f34..df02815eb2 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -85,8 +85,8 @@ class XResetModel : public QStandardItemModel
blockSignals(true);
bool r = QStandardItemModel::removeRows(row, count, parent);
blockSignals(false);
- emit beginResetModel();
- emit endResetModel();
+ beginResetModel();
+ endResetModel();
return r;
}
virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())
@@ -94,8 +94,8 @@ class XResetModel : public QStandardItemModel
blockSignals(true);
bool r = QStandardItemModel::insertRows(row, count, parent);
blockSignals(false);
- emit beginResetModel();
- emit endResetModel();
+ beginResetModel();
+ endResetModel();
return r;
}
};
@@ -106,6 +106,7 @@ class tst_QHeaderView : public QObject
public:
tst_QHeaderView();
+ static void initMain();
private slots:
void initTestCase();
@@ -265,6 +266,14 @@ protected:
QElapsedTimer timer;
};
+void tst_QHeaderView::initMain()
+{
+#ifdef Q_OS_WIN
+ // Ensure minimum size constraints of framed windows on High DPI screens
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+}
+
class QtTestModel: public QAbstractTableModel
{
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
index 10cd1dcc54..916694fd0f 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
+++ b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
@@ -3,4 +3,4 @@ TARGET = tst_qitemdelegate
QT += widgets widgets-private testlib
SOURCES += tst_qitemdelegate.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/itemviews/qlistview/qlistview.pro b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
index 75f45ab432..c3e19adc81 100644
--- a/tests/auto/widgets/itemviews/qlistview/qlistview.pro
+++ b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
@@ -2,4 +2,4 @@ CONFIG += testcase
TARGET = tst_qlistview
QT += widgets gui-private widgets-private core-private testlib testlib-private
SOURCES += tst_qlistview.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index 0b828b8484..3a60b3b7c6 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -2516,9 +2516,9 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents()
QPoint globalPos = lv.geometry().center();
QPoint pos = lv.viewport()->geometry().center();
- QWheelEvent wheelDownEvent(pos, globalPos, QPoint(0, 0), QPoint(0, -120), -120, Qt::Vertical, 0, 0);
- QWheelEvent wheelUpEvent(pos, globalPos, QPoint(0, 0), QPoint(0, 120), 120, Qt::Vertical, 0, 0);
- QWheelEvent wheelLeftDownEvent(pos, globalPos, QPoint(0, 0), QPoint(120, -120), -120, Qt::Vertical, 0, 0);
+ QWheelEvent wheelDownEvent(pos, globalPos, QPoint(0, 0), QPoint(0, -120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
+ QWheelEvent wheelUpEvent(pos, globalPos, QPoint(0, 0), QPoint(0, 120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
+ QWheelEvent wheelLeftDownEvent(pos, globalPos, QPoint(0, 0), QPoint(120, -120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
int hValue = lv.horizontalScrollBar()->value();
QApplication::sendEvent(lv.viewport(), &wheelDownEvent);
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 91088aeeca..fe2ede4183 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -1525,11 +1525,11 @@ void tst_QListWidget::itemData()
item.setData(Qt::DisplayRole, QString("0"));
QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item.setData(Qt::CheckStateRole, Qt::PartiallyChecked);
- QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
for (int i = 0; i < 4; ++i)
{
item.setData(Qt::UserRole + i, QString::number(i + 1));
- QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
}
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
diff --git a/tests/auto/widgets/itemviews/qtableview/BLACKLIST b/tests/auto/widgets/itemviews/qtableview/BLACKLIST
index be90475a6f..9648cef3de 100644
--- a/tests/auto/widgets/itemviews/qtableview/BLACKLIST
+++ b/tests/auto/widgets/itemviews/qtableview/BLACKLIST
@@ -1,4 +1,3 @@
[moveCursorBiggerJump]
osx
-[columnViewportPosition]
-winrt # QTBUG-72853
+
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index c8eecd3693..35c0c6c606 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -32,6 +32,9 @@
#include <private/qtablewidget_p.h>
#include <QtTest/QtTest>
#include "private/qapplication_p.h"
+#if QT_CONFIG(textmarkdownwriter)
+#include "private/qtextmarkdownwriter_p.h"
+#endif
#include <algorithm>
@@ -196,6 +199,10 @@ private slots:
void viewOptions();
void taskQTBUG_7232_AllowUserToControlSingleStep();
+
+#if QT_CONFIG(textmarkdownwriter)
+ void markdownWriter();
+#endif
};
// Testing get/set functions
@@ -4067,8 +4074,10 @@ void tst_QTableView::mouseWheel()
view.verticalScrollBar()->setValue(10);
QPoint pos = view.viewport()->geometry().center();
- QWheelEvent verticalEvent(pos, delta, 0, 0, Qt::Vertical);
- QWheelEvent horizontalEvent(pos, delta, 0, 0, Qt::Horizontal);
+ QWheelEvent verticalEvent(pos, view.mapToGlobal(pos), QPoint(), QPoint(0, delta),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
+ QWheelEvent horizontalEvent(pos, view.mapToGlobal(pos), QPoint(), QPoint(delta, 0),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QApplication::sendEvent(view.viewport(), &horizontalEvent);
QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 15);
QApplication::sendEvent(view.viewport(), &verticalEvent);
@@ -4353,7 +4362,9 @@ void tst_QTableView::taskQTBUG_5237_wheelEventOnHeader()
int sbValueBefore = view.verticalScrollBar()->value();
QHeaderView *header = view.verticalHeader();
QTest::mouseMove(header);
- QWheelEvent wheelEvent(header->geometry().center(), -720, 0, 0);
+ QPoint pos = header->geometry().center();
+ QWheelEvent wheelEvent(pos, header->viewport()->mapToGlobal(pos), QPoint(), QPoint(0, -720),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QApplication::sendEvent(header->viewport(), &wheelEvent);
int sbValueAfter = view.verticalScrollBar()->value();
QVERIFY(sbValueBefore != sbValueAfter);
@@ -4570,5 +4581,33 @@ void tst_QTableView::taskQTBUG_50171_selectRowAfterSwapColumns()
}
}
+// This has nothing to do with QTableView, but it's convenient to reuse the QtTestTableModel
+#if QT_CONFIG(textmarkdownwriter)
+
+// #define DEBUG_WRITE_OUTPUT
+
+void tst_QTableView::markdownWriter()
+{
+ QtTestTableModel model(2, 3);
+ QString md;
+ {
+ QTextStream stream(&md);
+ QTextMarkdownWriter writer(stream, QTextDocument::MarkdownDialectGitHub);
+ writer.writeTable(&model);
+ }
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(md, QString::fromLatin1("|1 |2 |3 |\n|-------|-------|-------|\n|[0,0,0]|[0,1,0]|[0,2,0]|\n|[1,0,0]|[1,1,0]|[1,2,0]|\n"));
+}
+#endif
+
QTEST_MAIN(tst_QTableView)
#include "tst_qtableview.moc"
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
index c2de5c2761..f640996690 100644
--- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -26,15 +26,12 @@
**
****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <qeventloop.h>
-#include <qlist.h>
-#include <qpair.h>
-#include <qheaderview.h>
-#include <qlineedit.h>
-
-#include <qtablewidget.h>
+#include <QHeaderView>
+#include <QLineEdit>
+#include <QMimeData>
+#include <QSignalSpy>
+#include <QTableWidget>
+#include <QTest>
class QObjectTableItem : public QObject, public QTableWidgetItem
{
@@ -46,11 +43,10 @@ class tst_QTableWidget : public QObject
Q_OBJECT
public:
- tst_QTableWidget();
+ using QObject::QObject;
private slots:
void initTestCase();
- void cleanupTestCase();
void init();
void getSetCheck();
void clear();
@@ -97,12 +93,12 @@ private slots:
#endif
private:
- QTableWidget *testWidget;
+ std::unique_ptr<QTableWidget> testWidget;
};
-typedef QPair<int, int> IntPair;
-typedef QList<int> IntList;
-typedef QList<IntPair> IntIntList;
+using IntPair = QPair<int, int>;
+using IntList = QVector<int>;
+using IntIntList = QVector<IntPair>;
Q_DECLARE_METATYPE(QTableWidgetSelectionRange)
@@ -143,45 +139,36 @@ void tst_QTableWidget::getSetCheck()
obj1.setItem(3, 3, new QTableWidgetItem("3,3"));
obj1.setCurrentItem(var3);
QCOMPARE(var3, obj1.currentItem());
- obj1.setCurrentItem((QTableWidgetItem *)0);
- QCOMPARE((QTableWidgetItem *)0, obj1.currentItem());
- obj1.setItem(0, 0, 0);
- QCOMPARE((QTableWidgetItem *)0, obj1.item(0, 0));
+ obj1.setCurrentItem(nullptr);
+ QCOMPARE(obj1.currentItem(), nullptr);
+ obj1.setItem(0, 0, nullptr);
+ QCOMPARE(obj1.item(0, 0), nullptr);
// const QTableWidgetItem * QTableWidget::itemPrototype()
// void QTableWidget::setItemPrototype(const QTableWidgetItem *)
const QTableWidgetItem *var4 = new QTableWidgetItem;
obj1.setItemPrototype(var4);
QCOMPARE(var4, obj1.itemPrototype());
- obj1.setItemPrototype((QTableWidgetItem *)0);
- QCOMPARE((const QTableWidgetItem *)0, obj1.itemPrototype());
-}
-
-tst_QTableWidget::tst_QTableWidget(): testWidget(0)
-{
+ obj1.setItemPrototype(nullptr);
+ QCOMPARE(obj1.itemPrototype(), nullptr);
}
void tst_QTableWidget::initTestCase()
{
- testWidget = new QTableWidget();
+ testWidget.reset(new QTableWidget);
testWidget->show();
QApplication::setKeyboardInputInterval(100);
}
-void tst_QTableWidget::cleanupTestCase()
-{
- delete testWidget;
-}
-
void tst_QTableWidget::init()
{
testWidget->clear();
testWidget->setRowCount(5);
testWidget->setColumnCount(5);
- for (int row=0; row < testWidget->rowCount(); ++row)
+ for (int row = 0; row < testWidget->rowCount(); ++row)
testWidget->showRow(row);
- for (int column=0; column < testWidget->columnCount(); ++column)
+ for (int column = 0; column < testWidget->columnCount(); ++column)
testWidget->showColumn(column);
}
@@ -319,13 +306,15 @@ void tst_QTableWidget::item()
QCOMPARE(testWidget->rowCount(), rowCount);
QCOMPARE(testWidget->columnCount(), columnCount);
- for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int r = 0; r < testWidget->rowCount(); ++r) {
for (int c = 0; c < testWidget->columnCount(); ++c)
testWidget->setItem(r, c, new QTableWidgetItem(QString::number(r * c + c)));
+ }
- for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int r = 0; r < testWidget->rowCount(); ++r) {
for (int c = 0; c < testWidget->columnCount(); ++c)
QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
+ }
QTableWidgetItem *item = testWidget->item(row, column);
QCOMPARE(!!item, expectItem);
@@ -361,15 +350,17 @@ void tst_QTableWidget::takeItem()
QCOMPARE(testWidget->rowCount(), rowCount);
QCOMPARE(testWidget->columnCount(), columnCount);
- for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int r = 0; r < testWidget->rowCount(); ++r) {
for (int c = 0; c < testWidget->columnCount(); ++c)
testWidget->setItem(r, c, new QTableWidgetItem(QString::number(r * c + c)));
+ }
- for (int r = 0; r < testWidget->rowCount(); ++r)
+ for (int r = 0; r < testWidget->rowCount(); ++r) {
for (int c = 0; c < testWidget->columnCount(); ++c)
QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
+ }
- QSignalSpy spy(testWidget, &QTableWidget::cellChanged);
+ QSignalSpy spy(testWidget.get(), &QTableWidget::cellChanged);
QTableWidgetItem *item = testWidget->takeItem(row, column);
QCOMPARE(!!item, expectItem);
if (expectItem) {
@@ -516,11 +507,11 @@ void tst_QTableWidget::selectedItems()
{
QFETCH(int, rowCount);
QFETCH(int, columnCount);
- QFETCH(IntIntList, createItems);
- QFETCH(IntList, hiddenRows);
- QFETCH(IntList, hiddenColumns);
- QFETCH(QTableWidgetSelectionRange, selectionRange);
- QFETCH(IntIntList, expectedItems);
+ QFETCH(const IntIntList, createItems);
+ QFETCH(const IntList, hiddenRows);
+ QFETCH(const IntList, hiddenColumns);
+ QFETCH(const QTableWidgetSelectionRange, selectionRange);
+ QFETCH(const IntIntList, expectedItems);
// set dimensions and test they are ok
testWidget->setRowCount(rowCount);
@@ -529,15 +520,15 @@ void tst_QTableWidget::selectedItems()
QCOMPARE(testWidget->columnCount(), columnCount);
// create and set items
- foreach (IntPair intPair, createItems) {
+ for (const auto &intPair : createItems) {
testWidget->setItem(intPair.first, intPair.second,
new QTableWidgetItem(QString("Item %1 %2")
.arg(intPair.first).arg(intPair.second)));
}
// hide rows/columns
- foreach (int row, hiddenRows)
+ for (int row : hiddenRows)
testWidget->setRowHidden(row, true);
- foreach (int column, hiddenColumns)
+ for (int column : hiddenColumns)
testWidget->setColumnHidden(column, true);
// make sure we don't have any previous selections hanging around
@@ -557,31 +548,18 @@ void tst_QTableWidget::selectedItems()
}
// check that the correct number of items and the expected items are there
- QList<QTableWidgetItem *> selectedItems = testWidget->selectedItems();
+ const QList<QTableWidgetItem *> selectedItems = testWidget->selectedItems();
QCOMPARE(selectedItems.count(), expectedItems.count());
- foreach (IntPair intPair, expectedItems)
+ for (const auto &intPair : expectedItems)
QVERIFY(selectedItems.contains(testWidget->item(intPair.first, intPair.second)));
// check that setItemSelected agrees with selectedItems
- for (int row = 0; row<testWidget->rowCount(); ++row) {
- bool hidden = false;
- foreach (int hiddenRow, hiddenRows){
- if(hiddenRow == row){
- hidden = true;
- break;
- }
- }
- if (hidden)
+ for (int row = 0; row < testWidget->rowCount(); ++row) {
+ if (hiddenRows.contains(row))
continue;
- for (int column = 0; column<testWidget->columnCount(); ++column) {
- foreach (int hiddenColumn, hiddenColumns){
- if(hiddenColumn == column){
- hidden = true;
- break;
- }
- }
- if (hidden)
+ for (int column = 0; column < testWidget->columnCount(); ++column) {
+ if (hiddenColumns.contains(column))
continue;
QTableWidgetItem *item = testWidget->item(row, column);
@@ -621,11 +599,13 @@ void tst_QTableWidget::removeRow()
QCOMPARE(testWidget->columnCount(), columnCount);
// fill table with items
- for (int r = 0; r < rowCount; ++r)
- for (int c = 0; c < columnCount; ++c)
+ for (int r = 0; r < rowCount; ++r) {
+ const QString rRow = QString::number(r) + QLatin1Char(':');
+ for (int c = 0; c < columnCount; ++c) {
testWidget->setItem(r, c,
- new QTableWidgetItem(
- QString::number(r) + ":" + QString::number(c)));
+ new QTableWidgetItem(rRow + QString::number(c)));
+ }
+ }
// remove and compare the results
testWidget->removeRow(row);
@@ -633,14 +613,18 @@ void tst_QTableWidget::removeRow()
QCOMPARE(testWidget->columnCount(), expectedColumnCount);
// check if the correct items were removed
- for (int r = 0; r < expectedRowCount; ++r)
- for (int c = 0; c < expectedColumnCount; ++c)
+ for (int r = 0; r < expectedRowCount; ++r) {
+ const QString rRow = QString::number(r < row ? r : r + 1) +
+ QLatin1Char(':');
+ for (int c = 0; c < expectedColumnCount; ++c) {
if (r < row)
QCOMPARE(testWidget->item(r, c)->text(),
- QString::number(r) + ":" + QString::number(c));
+ rRow + QString::number(c));
else
QCOMPARE(testWidget->item(r, c)->text(),
- QString::number(r + 1) + ":" + QString::number(c));
+ rRow + QString::number(c));
+ }
+ }
}
void tst_QTableWidget::removeColumn_data()
@@ -673,11 +657,14 @@ void tst_QTableWidget::removeColumn()
QCOMPARE(testWidget->columnCount(), columnCount);
// fill table with items
- for (int r = 0; r < rowCount; ++r)
- for (int c = 0; c < columnCount; ++c)
+ for (int r = 0; r < rowCount; ++r) {
+ const QString rStr = QString::number(r) + QLatin1Char(':');
+ for (int c = 0; c < columnCount; ++c) {
testWidget->setItem(r, c,
new QTableWidgetItem(
- QString::number(r) + ":" + QString::number(c)));
+ rStr + QString::number(c)));
+ }
+ }
// remove and compare the results
testWidget->removeColumn(column);
@@ -686,14 +673,17 @@ void tst_QTableWidget::removeColumn()
// check if the correct items were removed
- for (int r = 0; r < expectedRowCount; ++r)
- for (int c = 0; c < expectedColumnCount; ++c)
+ for (int r = 0; r < expectedRowCount; ++r) {
+ const QString rStr = QString::number(r) + QLatin1Char(':');
+ for (int c = 0; c < expectedColumnCount; ++c) {
if (c < column)
QCOMPARE(testWidget->item(r, c)->text(),
- QString::number(r) + ":" + QString::number(c));
+ rStr + QString::number(c));
else
QCOMPARE(testWidget->item(r, c)->text(),
- QString::number(r) + ":" + QString::number(c + 1));
+ rStr + QString::number(c + 1));
+ }
+ }
}
void tst_QTableWidget::insertRow_data()
@@ -819,7 +809,7 @@ void tst_QTableWidget::itemOwnership()
item = new QObjectTableItem();
testWidget->setItem(0, 0, item);
delete item;
- QCOMPARE(testWidget->item(0, 0), (QTableWidgetItem *)0);
+ QCOMPARE(testWidget->item(0, 0), nullptr);
//delete vertical headeritem from outside
headerItem = new QObjectTableItem();
@@ -887,7 +877,7 @@ void tst_QTableWidget::sortItems_data()
{
QTest::addColumn<int>("rowCount");
QTest::addColumn<int>("columnCount");
- QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<Qt::SortOrder>("sortOrder");
QTest::addColumn<int>("sortColumn");
QTest::addColumn<QStringList>("initial");
QTest::addColumn<QStringList>("expected");
@@ -897,7 +887,7 @@ void tst_QTableWidget::sortItems_data()
QTest::newRow("ascending")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
<< "0" << "a" << "o" << "8" << "k"
@@ -915,7 +905,7 @@ void tst_QTableWidget::sortItems_data()
QTest::newRow("descending")
<< 4 << 5
- << static_cast<int>(Qt::DescendingOrder)
+ << Qt::DescendingOrder
<< 0
<< (QStringList()
<< "0" << "a" << "o" << "8" << "k"
@@ -933,154 +923,151 @@ void tst_QTableWidget::sortItems_data()
QTest::newRow("empty table")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
- << 0 << 0 << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0)
+ << QString() << QString() << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString())
<< (QStringList()
- << 0 << 0 << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0)
+ << QString() << QString() << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString())
<< IntList()
<< IntList()
<< IntList();
-
QTest::newRow("half-empty table")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
- << "0" << 0 << 0 << 0 << 0
- << "3" << "d" << 0 << 0 << 0
- << "2" << "c" << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0)
+ << "0" << QString() << QString() << QString() << QString()
+ << "3" << "d" << QString() << QString() << QString()
+ << "2" << "c" << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString())
<< (QStringList()
- << "0" << 0 << 0 << 0 << 0
- << "2" << "c" << 0 << 0 << 0
- << "3" << "d" << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0)
+ << "0" << QString() << QString() << QString() << QString()
+ << "2" << "c" << QString() << QString() << QString()
+ << "3" << "d" << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString())
<< (IntList() << 0 << 2 << 1)
<< IntList()
<< IntList();
QTest::newRow("empty column, should not sort.")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 3
<< (QStringList()
- << "0" << 0 << 0 << 0 << 0
- << "3" << "d" << 0 << 0 << 0
- << "2" << "c" << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0)
+ << "0" << QString() << QString() << QString() << QString()
+ << "3" << "d" << QString() << QString() << QString()
+ << "2" << "c" << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString())
<< (QStringList()
- << "0" << 0 << 0 << 0 << 0
- << "3" << "d" << 0 << 0 << 0
- << "2" << "c" << 0 << 0 << 0
- << 0 << 0 << 0 << 0 << 0)
+ << "0" << QString() << QString() << QString() << QString()
+ << "3" << "d" << QString() << QString() << QString()
+ << "2" << "c" << QString() << QString() << QString()
+ << QString() << QString() << QString() << QString() << QString())
<< IntList()
<< IntList()
<< IntList();
QTest::newRow("descending with null cell, the null cell should be placed at the bottom")
<< 4 << 5
- << static_cast<int>(Qt::DescendingOrder)
+ << Qt::DescendingOrder
<< 0
<< (QStringList()
- << "0" << "a" << "o" << "8" << "k"
- << "3" << "d" << "k" << "o" << "6"
- << "2" << "c" << "9" << "y" << "8"
- << 0 << "b" << "7" << "3" << "u")
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << QString() << "b" << "7" << "3" << "u")
<< (QStringList()
- << "3" << "d" << "k" << "o" << "6"
- << "2" << "c" << "9" << "y" << "8"
- << "0" << "a" << "o" << "8" << "k"
- << 0 << "b" << "7" << "3" << "u")
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << "0" << "a" << "o" << "8" << "k"
+ << QString() << "b" << "7" << "3" << "u")
<< (IntList() << 2 << 0 << 1)
<< IntList()
<< IntList();
QTest::newRow("ascending with null cell, the null cell should be placed at the bottom")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
- << "0" << "a" << "o" << "8" << "k"
- << "3" << "d" << "k" << "o" << "6"
- << "2" << "c" << "9" << "y" << "8"
- << 0 << "b" << "7" << "3" << "u")
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << "2" << "c" << "9" << "y" << "8"
+ << QString() << "b" << "7" << "3" << "u")
<< (QStringList()
- << "0" << "a" << "o" << "8" << "k"
- << "2" << "c" << "9" << "y" << "8"
- << "3" << "d" << "k" << "o" << "6"
- << 0 << "b" << "7" << "3" << "u")
+ << "0" << "a" << "o" << "8" << "k"
+ << "2" << "c" << "9" << "y" << "8"
+ << "3" << "d" << "k" << "o" << "6"
+ << QString() << "b" << "7" << "3" << "u")
<< (IntList() << 0 << 2 << 1)
<< IntList()
<< IntList();
QTest::newRow("ascending with null cells, the null cells should be placed at the bottom")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
- << "3" << "d" << "k" << "o" << "6"
- << "0" << "a" << "o" << "8" << "k"
- << 0 << "c" << "9" << "y" << "8"
- << 0 << "b" << "7" << "3" << "u")
+ << "3" << "d" << "k" << "o" << "6"
+ << "0" << "a" << "o" << "8" << "k"
+ << QString() << "c" << "9" << "y" << "8"
+ << QString() << "b" << "7" << "3" << "u")
<< (QStringList()
- << "0" << "a" << "o" << "8" << "k"
- << "3" << "d" << "k" << "o" << "6"
- << 0 << "c" << "9" << "y" << "8"
- << 0 << "b" << "7" << "3" << "u")
+ << "0" << "a" << "o" << "8" << "k"
+ << "3" << "d" << "k" << "o" << "6"
+ << QString() << "c" << "9" << "y" << "8"
+ << QString() << "b" << "7" << "3" << "u")
<< (IntList() << 1 << 0)
<< IntList()
<< IntList();
QTest::newRow("ascending... Check a bug in PersistentIndexes")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
<< "3" << "c" << "9" << "y" << "8"
<< "2" << "b" << "7" << "3" << "u"
<< "4" << "d" << "k" << "o" << "6"
- << "1" << "a" << "o" << "8" << "k"
- )
+ << "1" << "a" << "o" << "8" << "k")
<< (QStringList()
<< "1" << "a" << "o" << "8" << "k"
<< "2" << "b" << "7" << "3" << "u"
<< "3" << "c" << "9" << "y" << "8"
- << "4" << "d" << "k" << "o" << "6"
- )
+ << "4" << "d" << "k" << "o" << "6")
<< (IntList() << 2 << 1 << 3 << 0)
<< IntList()
<< IntList();
QTest::newRow("ascending with some null cells inbetween")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
- << 0 << "a" << "o" << "8" << "k"
- << "2" << "c" << "9" << "y" << "8"
- << 0 << "d" << "k" << "o" << "6"
- << "1" << "b" << "7" << "3" << "u")
+ << QString() << "a" << "o" << "8" << "k"
+ << "2" << "c" << "9" << "y" << "8"
+ << QString() << "d" << "k" << "o" << "6"
+ << "1" << "b" << "7" << "3" << "u")
<< (QStringList()
- << "1" << "b" << "7" << "3" << "u"
- << "2" << "c" << "9" << "y" << "8"
- << 0 << "a" << "o" << "8" << "k"
- << 0 << "d" << "k" << "o" << "6")
+ << "1" << "b" << "7" << "3" << "u"
+ << "2" << "c" << "9" << "y" << "8"
+ << QString() << "a" << "o" << "8" << "k"
+ << QString() << "d" << "k" << "o" << "6")
<< (IntList() << 1 << 0)
<< IntList()
<< IntList();
QTest::newRow("ascending hidden")
<< 4 << 5
- << static_cast<int>(Qt::AscendingOrder)
+ << Qt::AscendingOrder
<< 0
<< (QStringList()
<< "0" << "a" << "o" << "8" << "k"
@@ -1098,7 +1085,7 @@ void tst_QTableWidget::sortItems_data()
QTest::newRow("descending hidden")
<< 4 << 5
- << static_cast<int>(Qt::DescendingOrder)
+ << Qt::DescendingOrder
<< 0
<< (QStringList()
<< "0" << "a" << "o" << "8" << "k"
@@ -1119,7 +1106,7 @@ void tst_QTableWidget::sortItems()
{
QFETCH(int, rowCount);
QFETCH(int, columnCount);
- QFETCH(int, sortOrder);
+ QFETCH(Qt::SortOrder, sortOrder);
QFETCH(int, sortColumn);
QFETCH(QStringList, initial);
QFETCH(QStringList, expected);
@@ -1131,13 +1118,13 @@ void tst_QTableWidget::sortItems()
testWidget->setColumnCount(columnCount);
QAbstractItemModel *model = testWidget->model();
- QList<QPersistentModelIndex> persistent;
+ QVector<QPersistentModelIndex> persistent;
int ti = 0;
for (int r = 0; r < rowCount; ++r) {
for (int c = 0; c < columnCount; ++c) {
- QString str = initial.at(ti++);
- if (!str.isNull()) {
+ QString str = initial.at(ti++);
+ if (!str.isEmpty()) {
testWidget->setItem(r, c, new QTableWidgetItem(str));
}
}
@@ -1150,7 +1137,7 @@ void tst_QTableWidget::sortItems()
QCOMPARE(testWidget->verticalHeader()->hiddenSectionCount(), initialHidden.count());
- testWidget->sortItems(sortColumn, static_cast<Qt::SortOrder>(sortOrder));
+ testWidget->sortItems(sortColumn, sortOrder);
int te = 0;
for (int i = 0; i < rows.count(); ++i) {
@@ -1175,7 +1162,7 @@ void tst_QTableWidget::setItemWithSorting_data()
{
QTest::addColumn<int>("rowCount");
QTest::addColumn<int>("columnCount");
- QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<Qt::SortOrder>("sortOrder");
QTest::addColumn<int>("sortColumn");
QTest::addColumn<QStringList>("initialValues");
QTest::addColumn<int>("row");
@@ -1187,7 +1174,7 @@ void tst_QTableWidget::setItemWithSorting_data()
QTest::newRow("2x1 no change (ascending)")
<< 2 << 1
- << static_cast<int>(Qt::AscendingOrder) << 0
+ << Qt::AscendingOrder << 0
<< (QStringList() << "0" << "1")
<< 1 << 0 << "2"
<< (QStringList() << "0" << "2")
@@ -1195,7 +1182,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< false;
QTest::newRow("2x1 no change (descending)")
<< 2 << 1
- << static_cast<int>(Qt::DescendingOrder) << 0
+ << Qt::DescendingOrder << 0
<< (QStringList() << "1" << "0")
<< 0 << 0 << "2"
<< (QStringList() << "2" << "0")
@@ -1203,7 +1190,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< false;
QTest::newRow("2x1 reorder (ascending)")
<< 2 << 1
- << static_cast<int>(Qt::AscendingOrder) << 0
+ << Qt::AscendingOrder << 0
<< (QStringList() << "0" << "1")
<< 0 << 0 << "2"
<< (QStringList() << "1" << "2")
@@ -1211,7 +1198,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< true;
QTest::newRow("2x1 reorder (descending)")
<< 2 << 1
- << static_cast<int>(Qt::DescendingOrder) << 0
+ << Qt::DescendingOrder << 0
<< (QStringList() << "1" << "0")
<< 1 << 0 << "2"
<< (QStringList() << "2" << "1")
@@ -1219,7 +1206,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< true;
QTest::newRow("2x2 no change (ascending)")
<< 2 << 2
- << static_cast<int>(Qt::AscendingOrder) << 0
+ << Qt::AscendingOrder << 0
<< (QStringList()
<< "0" << "00"
<< "1" << "11")
@@ -1231,7 +1218,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< false;
QTest::newRow("2x2 reorder (ascending)")
<< 2 << 2
- << static_cast<int>(Qt::AscendingOrder) << 0
+ << Qt::AscendingOrder << 0
<< (QStringList()
<< "0" << "00"
<< "1" << "11")
@@ -1243,7 +1230,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< true;
QTest::newRow("2x2 reorder (ascending, sortColumn = 1)")
<< 2 << 2
- << static_cast<int>(Qt::AscendingOrder) << 1
+ << Qt::AscendingOrder << 1
<< (QStringList()
<< "00" << "0"
<< "11" << "1")
@@ -1255,7 +1242,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< true;
QTest::newRow("2x2 no change (column != sortColumn)")
<< 2 << 2
- << static_cast<int>(Qt::AscendingOrder) << 1
+ << Qt::AscendingOrder << 1
<< (QStringList()
<< "00" << "0"
<< "11" << "1")
@@ -1267,7 +1254,7 @@ void tst_QTableWidget::setItemWithSorting_data()
<< false;
QTest::newRow("8x4 reorder (ascending, sortColumn = 3)")
<< 8 << 4
- << static_cast<int>(Qt::AscendingOrder) << 3
+ << Qt::AscendingOrder << 3
<< (QStringList()
<< "q" << "v" << "u" << "0"
<< "e" << "j" << "i" << "10"
@@ -1293,9 +1280,13 @@ void tst_QTableWidget::setItemWithSorting_data()
void tst_QTableWidget::setItemWithSorting()
{
+ static int dummy1 = qRegisterMetaType<QList<QPersistentModelIndex>>();
+ static int dummy2 = qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
+ Q_UNUSED(dummy1);
+ Q_UNUSED(dummy2);
QFETCH(int, rowCount);
QFETCH(int, columnCount);
- QFETCH(int, sortOrder);
+ QFETCH(Qt::SortOrder, sortOrder);
QFETCH(int, sortColumn);
QFETCH(QStringList, initialValues);
QFETCH(int, row);
@@ -1309,7 +1300,7 @@ void tst_QTableWidget::setItemWithSorting()
QTableWidget w(rowCount, columnCount);
QAbstractItemModel *model = w.model();
- QList<QPersistentModelIndex> persistent;
+ QVector<QPersistentModelIndex> persistent;
int ti = 0;
for (int r = 0; r < rowCount; ++r) {
@@ -1320,11 +1311,11 @@ void tst_QTableWidget::setItemWithSorting()
persistent << model->index(r, sortColumn);
}
- w.sortItems(sortColumn, static_cast<Qt::SortOrder>(sortOrder));
+ w.sortItems(sortColumn, sortOrder);
w.setSortingEnabled(true);
- QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
- QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
+ QSignalSpy dataChangedSpy(model, &QAbstractItemModel::dataChanged);
+ QSignalSpy layoutChangedSpy(model, &QAbstractItemModel::layoutChanged);
if (i == 0) {
// set a new item
@@ -1376,18 +1367,18 @@ public:
void tst_QTableWidget::itemData()
{
QTableWidgetDataChanged widget(2, 2);
- widget.setItem(0, 0, new QTableWidgetItem());
+ widget.setItem(0, 0, new QTableWidgetItem);
QTableWidgetItem *item = widget.item(0, 0);
QVERIFY(item);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setData(Qt::DisplayRole, QString("0"));
QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item->setData(Qt::CheckStateRole, Qt::PartiallyChecked);
- QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
for (int i = 0; i < 4; ++i)
{
item->setData(Qt::UserRole + i, QString::number(i + 1));
- QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
}
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
@@ -1399,7 +1390,7 @@ void tst_QTableWidget::setItemData()
{
QTableWidgetDataChanged table(10, 10);
table.setSortingEnabled(false);
- QSignalSpy dataChangedSpy(table.model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+ QSignalSpy dataChangedSpy(table.model(), &QAbstractItemModel::dataChanged);
QTableWidgetItem *item = new QTableWidgetItem;
table.setItem(0, 0, item);
@@ -1432,11 +1423,11 @@ void tst_QTableWidget::cellWidget()
QTableWidget table(10, 10);
QWidget widget;
- QCOMPARE(table.cellWidget(5, 5), static_cast<QWidget*>(0));
+ QCOMPARE(table.cellWidget(5, 5), nullptr);
table.setCellWidget(5, 5, &widget);
QCOMPARE(table.cellWidget(5, 5), &widget);
table.removeCellWidget(5, 5);
- QCOMPARE(table.cellWidget(5, 5), static_cast<QWidget*>(0));
+ QCOMPARE(table.cellWidget(5, 5), nullptr);
}
void tst_QTableWidget::cellWidgetGeometry()
@@ -1463,27 +1454,29 @@ void tst_QTableWidget::cellWidgetGeometry()
void tst_QTableWidget::sizeHint_data()
{
- QTest::addColumn<int>("scrollBarPolicy");
+ QTest::addColumn<Qt::ScrollBarPolicy>("scrollBarPolicy");
QTest::addColumn<QSize>("viewSize");
- QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize();
- QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize();
+ QTest::newRow("ScrollBarAlwaysOn") << Qt::ScrollBarAlwaysOn << QSize();
+ QTest::newRow("ScrollBarAlwaysOff") << Qt::ScrollBarAlwaysOff << QSize();
// make sure the scrollbars are shown by resizing the view to 40x40
- QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40);
- QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000);
+ QTest::newRow("ScrollBarAsNeeded (40x40)") << Qt::ScrollBarAsNeeded << QSize(40, 40);
+ QTest::newRow("ScrollBarAsNeeded (1000x1000)") << Qt::ScrollBarAsNeeded << QSize(1000, 1000);
}
void tst_QTableWidget::sizeHint()
{
- QFETCH(int, scrollBarPolicy);
+ QFETCH(Qt::ScrollBarPolicy, scrollBarPolicy);
QFETCH(QSize, viewSize);
QTableWidget view(2, 2);
view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
- view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
- view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
- for (int r = 0 ; r < view.rowCount(); ++r)
+ view.setVerticalScrollBarPolicy(scrollBarPolicy);
+ view.setHorizontalScrollBarPolicy(scrollBarPolicy);
+ for (int r = 0 ; r < view.rowCount(); ++r) {
+ const QString rStr = QString::number(r) + QLatin1Char('/');
for (int c = 0 ; c < view.columnCount(); ++c)
- view.setItem(r, c, new QTableWidgetItem(QString("%1/%2").arg(r).arg(c)));
+ view.setItem(r, c, new QTableWidgetItem(rStr + QString::number(c)));
+ }
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@@ -1520,7 +1513,7 @@ void tst_QTableWidget::task231094()
if (y == 1)
twi->setFlags(Qt::ItemIsEnabled);
else
- twi->setFlags(0);
+ twi->setFlags({});
tw.setItem(y, x, twi);
}
}
@@ -1558,15 +1551,15 @@ void tst_QTableWidget::task262056_sortDuplicate()
testWidget->setColumnCount(2);
testWidget->setRowCount(8);
testWidget->setSortingEnabled(true);
- QStringList items = (QStringList() << "AAA" << "BBB" << "CCC" << "CCC" << "DDD"\
- << "EEE" << "FFF" << "GGG");
- for (int i = 0; i<8; i++ ) {
+ const QStringList items({"AAA", "BBB", "CCC", "CCC", "DDD",
+ "EEE", "FFF", "GGG"});
+ for (int i = 0; i < 8; i++ ) {
QTableWidgetItem *twi = new QTableWidgetItem(items.at(i));
- testWidget->setItem(i,0,twi);
- testWidget->setItem(i,1,new QTableWidgetItem(QLatin1String("item ") + QString::number(i)));
+ testWidget->setItem(i, 0, twi);
+ testWidget->setItem(i, 1, new QTableWidgetItem(QLatin1String("item ") + QString::number(i)));
}
testWidget->sortItems(0, Qt::AscendingOrder);
- QSignalSpy layoutChangedSpy(testWidget->model(), SIGNAL(layoutChanged()));
+ QSignalSpy layoutChangedSpy(testWidget->model(), &QAbstractItemModel::layoutChanged);
testWidget->item(3,0)->setBackground(Qt::red);
QCOMPARE(layoutChangedSpy.count(),0);
@@ -1586,18 +1579,14 @@ void tst_QTableWidget::itemWithHeaderItems()
QTableWidgetItem *item1_0 = new QTableWidgetItem(QTableWidgetItem::UserType);
table.setItem(1, 0, item1_0);
- QCOMPARE(table.item(0, 1), static_cast<QTableWidgetItem *>(0));
+ QCOMPARE(table.item(0, 1), nullptr);
}
class TestTableWidget : public QTableWidget
{
Q_OBJECT
public:
- TestTableWidget(int rows, int columns, QWidget *parent = 0)
- : QTableWidget(rows, columns, parent)
- {
- }
-
+ using QTableWidget::QTableWidget;
using QTableWidget::mimeData;
using QTableWidget::indexFromItem;
using QTableWidget::keyPressEvent;
@@ -1661,18 +1650,19 @@ void tst_QTableWidget::selectedRowAfterSorting()
{
TestTableWidget table(3,3);
table.setSelectionBehavior(QAbstractItemView::SelectRows);
- for (int r = 0; r < 3; r++)
+ for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++)
- table.setItem(r,c,new QTableWidgetItem(QStringLiteral("0")));
+ table.setItem(r, c, new QTableWidgetItem(QStringLiteral("0")));
+ }
QHeaderView *localHorizontalHeader = table.horizontalHeader();
localHorizontalHeader->setSortIndicator(1,Qt::DescendingOrder);
table.setProperty("sortingEnabled",true);
table.selectRow(1);
table.item(1,1)->setText("9");
QCOMPARE(table.selectedItems().count(),3);
- foreach (QTableWidgetItem *item, table.selectedItems()) {
- QCOMPARE(item->row(),0);
- }
+ const auto selectedItems = table.selectedItems();
+ for (QTableWidgetItem *item : selectedItems)
+ QCOMPARE(item->row(), 0);
}
void tst_QTableWidget::search()
@@ -1717,10 +1707,11 @@ void tst_QTableWidget::search()
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void tst_QTableWidget::clearItemData()
{
- QTableWidget table(3,3);
- for (int r = 0; r < 3; r++)
+ QTableWidget table(3, 3);
+ for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++)
- table.setItem(r,c,new QTableWidgetItem(QStringLiteral("0")));
+ table.setItem(r, c, new QTableWidgetItem(QStringLiteral("0")));
+ }
QSignalSpy dataChangeSpy(table.model(), &QAbstractItemModel::dataChanged);
QVERIFY(dataChangeSpy.isValid());
QVERIFY(!table.model()->clearItemData(QModelIndex()));
diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
index 33d4f3bf91..0d97974b90 100644
--- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
@@ -1999,10 +1999,10 @@ void tst_QTreeWidget::itemData()
item.setData(0, Qt::DisplayRole, QString("0"));
QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item.setData(0, Qt::CheckStateRole, Qt::PartiallyChecked);
- QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
for (int i = 0; i < 4; ++i) {
item.setData(0, Qt::UserRole + i, QString::number(i + 1));
- QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
}
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro
index 73fd934502..af85a2bd13 100644
--- a/tests/auto/widgets/kernel/kernel.pro
+++ b/tests/auto/widgets/kernel/kernel.pro
@@ -22,5 +22,3 @@ SUBDIRS=\
darwin:SUBDIRS -= \ # Uses native recognizers
qgesturerecognizer \
-
-SUBDIRS -= qsound
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index 3d68e42baf..0d62c2cd4b 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -70,7 +70,7 @@ private slots:
void shortcutFromKeyEvent(); // QTBUG-48325
private:
- int m_lastEventType;
+ QEvent::Type m_lastEventType;
const int m_keyboardScheme;
QAction *m_lastAction;
};
@@ -82,7 +82,7 @@ tst_QAction::tst_QAction()
void tst_QAction::init()
{
- m_lastEventType = 0;
+ m_lastEventType = QEvent::None;
m_lastAction = nullptr;
}
@@ -94,23 +94,23 @@ void tst_QAction::cleanup()
// Testing get/set functions
void tst_QAction::getSetCheck()
{
- QAction obj1(0);
+ QAction obj1(nullptr);
// QActionGroup * QAction::actionGroup()
// void QAction::setActionGroup(QActionGroup *)
- QActionGroup *var1 = new QActionGroup(0);
+ QActionGroup *var1 = new QActionGroup(nullptr);
obj1.setActionGroup(var1);
QCOMPARE(var1, obj1.actionGroup());
- obj1.setActionGroup((QActionGroup *)0);
- QCOMPARE((QActionGroup *)0, obj1.actionGroup());
+ obj1.setActionGroup(nullptr);
+ QCOMPARE(obj1.actionGroup(), nullptr);
delete var1;
// QMenu * QAction::menu()
// void QAction::setMenu(QMenu *)
- QMenu *var2 = new QMenu(0);
+ QMenu *var2 = new QMenu(nullptr);
obj1.setMenu(var2);
QCOMPARE(var2, obj1.menu());
- obj1.setMenu((QMenu *)0);
- QCOMPARE((QMenu *)0, obj1.menu());
+ obj1.setMenu(nullptr);
+ QCOMPARE(obj1.menu(), nullptr);
delete var2;
QCOMPARE(obj1.priority(), QAction::NormalPriority);
@@ -148,7 +148,7 @@ void tst_QAction::setText()
{
QFETCH(QString, text);
- QAction action(0);
+ QAction action(nullptr);
action.setText(text);
QCOMPARE(action.text(), text);
@@ -161,7 +161,7 @@ void tst_QAction::setIconText()
{
QFETCH(QString, iconText);
- QAction action(0);
+ QAction action(nullptr);
action.setIconText(iconText);
QCOMPARE(action.iconText(), iconText);
@@ -171,7 +171,7 @@ void tst_QAction::setIconText()
void tst_QAction::setUnknownFont() // QTBUG-42728
{
- QAction action(0);
+ QAction action(nullptr);
QFont font("DoesNotExist", 11);
action.setFont(font);
@@ -182,17 +182,17 @@ void tst_QAction::setUnknownFont() // QTBUG-42728
void tst_QAction::updateState(QActionEvent *e)
{
if (!e) {
- m_lastEventType = 0;
- m_lastAction = 0;
+ m_lastEventType = QEvent::None;
+ m_lastAction = nullptr;
} else {
- m_lastEventType = (int)e->type();
+ m_lastEventType = e->type();
m_lastAction = e->action();
}
}
void tst_QAction::actionEvent()
{
- QAction a(0);
+ QAction a(nullptr);
a.setText("action text");
// add action
@@ -202,33 +202,33 @@ void tst_QAction::actionEvent()
testWidget.addAction(&a);
qApp->processEvents();
- QCOMPARE(m_lastEventType, (int)QEvent::ActionAdded);
+ QCOMPARE(m_lastEventType, QEvent::ActionAdded);
QCOMPARE(m_lastAction, &a);
// change action
a.setText("new action text");
qApp->processEvents();
- QCOMPARE(m_lastEventType, (int)QEvent::ActionChanged);
+ QCOMPARE(m_lastEventType, QEvent::ActionChanged);
QCOMPARE(m_lastAction, &a);
// remove action
testWidget.removeAction(&a);
qApp->processEvents();
- QCOMPARE(m_lastEventType, (int)QEvent::ActionRemoved);
+ QCOMPARE(m_lastEventType, QEvent::ActionRemoved);
QCOMPARE(m_lastAction, &a);
}
//basic testing of standard keys
void tst_QAction::setStandardKeys()
{
- QAction act(0);
+ QAction act(nullptr);
act.setShortcut(QKeySequence("CTRL+L"));
QList<QKeySequence> list;
act.setShortcuts(list);
act.setShortcuts(QKeySequence::Copy);
- QCOMPARE(act.shortcut(), act.shortcuts().first());
+ QCOMPARE(act.shortcut(), act.shortcuts().constFirst());
QList<QKeySequence> expected;
const QKeySequence ctrlC = QKeySequence(QStringLiteral("CTRL+C"));
@@ -263,7 +263,7 @@ void tst_QAction::alternateShortcuts()
QList<QKeySequence> shlist = QList<QKeySequence>() << QKeySequence("CTRL+P") << QKeySequence("CTRL+A");
act.setShortcuts(shlist);
- QSignalSpy spy(&act, SIGNAL(triggered()));
+ QSignalSpy spy(&act, &QAction::triggered);
act.setAutoRepeat(true);
QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier);
@@ -322,7 +322,7 @@ void tst_QAction::enabledVisibleInteraction()
testWidget.show();
QApplication::setActiveWindow(&testWidget);
- QAction act(0);
+ QAction act(nullptr);
// check defaults
QVERIFY(act.isEnabled());
QVERIFY(act.isVisible());
@@ -370,7 +370,7 @@ void tst_QAction::task229128TriggeredSignalWithoutActiongroup()
{
// test without a group
const QScopedPointer<QAction> actionWithoutGroup(new QAction("Test", nullptr));
- QSignalSpy spyWithoutGroup(actionWithoutGroup.data(), SIGNAL(triggered(bool)));
+ QSignalSpy spyWithoutGroup(actionWithoutGroup.data(), QOverload<bool>::of(&QAction::triggered));
QCOMPARE(spyWithoutGroup.count(), 0);
actionWithoutGroup->trigger();
// signal should be emitted
@@ -388,7 +388,7 @@ void tst_QAction::task229128TriggeredSignalWithoutActiongroup()
void tst_QAction::task229128TriggeredSignalWhenInActiongroup()
{
- QActionGroup ag(0);
+ QActionGroup ag(nullptr);
QAction *action = new QAction("Test", &ag);
QAction *checkedAction = new QAction("Test 2", &ag);
ag.addAction(action);
@@ -397,8 +397,8 @@ void tst_QAction::task229128TriggeredSignalWhenInActiongroup()
checkedAction->setCheckable(true);
checkedAction->setChecked(true);
- QSignalSpy actionSpy(checkedAction, SIGNAL(triggered(bool)));
- QSignalSpy actionGroupSpy(&ag, SIGNAL(triggered(QAction*)));
+ QSignalSpy actionSpy(checkedAction, QOverload<bool>::of(&QAction::triggered));
+ QSignalSpy actionGroupSpy(&ag, QOverload<QAction*>::of(&QActionGroup::triggered));
QCOMPARE(actionGroupSpy.count(), 0);
QCOMPARE(actionSpy.count(), 0);
checkedAction->trigger();
@@ -513,10 +513,10 @@ void tst_QAction::disableShortcutsWithBlockedWidgets()
class ShortcutOverrideWidget : public QWidget
{
public:
- ShortcutOverrideWidget(QWidget *parent = 0) : QWidget(parent), shortcutOverrideCount(0) {}
- int shortcutOverrideCount;
+ using QWidget::QWidget;
+ int shortcutOverrideCount = 0;
protected:
- bool event(QEvent *e)
+ bool event(QEvent *e) override
{
if (e->type() == QEvent::ShortcutOverride)
++shortcutOverrideCount;
diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
index 52ca10d31f..524040d003 100644
--- a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
+++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
@@ -41,6 +41,7 @@ private slots:
void enabledPropagation();
void visiblePropagation();
void exclusive();
+ void exclusiveOptional();
void separators();
void testActionInTwoQActionGroup();
void unCheckCurrentAction();
@@ -48,11 +49,11 @@ private slots:
void tst_QActionGroup::enabledPropagation()
{
- QActionGroup testActionGroup( 0 );
+ QActionGroup testActionGroup(nullptr);
QAction* childAction = new QAction( &testActionGroup );
QAction* anotherChildAction = new QAction( &testActionGroup );
- QAction* freeAction = new QAction(0);
+ QAction* freeAction = new QAction(nullptr);
QVERIFY( testActionGroup.isEnabled() );
QVERIFY( childAction->isEnabled() );
@@ -87,11 +88,11 @@ void tst_QActionGroup::enabledPropagation()
void tst_QActionGroup::visiblePropagation()
{
- QActionGroup testActionGroup( 0 );
+ QActionGroup testActionGroup(nullptr);
QAction* childAction = new QAction( &testActionGroup );
QAction* anotherChildAction = new QAction( &testActionGroup );
- QAction* freeAction = new QAction(0);
+ QAction* freeAction = new QAction(nullptr);
QVERIFY( testActionGroup.isVisible() );
QVERIFY( childAction->isVisible() );
@@ -124,7 +125,7 @@ void tst_QActionGroup::visiblePropagation()
void tst_QActionGroup::exclusive()
{
- QActionGroup group(0);
+ QActionGroup group(nullptr);
group.setExclusive(false);
QVERIFY( !group.isExclusive() );
@@ -151,6 +152,52 @@ void tst_QActionGroup::exclusive()
QVERIFY( !actThree->isChecked() );
}
+void tst_QActionGroup::exclusiveOptional()
+{
+ QActionGroup group(0);
+ group.setExclusive(true);
+ QVERIFY( group.isExclusive() );
+
+ QAction* actOne = new QAction( &group );
+ actOne->setCheckable( true );
+ QAction* actTwo = new QAction( &group );
+ actTwo->setCheckable( true );
+ QAction* actThree = new QAction( &group );
+ actThree->setCheckable( true );
+
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actOne->trigger();
+ QVERIFY( actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actOne->trigger();
+ QVERIFY( actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ group.setExclusionPolicy( QActionGroup::ExclusionPolicy::ExclusiveOptional );
+ QVERIFY( group.isExclusive() );
+
+ actOne->trigger();
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actTwo->trigger();
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actTwo->trigger();
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+}
+
void tst_QActionGroup::separators()
{
QMainWindow mw;
@@ -166,26 +213,24 @@ void tst_QActionGroup::separators()
separator->setSeparator(true);
actGroup.addAction(separator);
- QListIterator<QAction*> it(actGroup.actions());
- while (it.hasNext())
- menu.addAction(it.next());
+ menu.addActions(actGroup.actions());
- QCOMPARE((int)menu.actions().size(), 2);
+ QCOMPARE(menu.actions().size(), 2);
- it = QListIterator<QAction*>(actGroup.actions());
- while (it.hasNext())
- menu.removeAction(it.next());
+ const auto removeActions = [&menu](const QList<QAction *> &actions) {
+ for (QAction *action : actions)
+ menu.removeAction(action);
+ };
+ removeActions(actGroup.actions());
- QCOMPARE((int)menu.actions().size(), 0);
+ QCOMPARE(menu.actions().size(), 0);
action = new QAction(&actGroup);
action->setText("test two");
- it = QListIterator<QAction*>(actGroup.actions());
- while (it.hasNext())
- menu.addAction(it.next());
+ menu.addActions(actGroup.actions());
- QCOMPARE((int)menu.actions().size(), 3);
+ QCOMPARE(menu.actions().size(), 3);
}
void tst_QActionGroup::testActionInTwoQActionGroup()
@@ -205,7 +250,7 @@ void tst_QActionGroup::testActionInTwoQActionGroup()
void tst_QActionGroup::unCheckCurrentAction()
{
- QActionGroup group(0);
+ QActionGroup group(nullptr);
QAction action1(&group) ,action2(&group);
action1.setCheckable(true);
action2.setCheckable(true);
diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST
index d7de7bf16e..c68c7d6b14 100644
--- a/tests/auto/widgets/kernel/qapplication/BLACKLIST
+++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST
@@ -1,4 +1,3 @@
[touchEventPropagation]
# QTBUG-66745
-opensuse
opensuse-leap
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index 7ee085b81c..367a5767c4 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -890,7 +890,9 @@ void tst_QApplication::libraryPaths()
QStringList actual = QApplication::libraryPaths();
actual.sort();
- QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
+ QStringList expected;
+ expected << testDir << appDirPath;
+ expected = QSet<QString>(expected.constBegin(), expected.constEnd()).values();
expected.sort();
QVERIFY2(isPathListIncluded(actual, expected),
@@ -907,7 +909,9 @@ void tst_QApplication::libraryPaths()
QStringList actual = QApplication::libraryPaths();
actual.sort();
- QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
+ QStringList expected;
+ expected << installPathPlugins << appDirPath;
+ expected = QSet<QString>(expected.constBegin(), expected.constEnd()).values();
expected.sort();
#ifdef Q_OS_WINRT
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
index b2650d1f32..00bde3cb25 100644
--- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -47,6 +47,7 @@ private slots:
void sizeConstraints();
void setGeometry();
void setStyleShouldChangeSpacing();
+ void widgetSurplus();
void testLayoutEngine_data();
void testLayoutEngine();
@@ -193,7 +194,7 @@ void tst_QBoxLayout::setGeometry()
setFrameless(&toplevel);
QWidget w(&toplevel);
QVBoxLayout *lay = new QVBoxLayout;
- lay->setMargin(0);
+ lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
QHBoxLayout *lay2 = new QHBoxLayout;
QDial *dial = new QDial;
@@ -236,6 +237,69 @@ void tst_QBoxLayout::setStyleShouldChangeSpacing()
QTRY_COMPARE(spacing(), 10);
}
+class MarginEatingStyle : public QProxyStyle
+{
+public:
+ MarginEatingStyle() : QProxyStyle(QStyleFactory::create("windows"))
+ {
+ }
+
+ virtual QRect subElementRect(SubElement sr, const QStyleOption *opt,
+ const QWidget *widget) const
+ {
+ QRect rect = opt->rect;
+ switch (sr) {
+ case SE_GroupBoxLayoutItem:
+ // this is a simplifed version of what the macOS style does
+ rect.setTop(rect.top() + 20);
+ rect.setLeft(rect.left() + 20);
+ rect.setRight(rect.right() - 20);
+ rect.setBottom(rect.bottom() - 20);
+ break;
+ default:
+ return QProxyStyle::subElementRect(sr, opt, widget);
+ }
+
+ return rect;
+ }
+};
+
+void tst_QBoxLayout::widgetSurplus()
+{
+ // Test case for QTBUG-67608 - a style requests space in the margin
+
+ QDialog window;
+ QScopedPointer<MarginEatingStyle> marginEater(new MarginEatingStyle);
+ QVBoxLayout *vbox = new QVBoxLayout(&window);
+ vbox->setContentsMargins(0, 0, 0, 0);
+ vbox->setSpacing(0);
+
+ QLabel *hiddenLabel = new QLabel(tr("Invisible label"));
+ hiddenLabel->setVisible(false);
+
+ QGroupBox *groupBox = new QGroupBox(tr("Groupbox Title"));
+ groupBox->setStyle(marginEater.data());
+ groupBox->setObjectName("Test group box");
+ QPushButton *button1 = new QPushButton(tr("Button 1"));
+ QPushButton *button2 = new QPushButton(tr("Button 2"));
+ QVBoxLayout *groupLayout = new QVBoxLayout;
+ groupLayout->addWidget(button1);
+ groupLayout->addWidget(button2);
+ groupBox->setLayout(groupLayout);
+
+ QLabel *label = new QLabel(tr("Visible label"));
+
+ vbox->addWidget(hiddenLabel);
+ vbox->addWidget(groupBox);
+ vbox->addWidget(label);
+ window.setLayout(vbox);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QCOMPARE(groupBox->y(), 0);
+ QCOMPARE(groupBox->x(), 0);
+}
+
void tst_QBoxLayout::taskQTBUG_7103_minMaxWidthNotRespected()
{
QLabel *label = new QLabel("Qt uses standard C++, but makes extensive use of the C pre-processor to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on all major platforms, and has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support and a unified cross-platform API for file handling.");
@@ -507,6 +571,10 @@ void tst_QBoxLayout::replaceWidget()
QCOMPARE(boxLayout->indexOf(replaceFrom), 1);
QCOMPARE(boxLayout->indexOf(replaceTo), -1);
+ QCOMPARE(boxLayout->count(), 3);
+ boxLayout->replaceWidget(replaceFrom, replaceFrom);
+ QCOMPARE(boxLayout->count(), 3);
+
delete boxLayout->replaceWidget(replaceFrom, replaceTo);
QCOMPARE(boxLayout->indexOf(replaceFrom), -1);
diff --git a/tests/auto/widgets/kernel/qformlayout/qformlayout.pro b/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
index 617183fee6..0766b50f68 100644
--- a/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
+++ b/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
@@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qformlayout
-QT += widgets testlib testlib-private
+QT += widgets widgets-private testlib testlib-private
SOURCES += tst_qformlayout.cpp
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
index cff3dad35e..c6760000f4 100644
--- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -38,6 +38,9 @@
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
+
+#include <private/qdialog_p.h>
+
#include <QStyleFactory>
#include <QSharedPointer>
@@ -52,7 +55,7 @@ using namespace QTestPrivate;
Q_CONSTEXPR QFormLayout::ItemRole invalidRole = QFormLayout::ItemRole(3);
struct QFormLayoutTakeRowResultHolder {
- QFormLayoutTakeRowResultHolder(QFormLayout::TakeRowResult result) Q_DECL_NOTHROW
+ QFormLayoutTakeRowResultHolder(QFormLayout::TakeRowResult result) noexcept
: labelItem(result.labelItem),
fieldItem(result.fieldItem)
{
@@ -66,20 +69,20 @@ struct QFormLayoutTakeRowResultHolder {
if (fieldItem)
disposer.setItem(0, QFormLayout::FieldRole, fieldItem);
}
- QFormLayoutTakeRowResultHolder(QFormLayoutTakeRowResultHolder &&other) Q_DECL_NOTHROW
+ QFormLayoutTakeRowResultHolder(QFormLayoutTakeRowResultHolder &&other) noexcept
: labelItem(other.labelItem),
fieldItem(other.fieldItem)
{
other.labelItem = nullptr;
other.fieldItem = nullptr;
}
- QFormLayoutTakeRowResultHolder &operator=(QFormLayoutTakeRowResultHolder &&other) Q_DECL_NOTHROW
+ QFormLayoutTakeRowResultHolder &operator=(QFormLayoutTakeRowResultHolder &&other) noexcept
{
swap(other);
return *this;
}
- void swap(QFormLayoutTakeRowResultHolder &other) Q_DECL_NOTHROW
+ void swap(QFormLayoutTakeRowResultHolder &other) noexcept
{
qSwap(labelItem, other.labelItem);
qSwap(fieldItem, other.fieldItem);
@@ -1196,22 +1199,20 @@ void tst_QFormLayout::layoutAlone()
void tst_QFormLayout::taskQTBUG_27420_takeAtShouldUnparentLayout()
{
QSharedPointer<QFormLayout> outer(new QFormLayout);
- QPointer<QFormLayout> inner = new QFormLayout;
+ QAutoPointer<QFormLayout> holder{new QFormLayout};
+ auto inner = holder.get();
outer->addRow(inner);
QCOMPARE(outer->count(), 1);
QCOMPARE(inner->parent(), outer.data());
QLayoutItem *item = outer->takeAt(0);
- QCOMPARE(item->layout(), inner.data());
+ QCOMPARE(item->layout(), inner);
QVERIFY(!item->layout()->parent());
outer.reset();
- if (inner)
- delete item; // success: a taken item/layout should not be deleted when the old parent is deleted
- else
- QVERIFY(!inner.isNull());
+ QVERIFY(holder); // a taken item/layout should not be deleted when the old parent is deleted
}
void tst_QFormLayout::taskQTBUG_40609_addingWidgetToItsOwnLayout(){
diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
index 5e0327319b..1d63d140fb 100644
--- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
+++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
@@ -219,9 +219,9 @@ void tst_QGridLayout::badDistributionBug()
QDialog dialog;
Ui::SortDialog ui;
ui.setupUi(&dialog);
- ui.gridLayout->setMargin(0);
+ ui.gridLayout->setContentsMargins(0, 0, 0, 0);
ui.gridLayout->setSpacing(0);
- ui.vboxLayout->setMargin(0);
+ ui.vboxLayout->setContentsMargins(0, 0, 0, 0);
ui.vboxLayout->setSpacing(0);
ui.okButton->setFixedHeight(20);
ui.moreButton->setFixedHeight(20);
@@ -237,7 +237,7 @@ void tst_QGridLayout::setMinAndMaxSize()
QWidget widget;
setFrameless(&widget);
QGridLayout layout(&widget);
- layout.setMargin(0);
+ layout.setContentsMargins(0, 0, 0, 0);
layout.setSpacing(0);
layout.setSizeConstraint(QLayout::SetMinAndMaxSize);
widget.show();
@@ -396,7 +396,7 @@ void tst_QGridLayout::spacingAndSpacers()
QWidget widget;
setFrameless(&widget);
QGridLayout layout(&widget);
- layout.setMargin(0);
+ layout.setContentsMargins(0, 0, 0, 0);
layout.setSpacing(0);
widget.show();
@@ -1541,7 +1541,7 @@ void tst_QGridLayout::spacerWithSpacing()
QWidget window;
QGridLayout layout(&window);
layout.setSpacing(1);
- layout.setMargin(0);
+ layout.setContentsMargins(0, 0, 0, 0);
populate(&layout, 0, i);
populate(&layout, 1, j);
populate(&layout, 2, k);
@@ -1651,7 +1651,7 @@ void tst_QGridLayout::taskQTBUG_52357_spacingWhenItemIsHidden()
QWidget widget;
setFrameless(&widget);
QGridLayout layout(&widget);
- layout.setMargin(0);
+ layout.setContentsMargins(0, 0, 0, 0);
layout.setSpacing(5);
QPushButton button1;
layout.addWidget(&button1, 0, 0);
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
index 936f581d89..140a367afe 100644
--- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -308,7 +308,7 @@ void tst_QLayout::controlTypes2()
{
QWidget main;
QVBoxLayout *const layout = new QVBoxLayout(&main);
- layout->setMargin(0);
+ layout->setContentsMargins(0, 0, 0, 0);
QComboBox *combo = new QComboBox(&main);
layout->addWidget(combo);
QCOMPARE(layout->controlTypes(), QSizePolicy::ComboBox);
@@ -319,7 +319,7 @@ void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated()
QWidget main;
QVBoxLayout *const layout = new QVBoxLayout(&main);
- layout->setMargin(0);
+ layout->setContentsMargins(0, 0, 0, 0);
SizeHinterFrame *frame = new SizeHinterFrame(QSize(200, 10), QSize(200, 8));
frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
layout->addWidget(frame);
diff --git a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
index 53753e195a..84120c70e9 100644
--- a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
+++ b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
@@ -41,7 +41,6 @@
#include <qshortcut.h>
#include <qscreen.h>
-class AccelForm;
QT_BEGIN_NAMESPACE
class QMainWindow;
class QTextEdit;
@@ -51,15 +50,14 @@ class tst_QShortcut : public QObject
{
Q_OBJECT
public:
- tst_QShortcut();
- virtual ~tst_QShortcut();
-
enum Action {
SetupAccel,
TestAccel,
- ClearAll
- } currentAction;
+ ClearAll,
+ TestEnd
+ };
+ Q_ENUM(Action)
enum Widget {
NoWidget,
@@ -70,8 +68,8 @@ public:
TriggerSlot5,
TriggerSlot6,
TriggerSlot7,
- SendKeyEvent
};
+ Q_ENUM(Widget)
enum Result {
NoResult,
@@ -84,7 +82,8 @@ public:
Slot7Triggered,
SentKeyEvent,
Ambiguous
- } currentResult;
+ } currentResult = NoResult;
+ Q_ENUM(Result)
public slots:
void slotTrig1() { currentResult = Slot1Triggered; }
@@ -101,16 +100,9 @@ public slots:
void ambigSlot5() { currentResult = Ambiguous; ambigResult = Slot5Triggered; }
void ambigSlot6() { currentResult = Ambiguous; ambigResult = Slot6Triggered; }
void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; }
- void statusMessage( const QString& message ) { sbText = message; }
- void shortcutDestroyed(QObject* obj);
- void sendKeyEvent() { sendKeyEvents(edit, Qt::CTRL + Qt::Key_B, 0); currentResult = SentKeyEvent; }
-
-public slots:
- void initTestCase();
- void cleanupTestCase();
- void cleanup() { QCOMPARE(QApplication::topLevelWidgets().size(), 1); }
private slots:
+ void cleanup();
void number_data();
void number();
void text_data();
@@ -129,29 +121,19 @@ protected:
static Qt::KeyboardModifiers toButtons( int key );
void defElements();
- void clearAllShortcuts();
- QShortcut *setupShortcut(int testWidget, const QKeySequence &ks);
- QShortcut *setupShortcut(int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0);
-
- QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0);
- QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QKeySequence &ks, Qt::ShortcutContext context = Qt::WindowShortcut);
+ QShortcut *setupShortcut(QWidget *parent, const QString &name, const QKeySequence &ks,
+ Qt::ShortcutContext context = Qt::WindowShortcut);
+ QShortcut *setupShortcut(QWidget *parent, const QString &name, Widget testWidget,
+ const QKeySequence &ks, Qt::ShortcutContext context = Qt::WindowShortcut);
- void sendKeyEvents(QWidget *w, int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0);
- void sendKeyEvents(int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0);
+ static void sendKeyEvents(QWidget *w, int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0,
+ int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0);
void testElement();
- QMainWindow *mainW;
- QList<QShortcut*> shortcuts;
- QTextEdit *edit;
- QString sbText;
Result ambigResult;
};
-Q_DECLARE_METATYPE(tst_QShortcut::Widget);
-Q_DECLARE_METATYPE(tst_QShortcut::Result);
-Q_DECLARE_METATYPE(tst_QShortcut::Action);
-
class TestEdit : public QTextEdit
{
Q_OBJECT
@@ -163,7 +145,8 @@ public:
}
protected:
- bool event(QEvent *e) {
+ bool event(QEvent *e) override
+ {
// Make testedit allow any Ctrl+Key as shortcut
if (e->type() == QEvent::ShortcutOverride) {
QKeyEvent *ke = static_cast<QKeyEvent*>(e);
@@ -196,33 +179,28 @@ protected:
}
};
-tst_QShortcut::tst_QShortcut(): mainW( 0 )
+class MainWindow : public QMainWindow
{
-}
+public:
+ MainWindow();
-tst_QShortcut::~tst_QShortcut()
-{
- clearAllShortcuts();
-}
+ TestEdit *testEdit() const { return m_testEdit; }
-void tst_QShortcut::initTestCase()
+private:
+ TestEdit *m_testEdit;
+};
+
+MainWindow::MainWindow()
{
- currentResult = NoResult;
- mainW = new QMainWindow(0);
- mainW->setWindowFlags(Qt::X11BypassWindowManagerHint);
- edit = new TestEdit(mainW, "test_edit");
- mainW->setFixedSize( 200, 200 );
- mainW->setCentralWidget( edit );
- mainW->show();
- mainW->activateWindow();
- QVERIFY(QTest::qWaitForWindowActive(mainW));
- connect( mainW->statusBar(), SIGNAL(messageChanged(QString)),
- this, SLOT(statusMessage(QString)) );
+ setWindowFlags(Qt::X11BypassWindowManagerHint);
+ m_testEdit = new TestEdit(this, "test_edit");
+ setCentralWidget(m_testEdit);
+ setFixedSize(200, 200);
}
-void tst_QShortcut::cleanupTestCase()
+void tst_QShortcut::cleanup()
{
- delete mainW;
+ QVERIFY(QApplication::topLevelWidgets().size() <= 1); // The data driven tests keep a widget around
}
Qt::KeyboardModifiers tst_QShortcut::toButtons( int key )
@@ -277,7 +255,7 @@ void tst_QShortcut::number_data()
defElements();
// Clear all
- QTest::newRow("N00 - clear") << ClearAll << NoWidget <<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<<NoResult;
+ QTest::newRow("N00 - clear") << ClearAll << NoWidget <<QString()<<0<<0<<0<<0<<0<<0<<0<<0<<NoResult;
//===========================================
// [Shift + key] on non-shift shortcuts testing
@@ -289,15 +267,15 @@ void tst_QShortcut::number_data()
Shift + Qt::Key_Plus on Qt::Key_Pluss
Qt::Key_Plus on Qt::Key_Pluss
*/
- QTest::newRow("N001 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N001 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("N001:Shift + M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N001:M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N001 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ //QTest::newRow("N001:Shift + M - [M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N001:M - [M]") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N001 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("N001:Shift++ [+]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N001:+ [+]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N001 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ //QTest::newRow("N001:Shift++ [+]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N001:+ [+]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N001 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_M on Shift + Qt::Key_M
@@ -305,32 +283,32 @@ void tst_QShortcut::number_data()
Shift + Qt::Key_Plus on Shift + Qt::Key_Pluss
Qt::Key_Plus on Shift + Qt::Key_Pluss
*/
- QTest::newRow("N002 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N002:M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N002 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N002:Shift++ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N002:+ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N002 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N002 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N002:M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT + Qt::Key_Plus) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002:Shift++ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N002:+ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N002 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Qt::Key_F1
Qt::Key_F1 on Qt::Key_F1
*/
- QTest::newRow("N003 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N003 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("N003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N003:F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N003 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ //QTest::newRow("N003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N003:F1 - [F1]") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N003 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Shift + Qt::Key_F1
Qt::Key_F1 on Shift + Qt::Key_F1
*/
- QTest::newRow("N004 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N004 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N004 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N004 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Qt::Key_Tab
@@ -338,14 +316,14 @@ void tst_QShortcut::number_data()
Qt::Key_Backtab on Qt::Key_Tab
Shift + Qt::Key_Backtab on Qt::Key_Tab
*/
- QTest::newRow("N005a - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005a:Tab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N005a - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005a:Tab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("N005a:Shift+Tab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ //QTest::newRow("N005a:Shift+Tab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
// (Shift+)BackTab != Tab, but Shift+BackTab == Shift+Tab
- QTest::newRow("N005a:Backtab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005a:Shift+Backtab - [Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005a - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N005a:Backtab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005a:Shift+Backtab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005a - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Shift + Qt::Key_Tab
@@ -353,12 +331,12 @@ void tst_QShortcut::number_data()
Qt::Key_Backtab on Shift + Qt::Key_Tab
Shift + Qt::Key_Backtab on Shift + Qt::Key_Tab
*/
- QTest::newRow("N005b - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005b:Tab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005b:Shift+Tab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N005b:BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N005b:Shift+BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N005b - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N005b - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005b:Tab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005b:Shift+Tab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N005b:BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N005b:Shift+BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N005b - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Qt::Key_Backtab
@@ -366,15 +344,15 @@ void tst_QShortcut::number_data()
Qt::Key_Backtab on Qt::Key_Backtab
Shift + Qt::Key_Backtab on Qt::Key_Backtab
*/
- QTest::newRow("N006a - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N006a:Tab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006a - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006a:Tab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
// This should work, since platform dependent code will transform the
// Shift+Tab into a Shift+BackTab, which should trigger the shortcut
- QTest::newRow("N006a:Shift+Tab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
- QTest::newRow("N006a:BackTab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N006a:Shift+Tab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
+ QTest::newRow("N006a:BackTab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N006a - clear") << ClearAll << NoWidget<< QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ //QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N006a - clear") << ClearAll << NoWidget<< QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_Tab on Shift + Qt::Key_Backtab
@@ -382,12 +360,12 @@ void tst_QShortcut::number_data()
Qt::Key_Backtab on Shift + Qt::Key_Backtab
Shift + Qt::Key_Backtab on Shift + Qt::Key_Backtab
*/
- QTest::newRow("N006b - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N006b:Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N006b:Shift+Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N006b:BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N006b:Shift+BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
- QTest::newRow("N006b - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N006b - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006b:Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006b:Shift+Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N006b:BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N006b:Shift+BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL
+ QTest::newRow("N006b - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
//===========================================
// [Shift + key] and [key] on shortcuts with
@@ -398,11 +376,11 @@ void tst_QShortcut::number_data()
Qt::Key_F1
Shift + Qt::Key_F1
*/
- QTest::newRow("N007 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N007 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N007:F1") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N007:Shift + F1") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N007 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N007 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N007 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N007:F1") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N007:Shift + F1") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N007 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_M
@@ -410,51 +388,51 @@ void tst_QShortcut::number_data()
Ctrl + Qt::Key_M
Alt + Qt::Key_M
*/
- QTest::newRow("N01 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N02 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N03 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N04 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N:Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N:Shift+Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N:Ctrl+Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N:Alt+Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N01 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N02 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N03 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N04 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N:Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Shift+Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Ctrl+Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Alt+Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
/* Testing Single Sequence Ambiguity
Qt::Key_M on shortcut2
*/
- QTest::newRow("N05 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N:Qt::Key_M on slot") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
- QTest::newRow("N05 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N05 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N:Qt::Key_M on slot") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
+ QTest::newRow("N05 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Specialkeys
Qt::Key_aring
Qt::Key_Aring
Qt::UNICODE_ACCEL + Qt::Key_K
*/
- QTest::newRow("N06 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N07 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N08 - slot2") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N06 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N07 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N08 - slot2") << SetupAccel << TriggerSlot1 << QString() << int(Qt::UNICODE_ACCEL + Qt::Key_K) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N:Qt::Key_aring") << TestAccel << NoWidget << QString("") << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N:Qt::Key_Aring") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString("") << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N:Qt::UNICODE_ACCEL + Qt::Key_K")<< TestAccel << NoWidget << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N09 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N:Qt::Key_aring") << TestAccel << NoWidget << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Qt::Key_Aring") << TestAccel << NoWidget << QString() << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString() << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString() << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Qt::UNICODE_ACCEL + Qt::Key_K")<< TestAccel << NoWidget << QString() << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N09 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Multiple Sequences
Qt::Key_M
Qt::Key_I, Qt::Key_M
Shift+Qt::Key_I, Qt::Key_M
*/
- QTest::newRow("N10 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N11 - slot2") << SetupAccel << TriggerSlot2 << QString("") << int(Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("N12 - slot1") << SetupAccel << TriggerSlot1 << QString("") << int(Qt::SHIFT + Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult;
-
- QTest::newRow("N:Qt::Key_M (2)") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("N:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("N13 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("N10 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N11 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("N12 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult;
+
+ QTest::newRow("N:Qt::Key_M (2)") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("N:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("N:end") << TestEnd << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
}
// ------------------------------------------------------------------
@@ -464,7 +442,7 @@ void tst_QShortcut::text_data()
{
defElements();
// Clear all
- QTest::newRow("T00 - clear") << ClearAll << NoWidget <<QString("")<<0<<0<<0<<0<<0<<0<<0<<0<< NoResult;
+ QTest::newRow("T00 - clear") << ClearAll << NoWidget <<QString()<<0<<0<<0<<0<<0<<0<<0<<0<< NoResult;
//===========================================
// [Shift + key] on non-shift shortcuts testing
@@ -478,13 +456,13 @@ void tst_QShortcut::text_data()
*/
QTest::newRow("T001 - slot1") << SetupAccel << TriggerSlot1 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("T001:Shift+M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T001:M - [M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ //QTest::newRow("T001:Shift+M - [M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T001:M - [M]") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
QTest::newRow("T001 - slot2") << SetupAccel << TriggerSlot2 << QString("+") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("T001:Shift++ [+]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T001:+ [+]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T001 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ //QTest::newRow("T001:Shift++ [+]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T001:+ [+]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T001 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_M on Shift + Qt::Key_M
@@ -495,12 +473,12 @@ void tst_QShortcut::text_data()
Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Pluss
*/
QTest::newRow("T002 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T002:M - [Shift+M]") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T002:M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T002 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T002:Shift++ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T002:+ [Shift++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T002 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("T002:Shift++ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T002:+ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Plus
@@ -509,10 +487,10 @@ void tst_QShortcut::text_data()
*/
QTest::newRow("T002b - slot1") << SetupAccel << TriggerSlot1 << QString("Ctrl++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("T002b:Shift+Ctrl++ [Ctrl++]")<< TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T002b:Ctrl++ [Ctrl++]") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T002b:+ [Ctrl++]") << TestAccel << NoWidget << QString("") << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T002b - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ //QTest::newRow("T002b:Shift+Ctrl++ [Ctrl++]")<< TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T002b:Ctrl++ [Ctrl++]") << TestAccel << NoWidget << QString() << int(Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T002b:+ [Ctrl++]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T002b - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Qt::Key_F1
@@ -520,18 +498,18 @@ void tst_QShortcut::text_data()
*/
QTest::newRow("T003 - slot1") << SetupAccel << TriggerSlot1 << QString("F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
//commented out because the behaviour changed, those tests should be updated
- //QTest::newRow("T003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T003:F1 - [F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T003 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ //QTest::newRow("T003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T003:F1 - [F1]") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T003 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Shift + Qt::Key_F1 on Shift + Qt::Key_F1
Qt::Key_F1 on Shift + Qt::Key_F1
*/
QTest::newRow("T004 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T004 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("T004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+ QTest::newRow("T004 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
//===========================================
// [Shift + key] and [key] on shortcuts with
@@ -544,9 +522,9 @@ void tst_QShortcut::text_data()
*/
QTest::newRow("T007 - slot1") << SetupAccel << TriggerSlot1 << QString("F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T007 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T007:F1") << TestAccel << NoWidget << QString("") << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T007:Shift + F1") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T007 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("T007:F1") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T007:Shift + F1") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T007 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Sequences
Qt::Key_M
@@ -559,17 +537,17 @@ void tst_QShortcut::text_data()
QTest::newRow("T03 - slot1") << SetupAccel << TriggerSlot1 << QString("Ctrl+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T04 - slot2") << SetupAccel << TriggerSlot2 << QString("Alt+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T:Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T:Shift + Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T:Ctrl + Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T:Alt + Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Shift + Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Ctrl + Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Alt + Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
/* Testing Single Sequence Ambiguity
Qt::Key_M on shortcut2
*/
QTest::newRow("T05 - slot2") << SetupAccel << TriggerSlot2 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T:Qt::Key_M on TriggerSlot2") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
- QTest::newRow("T06 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("T:Qt::Key_M on TriggerSlot2") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous;
+ QTest::newRow("T06 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Single Specialkeys
Qt::Key_aring
@@ -580,12 +558,12 @@ void tst_QShortcut::text_data()
QTest::newRow("T06 - slot1") << SetupAccel << TriggerSlot1 << QString::fromLatin1("\x0C5")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T07 - slot2") << SetupAccel << TriggerSlot2 << QString::fromLatin1("Shift+\x0C5")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T08 - slot2") << SetupAccel << TriggerSlot1 << QString("K") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T:Qt::Key_aring") << TestAccel << NoWidget << QString("") << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T:Qt::Key_Aring") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString("") << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T:Qt::UNICODE_ACCEL + Qt::Key_K")<< TestAccel << NoWidget << QString("") << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T09 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("T:Qt::Key_aring") << TestAccel << NoWidget << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Qt::Key_Aring") << TestAccel << NoWidget << QString() << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString() << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString() << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Qt::UNICODE_ACCEL + Qt::Key_K")<< TestAccel << NoWidget << QString() << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T09 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
/* Testing Multiple Sequences
Qt::Key_M
@@ -595,10 +573,38 @@ void tst_QShortcut::text_data()
QTest::newRow("T10 - slot1") << SetupAccel << TriggerSlot1 << QString("M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T11 - slot2") << SetupAccel << TriggerSlot2 << QString("I, M")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
QTest::newRow("T12 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+I, M")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
- QTest::newRow("T:Qt::Key_M (2)") << TestAccel << NoWidget << QString("") << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
- QTest::newRow("T:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString("") << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
- QTest::newRow("T13 - clear") << ClearAll << NoWidget << QString("") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all
+ QTest::newRow("T:Qt::Key_M (2)") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered;
+ QTest::newRow("T:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered;
+ QTest::newRow("T:end") << TestEnd << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult;
+}
+
+class ButtonWidget : public QWidget
+{
+public:
+ ButtonWidget();
+
+ QPushButton *pushButton1() const { return m_pb1; }
+ QPushButton *pushButton2() const { return m_pb2; }
+
+private:
+ QPushButton *m_pb1;
+ QPushButton *m_pb2;
+};
+
+ButtonWidget::ButtonWidget()
+{
+ // Setup two identical shortcuts on different pushbuttons
+ QString name = QLatin1String("pushbutton-1");
+ m_pb1 = new QPushButton(name, this);
+ m_pb1->setObjectName(name);
+ name = QLatin1String("pushbutton-2");
+ m_pb2 = new QPushButton(name, this);
+ m_pb2->setObjectName(name);
+ auto hLayout = new QHBoxLayout(this);
+ hLayout->addWidget(m_pb1);
+ hLayout->addWidget(m_pb2);
+ hLayout->addStretch();
}
// ------------------------------------------------------------------
@@ -606,9 +612,11 @@ void tst_QShortcut::text_data()
// ------------------------------------------------------------------
void tst_QShortcut::disabledItems()
{
- clearAllShortcuts();
- mainW->activateWindow();
- QVERIFY(QTest::qWaitForWindowActive(mainW));
+ ButtonWidget mainW;
+ mainW.setWindowTitle(QTest::currentTestFunction());
+ mainW.show();
+ mainW.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&mainW));
/* Testing Disabled Shortcuts
Qt::Key_M on slot1
@@ -618,27 +626,27 @@ void tst_QShortcut::disabledItems()
*/
// Setup two identical shortcuts on different pushbuttons
- QPushButton pb1(mainW);
- QPushButton pb2(mainW);
- pb1.setObjectName("pushbutton-1");
- pb2.setObjectName("pushbutton-2");
- pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger
- pb2.show();
-
- QShortcut *cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M");
- QShortcut *cut2 = setupShortcut(&pb1, "shortcut2-pb1", TriggerSlot1, "Shift+M");
- QShortcut *cut3 = setupShortcut(&pb2, "shortcut3-pb2", TriggerSlot2, "M");
- QShortcut *cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+M");
+ auto pb1 = mainW.pushButton1();
+ auto pb2 = mainW.pushButton2();
+ const int shiftM = Qt::SHIFT + Qt::Key_M;
+ QShortcut *cut1 = setupShortcut(pb1, "shortcut1-pb1", TriggerSlot1,
+ QKeySequence(Qt::Key_M));
+ QShortcut *cut2 = setupShortcut(pb1, "shortcut2-pb1", TriggerSlot1,
+ QKeySequence(shiftM));
+ QShortcut *cut3 = setupShortcut(pb2, "shortcut3-pb2", TriggerSlot2,
+ QKeySequence(Qt::Key_M));
+ QShortcut *cut4 = setupShortcut(pb2, "shortcut4-pb2", TriggerSlot2,
+ QKeySequence(shiftM));
cut3->setEnabled(false);
cut4->setEnabled(false);
currentResult = NoResult;
- sendKeyEvents(Qt::Key_M, 'm');
+ sendKeyEvents(&mainW, Qt::Key_M, 'm');
QCOMPARE(currentResult, Slot1Triggered);
currentResult = NoResult;
- sendKeyEvents(Qt::SHIFT+Qt::Key_M, 'M');
+ sendKeyEvents(&mainW, shiftM, 'M');
QCOMPARE(currentResult, Slot1Triggered);
cut2->setEnabled(false);
@@ -651,11 +659,11 @@ void tst_QShortcut::disabledItems()
Shift + Qt::Key_M on slot2
*/
currentResult = NoResult;
- sendKeyEvents( Qt::Key_M, 'm' );
+ sendKeyEvents(&mainW, Qt::Key_M, 'm' );
QCOMPARE( currentResult, Slot1Triggered );
currentResult = NoResult;
- sendKeyEvents( Qt::SHIFT+Qt::Key_M, 'M' );
+ sendKeyEvents(&mainW, shiftM, 'M' );
QCOMPARE( currentResult, Slot2Triggered );
@@ -663,67 +671,34 @@ void tst_QShortcut::disabledItems()
Qt::Key_F5 on slot1
Shift + Qt::Key_F5 on slot2 (disabled)
*/
- clearAllShortcuts();
- cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "F5");
- cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+F5");
-
- cut1->setKey(QKeySequence("F5"));
- cut4->setKey(QKeySequence("Shift+F5"));
+ qDeleteAll(mainW.findChildren<QShortcut *>());
+ const int shiftF5 = Qt::SHIFT + Qt::Key_F5;
+ cut1 = setupShortcut(pb1, "shortcut1-pb1", TriggerSlot1, QKeySequence(Qt::Key_F5));
+ cut4 = setupShortcut(pb2, "shortcut4-pb2", TriggerSlot2, QKeySequence(shiftF5));
cut1->setEnabled(true);
cut4->setEnabled(false);
currentResult = NoResult;
- sendKeyEvents( Qt::Key_F5, 0 );
+ sendKeyEvents(&mainW, Qt::Key_F5, 0 );
QCOMPARE( currentResult, Slot1Triggered );
currentResult = NoResult;
- sendKeyEvents( Qt::SHIFT+Qt::Key_F5, 0 );
- QCOMPARE( currentResult, NoResult );
-
-#if 0
- qFatal("Not testing statusbar text feedback yet, since not implemented");
- /* Testing Disabled Accel, and the corresponding statusbar feedback
- Ctrl + Qt::Key_K, Ctrl + Qt::Key_L on slot1
- Ctrl + Qt::Key_K, Ctrl + Qt::Key_M on slot2 (disabled)
- */
- cut1->setKey(QKeySequence("Ctrl+K, Ctrl+L"));
- cut4->setKey(QKeySequence("Ctrl+K, Ctrl+M"));
-
- cut1->setEnabled(true);
- cut4->setEnabled(false);
-
- currentResult = NoResult;
- sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 );
- sendKeyEvents( Qt::CTRL+Qt::Key_Q, 0 );
- QCOMPARE( currentResult, NoResult );
- if (over_330)
- QCOMPARE( sbText, QString("Ctrl+K, Ctrl+Q not defined") );
-
- currentResult = NoResult;
- sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 );
- sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 );
+ sendKeyEvents(&mainW, shiftF5, 0 );
QCOMPARE( currentResult, NoResult );
- if (over_330)
- QCOMPARE( sbText, QString() );
-
- currentResult = NoResult;
- sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 );
- sendKeyEvents( Qt::CTRL+Qt::Key_L, 0 );
- QCOMPARE( currentResult, Slot1Triggered );
- if (over_330)
- QCOMPARE( sbText, QString() );
-#endif
- clearAllShortcuts();
- cut1 = 0;
- cut4 = 0;
}
// ------------------------------------------------------------------
// Ambiguous Elements -----------------------------------------------
// ------------------------------------------------------------------
void tst_QShortcut::ambiguousRotation()
{
- clearAllShortcuts();
+ MainWindow mainW;
+ const QString name = QLatin1String(QTest::currentTestFunction());
+ mainW.setWindowTitle(name);
+ mainW.show();
+ mainW.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&mainW));
+
/* Testing Shortcut rotation scheme
Ctrl + Qt::Key_A on slot1 (disabled)
Ctrl + Qt::Key_A on slot2 (disabled)
@@ -733,13 +708,15 @@ void tst_QShortcut::ambiguousRotation()
Ctrl + Qt::Key_A on slot6
Ctrl + Qt::Key_A on slot7 (disabled)
*/
- QShortcut *cut1 = setupShortcut(TriggerSlot1, "Ctrl+A");
- QShortcut *cut2 = setupShortcut(TriggerSlot2, "Ctrl+A");
- QShortcut *cut3 = setupShortcut(TriggerSlot3, "Ctrl+A");
- QShortcut *cut4 = setupShortcut(TriggerSlot4, "Ctrl+A");
- QShortcut *cut5 = setupShortcut(TriggerSlot5, "Ctrl+A");
- QShortcut *cut6 = setupShortcut(TriggerSlot6, "Ctrl+A");
- QShortcut *cut7 = setupShortcut(TriggerSlot7, "Ctrl+A");
+ const int ctrlA = Qt::CTRL + Qt::Key_A;
+ QKeySequence ctrlA_Sequence(ctrlA);
+ QShortcut *cut1 = setupShortcut(&mainW, name, TriggerSlot1, ctrlA_Sequence);
+ QShortcut *cut2 = setupShortcut(&mainW, name, TriggerSlot2, ctrlA_Sequence);
+ QShortcut *cut3 = setupShortcut(&mainW, name, TriggerSlot3, ctrlA_Sequence);
+ QShortcut *cut4 = setupShortcut(&mainW, name, TriggerSlot4, ctrlA_Sequence);
+ QShortcut *cut5 = setupShortcut(&mainW, name, TriggerSlot5, ctrlA_Sequence);
+ QShortcut *cut6 = setupShortcut(&mainW, name, TriggerSlot6, ctrlA_Sequence);
+ QShortcut *cut7 = setupShortcut(&mainW, name, TriggerSlot7, ctrlA_Sequence);
cut1->setEnabled(false);
cut2->setEnabled(false);
@@ -753,37 +730,37 @@ void tst_QShortcut::ambiguousRotation()
// Continue...
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot3Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot4Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot6Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot3Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot4Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot6Triggered);
@@ -808,94 +785,87 @@ void tst_QShortcut::ambiguousRotation()
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot1Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot2Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot5Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot7Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot1Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot2Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot5Triggered);
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(Qt::CTRL+Qt::Key_A);
+ sendKeyEvents(&mainW, ctrlA);
QCOMPARE(currentResult, Ambiguous);
QCOMPARE(ambigResult, Slot7Triggered);
-
- clearAllShortcuts();
- cut1 = 0; cut2 = 0;
- cut3 = 0; cut4 = 0;
- cut5 = 0; cut6 = 0;
- cut7 = 0;
}
void tst_QShortcut::ambiguousItems()
{
- clearAllShortcuts();
+ ButtonWidget mainW;
+ mainW.setWindowTitle(QTest::currentTestFunction());
+ mainW.show();
+ mainW.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&mainW));
+
/* Testing Ambiguous Shortcuts
Qt::Key_M on Pushbutton 1
Qt::Key_M on Pushbutton 2
*/
// Setup two identical shortcuts on different pushbuttons
- QPushButton pb1(mainW);
- QPushButton pb2(mainW);
- pb1.setObjectName("pushbutton-1");
- pb2.setObjectName("pushbutton-2");
- pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger
- pb2.show();
+ auto pb1 = mainW.pushButton1();
+ auto pb2 = mainW.pushButton2();
- setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M");
- setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, "M");
+ setupShortcut(pb1, "shortcut1-pb1", TriggerSlot1, QKeySequence(Qt::Key_M));
+ setupShortcut(pb2, "shortcut2-pb2", TriggerSlot2, QKeySequence(Qt::Key_M));
currentResult = NoResult;
- sendKeyEvents( Qt::Key_M, 'm' );
+ sendKeyEvents(&mainW, Qt::Key_M, 'm' );
QCOMPARE( currentResult, Ambiguous );
QCOMPARE( ambigResult, Slot1Triggered );
currentResult = NoResult;
- sendKeyEvents( Qt::Key_M, 'm' );
+ sendKeyEvents(&mainW, Qt::Key_M, 'm' );
QCOMPARE( currentResult, Ambiguous );
QCOMPARE( ambigResult, Slot2Triggered );
currentResult = NoResult;
- sendKeyEvents( Qt::Key_M, 'm' );
+ sendKeyEvents(&mainW, Qt::Key_M, 'm' );
QCOMPARE( currentResult, Ambiguous );
QCOMPARE( ambigResult, Slot1Triggered );
-
- clearAllShortcuts();
}
@@ -904,32 +874,31 @@ void tst_QShortcut::ambiguousItems()
// ------------------------------------------------------------------
void tst_QShortcut::unicodeCompare()
{
- clearAllShortcuts();
+ ButtonWidget mainW;
+ mainW.setWindowTitle(QTest::currentTestFunction());
+ mainW.show();
+ mainW.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&mainW));
+
/* Testing Unicode/non-Unicode Shortcuts
Qt::Key_M on Pushbutton 1
Qt::Key_M on Pushbutton 2
*/
- QPushButton pb1(mainW);
- QPushButton pb2(mainW);
- pb1.setObjectName("pushbutton-1");
- pb2.setObjectName("pushbutton-2");
- pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger
- pb2.show();
+ auto pb1 = mainW.pushButton1();
+ auto pb2 = mainW.pushButton2();
QKeySequence ks1("Ctrl+M"); // Unicode
QKeySequence ks2(Qt::CTRL+Qt::Key_M); // non-Unicode
- setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, ks1);
- setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, ks2);
+ setupShortcut(pb1, "shortcut1-pb1", TriggerSlot1, ks1);
+ setupShortcut(pb2, "shortcut2-pb2", TriggerSlot2, ks2);
currentResult = NoResult;
- sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 );
+ sendKeyEvents(&mainW, Qt::CTRL + Qt::Key_M, 0);
QCOMPARE( currentResult, Ambiguous );
// They _are_ ambiguous, so the QKeySequence operator==
// should indicate the same
QVERIFY( ks1 == ks2 );
QVERIFY( !(ks1 != ks2) );
-
- clearAllShortcuts();
}
// ------------------------------------------------------------------
@@ -937,25 +906,29 @@ void tst_QShortcut::unicodeCompare()
// ------------------------------------------------------------------
void tst_QShortcut::keypressConsumption()
{
- clearAllShortcuts();
- edit->clear();
- QCOMPARE(edit->toPlainText().size(), 0);
+ MainWindow mainW;
+ mainW.setWindowTitle(QTest::currentTestFunction());
+ mainW.show();
+ mainW.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&mainW));
+ auto edit = mainW.testEdit();
- QShortcut *cut1 = setupShortcut(edit, "shortcut1-line", TriggerSlot1, "Ctrl+I, A");
- QShortcut *cut2 = setupShortcut(edit, "shortcut1-line", TriggerSlot2, "Ctrl+I, B");
+ const int ctrlI = Qt::CTRL + Qt::Key_I;
+ QShortcut *cut1 = setupShortcut(edit, "shortcut1-line", TriggerSlot1, QKeySequence(ctrlI, Qt::Key_A));
+ QShortcut *cut2 = setupShortcut(edit, "shortcut1-line", TriggerSlot2, QKeySequence(ctrlI, Qt::Key_B));
currentResult = NoResult;
ambigResult = NoResult;
- sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit
+ sendKeyEvents(edit, ctrlI, 0); // Send key to edit
QCOMPARE( currentResult, NoResult );
QCOMPARE( ambigResult, NoResult );
- QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(edit->toPlainText(), QString());
// Make sure next keypress is eaten (failing multiple keysequence)
sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit
QCOMPARE( currentResult, NoResult );
QCOMPARE( ambigResult, NoResult );
- QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(edit->toPlainText(), QString());
// Next keypress should be normal
sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit
@@ -983,11 +956,15 @@ void tst_QShortcut::keypressConsumption()
QCOMPARE( ambigResult, NoResult );
QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>a"));
- clearAllShortcuts();
+ qDeleteAll(mainW.findChildren<QShortcut *>());
edit->clear();
QCOMPARE(edit->toPlainText().size(), 0);
- setupShortcut(edit, "first", SendKeyEvent, "Ctrl+A");
+ auto cut = setupShortcut(edit, QLatin1String("first"), QKeySequence(Qt::CTRL + Qt::Key_A));
+ connect(cut, &QShortcut::activated, edit, [this, edit] () {
+ this->sendKeyEvents(edit, Qt::CTRL + Qt::Key_B, 0);
+ this->currentResult = tst_QShortcut::SentKeyEvent;
+ });
// Verify reentrancy when a non-shortcut is triggered as part
// of shortcut processing.
@@ -996,7 +973,7 @@ void tst_QShortcut::keypressConsumption()
sendKeyEvents(edit, Qt::CTRL + Qt::Key_A, 0);
QCOMPARE(currentResult, SentKeyEvent);
QCOMPARE(ambigResult, NoResult);
- QCOMPARE(edit->toPlainText(), QString(QString("<Ctrl+B>")));
+ QCOMPARE(edit->toPlainText(), QLatin1String("<Ctrl+B>"));
}
// ------------------------------------------------------------------
@@ -1004,12 +981,17 @@ void tst_QShortcut::keypressConsumption()
// ------------------------------------------------------------------
void tst_QShortcut::context()
{
- clearAllShortcuts();
+ const QString name = QLatin1String(QTest::currentTestFunction());
+ MainWindow mainW;
+ mainW.setWindowTitle(name + QLatin1String("_Helper"));
+ mainW.show();
+ auto edit = mainW.testEdit();
QWidget myBox;
- TestEdit *other1 = new TestEdit(&myBox, "test_edit_other1");
- TestEdit *other2 = new TestEdit(&myBox, "test_edit_other2");
- QHBoxLayout *layout = new QHBoxLayout(&myBox);
+ myBox.setWindowTitle(name);
+ auto other1 = new TestEdit(&myBox, "test_edit_other1");
+ auto other2 = new TestEdit(&myBox, "test_edit_other2");
+ auto layout = new QHBoxLayout(&myBox);
layout->addWidget(other1);
layout->addWidget(other2);
myBox.show();
@@ -1034,8 +1016,8 @@ void tst_QShortcut::context()
// Focus on 'other1' edit, so Active Window context should trigger
other1->activateWindow(); // <---
QApplication::setActiveWindow(other1);
- QCOMPARE(qApp->activeWindow(), other1->window());
- QCOMPARE(qApp->focusWidget(), (QWidget *)other1);
+ QCOMPARE(QApplication::activeWindow(), other1->window());
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other1));
currentResult = NoResult;
ambigResult = NoResult;
@@ -1043,13 +1025,13 @@ void tst_QShortcut::context()
other1->clear();
other2->clear();
- QCOMPARE(qApp->focusWidget(), (QWidget *)other1);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other1));
sendKeyEvents(other1, Qt::ALT+Qt::Key_1);
QCOMPARE(currentResult, Slot1Triggered);
QCOMPARE(ambigResult, NoResult);
- QCOMPARE(edit->toPlainText(), QString(""));
- QCOMPARE(other1->toPlainText(), QString(""));
- QCOMPARE(other2->toPlainText(), QString(""));
+ QCOMPARE(edit->toPlainText(), QString());
+ QCOMPARE(other1->toPlainText(), QString());
+ QCOMPARE(other2->toPlainText(), QString());
// ..but not Focus context on 'other2'..
currentResult = NoResult;
@@ -1061,9 +1043,9 @@ void tst_QShortcut::context()
sendKeyEvents(other1, Qt::ALT+Qt::Key_2);
QCOMPARE(currentResult, NoResult);
QCOMPARE(ambigResult, NoResult);
- QCOMPARE(edit->toPlainText(), QString(""));
+ QCOMPARE(edit->toPlainText(), QString());
QCOMPARE(other1->toPlainText(), QString("<Alt+2>"));
- QCOMPARE(other2->toPlainText(), QString(""));
+ QCOMPARE(other2->toPlainText(), QString());
// ..however, application global context on 'edit' should..
currentResult = NoResult;
@@ -1075,15 +1057,15 @@ void tst_QShortcut::context()
sendKeyEvents(other1, Qt::ALT+Qt::Key_3);
QCOMPARE(currentResult, Slot3Triggered);
QCOMPARE(ambigResult, NoResult);
- QCOMPARE(edit->toPlainText(), QString(""));
- QCOMPARE(other1->toPlainText(), QString(""));
- QCOMPARE(other2->toPlainText(), QString(""));
+ QCOMPARE(edit->toPlainText(), QString());
+ QCOMPARE(other1->toPlainText(), QString());
+ QCOMPARE(other2->toPlainText(), QString());
// Changing focus to 'other2' should make the Focus context there work
other2->activateWindow();
other2->setFocus(); // ###
- QTRY_COMPARE(qApp->activeWindow(), other2->window());
- QCOMPARE(qApp->focusWidget(), (QWidget *)other2);
+ QTRY_COMPARE(QApplication::activeWindow(), other2->window());
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other2));
currentResult = NoResult;
ambigResult = NoResult;
@@ -1094,20 +1076,18 @@ void tst_QShortcut::context()
sendKeyEvents(other2, Qt::ALT+Qt::Key_2);
QCOMPARE(currentResult, Slot2Triggered);
QCOMPARE(ambigResult, NoResult);
- QCOMPARE(edit->toPlainText(), QString(""));
- QCOMPARE(other1->toPlainText(), QString(""));
- QCOMPARE(other2->toPlainText(), QString(""));
-
- clearAllShortcuts();
+ QCOMPARE(edit->toPlainText(), QString());
+ QCOMPARE(other1->toPlainText(), QString());
+ QCOMPARE(other2->toPlainText(), QString());
}
// QTBUG-38986, do not generate duplicated QEvent::ShortcutOverride in event processing.
class OverrideCountingWidget : public QWidget
{
public:
- OverrideCountingWidget(QWidget *parent = 0) : QWidget(parent), overrideCount(0) {}
+ using QWidget::QWidget;
- int overrideCount;
+ int overrideCount = 0;
bool event(QEvent *e) override
{
@@ -1131,95 +1111,55 @@ void tst_QShortcut::duplicatedShortcutOverride()
QCOMPARE(w.overrideCount, 1);
}
-// ------------------------------------------------------------------
-// Element Testing helper functions ---------------------------------
-// ------------------------------------------------------------------
-void tst_QShortcut::clearAllShortcuts()
-{
- QList<QShortcut *> shortcutsCpy = shortcuts;
- qDeleteAll(shortcutsCpy);
- shortcuts.clear();
-}
-
-QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QKeySequence &ks)
-{
- return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget, ks);
-}
-
-QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QString &txt, int k1, int k2, int k3, int k4)
-{
- return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget,
- (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt)));
-}
-
-QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1, int k2, int k3, int k4)
+QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const QString &name, const QKeySequence &ks, Qt::ShortcutContext context)
{
- return setupShortcut(parent, name, testWidget,
- (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt)));
+ // Set up shortcut for next test
+ auto cut = new QShortcut(ks, parent, nullptr, nullptr, context);
+ cut->setObjectName(name);
+ return cut;
}
-QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget,
+QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const QString &name, Widget testWidget,
const QKeySequence &ks, Qt::ShortcutContext context)
{
// Set up shortcut for next test
- QShortcut *cut = new QShortcut(QKeySequence(), parent, 0, 0, context);
- cut->setObjectName(name);
- cut->setKey(ks);
+ auto cut = setupShortcut(parent, name, ks, context);
- const char *normal = 0;
- const char *ambig = 0;
- switch(testWidget)
- {
+ switch (testWidget) {
case TriggerSlot1:
- normal = SLOT(slotTrig1());
- ambig = SLOT(ambigSlot1());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig1);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot1);
break;
case TriggerSlot2:
- normal = SLOT(slotTrig2());
- ambig = SLOT(ambigSlot2());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig2);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot2);
break;
case TriggerSlot3:
- normal = SLOT(slotTrig3());
- ambig = SLOT(ambigSlot3());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig3);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot3);
break;
case TriggerSlot4:
- normal = SLOT(slotTrig4());
- ambig = SLOT(ambigSlot4());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig4);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot4);
break;
case TriggerSlot5:
- normal = SLOT(slotTrig5());
- ambig = SLOT(ambigSlot5());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig5);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot5);
break;
case TriggerSlot6:
- normal = SLOT(slotTrig6());
- ambig = SLOT(ambigSlot6());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig6);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot6);
break;
case TriggerSlot7:
- normal = SLOT(slotTrig7());
- ambig = SLOT(ambigSlot7());
+ connect(cut, &QShortcut::activated, this, &tst_QShortcut::slotTrig7);
+ connect(cut, &QShortcut::activatedAmbiguously, this, &tst_QShortcut::ambigSlot7);
+ break;
+ case NoWidget:
break;
- case SendKeyEvent:
- normal = SLOT(sendKeyEvent());
}
- connect(cut, SIGNAL(activated()), this, normal);
- if (ambig)
- connect(cut, SIGNAL(activatedAmbiguously()), this, ambig);
- connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*)));
- shortcuts.append(cut);
return cut;
}
-void tst_QShortcut::shortcutDestroyed(QObject* obj)
-{
- shortcuts.erase(std::remove(shortcuts.begin(), shortcuts.end(), obj),
- shortcuts.end());
-}
-
-void tst_QShortcut::sendKeyEvents(int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4)
-{
- sendKeyEvents(mainW, k1, c1, k2, c2, k3, c3, k4, c4);
-}
-
void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4)
{
Qt::KeyboardModifiers b1 = toButtons( k1 );
@@ -1259,6 +1199,8 @@ void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2
void tst_QShortcut::testElement()
{
+ static QScopedPointer<MainWindow> mainW;
+
currentResult = NoResult;
QFETCH(tst_QShortcut::Action, action);
QFETCH(tst_QShortcut::Widget, testWidget);
@@ -1273,13 +1215,29 @@ void tst_QShortcut::testElement()
QFETCH(int, c4);
QFETCH(tst_QShortcut::Result, result);
- if (action == ClearAll) {
- clearAllShortcuts();
- } else if (action == SetupAccel) {
- setupShortcut(testWidget, txt, k1, k2, k3, k4);
- } else {
- sendKeyEvents(k1, c1, k2, c2, k3, c3, k4, c4);
- QCOMPARE((int)currentResult, (int)result);
+ if (mainW.isNull()) {
+ mainW.reset(new MainWindow);
+ mainW->setWindowTitle(QTest::currentTestFunction());
+ mainW->show();
+ mainW->activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(mainW.data()));
+ }
+
+ switch (action) {
+ case ClearAll:
+ qDeleteAll(mainW->findChildren<QShortcut *>());
+ break;
+ case SetupAccel:
+ setupShortcut(mainW.data(), txt, testWidget, txt.isEmpty()
+ ? QKeySequence(k1, k2, k3, k4) : QKeySequence::fromString(txt));
+ break;
+ case TestAccel:
+ sendKeyEvents(mainW.data(), k1, c1, k2, c2, k3, c3, k4, c4);
+ QCOMPARE(currentResult, result);
+ break;
+ case TestEnd:
+ mainW.reset();
+ break;
}
}
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 03bec4286b..26f9ce1b85 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -2,30 +2,31 @@
[normalGeometry]
ubuntu-16.04
[saveRestoreGeometry]
-xcb
+opensuse-leap
+ubuntu-16.04
b2qt
+opensuse-42.3
[restoreVersion1Geometry]
-osx
-[updateWhileMinimized]
ubuntu-16.04
+[updateWhileMinimized]
ubuntu-18.04
rhel-7.4
+ubuntu-16.04
rhel-7.6
-osx
[focusProxyAndInputMethods]
-linux
+rhel-7.6
+opensuse-leap
+ubuntu
[raise]
-# QTBUG-68175
-opensuse
opensuse-leap
-[setWindowGeometry]
-osx
-[windowMoveResize]
-osx
+# QTBUG-68175
+opensuse-42.3
[childEvents]
osx ci
[renderInvisible]
-osx
+osx-10.12
+osx-10.11
+osx-10.14
[optimizedResizeMove]
osx
[optimizedResize_topLevel]
@@ -40,12 +41,11 @@ opensuse
opensuse-leap
[moveInResizeEvent]
ubuntu-16.04
-[moveChild:right]
-osx
-[activateWindow]
-osx-10.12 ci
[multipleToplevelFocusCheck]
-linux
+rhel-7.6
+opensuse-leap
+ubuntu
[windowState]
# QTBUG-75270
winrt
+
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
index c1908af2a2..d3fbd6d0d9 100644
--- a/tests/auto/widgets/kernel/qwidget/qwidget.pro
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -16,4 +16,4 @@ mac {
OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm
}
-win32:!winrt: LIBS += -luser32 -lgdi32
+win32:!winrt: QMAKE_USE += user32 gdi32
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index a95d6e76b3..1724d3ce8c 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -46,6 +46,7 @@
#include <qstylefactory.h>
#include <qdesktopwidget.h>
#include <private/qwidget_p.h>
+#include <private/qwidgetrepaintmanager_p.h>
#include <private/qapplication_p.h>
#include <private/qhighdpiscaling_p.h>
#include <qcalendarwidget.h>
@@ -54,6 +55,7 @@
#include <qrandom.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpaintengine.h>
#include <QtGui/qbackingstore.h>
#include <QtGui/qguiapplication.h>
@@ -1137,6 +1139,7 @@ void tst_QWidget::visible()
QVERIFY( !childWidget->isVisible() );
testWidget->show();
+ QVERIFY(testWidget->screen());
QVERIFY( testWidget->isVisible() );
QVERIFY( childWidget->isVisible() );
@@ -2527,8 +2530,8 @@ void tst_QWidget::showMinimizedKeepsFocus()
{
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
if (m_platform == QStringLiteral("offscreen"))
QSKIP("Platform offscreen does not support showMinimized()");
@@ -2739,8 +2742,8 @@ void tst_QWidget::icon()
void tst_QWidget::hideWhenFocusWidgetIsChild()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
QScopedPointer<QWidget> testWidget(new QWidget);
testWidget->setWindowTitle(__FUNCTION__);
@@ -5541,8 +5544,8 @@ void tst_QWidget::multipleToplevelFocusCheck()
QSKIP("QTBUG-52974");
#endif
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
else if (m_platform == QStringLiteral("winrt"))
QSKIP("Winrt: Sometimes crashes in QTextLayout. - QTBUG-68297");
TopLevelFocusCheck w1;
@@ -6256,7 +6259,11 @@ public:
return false;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEvent(const QByteArray &eventType, void *message, qintptr *) override
+#else
bool nativeEvent(const QByteArray &eventType, void *message, long *) override
+#endif
{
if (isMapNotify(eventType, message))
gotExpectedMapNotify = true;
@@ -6264,7 +6271,11 @@ public:
}
// QAbstractNativeEventFilter interface
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
+#else
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
+#endif
{
if (isMapNotify(eventType, message))
gotExpectedGlobalEvent = true;
@@ -7095,7 +7106,7 @@ void tst_QWidget::renderWithPainter()
// Make sure QWidget::render does not modify the render hints set on the painter.
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
- | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
+ | QPainter::TextAntialiasing);
QPainter::RenderHints oldRenderHints = painter.renderHints();
widget.render(&painter);
QCOMPARE(painter.renderHints(), oldRenderHints);
@@ -7693,9 +7704,7 @@ void tst_QWidget::moveWindowInShowEvent()
void tst_QWidget::repaintWhenChildDeleted()
{
#ifdef Q_OS_WIN
- if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
- QTest::qWait(1000);
- }
+ QTest::qWait(1000);
#endif
ColorWidget w(nullptr, Qt::FramelessWindowHint, Qt::red);
w.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
@@ -8064,7 +8073,7 @@ public:
sp.setHeightForWidth(hfwLayout);
QVBoxLayout *vbox = new QVBoxLayout;
- vbox->setMargin(0);
+ vbox->setContentsMargins(0, 0, 0, 0);
vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
setLayout(vbox);
}
@@ -8892,11 +8901,10 @@ void tst_QWidget::translucentWidget()
#ifdef Q_OS_WIN
QWidget *desktopWidget = QApplication::desktop()->screen(0);
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
- widgetSnapshot = grabWindow(desktopWidget->windowHandle(), labelPos.x(), labelPos.y(), label.width(), label.height());
- else
+ widgetSnapshot = grabWindow(desktopWidget->windowHandle(), labelPos.x(), labelPos.y(), label.width(), label.height());
+#else
+ widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
#endif
- widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
const QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
const QImage expected = pm.toImage().scaled(label.devicePixelRatioF() * pm.size());
if (m_platform == QStringLiteral("winrt"))
@@ -9555,7 +9563,7 @@ void tst_QWidget::destroyBackingStore()
QTRY_VERIFY(w.numPaintEvents > 0);
w.reset();
w.update();
- qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
+ qt_widget_private(&w)->topData()->repaintManager.reset(new QWidgetRepaintManager(&w));
w.update();
QApplication::processEvents();
@@ -9570,14 +9578,14 @@ void tst_QWidget::destroyBackingStore()
#endif // QT_BUILD_INTERNAL
// Helper function
-QWidgetBackingStore* backingStore(QWidget &widget)
+QWidgetRepaintManager* repaintManager(QWidget &widget)
{
- QWidgetBackingStore *backingStore = nullptr;
+ QWidgetRepaintManager *repaintManager = nullptr;
#ifdef QT_BUILD_INTERNAL
if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
- backingStore = topExtra->backingStoreTracker.data();
+ repaintManager = topExtra->repaintManager.get();
#endif
- return backingStore;
+ return repaintManager;
}
// Tables of 5000 elements do not make sense on Windows Mobile.
@@ -9674,8 +9682,8 @@ void tst_QWidget::setGraphicsEffect()
void tst_QWidget::activateWindow()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
// Test case for QTBUG-26711
@@ -9743,8 +9751,8 @@ void tst_QWidget::openModal_taskQTBUG_5804()
void tst_QWidget::focusProxyAndInputMethods()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
QScopedPointer<QWidget> toplevel(new QWidget(nullptr, Qt::X11BypassWindowManagerHint));
toplevel->setWindowTitle(QLatin1String(QTest::currentTestFunction()));
toplevel->resize(200, 200);
@@ -9775,12 +9783,12 @@ class scrollWidgetWBS : public QWidget
public:
void deleteBackingStore()
{
- static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
+ static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->repaintManager.reset(nullptr);
}
void enableBackingStore()
{
- if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
- static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
+ if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeRepaintManager()) {
+ static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBackingStore(this->rect());
repaint();
}
@@ -10111,7 +10119,7 @@ void tst_QWidget::grabMouse()
w.setObjectName(QLatin1String("tst_qwidget_grabMouse"));
w.setWindowTitle(w.objectName());
QLayout *layout = new QVBoxLayout(&w);
- layout->setMargin(50);
+ layout->setContentsMargins(50, 50, 50, 50);
GrabLoggerWidget *grabber = new GrabLoggerWidget(&log, &w);
const QString grabberObjectName = QLatin1String("tst_qwidget_grabMouse_grabber");
grabber->setObjectName(grabberObjectName);
diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
index 934f2e8025..39d7b695f6 100644
--- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
@@ -2,7 +2,7 @@
# QTBUG-66345
opensuse-42.3
ubuntu-16.04
-ubuntu-18.04
[setWindowState]
ubuntu-18.04
-rhel
+rhel-7.6
+
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/button.png b/tests/auto/widgets/styles/qstyle/images/mac/button.png
deleted file mode 100644
index 7b11325e87..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/button.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/combobox.png b/tests/auto/widgets/styles/qstyle/images/mac/combobox.png
deleted file mode 100644
index ded0b11f29..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/combobox.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png b/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png
deleted file mode 100644
index 8d2861b65b..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/lineedit.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/mdi.png b/tests/auto/widgets/styles/qstyle/images/mac/mdi.png
deleted file mode 100644
index 8c09ae4338..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/mdi.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/menu.png b/tests/auto/widgets/styles/qstyle/images/mac/menu.png
deleted file mode 100644
index 5dd9111d69..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/menu.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png b/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png
deleted file mode 100644
index 8828e220a2..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/radiobutton.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/slider.png b/tests/auto/widgets/styles/qstyle/images/mac/slider.png
deleted file mode 100644
index fc65035631..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/slider.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png b/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png
deleted file mode 100644
index ee88441ecb..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/mac/spinbox.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/button.png b/tests/auto/widgets/styles/qstyle/images/vista/button.png
deleted file mode 100644
index a6c45276ca..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/button.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/combobox.png b/tests/auto/widgets/styles/qstyle/images/vista/combobox.png
deleted file mode 100644
index 9b82f64d32..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/combobox.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png b/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png
deleted file mode 100644
index b2c6ac1ae4..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/lineedit.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/menu.png b/tests/auto/widgets/styles/qstyle/images/vista/menu.png
deleted file mode 100644
index b114099cc3..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/menu.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png b/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png
deleted file mode 100644
index c8aa7864df..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/radiobutton.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/slider.png b/tests/auto/widgets/styles/qstyle/images/vista/slider.png
deleted file mode 100644
index 7c156ded9d..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/slider.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png b/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png
deleted file mode 100644
index b8d0823ab2..0000000000
--- a/tests/auto/widgets/styles/qstyle/images/vista/spinbox.png
+++ /dev/null
Binary files differ
diff --git a/tests/auto/widgets/styles/qstyle/qstyle.pro b/tests/auto/widgets/styles/qstyle/qstyle.pro
index 9ad0940245..4dc0525c49 100644
--- a/tests/auto/widgets/styles/qstyle/qstyle.pro
+++ b/tests/auto/widgets/styles/qstyle/qstyle.pro
@@ -2,8 +2,3 @@ CONFIG += testcase
TARGET = tst_qstyle
QT += widgets testlib testlib-private
SOURCES += tst_qstyle.cpp
-
-android:!android-embedded {
- RESOURCES += \
- testdata.qrc
-}
diff --git a/tests/auto/widgets/styles/qstyle/testdata.qrc b/tests/auto/widgets/styles/qstyle/testdata.qrc
deleted file mode 100644
index 29bb46726e..0000000000
--- a/tests/auto/widgets/styles/qstyle/testdata.qrc
+++ /dev/null
@@ -1,19 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>images/mac/button.png</file>
- <file>images/mac/combobox.png</file>
- <file>images/mac/lineedit.png</file>
- <file>images/mac/mdi.png</file>
- <file>images/mac/menu.png</file>
- <file>images/mac/radiobutton.png</file>
- <file>images/mac/slider.png</file>
- <file>images/mac/spinbox.png</file>
- <file>images/vista/button.png</file>
- <file>images/vista/combobox.png</file>
- <file>images/vista/lineedit.png</file>
- <file>images/vista/menu.png</file>
- <file>images/vista/radiobutton.png</file>
- <file>images/vista/slider.png</file>
- <file>images/vista/spinbox.png</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
index a552c91928..ae084310b1 100644
--- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
+++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
@@ -73,7 +73,6 @@ public:
private:
bool testAllFunctions(QStyle *);
bool testScrollBarSubControls();
- void testPainting(QStyle *style, const QString &platform);
private slots:
void drawItemPixmap();
void init();
@@ -333,138 +332,15 @@ void tst_QStyle::testWindowsStyle()
delete wstyle;
}
-void writeImage(const QString &fileName, QImage image)
-{
- QImageWriter imageWriter(fileName);
- imageWriter.setFormat("png");
- qDebug() << "result " << imageWriter.write(image);
-}
-
-QImage readImage(const QString &fileName)
-{
- QImageReader reader(fileName);
- return reader.read();
-}
-
-
#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA) && !defined(Q_OS_WINRT)
void tst_QStyle::testWindowsVistaStyle()
{
QStyle *vistastyle = QStyleFactory::create("WindowsVista");
QVERIFY(testAllFunctions(vistastyle));
-
- if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA)
- testPainting(vistastyle, "vista");
delete vistastyle;
}
#endif
-void comparePixmap(const QString &filename, const QPixmap &pixmap)
-{
- QImage oldFile = readImage(filename);
- QPixmap oldPixmap = QPixmap::fromImage(oldFile);
- if (!oldFile.isNull())
- QCOMPARE(pixmap, oldPixmap);
- else
- writeImage(filename, pixmap.toImage());
-}
-
-void tst_QStyle::testPainting(QStyle *style, const QString &platform)
-{
-qDebug("TEST PAINTING");
- //Test Menu
- QString fileName = "images/" + platform + "/menu.png";
- QMenu menu;
- menu.setStyle(style);
- menu.show();
- menu.addAction(new QAction("Test 1", &menu));
- menu.addAction(new QAction("Test 2", &menu));
- QPixmap pixmap = menu.grab();
- comparePixmap(fileName, pixmap);
-
- //Push button
- fileName = "images/" + platform + "/button.png";
- QPushButton button("OK");
- button.setStyle(style);
- button.show();
- pixmap = button.grab();
- button.hide();
- comparePixmap(fileName, pixmap);
-
- //Push button
- fileName = "images/" + platform + "/radiobutton.png";
- QRadioButton radiobutton("Check");
- radiobutton.setStyle(style);
- radiobutton.show();
- pixmap = radiobutton.grab();
- radiobutton.hide();
- comparePixmap(fileName, pixmap);
-
- //Combo box
- fileName = "images/" + platform + "/combobox.png";
- QComboBox combobox;
- combobox.setStyle(style);
- combobox.addItem("Test 1");
- combobox.addItem("Test 2");
- combobox.show();
- pixmap = combobox.grab();
- combobox.hide();
- comparePixmap(fileName, pixmap);
-
- //Spin box
- fileName = "images/" + platform + "/spinbox.png";
- QDoubleSpinBox spinbox;
- spinbox.setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
- spinbox.setStyle(style);
- spinbox.show();
- pixmap = spinbox.grab();
- spinbox.hide();
- comparePixmap(fileName, pixmap);
- QLocale::setDefault(QLocale::system());
-
- //Slider
- fileName = "images/" + platform + "/slider.png";
- QSlider slider;
- slider.setStyle(style);
- slider.show();
- pixmap = slider.grab();
- slider.hide();
- comparePixmap(fileName, pixmap);
-
- //Line edit
- fileName = "images/" + platform + "/lineedit.png";
- QLineEdit lineedit("Test text");
- lineedit.setStyle(style);
- lineedit.show();
- pixmap = lineedit.grab();
- lineedit.hide();
- comparePixmap(fileName, pixmap);
-
- //MDI
- fileName = "images/" + platform + "/mdi.png";
- QMdiArea mdiArea;
- mdiArea.addSubWindow(new QWidget(&mdiArea));
- mdiArea.resize(200, 200);
- mdiArea.setStyle(style);
- mdiArea.show();
- pixmap = mdiArea.grab();
- mdiArea.hide();
- comparePixmap(fileName, pixmap);
-
- // QToolButton
- fileName = "images/" + platform + "/toolbutton.png";
- QToolButton tb;
- tb.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
- tb.setText("AaQqPpXx");
- tb.setIcon(style->standardPixmap(QStyle::SP_DirHomeIcon));
- tb.setStyle(style);
- tb.show();
- pixmap = tb.grab();
- tb.hide();
- comparePixmap(fileName, pixmap);
-
-}
-
#ifdef Q_OS_MAC
void tst_QStyle::testMacStyle()
{
diff --git a/tests/auto/widgets/util/qcompleter/BLACKLIST b/tests/auto/widgets/util/qcompleter/BLACKLIST
index fdc424b6ac..367270fdf2 100644
--- a/tests/auto/widgets/util/qcompleter/BLACKLIST
+++ b/tests/auto/widgets/util/qcompleter/BLACKLIST
@@ -1,2 +1,6 @@
[QTBUG_14292_filesystem]
-linux
+ubuntu-16.04
+opensuse-leap
+rhel-7.4
+rhel-6.6
+opensuse-42.3
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
index 007825d39c..a17a9f6c33 100644
--- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
@@ -124,13 +124,19 @@ void tst_QAbstractScrollArea::scrollBarWidgets()
QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
+ auto sort = [](const QWidgetList l) {
+ QWidgetList list = l;
+ std::sort(list.begin(), list.end());
+ return list;
+ };
+
// two widgets at Bottom.
area.addScrollBarWidget(w3, Qt::AlignBottom);
- QCOMPARE(area.scrollBarWidgets(all).toSet(), allList.toSet());
+ QCOMPARE(sort(area.scrollBarWidgets(all)), sort(allList));
QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
- QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom).toSet(), (w2List + w3List).toSet());
+ QCOMPARE(sort(area.scrollBarWidgets(Qt::AlignBottom)), sort(w2List + w3List));
//delete
delete w1;
diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
index 1a0d7a9289..f77efe036a 100644
--- a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
+++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
@@ -33,7 +33,7 @@
#include <QSlider>
#include <QStyle>
#include <QStyleOption>
-#include <QTime>
+#include <QElapsedTimer>
#include <QDebug>
#include <QtTest/private/qtesthelpers_p.h>
@@ -91,7 +91,7 @@ private slots:
void connectedSliders();
private:
- void waitUntilTimeElapsed(const QTime& t, int ms);
+ void waitUntilTimeElapsed(const QElapsedTimer &t, int ms);
QWidget *topLevel;
Slider *slider;
@@ -1662,8 +1662,12 @@ void tst_QAbstractSlider::wheelEvent()
slider->setOrientation(sliderOrientation);
Qt::KeyboardModifier k = withModifiers ? Qt::ControlModifier : Qt::NoModifier;
- QWheelEvent event(slider->rect().bottomRight() + distanceFromBottomRight, WHEEL_DELTA * deltaMultiple,
- Qt::NoButton, k, wheelOrientation);
+
+ const QPoint wheelPoint = slider->rect().bottomRight() + distanceFromBottomRight;
+ const QPoint angleDelta(wheelOrientation == Qt::Horizontal ? WHEEL_DELTA * deltaMultiple : 0,
+ wheelOrientation == Qt::Vertical ? WHEEL_DELTA * deltaMultiple : 0);
+ QWheelEvent event(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), angleDelta,
+ Qt::NoButton, k, Qt::NoScrollPhase, false);
QVERIFY(applicationInstance->sendEvent(slider,&event));
#ifdef Q_OS_MAC
QEXPECT_FAIL("Normal data page", "QTBUG-23679", Continue);
@@ -1674,8 +1678,8 @@ void tst_QAbstractSlider::wheelEvent()
slider->setSliderPosition(initialSliderPosition);
k = withModifiers ? Qt::ShiftModifier : Qt::NoModifier;
- event = QWheelEvent(slider->rect().bottomRight() + distanceFromBottomRight, WHEEL_DELTA * deltaMultiple,
- Qt::NoButton, k, wheelOrientation);
+ event = QWheelEvent(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), angleDelta,
+ Qt::NoButton, k, Qt::NoScrollPhase, false);
QSignalSpy spy1(slider, SIGNAL(actionTriggered(int)));
QSignalSpy spy2(slider, SIGNAL(valueChanged(int)));
QVERIFY(applicationInstance->sendEvent(slider,&event));
@@ -1715,16 +1719,16 @@ void tst_QAbstractSlider::fineGrainedWheelEvent()
slider->setSliderPosition(0);
const int singleStepDelta = invertedControls ? (-WHEEL_DELTA / 3) : (WHEEL_DELTA / 3);
-
- QWheelEvent eventDown(slider->rect().bottomRight(), singleStepDelta / 2,
- Qt::NoButton, Qt::NoModifier, Qt::Vertical);
+ const QPoint wheelPoint = slider->rect().bottomRight();
+ QWheelEvent eventDown(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), QPoint(0, singleStepDelta / 2),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QVERIFY(applicationInstance->sendEvent(slider,&eventDown));
QCOMPARE(slider->sliderPosition(), 0);
QVERIFY(applicationInstance->sendEvent(slider,&eventDown));
QCOMPARE(slider->sliderPosition(), 1);
- QWheelEvent eventUp(slider->rect().bottomRight(), -singleStepDelta / 2,
- Qt::NoButton, Qt::NoModifier, Qt::Vertical);
+ QWheelEvent eventUp(wheelPoint, slider->mapToGlobal(wheelPoint), QPoint(), QPoint(0, -singleStepDelta / 2),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QVERIFY(applicationInstance->sendEvent(slider,&eventUp));
QCOMPARE(slider->sliderPosition(), 1);
QVERIFY(applicationInstance->sendEvent(slider,&eventUp));
@@ -2053,11 +2057,11 @@ void tst_QAbstractSlider::setValue()
QVERIFY(sliderMovedTimeStamp < valueChangedTimeStamp);
}
-void tst_QAbstractSlider::waitUntilTimeElapsed(const QTime& t, int ms)
+void tst_QAbstractSlider::waitUntilTimeElapsed(const QElapsedTimer &t, int ms)
{
const int eps = 80;
while (t.elapsed() < ms + eps)
- QTest::qWait(qMax(ms - t.elapsed() + eps, 25));
+ QTest::qWait(qMax(int(ms - t.elapsed() + eps), 25));
}
void tst_QAbstractSlider::setRepeatAction()
@@ -2073,7 +2077,7 @@ void tst_QAbstractSlider::setRepeatAction()
QCOMPARE(spy.count(), 0);
QCOMPARE(slider->value(), 55);
- QTime t;
+ QElapsedTimer t;
t.start();
QTest::qWait(300);
QCOMPARE(spy.count(), 0);
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index a576770811..4e16edaca8 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -254,12 +254,22 @@ void tst_QComboBox::getSetCheck()
obj1.setMaxCount(INT_MAX);
QCOMPARE(INT_MAX, obj1.maxCount());
+ // QCompleter *QComboBox::completer()
+ // void QComboBox::setCompleter(QCompleter *)
+ obj1.setCompleter(nullptr);
+ QCOMPARE(nullptr, obj1.completer());
+ QCompleter completer;
+ obj1.setCompleter(&completer);
+ QVERIFY(obj1.completer() == nullptr); // no QLineEdit is set
+
+#if QT_DEPRECATED_SINCE(5, 13)
// bool QComboBox::autoCompletion()
// void QComboBox::setAutoCompletion(bool)
obj1.setAutoCompletion(false);
QCOMPARE(false, obj1.autoCompletion());
obj1.setAutoCompletion(true);
QCOMPARE(true, obj1.autoCompletion());
+#endif
// bool QComboBox::duplicatesEnabled()
// void QComboBox::setDuplicatesEnabled(bool)
@@ -317,6 +327,9 @@ void tst_QComboBox::getSetCheck()
QCOMPARE(var8, obj1.lineEdit());
// delete var8; // No delete, since QComboBox takes ownership
+ // After setting a line edit, completer() should not return nullptr anymore
+ QVERIFY(obj1.completer() != nullptr);
+
// const QValidator * QComboBox::validator()
// void QComboBox::setValidator(const QValidator *)
QIntValidator *var9 = new QIntValidator(0);
@@ -777,7 +790,9 @@ void tst_QComboBox::virtualAutocompletion()
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QComboBox *testWidget = topLevel.comboBox();
testWidget->clear();
+#if QT_DEPRECATED_SINCE(5, 13)
testWidget->setAutoCompletion(true);
+#endif
testWidget->addItem("Foo");
testWidget->addItem("Bar");
testWidget->addItem("Boat");
@@ -837,7 +852,9 @@ void tst_QComboBox::autoCompletionCaseSensitivity()
QCOMPARE(qApp->focusWidget(), (QWidget *)testWidget);
testWidget->clear();
+#if QT_DEPRECATED_SINCE(5, 13)
testWidget->setAutoCompletion(true);
+#endif
testWidget->addItem("Cow");
testWidget->addItem("irrelevant1");
testWidget->addItem("aww");
@@ -2102,7 +2119,9 @@ void tst_QComboBox::mouseWheel()
box.setEditable(i==0?false:true);
box.setCurrentIndex(startIndex);
- QWheelEvent event = QWheelEvent(box.rect().bottomRight() , WHEEL_DELTA * wheelDirection, Qt::NoButton, Qt::NoModifier);
+ const QPoint wheelPoint = box.rect().bottomRight();
+ QWheelEvent event(wheelPoint, box.mapToGlobal(wheelPoint), QPoint(), QPoint(0, WHEEL_DELTA * wheelDirection),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QVERIFY(applicationInstance->sendEvent(&box,&event));
QCOMPARE(box.currentIndex(), expectedIndex);
@@ -2131,7 +2150,9 @@ void tst_QComboBox::popupWheelHandling()
comboBox->showPopup();
QTRY_VERIFY(comboBox->view() && comboBox->view()->isVisible());
const QPoint popupPos = comboBox->view()->pos();
- QWheelEvent event(QPointF(10, 10), WHEEL_DELTA, Qt::NoButton, Qt::NoModifier);
+ const QPoint wheelPoint(10, 10);
+ QWheelEvent event(wheelPoint, scrollArea.mapToGlobal(wheelPoint), QPoint(), QPoint(0, WHEEL_DELTA),
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
QVERIFY(QCoreApplication::sendEvent(scrollArea.windowHandle(), &event));
QCoreApplication::processEvents();
QVERIFY(comboBox->view()->isVisible());
@@ -3050,7 +3071,9 @@ void tst_QComboBox::task_QTBUG_31146_popupCompletion()
{
QComboBox comboBox;
comboBox.setEditable(true);
+#if QT_DEPRECATED_SINCE(5, 13)
comboBox.setAutoCompletion(true);
+#endif
comboBox.setInsertPolicy(QComboBox::NoInsert);
comboBox.completer()->setCaseSensitivity(Qt::CaseInsensitive);
comboBox.completer()->setCompletionMode(QCompleter::PopupCompletion);
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index b5ef454b14..26b4b7d020 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -307,19 +307,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
{
switch (modifier) {
case Qt::NoModifier:
- return QLatin1Literal("No");
+ return QLatin1String("No");
break;
case Qt::ControlModifier:
- return QLatin1Literal("Ctrl");
+ return QLatin1String("Ctrl");
break;
case Qt::ShiftModifier:
- return QLatin1Literal("Shift");
+ return QLatin1String("Shift");
break;
case Qt::AltModifier:
- return QLatin1Literal("Alt");
+ return QLatin1String("Alt");
break;
case Qt::MetaModifier:
- return QLatin1Literal("Meta");
+ return QLatin1String("Meta");
break;
default:
qFatal("Unexpected keyboard modifier");
@@ -331,25 +331,24 @@ static QLatin1String sectionToName(const QDateTimeEdit::Section section)
{
switch (section) {
case QDateTimeEdit::SecondSection:
- return QLatin1Literal("Second");
+ return QLatin1String("Second");
case QDateTimeEdit::MinuteSection:
- return QLatin1Literal("Minute");
+ return QLatin1String("Minute");
case QDateTimeEdit::HourSection:
- return QLatin1Literal("Hours");
+ return QLatin1String("Hours");
case QDateTimeEdit::DaySection:
- return QLatin1Literal("Day");
+ return QLatin1String("Day");
case QDateTimeEdit::MonthSection:
- return QLatin1Literal("Month");
+ return QLatin1String("Month");
case QDateTimeEdit::YearSection:
- return QLatin1Literal("Year");
+ return QLatin1String("Year");
default:
qFatal("Unexpected section");
return QLatin1String();
}
}
-static QDate stepDate(const QDate& startDate, const QDateTimeEdit::Section section,
- const int steps)
+static QDate stepDate(QDate startDate, const QDateTimeEdit::Section section, const int steps)
{
switch (section) {
case QDateTimeEdit::DaySection:
@@ -364,8 +363,7 @@ static QDate stepDate(const QDate& startDate, const QDateTimeEdit::Section secti
}
}
-static QTime stepTime(const QTime& startTime, const QDateTimeEdit::Section section,
- const int steps)
+static QTime stepTime(QTime startTime, const QDateTimeEdit::Section section, const int steps)
{
switch (section) {
case QDateTimeEdit::SecondSection:
@@ -3141,7 +3139,6 @@ void tst_QDateTimeEdit::wheelEvent_data()
{
#if QT_CONFIG(wheelevent)
QTest::addColumn<QPoint>("angleDelta");
- QTest::addColumn<int>("qt4Delta");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<Qt::MouseEventSource>("source");
@@ -3217,16 +3214,16 @@ void tst_QDateTimeEdit::wheelEvent_data()
QLatin1String sourceName;
switch (source) {
case Qt::MouseEventNotSynthesized:
- sourceName = QLatin1Literal("NotSynthesized");
+ sourceName = QLatin1String("NotSynthesized");
break;
case Qt::MouseEventSynthesizedBySystem:
- sourceName = QLatin1Literal("SynthesizedBySystem");
+ sourceName = QLatin1String("SynthesizedBySystem");
break;
case Qt::MouseEventSynthesizedByQt:
- sourceName = QLatin1Literal("SynthesizedByQt");
+ sourceName = QLatin1String("SynthesizedByQt");
break;
case Qt::MouseEventSynthesizedByApplication:
- sourceName = QLatin1Literal("SynthesizedByApplication");
+ sourceName = QLatin1String("SynthesizedByApplication");
break;
default:
qFatal("Unexpected wheel event source");
@@ -3255,7 +3252,6 @@ void tst_QDateTimeEdit::wheelEvent_data()
modifierName.latin1(),
sourceName.latin1())
<< angleDelta
- << units
<< static_cast<int>(stepModifier)
<< modifiers
<< source
@@ -3277,7 +3273,6 @@ void tst_QDateTimeEdit::wheelEvent()
{
#if QT_CONFIG(wheelevent)
QFETCH(QPoint, angleDelta);
- QFETCH(int, qt4Delta);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(Qt::MouseEventSource, source);
@@ -3294,9 +3289,8 @@ void tst_QDateTimeEdit::wheelEvent()
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
edit.setStyle(style.data());
- QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
- Qt::Vertical, Qt::NoButton, modifiers, Qt::NoScrollPhase,
- source);
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta,
+ Qt::NoButton, modifiers, Qt::NoScrollPhase, false, source);
QCOMPARE(edit.date(), startDate);
for (QDate expected : expectedDates) {
@@ -3454,7 +3448,7 @@ void tst_QDateTimeEdit::timeSpec()
}
QVERIFY(edit.minimumTime() != min.time());
QVERIFY(edit.minimumDateTime().timeSpec() != min.timeSpec());
- QCOMPARE(edit.minimumDateTime().toTime_t(), min.toTime_t());
+ QCOMPARE(edit.minimumDateTime().toSecsSinceEpoch(), min.toSecsSinceEpoch());
} else {
QSKIP("Not tested in the GMT timezone");
}
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index f8ce6a2c0a..625116654d 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -670,7 +670,11 @@ void tst_QDockWidget::dockLocationChanged()
spy.clear();
dw.setFloating(true);
- QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::NoDockWidgetArea);
+ spy.clear();
+
dw.setFloating(false);
QTRY_COMPARE(spy.count(), 1);
QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST b/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST
index c1b6c9693e..8f5648d0f9 100644
--- a/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST
+++ b/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST
@@ -1,2 +1,4 @@
[editingFinished]
-*
+osx-10.12
+osx-10.14
+osx-10.13
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
index 954ee6471d..c760d9cc99 100644
--- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
+++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
@@ -221,19 +221,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
{
switch (modifier) {
case Qt::NoModifier:
- return QLatin1Literal("No");
+ return QLatin1String("No");
break;
case Qt::ControlModifier:
- return QLatin1Literal("Ctrl");
+ return QLatin1String("Ctrl");
break;
case Qt::ShiftModifier:
- return QLatin1Literal("Shift");
+ return QLatin1String("Shift");
break;
case Qt::AltModifier:
- return QLatin1Literal("Alt");
+ return QLatin1String("Alt");
break;
case Qt::MetaModifier:
- return QLatin1Literal("Meta");
+ return QLatin1String("Meta");
break;
default:
qFatal("Unexpected keyboard modifier");
@@ -1377,7 +1377,6 @@ void tst_QDoubleSpinBox::wheelEvents_data()
{
#if QT_CONFIG(wheelevent)
QTest::addColumn<QPoint>("angleDelta");
- QTest::addColumn<int>("qt4Delta");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifier");
QTest::addColumn<Qt::MouseEventSource>("source");
@@ -1448,16 +1447,16 @@ void tst_QDoubleSpinBox::wheelEvents_data()
QLatin1String sourceName;
switch (source) {
case Qt::MouseEventNotSynthesized:
- sourceName = QLatin1Literal("NotSynthesized");
+ sourceName = QLatin1String("NotSynthesized");
break;
case Qt::MouseEventSynthesizedBySystem:
- sourceName = QLatin1Literal("SynthesizedBySystem");
+ sourceName = QLatin1String("SynthesizedBySystem");
break;
case Qt::MouseEventSynthesizedByQt:
- sourceName = QLatin1Literal("SynthesizedByQt");
+ sourceName = QLatin1String("SynthesizedByQt");
break;
case Qt::MouseEventSynthesizedByApplication:
- sourceName = QLatin1Literal("SynthesizedByApplication");
+ sourceName = QLatin1String("SynthesizedByApplication");
break;
default:
qFatal("Unexpected wheel event source");
@@ -1476,7 +1475,6 @@ void tst_QDoubleSpinBox::wheelEvents_data()
modifierName.latin1(),
sourceName.latin1())
<< angleDelta
- << units
<< static_cast<int>(stepModifier)
<< modifiers
<< source
@@ -1496,7 +1494,6 @@ void tst_QDoubleSpinBox::wheelEvents()
{
#if QT_CONFIG(wheelevent)
QFETCH(QPoint, angleDelta);
- QFETCH(int, qt4Delta);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifier);
QFETCH(Qt::MouseEventSource, source);
@@ -1512,9 +1509,8 @@ void tst_QDoubleSpinBox::wheelEvents()
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spinBox.setStyle(style.data());
- QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
- Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase,
- source);
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta,
+ Qt::NoButton, modifier, Qt::NoScrollPhase, false, source);
for (int expected : expectedValues) {
qApp->sendEvent(&spinBox, &event);
QCOMPARE(spinBox.value(), expected);
diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
index 1813e5ad5f..5392d36ae0 100644
--- a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
+++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
@@ -108,7 +108,7 @@ void tst_QFontComboBox::currentFont()
QFont oldCurrentFont = box.currentFont();
box.setCurrentFont(currentFont);
- QRegExp foundry(" \\[.*\\]");
+ QRegularExpression foundry(" \\[.*\\]");
if (!box.currentFont().family().contains(foundry)) {
QCOMPARE(box.currentFont(), currentFont);
}
diff --git a/tests/auto/widgets/widgets/qframe/tst_qframe.cpp b/tests/auto/widgets/widgets/qframe/tst_qframe.cpp
index 432f4474c5..05f9cd2e4a 100644
--- a/tests/auto/widgets/widgets/qframe/tst_qframe.cpp
+++ b/tests/auto/widgets/widgets/qframe/tst_qframe.cpp
@@ -37,6 +37,10 @@
class tst_QFrame : public QObject
{
Q_OBJECT
+
+public:
+ static void initMain() { QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); }
+
private slots:
void testDefaults();
void testInitStyleOption_data();
diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
index 34862f6810..f599ac73c6 100644
--- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
+++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
@@ -461,7 +461,7 @@ void tst_QLabel::unicodeText()
QVBoxLayout *layout = new QVBoxLayout();
QLabel *label = new QLabel(text, &frame);
layout->addWidget(label);
- layout->setMargin(8);
+ layout->setContentsMargins(8, 8, 8, 8);
frame.setLayout(layout);
frame.show();
QVERIFY(QTest::qWaitForWindowExposed(&frame));
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 27cc385df4..0cfbc651ad 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -3530,6 +3530,13 @@ void tst_QLineEdit::textMargin()
centerOnScreen(&tlw);
tlw.show();
+ const QMargins margins = testWidget.textMargins();
+ QCOMPARE(left, margins.left());
+ QCOMPARE(top, margins.top());
+ QCOMPARE(right, margins.right());
+ QCOMPARE(bottom, margins.bottom());
+
+#if QT_DEPRECATED_SINCE(5, 14)
int l;
int t;
int r;
@@ -3539,6 +3546,7 @@ void tst_QLineEdit::textMargin()
QCOMPARE(top, t);
QCOMPARE(right, r);
QCOMPARE(bottom, b);
+#endif
QTest::mouseClick(&testWidget, Qt::LeftButton, 0, mousePressPos);
QTRY_COMPARE(testWidget.cursorPosition(), cursorPosition);
@@ -3615,6 +3623,14 @@ void tst_QLineEdit::task174640_editingFinished()
le2->setFocus();
QTRY_VERIFY(le2->hasFocus());
+ // editingFinished will not be emitted anew because no editing happened
+ QCOMPARE(editingFinishedSpy.count(), 0);
+
+ le1->setFocus();
+ QTRY_VERIFY(le1->hasFocus());
+ QTest::keyPress(le1, Qt::Key_Plus);
+ le2->setFocus();
+ QTRY_VERIFY(le2->hasFocus());
QCOMPARE(editingFinishedSpy.count(), 1);
editingFinishedSpy.clear();
@@ -3632,6 +3648,8 @@ void tst_QLineEdit::task174640_editingFinished()
delete testMenu1;
QCOMPARE(editingFinishedSpy.count(), 0);
QTRY_VERIFY(le1->hasFocus());
+ // Ensure le1 has been edited
+ QTest::keyPress(le1, Qt::Key_Plus);
QMenu *testMenu2 = new QMenu(le2);
testMenu2->addAction("foo2");
@@ -3986,7 +4004,7 @@ void tst_QLineEdit::QTBUG7174_inputMaskCursorBlink()
edit.setFocus();
edit.setText(QLatin1String("AAAA"));
edit.show();
- QRect cursorRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
+ QRect cursorRect = edit.inputMethodQuery(Qt::ImCursorRectangle).toRect();
QVERIFY(QTest::qWaitForWindowExposed(&edit));
edit.updateRegion = QRegion();
QTest::qWait(QApplication::cursorFlashTime());
diff --git a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST
index b1c8d7dfde..1dd876ea97 100644
--- a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST
@@ -1,7 +1,16 @@
-[updateScrollBars]
-osx
[tileSubWindows]
-osx
-xcb
+ubuntu-16.04
+rhel-7.6
+opensuse-leap
+osx-10.11
+osx-10.13
+ubuntu-18.04
+osx-10.14
+rhel-7.4
+osx-10.12
+opensuse-42.3
[resizeTimer]
-osx
+osx-10.12
+osx-10.14
+osx-10.13
+
diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
index 67b79e3faf..6d38dc262f 100644
--- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
+++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
@@ -333,6 +333,7 @@ void tst_QMdiArea::subWindowActivated()
for ( i = 0; i < count; ++i ) {
QWidget *widget = new QWidget(workspace, 0);
widget->setAttribute(Qt::WA_DeleteOnClose);
+ widget->setFocus();
workspace->addSubWindow(widget)->show();
widget->show();
qApp->processEvents();
@@ -478,9 +479,6 @@ void tst_QMdiArea::subWindowActivated2()
// Check that we only emit _one_ signal and the active window
// is unchanged after hide/show.
mdiArea.hide();
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- qt_x11_wait_for_window_manager(&mdiArea);
-#endif
QTest::qWait(100);
QTRY_COMPARE(spy.count(), 1);
QVERIFY(!mdiArea.activeSubWindow());
@@ -879,7 +877,7 @@ void tst_QMdiArea::minimumSizeHint()
{
QMdiArea workspace;
workspace.show();
- QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MDIMinimizedWidth),
+ QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth),
workspace.style()->pixelMetric(QStyle::PM_TitleBarHeight));
qApp->processEvents();
QAbstractScrollArea dummyScrollArea;
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST
deleted file mode 100644
index 26d1776b0d..0000000000
--- a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[setOpaqueResizeAndMove]
-osx-10.12
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
index 2b59a227b3..3ee9c72209 100644
--- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
+++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
@@ -52,9 +52,7 @@
#include <QVector>
QT_BEGIN_NAMESPACE
-#if 1 // Used to be excluded in Qt4 for Q_WS_WIN
extern bool qt_tab_all_widgets();
-#endif
QT_END_NAMESPACE
static inline bool tabAllWidgets()
@@ -613,7 +611,7 @@ void tst_QMdiSubWindow::showShaded()
// Calculate mouse position for bottom right corner and simulate a
// vertical resize with the mouse.
- int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2;
+ int offset = window->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth) / 2;
QPoint mousePosition(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2));
QWidget *mouseReceiver = nullptr;
#ifdef Q_OS_MAC
@@ -759,7 +757,7 @@ void tst_QMdiSubWindow::setOpaqueResizeAndMove()
QTRY_COMPARE(priv->resizeTimerId, -1);
// Enter resize mode.
- int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2;
+ int offset = window->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth) / 2;
QPoint mousePosition(mouseReceiver->width() - qMax(offset, 2), mouseReceiver->height() - qMax(offset, 2));
sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton);
sendMousePress(mouseReceiver, mousePosition);
@@ -1762,7 +1760,8 @@ void tst_QMdiSubWindow::fixedMinMaxSize()
int minimizedHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
if (!subWindow->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, subWindow))
minimizedHeight += 8;
- int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MDIMinimizedWidth, &options);
+ int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth,
+ &options);
const QSize minimizedSize = QSize(minimizedWidth, minimizedHeight);
// Even though the sub window has a minimum size set, it should be possible
diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST
index bac14ea225..ad6d2f340c 100644
--- a/tests/auto/widgets/widgets/qmenu/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST
@@ -1,13 +1,13 @@
[task258920_mouseBorder]
-osx
-[submenuTearOffDontClose]
-osx-10.12 ci
+osx-10.14
+osx-10.13
[layoutDirection]
+osx-10.12
+osx-10.13
# Fails when enabling synchronous expose events QTBUG-62092
-osx ci
[pushButtonPopulateOnAboutToShow]
-osx
+osx-10.13
[tearOff]
-osx
+osx-10.14
[activeSubMenuPosition]
winrt
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index 3bfbe754ef..9c40c0bd57 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -610,7 +610,7 @@ void tst_QMenu::widgetActionFocus()
static QMenu *getTornOffMenu()
{
- foreach (QWidget *w, QApplication::allWidgets()) {
+ for (QWidget *w : QApplication::allWidgets()) {
if (w->isVisible() && w->inherits("QTornOffMenu"))
return static_cast<QMenu *>(w);
}
@@ -948,30 +948,28 @@ void tst_QMenu::menuSizeHint()
{
QMenu menu;
//this is a list of arbitrary strings so that we check the geometry
- QStringList list = QStringList() << "trer" << "ezrfgtgvqd" << "sdgzgzerzerzer" << "eerzertz" << "er";
- foreach (QString str, list)
+ for (auto str : {"trer", "ezrfgtgvqd", "sdgzgzerzerzer", "eerzertz", "er"})
menu.addAction(str);
- int left, top, right, bottom;
- menu.getContentsMargins(&left, &top, &right, &bottom);
+ const QMargins cm = menu.contentsMargins();
const int panelWidth = menu.style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, &menu);
const int hmargin = menu.style()->pixelMetric(QStyle::PM_MenuHMargin, 0, &menu),
vmargin = menu.style()->pixelMetric(QStyle::PM_MenuVMargin, 0, &menu);
int maxWidth =0;
QRect result;
- foreach (QAction *action, menu.actions()) {
+ for (QAction *action : menu.actions()) {
maxWidth = qMax(maxWidth, menu.actionGeometry(action).width());
result |= menu.actionGeometry(action);
- QCOMPARE(result.x(), left + hmargin + panelWidth);
- QCOMPARE(result.y(), top + vmargin + panelWidth);
+ QCOMPARE(result.x(), cm.left() + hmargin + panelWidth);
+ QCOMPARE(result.y(), cm.top() + vmargin + panelWidth);
}
QStyleOption opt(0);
opt.rect = menu.rect();
opt.state = QStyle::State_None;
- QSize resSize = QSize(result.x(), result.y()) + result.size() + QSize(hmargin + right + panelWidth, vmargin + top + panelWidth);
+ QSize resSize = QSize(result.x(), result.y()) + result.size() + QSize(hmargin + cm.right() + panelWidth, vmargin + cm.top() + panelWidth);
resSize = menu.style()->sizeFromContents(QStyle::CT_Menu, &opt,
resSize.expandedTo(QApplication::globalStrut()), &menu);
@@ -1572,8 +1570,7 @@ void tst_QMenu::menuSize_Scrolling()
int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin, nullptr, this);
int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this);
- int leftMargin, topMargin, rightMargin, bottomMargin;
- getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ const QMargins cm = contentsMargins();
QRect lastItem = actionGeometry(actions().at(actions().length() - 1));
QSize s = size();
#ifdef Q_OS_WINRT
@@ -1586,7 +1583,7 @@ void tst_QMenu::menuSize_Scrolling()
return;
}
- QCOMPARE( s.width(), lastItem.right() + fw + hmargin + rightMargin + 1);
+ QCOMPARE( s.width(), lastItem.right() + fw + hmargin + cm.right() + 1);
QMenu::showEvent(e);
}
diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
index f897797f00..c9e15e531c 100644
--- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
@@ -3,6 +3,6 @@ ubuntu-16.04
#QTBUG-66255
ubuntu-18.04
[activatedCount]
-*
+opensuse-42.3
[QTBUG_65488_hiddenActionTriggered]
winrt
diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
index cb829c81a6..d6ba85d61f 100644
--- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
+++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
@@ -113,10 +113,7 @@ private slots:
void check_escKey();
#endif
-#ifndef Q_OS_WINCE
void allowActiveAndDisabled();
-#endif
-
void taskQTBUG56860_focus();
void check_endKey();
void check_homeKey();
diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST
index b67c8354e8..b281eca3bf 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST
+++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST
@@ -1,5 +1,3 @@
-[clearAndGrab]
-ubuntu
-
[stackWidgetOpaqueChildIsVisible]
-windows
+windows-10 msvc-2017
+
diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
index 21c9f41646..76f8ebc804 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
+++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
@@ -49,6 +49,9 @@ class tst_QOpenGLWidget : public QObject
{
Q_OBJECT
+public:
+ static void initMain() { QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); }
+
private slots:
void initTestCase();
void create();
diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
index df5ff9d448..f2f9cfc009 100644
--- a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
+++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
@@ -171,11 +171,8 @@ void tst_QProgressBar::format()
bar.setFormat("%v of %m (%p%)");
qApp->processEvents();
-#ifndef Q_OS_MAC
+#if !defined(Q_OS_MACOS) && !defined(Q_OS_WIN)
// Animated scroll bars get paint events all the time
-#ifdef Q_OS_WIN
- if (QSysInfo::WindowsVersion < QSysInfo::WV_VISTA)
-#endif
QVERIFY(!bar.repainted);
#endif
diff --git a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
index d1923e4bb0..9f08bd337b 100644
--- a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
@@ -87,7 +87,7 @@ public:
protected:
QVariant inputMethodQuery(Qt::InputMethodQuery query) const
{
- if (query == Qt::ImMicroFocus)
+ if (query == Qt::ImCursorRectangle)
return QRect(width() / 2, height() / 2, 5, 5);
return QWidget::inputMethodQuery(query);
}
@@ -110,7 +110,7 @@ void tst_QScrollArea::ensureMicroFocusVisible_Task_167838()
parent->resize(300, 300);
scrollArea.setWidget(parent);
scrollArea.ensureWidgetVisible(child, 10, 10);
- QRect microFocus = child->inputMethodQuery(Qt::ImMicroFocus).toRect();
+ QRect microFocus = child->inputMethodQuery(Qt::ImCursorRectangle).toRect();
QPoint p = child->mapTo(scrollArea.viewport(), microFocus.topLeft());
microFocus.translate(p - microFocus.topLeft());
QVERIFY(scrollArea.viewport()->rect().contains(microFocus));
diff --git a/tests/auto/widgets/widgets/qscrollbar/BLACKLIST b/tests/auto/widgets/widgets/qscrollbar/BLACKLIST
deleted file mode 100644
index 277ae4d260..0000000000
--- a/tests/auto/widgets/widgets/qscrollbar/BLACKLIST
+++ /dev/null
@@ -1,3 +0,0 @@
-#QTBUG-66321
-[QTBUG_42871]
-macos
diff --git a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp
index 278f5cdd68..339ff293f4 100644
--- a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp
+++ b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp
@@ -151,8 +151,11 @@ void tst_QScrollBar::QTBUG_27308()
testWidget.setValue(testWidget.minimum());
testWidget.setEnabled(false);
- QWheelEvent event(testWidget.rect().center(),
- -WHEEL_DELTA, Qt::NoButton, Qt::NoModifier, testWidget.orientation());
+ const QPoint wheelPoint = testWidget.rect().center();
+ const QPoint angleDelta(testWidget.orientation() == Qt::Horizontal ? -WHEEL_DELTA : 0,
+ testWidget.orientation() == Qt::Vertical ? -WHEEL_DELTA : 0);
+ QWheelEvent event(wheelPoint, testWidget.mapToGlobal(wheelPoint), QPoint(), angleDelta,
+ Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
qApp->sendEvent(&testWidget, &event);
QCOMPARE(testWidget.value(), testWidget.minimum());
}
diff --git a/tests/auto/widgets/widgets/qspinbox/BLACKLIST b/tests/auto/widgets/widgets/qspinbox/BLACKLIST
index a38511bfb4..96a7732165 100644
--- a/tests/auto/widgets/widgets/qspinbox/BLACKLIST
+++ b/tests/auto/widgets/widgets/qspinbox/BLACKLIST
@@ -1,3 +1,2 @@
[stepModifierPressAndHold]
-opensuse ci # QTBUG-69492
-opensuse-leap ci
+opensuse-42.3
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
index 52d7dad7cf..d75e701d1c 100644
--- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -206,7 +206,7 @@ private slots:
void stepModifierPressAndHold_data();
void stepModifierPressAndHold();
public slots:
- void valueChangedHelper(const QString &);
+ void textChangedHelper(const QString &);
void valueChangedHelper(int);
private:
QStringList actualTexts;
@@ -222,19 +222,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
{
switch (modifier) {
case Qt::NoModifier:
- return QLatin1Literal("No");
+ return QLatin1String("No");
break;
case Qt::ControlModifier:
- return QLatin1Literal("Ctrl");
+ return QLatin1String("Ctrl");
break;
case Qt::ShiftModifier:
- return QLatin1Literal("Shift");
+ return QLatin1String("Shift");
break;
case Qt::AltModifier:
- return QLatin1Literal("Alt");
+ return QLatin1String("Alt");
break;
case Qt::MetaModifier:
- return QLatin1Literal("Meta");
+ return QLatin1String("Meta");
break;
default:
qFatal("Unexpected keyboard modifier");
@@ -490,7 +490,7 @@ void tst_QSpinBox::setPrefixSuffix()
}
}
-void tst_QSpinBox::valueChangedHelper(const QString &text)
+void tst_QSpinBox::textChangedHelper(const QString &text)
{
actualTexts << text;
}
@@ -568,7 +568,7 @@ void tst_QSpinBox::setTracking()
QSpinBox spin(0);
spin.setKeyboardTracking(tracking);
spin.show();
- connect(&spin, SIGNAL(valueChanged(QString)), this, SLOT(valueChangedHelper(QString)));
+ connect(&spin, &QSpinBox::textChanged, this, &tst_QSpinBox::textChangedHelper);
keys.simulate(&spin);
QCOMPARE(actualTexts, texts);
@@ -1331,7 +1331,6 @@ void tst_QSpinBox::wheelEvents_data()
{
#if QT_CONFIG(wheelevent)
QTest::addColumn<QPoint>("angleDelta");
- QTest::addColumn<int>("qt4Delta");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifier");
QTest::addColumn<Qt::MouseEventSource>("source");
@@ -1402,16 +1401,16 @@ void tst_QSpinBox::wheelEvents_data()
QLatin1String sourceName;
switch (source) {
case Qt::MouseEventNotSynthesized:
- sourceName = QLatin1Literal("NotSynthesized");
+ sourceName = QLatin1String("NotSynthesized");
break;
case Qt::MouseEventSynthesizedBySystem:
- sourceName = QLatin1Literal("SynthesizedBySystem");
+ sourceName = QLatin1String("SynthesizedBySystem");
break;
case Qt::MouseEventSynthesizedByQt:
- sourceName = QLatin1Literal("SynthesizedByQt");
+ sourceName = QLatin1String("SynthesizedByQt");
break;
case Qt::MouseEventSynthesizedByApplication:
- sourceName = QLatin1Literal("SynthesizedByApplication");
+ sourceName = QLatin1String("SynthesizedByApplication");
break;
default:
qFatal("Unexpected wheel event source");
@@ -1430,7 +1429,6 @@ void tst_QSpinBox::wheelEvents_data()
modifierName.latin1(),
sourceName.latin1())
<< angleDelta
- << units
<< static_cast<int>(stepModifier)
<< modifiers
<< source
@@ -1450,7 +1448,6 @@ void tst_QSpinBox::wheelEvents()
{
#if QT_CONFIG(wheelevent)
QFETCH(QPoint, angleDelta);
- QFETCH(int, qt4Delta);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifier);
QFETCH(Qt::MouseEventSource, source);
@@ -1466,9 +1463,8 @@ void tst_QSpinBox::wheelEvents()
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spinBox.setStyle(style.data());
- QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
- Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase,
- source);
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta,
+ Qt::NoButton, modifier, Qt::NoScrollPhase, false, source);
for (int expected : expectedValues) {
qApp->sendEvent(&spinBox, &event);
QCOMPARE(spinBox.value(), expected);
diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
index 8b45ac20b7..cbeb77a25e 100644
--- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
+++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
@@ -599,7 +599,7 @@ void tst_QSplitter::testShowHide()
QWidget widget(&topLevel);
widget.resize(400 + split->handleWidth(), 200);
QVBoxLayout *lay=new QVBoxLayout(&widget);
- lay->setMargin(0);
+ lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
split->addWidget(new QWidget);
split->addWidget(new QWidget);
diff --git a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
index 6523209c32..b61cc8fa13 100644
--- a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
+++ b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
@@ -8,4 +8,4 @@ INCLUDEPATH += ../
HEADERS +=
SOURCES += tst_qtabwidget.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp
index cbf5196bb9..feade7d443 100644
--- a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp
+++ b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp
@@ -620,7 +620,7 @@ void tst_QTabWidget::heightForWidth()
QWidget *window = new QWidget;
QVBoxLayout *lay = new QVBoxLayout(window);
- lay->setMargin(0);
+ lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
QTabWidget *tabWid = new QTabWidget(window);
QWidget *w = new QWidget;
@@ -637,7 +637,7 @@ void tst_QTabWidget::heightForWidth()
);
label->setWordWrap(true);
lay2->addWidget(label);
- lay2->setMargin(0);
+ lay2->setContentsMargins(0, 0, 0, 0);
lay->addWidget(tabWid);
int h = window->heightForWidth(160);
diff --git a/tests/auto/widgets/widgets/qtextbrowser/heading.html b/tests/auto/widgets/widgets/qtextbrowser/heading.html
new file mode 100644
index 0000000000..8b23807f65
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/heading.html
@@ -0,0 +1,2 @@
+<h3>this is a heading</h3>
+<p>this is a paragraph</p>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/markdown.md b/tests/auto/widgets/widgets/qtextbrowser/markdown.md
new file mode 100644
index 0000000000..be56aef234
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/markdown.md
@@ -0,0 +1,2 @@
+### this is a heading
+this is a paragraph
diff --git a/tests/auto/widgets/widgets/qtextbrowser/markdown.really b/tests/auto/widgets/widgets/qtextbrowser/markdown.really
new file mode 100644
index 0000000000..be56aef234
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/markdown.really
@@ -0,0 +1,2 @@
+### this is a heading
+this is a paragraph
diff --git a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
index 9680ffd871..dfdcf26497 100644
--- a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
+++ b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
@@ -4,6 +4,6 @@ SOURCES += tst_qtextbrowser.cpp
QT += widgets testlib
-TESTDATA += *.html subdir/*
+TESTDATA += *.html *.md markdown.really subdir/*
builtin_testdata: DEFINES += BUILTIN_TESTDATA
diff --git a/tests/auto/widgets/widgets/qtextbrowser/quotesAndFractions.md b/tests/auto/widgets/widgets/qtextbrowser/quotesAndFractions.md
new file mode 100644
index 0000000000..6bad9cb95b
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/quotesAndFractions.md
@@ -0,0 +1 @@
+you’ll hope to see âquotesâž ï¹ 1½ â…” ¼ â…— â…š â… some “vulgar†fractions (pardon my «French»)
diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
index 8a1b228c71..27bf0ce7be 100644
--- a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
+++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -38,7 +38,7 @@
class TestBrowser : public QTextBrowser
{
public:
- inline TestBrowser() : htmlLoadAttempts(0) {
+ inline TestBrowser() {
show();
QApplication::setActiveWindow(this);
activateWindow();
@@ -47,11 +47,12 @@ public:
QVERIFY(hasFocus());
}
- virtual QVariant loadResource(int type, const QUrl &name);
+ QVariant loadResource(int type, const QUrl &name) override;
- int htmlLoadAttempts;
+ int htmlLoadAttempts = 0;
QUrl lastResource;
QUrl sourceInsideLoadResource;
+ QUrl baseInsideLoadResource;
};
QVariant TestBrowser::loadResource(int type, const QUrl &name)
@@ -60,6 +61,7 @@ QVariant TestBrowser::loadResource(int type, const QUrl &name)
htmlLoadAttempts++;
lastResource = name;
sourceInsideLoadResource = source();
+ baseInsideLoadResource = document()->baseUrl();
return QTextBrowser::loadResource(type, name);
}
@@ -90,6 +92,10 @@ private slots:
void focusIndicator();
void focusHistory();
void urlEncoding();
+ void sourceType_data();
+ void sourceType();
+ void unicode_data();
+ void unicode();
private:
TestBrowser *browser;
@@ -108,7 +114,7 @@ void tst_QTextBrowser::init()
void tst_QTextBrowser::cleanup()
{
delete browser;
- browser = 0;
+ browser = nullptr;
}
void tst_QTextBrowser::noReloadOnAnchorJump()
@@ -428,11 +434,18 @@ void tst_QTextBrowser::sourceInsideLoadResource()
#ifdef Q_OS_WINRT
QSKIP("Paths cannot be compared if applications are sandboxed.");
#endif
- QUrl url = QUrl::fromLocalFile("pagewithimage.html");
+ QUrl url = QUrl::fromLocalFile("pagewithimage.html"); // "file://pagewithimage.html"
browser->setSource(url);
QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
+ // baseUrl was not set because the source URL was a relative one
+ QCOMPARE(browser->baseInsideLoadResource, QUrl());
QEXPECT_FAIL("", "This is currently not supported", Continue);
QCOMPARE(browser->sourceInsideLoadResource.toString(), url.toString());
+ url = QUrl::fromLocalFile(QDir::current().filePath("pagewithimage.html")); // "file:///home/user/path/to/pagewithimage.html"
+ browser->setSource(url);
+ QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
+ // baseUrl has the full path, and that's where relative-path resources come from
+ QCOMPARE(browser->baseInsideLoadResource, QUrl::fromLocalFile(QDir::currentPath() + QLatin1Char('/')));
}
void tst_QTextBrowser::textInteractionFlags_vs_readOnly()
@@ -669,5 +682,72 @@ void tst_QTextBrowser::urlEncoding()
delete browser;
}
+void tst_QTextBrowser::sourceType_data()
+{
+ QTest::addColumn<QString>("sourceFile");
+ QTest::addColumn<QTextDocument::ResourceType>("sourceType");
+ QTest::addColumn<int>("expectedMaxHeadingLevel");
+ QTest::addColumn<QTextDocument::ResourceType>("expectedSourceType");
+
+#if QT_CONFIG(textmarkdownreader)
+ const int maxMdHeadingLevel = 3;
+ const QTextDocument::ResourceType mdExpectedType = QTextDocument::MarkdownResource;
+#else
+ // If Qt doesn't support markdown, and we read a MD document anyway, it won't have any H3's.
+ const int maxMdHeadingLevel = 0;
+ const QTextDocument::ResourceType mdExpectedType = QTextDocument::HtmlResource;
+#endif
+ QTest::newRow("markdown detected") << "markdown.md" << QTextDocument::UnknownResource << maxMdHeadingLevel << mdExpectedType;
+ QTest::newRow("markdown specified") << "markdown.really" << QTextDocument::MarkdownResource << maxMdHeadingLevel << mdExpectedType;
+ QTest::newRow("markdown not identified") << "markdown.really" << QTextDocument::UnknownResource << 0 << QTextDocument::HtmlResource;
+ QTest::newRow("html detected") << "heading.html" << QTextDocument::UnknownResource << 3 << QTextDocument::HtmlResource;
+ QTest::newRow("html specified") << "heading.html" << QTextDocument::HtmlResource << 3 << QTextDocument::HtmlResource;
+}
+
+void tst_QTextBrowser::sourceType()
+{
+ QFETCH(QString, sourceFile);
+ QFETCH(QTextDocument::ResourceType, sourceType);
+ QFETCH(int, expectedMaxHeadingLevel);
+ QFETCH(QTextDocument::ResourceType, expectedSourceType);
+ if (sourceType == QTextDocument::UnknownResource)
+ // verify that the property setter works, with its default parameter for sourceType
+ browser->setProperty("source", QUrl::fromLocalFile(QFINDTESTDATA(sourceFile)));
+ else
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA(sourceFile)), sourceType);
+ QCOMPARE(browser->sourceType(), expectedSourceType);
+ QTextFrame::iterator iterator = browser->document()->rootFrame()->begin();
+ int maxHeadingLevel = -1;
+ while (!iterator.atEnd())
+ maxHeadingLevel = qMax(iterator++.currentBlock().blockFormat().intProperty(QTextFormat::HeadingLevel), maxHeadingLevel);
+ QCOMPARE(maxHeadingLevel, expectedMaxHeadingLevel);
+}
+
+void tst_QTextBrowser::unicode_data()
+{
+ QTest::addColumn<QString>("sourceFile");
+ QTest::addColumn<QTextDocument::ResourceType>("sourceType");
+ QTest::addColumn<QString>("expectedText");
+
+#if QT_CONFIG(textmarkdownreader)
+ QTest::newRow("markdown with quotes and fractions") << "quotesAndFractions.md" << QTextDocument::MarkdownResource <<
+ "you\u2019ll hope to see \u275Dquotes\u275E \uFE601\u00BD \u2154 \u00BC \u2157 \u215A \u215D some \u201Cvulgar\u201D fractions (pardon my \u00ABFrench\u00BB)";
+#endif
+}
+
+void tst_QTextBrowser::unicode()
+{
+ QFETCH(QString, sourceFile);
+ QFETCH(QTextDocument::ResourceType, sourceType);
+ QFETCH(QString, expectedText);
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA(sourceFile)), sourceType);
+ QTextFrame::iterator iterator = browser->document()->rootFrame()->begin();
+ while (!iterator.atEnd()) {
+ QString blockText = iterator++.currentBlock().text();
+ if (!blockText.isEmpty())
+ QCOMPARE(blockText, expectedText);
+ }
+}
+
QTEST_MAIN(tst_QTextBrowser)
#include "tst_qtextbrowser.moc"
diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
index 3669935823..c2cf31bfa4 100644
--- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
+++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
@@ -160,6 +160,7 @@ private slots:
void selectionChanged();
#ifndef QT_NO_CLIPBOARD
void copyPasteBackgroundImage();
+ void copyPasteForegroundImage();
#endif
void setText();
void cursorRect();
@@ -1904,6 +1905,36 @@ void tst_QTextEdit::copyPasteBackgroundImage()
ba.texture().cacheKey() == bb.texture().cacheKey());
QFile::remove(QLatin1String("foo.png"));
}
+
+void tst_QTextEdit::copyPasteForegroundImage()
+{
+ ed->clear();
+
+ QPixmap pix(20, 20);
+ pix.fill(Qt::blue);
+
+ QTextCharFormat fmt;
+ {
+ QBrush textureBrush;
+ {
+ textureBrush.setTexture(pix);
+ }
+ textureBrush.setStyle(Qt::TexturePattern);
+ fmt.setForeground(textureBrush);
+ }
+ ed->textCursor().insertText("Foobar", fmt);
+
+ ed->moveCursor(QTextCursor::Start);
+ ed->moveCursor(QTextCursor::End, QTextCursor::KeepAnchor);
+
+ ed->copy();
+ ed->clear();
+ ed->paste();
+
+ QBrush brush = ed->textCursor().charFormat().foreground();
+ QCOMPARE(brush.style(), Qt::TexturePattern);
+ QCOMPARE(brush.texture().cacheKey(), pix.cacheKey());
+}
#endif
void tst_QTextEdit::setText()
@@ -2638,12 +2669,14 @@ void tst_QTextEdit::wheelEvent()
ed.setReadOnly(true);
float defaultFontSize = ed.font().pointSizeF();
- QWheelEvent wheelUp(QPointF(), QPointF(), QPoint(), QPoint(0, 120), 120, Qt::Vertical, Qt::NoButton, Qt::ControlModifier);
+ QWheelEvent wheelUp(QPointF(), QPointF(), QPoint(), QPoint(0, 120),
+ Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, Qt::MouseEventNotSynthesized);
ed.wheelEvent(&wheelUp);
QCOMPARE(defaultFontSize + 1, ed.font().pointSizeF());
- QWheelEvent wheelHalfDown(QPointF(), QPointF(), QPoint(), QPoint(0, -60), -60, Qt::Vertical, Qt::NoButton, Qt::ControlModifier);
+ QWheelEvent wheelHalfDown(QPointF(), QPointF(), QPoint(), QPoint(0, -60),
+ Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, Qt::MouseEventNotSynthesized);
ed.wheelEvent(&wheelHalfDown);
QCOMPARE(defaultFontSize + 0.5, ed.font().pointSizeF());
diff --git a/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST b/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST
index df4fda196f..52ba36562f 100644
--- a/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST
+++ b/tests/auto/widgets/widgets/qtoolbutton/BLACKLIST
@@ -1,2 +1,2 @@
[task176137_autoRepeatOfAction]
-osx ci
+osx-10.13
diff --git a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp
index 752e39c23f..d40c8c2fd6 100644
--- a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp
+++ b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp
@@ -34,6 +34,7 @@
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
+#include <QElapsedTimer>
#include <QtDebug>
#include <QtTest/QtTest>
#include <QXmlDefaultHandler>
@@ -259,7 +260,7 @@ public:
// Delibrately wait a maximum of 10 seconds for the sake
// of the test, so it doesn't unduly hang
const int waitTime = qMax(10000, msecs);
- QTime t;
+ QElapsedTimer t;
t.start();
while (t.elapsed() < waitTime) {
QCoreApplication::processEvents();
diff --git a/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp b/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp
index 15f10232bd..b5d9fea315 100644
--- a/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp
+++ b/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp
@@ -72,7 +72,7 @@ int main(int argc, const char *argv[])
QFile in_file(file_name);
if (!in_file.open(QIODevice::ReadOnly)) {
- qerr << "Could not open " << file_name << ": " << strerror(errno) << endl;
+ qerr << "Could not open " << file_name << ": " << strerror(errno) << Qt::endl;
return 1;
}
@@ -87,7 +87,7 @@ int main(int argc, const char *argv[])
} else {
_out_file.setFileName(out_file_name);
if (!_out_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- qerr << "Could not open " << out_file_name << ": " << strerror(errno) << endl;
+ qerr << "Could not open " << out_file_name << ": " << strerror(errno) << Qt::endl;
return 1;
}
_out_stream.setDevice(&_out_file);
diff --git a/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp b/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp
index 17351883c3..556603a681 100644
--- a/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp
+++ b/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp
@@ -28,7 +28,7 @@
#include <qxml.h>
-#include <qregexp.h>
+#include <qregularexpression.h>
#include "parser.h"
@@ -139,11 +139,11 @@ bool ContentHandler::startElement(const QString &namespaceURI,
QString ContentHandler::escapeStr(const QString &s)
{
QString result = s;
- result.replace(QRegExp("\""), "\\\"");
- result.replace(QRegExp("\\"), "\\\\");
- result.replace(QRegExp("\n"), "\\n");
- result.replace(QRegExp("\r"), "\\r");
- result.replace(QRegExp("\t"), "\\t");
+ result.replace(QRegularExpression("\""), "\\\"");
+ result.replace(QRegularExpression("\\"), "\\\\");
+ result.replace(QRegularExpression("\n"), "\\n");
+ result.replace(QRegularExpression("\r"), "\\r");
+ result.replace(QRegularExpression("\t"), "\\t");
return result;
}
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak
deleted file mode 100644
index 2d80c8f3fb..0000000000
--- a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE doc [
-<!ENTITY e "&#x10000;&#x10FFFD;&#x10FFFF;">
-<!ELEMENT doc (#PCDATA)>
-]>
-<doc>&e;</doc>
diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp
index c9f9cd9bd2..aa496d6c54 100644
--- a/tests/baselineserver/shared/baselineprotocol.cpp
+++ b/tests/baselineserver/shared/baselineprotocol.cpp
@@ -38,6 +38,7 @@
#include <QDir>
#include <QTime>
#include <QPointer>
+#include <QRegExp>
const QString PI_Project(QLS("Project"));
const QString PI_TestCase(QLS("TestCase"));
@@ -291,7 +292,8 @@ void ImageItem::writeImageToStream(QDataStream &out) const
out << quint8('Q') << quint8(image.format());
out << quint8(QSysInfo::ByteOrder) << quint8(0); // pad to multiple of 4 bytes
out << quint32(image.width()) << quint32(image.height()) << quint32(image.bytesPerLine());
- out << qCompress((const uchar *)image.constBits(), image.byteCount());
+ out << qCompress(reinterpret_cast<const uchar *>(image.constBits()),
+ int(image.sizeInBytes()));
//# can be followed by colormap for formats that use it
}
diff --git a/tests/benchmarks/corelib/corelib.pro b/tests/benchmarks/corelib/corelib.pro
index b5781ad49e..010abd7751 100644
--- a/tests/benchmarks/corelib/corelib.pro
+++ b/tests/benchmarks/corelib/corelib.pro
@@ -4,7 +4,9 @@ SUBDIRS = \
json \
mimetypes \
kernel \
+ text \
thread \
+ time \
tools \
codecs \
plugin
diff --git a/tests/benchmarks/corelib/io/qdiriterator/main.cpp b/tests/benchmarks/corelib/io/qdiriterator/main.cpp
index e71daccf7d..eae752d99a 100644
--- a/tests/benchmarks/corelib/io/qdiriterator/main.cpp
+++ b/tests/benchmarks/corelib/io/qdiriterator/main.cpp
@@ -78,24 +78,22 @@ void tst_qdiriterator::data()
}
#ifdef Q_OS_WIN
-static int posix_helper(const wchar_t *dirpath)
+static int posix_helper(const wchar_t *dirpath, size_t length)
{
int count = 0;
HANDLE hSearch;
WIN32_FIND_DATA fd;
- const size_t origDirPathLength = wcslen(dirpath);
-
wchar_t appendedPath[MAX_PATH];
- wcscpy(appendedPath, dirpath);
- wcscat(appendedPath, L"\\*");
+ Q_ASSERT(MAX_PATH > length + 3);
+ wcsncpy(appendedPath, dirpath, length);
+ wcscpy(appendedPath + length, L"\\*");
#ifndef Q_OS_WINRT
hSearch = FindFirstFile(appendedPath, &fd);
#else
hSearch = FindFirstFileEx(appendedPath, FindExInfoStandard, &fd,
FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
#endif
- appendedPath[origDirPathLength] = 0;
if (hSearch == INVALID_HANDLE_VALUE) {
qWarning("FindFirstFile failed");
@@ -107,10 +105,12 @@ static int posix_helper(const wchar_t *dirpath)
!(fd.cFileName[0] == L'.' && fd.cFileName[1] == L'.' && fd.cFileName[2] == 0))
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- wcscat(appendedPath, L"\\");
- wcscat(appendedPath, fd.cFileName);
- count += posix_helper(appendedPath);
- appendedPath[origDirPathLength] = 0;
+ // newLength will "point" to where we put a * earlier, so we overwrite that.
+ size_t newLength = length + 1; // "+ 1" for directory separator
+ Q_ASSERT(newLength + wcslen(fd.cFileName) + 1 < MAX_PATH); // "+ 1" for null-terminator
+ wcscpy(appendedPath + newLength, fd.cFileName);
+ newLength += wcslen(fd.cFileName);
+ count += posix_helper(appendedPath, newLength);
}
else {
++count;
@@ -164,8 +164,8 @@ void tst_qdiriterator::posix()
QBENCHMARK {
#ifdef Q_OS_WIN
wchar_t wPath[MAX_PATH];
- path.toWCharArray(wPath);
- count = posix_helper(wPath);
+ const int end = path.toWCharArray(wPath);
+ count = posix_helper(wPath, end);
#else
count = posix_helper(dirpath.constData());
#endif
diff --git a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp
index d68264b78f..6ee8b4e93b 100644
--- a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp
+++ b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp
@@ -218,8 +218,9 @@ void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path)
#ifdef Q_OS_WIN
wchar_t szSearchPath[MAX_PATH];
- QString::fromLatin1(path).toWCharArray(szSearchPath);
- wcscat(szSearchPath, L"\\*");
+ const int end = QString::fromLatin1(path + "\\*").toWCharArray(szSearchPath);
+ Q_ASSERT(end < MAX_PATH);
+ szSearchPath[end] = L'\0';
#ifndef Q_OS_WINRT
HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult);
#else
diff --git a/tests/benchmarks/corelib/kernel/kernel.pro b/tests/benchmarks/corelib/kernel/kernel.pro
index 02eeeaa254..92f7174419 100644
--- a/tests/benchmarks/corelib/kernel/kernel.pro
+++ b/tests/benchmarks/corelib/kernel/kernel.pro
@@ -5,7 +5,8 @@ SUBDIRS = \
qmetatype \
qobject \
qvariant \
- qcoreapplication
+ qcoreapplication \
+ qtimer_vs_qmetaobject
!qtHaveModule(widgets): SUBDIRS -= \
qmetaobject \
diff --git a/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp b/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
index 66a29780f0..6af5b8d586 100644
--- a/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
+++ b/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
@@ -28,6 +28,7 @@
#include <QtCore>
#include <QtTest/QtTest>
+#include <QThread>
#define INVOKE_COUNT 10000
@@ -35,8 +36,10 @@ class qtimer_vs_qmetaobject : public QObject
{
Q_OBJECT
private slots:
- void testZeroTimerSingleShot();
- void testQueuedInvokeMethod();
+ void bench();
+ void bench_data();
+ void benchBackgroundThread();
+ void benchBackgroundThread_data() { bench_data(); }
};
class InvokeCounter : public QObject {
@@ -47,36 +50,89 @@ public slots:
void invokeSlot() {
count++;
if (count == INVOKE_COUNT)
- QTestEventLoop::instance().exitLoop();
+ emit allInvoked();
}
+signals:
+ void allInvoked();
protected:
int count;
};
-void qtimer_vs_qmetaobject::testZeroTimerSingleShot()
+void qtimer_vs_qmetaobject::bench()
{
+ QFETCH(int, type);
+
+ std::function<void(InvokeCounter*)> invoke;
+ if (type == 0) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, invokeCounter, SLOT(invokeSlot()));
+ };
+ } else if (type == 1) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, invokeCounter, &InvokeCounter::invokeSlot);
+ };
+ } else if (type == 2) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, invokeCounter, [invokeCounter]() {
+ invokeCounter->invokeSlot();
+ });
+ };
+ } else if (type == 3) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, [invokeCounter]() {
+ invokeCounter->invokeSlot();
+ });
+ };
+ } else if (type == 4) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QMetaObject::invokeMethod(invokeCounter, "invokeSlot", Qt::QueuedConnection);
+ };
+ } else if (type == 5) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QMetaObject::invokeMethod(invokeCounter, &InvokeCounter::invokeSlot, Qt::QueuedConnection);
+ };
+ } else if (type == 6) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QMetaObject::invokeMethod(invokeCounter, [invokeCounter]() {
+ invokeCounter->invokeSlot();
+ }, Qt::QueuedConnection);
+ };
+ } else {
+ QFAIL("unhandled data tag");
+ }
+
QBENCHMARK {
InvokeCounter invokeCounter;
+ QSignalSpy spy(&invokeCounter, &InvokeCounter::allInvoked);
for(int i = 0; i < INVOKE_COUNT; ++i) {
- QTimer::singleShot(0, &invokeCounter, SLOT(invokeSlot()));
+ invoke(&invokeCounter);
}
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(spy.wait(10000));
}
}
-void qtimer_vs_qmetaobject::testQueuedInvokeMethod()
+void qtimer_vs_qmetaobject::bench_data()
{
- QBENCHMARK {
- InvokeCounter invokeCounter;
- for(int i = 0; i < INVOKE_COUNT; ++i) {
- QMetaObject::invokeMethod(&invokeCounter, "invokeSlot", Qt::QueuedConnection);
- }
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- }
+ QTest::addColumn<int>("type");
+ QTest::addRow("singleShot_slot") << 0;
+ QTest::addRow("singleShot_pmf") << 1;
+ QTest::addRow("singleShot_functor") << 2;
+ QTest::addRow("singleShot_functor_noctx") << 3;
+ QTest::addRow("invokeMethod_string") << 4;
+ QTest::addRow("invokeMethod_pmf") << 5;
+ QTest::addRow("invokeMethod_functor") << 6;
}
+void qtimer_vs_qmetaobject::benchBackgroundThread()
+{
+#if !QT_CONFIG(cxx11_future)
+ QSKIP("This test requires QThread::create");
+#else
+ QScopedPointer<QThread> thread(QThread::create([this]() { bench(); }));
+ thread->start();
+ QVERIFY(thread->wait());
+#endif
+}
QTEST_MAIN(qtimer_vs_qmetaobject)
diff --git a/tests/benchmarks/corelib/tools/qbytearray/main.cpp b/tests/benchmarks/corelib/text/qbytearray/main.cpp
index e421e7436b..e421e7436b 100644
--- a/tests/benchmarks/corelib/tools/qbytearray/main.cpp
+++ b/tests/benchmarks/corelib/text/qbytearray/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qbytearray/qbytearray.pro b/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro
index cf28b0247f..cf28b0247f 100644
--- a/tests/benchmarks/corelib/tools/qbytearray/qbytearray.pro
+++ b/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro
diff --git a/tests/benchmarks/corelib/tools/qchar/main.cpp b/tests/benchmarks/corelib/text/qchar/main.cpp
index 4dcf86786d..4dcf86786d 100644
--- a/tests/benchmarks/corelib/tools/qchar/main.cpp
+++ b/tests/benchmarks/corelib/text/qchar/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qchar/qchar.pro b/tests/benchmarks/corelib/text/qchar/qchar.pro
index 80a9861f48..80a9861f48 100644
--- a/tests/benchmarks/corelib/tools/qchar/qchar.pro
+++ b/tests/benchmarks/corelib/text/qchar/qchar.pro
diff --git a/tests/benchmarks/corelib/tools/qlocale/main.cpp b/tests/benchmarks/corelib/text/qlocale/main.cpp
index 38d94af143..38d94af143 100644
--- a/tests/benchmarks/corelib/tools/qlocale/main.cpp
+++ b/tests/benchmarks/corelib/text/qlocale/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qlocale/qlocale.pro b/tests/benchmarks/corelib/text/qlocale/qlocale.pro
index e56bbe0341..e56bbe0341 100644
--- a/tests/benchmarks/corelib/tools/qlocale/qlocale.pro
+++ b/tests/benchmarks/corelib/text/qlocale/qlocale.pro
diff --git a/tests/benchmarks/corelib/tools/qregexp/main.cpp b/tests/benchmarks/corelib/text/qregexp/main.cpp
index 798b23f2b0..798b23f2b0 100644
--- a/tests/benchmarks/corelib/tools/qregexp/main.cpp
+++ b/tests/benchmarks/corelib/text/qregexp/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qregexp/qregexp.pro b/tests/benchmarks/corelib/text/qregexp/qregexp.pro
index f64ae781a2..f64ae781a2 100644
--- a/tests/benchmarks/corelib/tools/qregexp/qregexp.pro
+++ b/tests/benchmarks/corelib/text/qregexp/qregexp.pro
diff --git a/tests/benchmarks/corelib/tools/qregexp/qregexp.qrc b/tests/benchmarks/corelib/text/qregexp/qregexp.qrc
index a7fe13c035..a7fe13c035 100644
--- a/tests/benchmarks/corelib/tools/qregexp/qregexp.qrc
+++ b/tests/benchmarks/corelib/text/qregexp/qregexp.qrc
diff --git a/tests/benchmarks/corelib/tools/qstring/main.cpp b/tests/benchmarks/corelib/text/qstring/main.cpp
index 826a843c10..826a843c10 100644
--- a/tests/benchmarks/corelib/tools/qstring/main.cpp
+++ b/tests/benchmarks/corelib/text/qstring/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qstring/qstring.pro b/tests/benchmarks/corelib/text/qstring/qstring.pro
index 9f5e34b915..9f5e34b915 100644
--- a/tests/benchmarks/corelib/tools/qstring/qstring.pro
+++ b/tests/benchmarks/corelib/text/qstring/qstring.pro
diff --git a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp b/tests/benchmarks/corelib/text/qstringbuilder/main.cpp
index d0dfe3b1a7..0de6d33846 100644
--- a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp
+++ b/tests/benchmarks/corelib/text/qstringbuilder/main.cpp
@@ -401,7 +401,7 @@ private slots:
}
private:
- const QLatin1Literal l1literal;
+ const QLatin1String l1literal;
const QLatin1String l1string;
const QByteArray ba;
const QString string;
diff --git a/tests/benchmarks/corelib/tools/qstringbuilder/qstringbuilder.pro b/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro
index fa4cbe3c13..fa4cbe3c13 100644
--- a/tests/benchmarks/corelib/tools/qstringbuilder/qstringbuilder.pro
+++ b/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro
diff --git a/tests/benchmarks/corelib/tools/qstringlist/.gitignore b/tests/benchmarks/corelib/text/qstringlist/.gitignore
index 3e0cdc952f..3e0cdc952f 100644
--- a/tests/benchmarks/corelib/tools/qstringlist/.gitignore
+++ b/tests/benchmarks/corelib/text/qstringlist/.gitignore
diff --git a/tests/benchmarks/corelib/tools/qstringlist/main.cpp b/tests/benchmarks/corelib/text/qstringlist/main.cpp
index ae355a8b89..ae355a8b89 100644
--- a/tests/benchmarks/corelib/tools/qstringlist/main.cpp
+++ b/tests/benchmarks/corelib/text/qstringlist/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qstringlist/qstringlist.pro b/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro
index 5803e7da0e..5803e7da0e 100644
--- a/tests/benchmarks/corelib/tools/qstringlist/qstringlist.pro
+++ b/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro
diff --git a/tests/benchmarks/corelib/text/text.pro b/tests/benchmarks/corelib/text/text.pro
new file mode 100644
index 0000000000..a2397b37fe
--- /dev/null
+++ b/tests/benchmarks/corelib/text/text.pro
@@ -0,0 +1,9 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qbytearray \
+ qchar \
+ qlocale \
+ qstringbuilder \
+ qstringlist
+
+*g++*: SUBDIRS += qstring
diff --git a/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro b/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro
index 86102adecd..a1827d0276 100644
--- a/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro
+++ b/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro
@@ -1,6 +1,7 @@
TEMPLATE = app
TARGET = tst_bench_qreadwritelock
-QT = core testlib
+QT = core-private testlib
SOURCES += tst_qreadwritelock.cpp
CONFIG += c++14 # for std::shared_timed_mutex
+CONFIG += c++1z # for std::shared_mutex
diff --git a/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp b/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
index fcf600a059..1d47d98657 100644
--- a/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
+++ b/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
@@ -28,12 +28,14 @@
#include <QtCore/QtCore>
#include <QtTest/QtTest>
+#include <QtCore/private/qmemory_p.h>
#include <mutex>
#if QT_HAS_INCLUDE(<shared_mutex>)
#if __cplusplus > 201103L
#include <shared_mutex>
#endif
#endif
+#include <vector>
// Wrapers that take pointers instead of reference to have the same interface as Qt
template <typename T>
@@ -63,6 +65,8 @@ private slots:
void uncontended();
void readOnly_data();
void readOnly();
+ void writeOnly_data();
+ void writeOnly();
// void readWrite();
};
@@ -106,6 +110,14 @@ void tst_QReadWriteLock::uncontended_data()
<< FunctionPtrHolder(testUncontended<QReadWriteLock, QWriteLocker>);
QTest::newRow("std::mutex") << FunctionPtrHolder(
testUncontended<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
+#ifdef __cpp_lib_shared_mutex
+ QTest::newRow("std::shared_mutex, read") << FunctionPtrHolder(
+ testUncontended<std::shared_mutex,
+ LockerWrapper<std::shared_lock<std::shared_mutex>>>);
+ QTest::newRow("std::shared_mutex, write") << FunctionPtrHolder(
+ testUncontended<std::shared_mutex,
+ LockerWrapper<std::unique_lock<std::shared_mutex>>>);
+#endif
#if defined __cpp_lib_shared_timed_mutex
QTest::newRow("std::shared_timed_mutex, read") << FunctionPtrHolder(
testUncontended<std::shared_timed_mutex,
@@ -130,7 +142,7 @@ void testReadOnly()
struct Thread : QThread
{
Mutex *lock;
- void run()
+ void run() override
{
for (int i = 0; i < Iterations; ++i) {
QString s = QString::number(i); // Do something outside the lock
@@ -140,21 +152,20 @@ void testReadOnly()
}
};
Mutex lock;
- QVector<QThread *> threads;
+ std::vector<std::unique_ptr<Thread>> threads;
for (int i = 0; i < threadCount; ++i) {
- auto t = new Thread;
+ auto t = qt_make_unique<Thread>();
t->lock = &lock;
- threads.append(t);
+ threads.push_back(std::move(t));
}
QBENCHMARK {
- for (auto t : threads) {
+ for (auto &t : threads) {
t->start();
}
- for (auto t : threads) {
+ for (auto &t : threads) {
t->wait();
}
}
- qDeleteAll(threads);
}
void tst_QReadWriteLock::readOnly_data()
@@ -166,6 +177,11 @@ void tst_QReadWriteLock::readOnly_data()
QTest::newRow("QReadWriteLock") << FunctionPtrHolder(testReadOnly<QReadWriteLock, QReadLocker>);
QTest::newRow("std::mutex") << FunctionPtrHolder(
testReadOnly<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
+#ifdef __cpp_lib_shared_mutex
+ QTest::newRow("std::shared_mutex") << FunctionPtrHolder(
+ testReadOnly<std::shared_mutex,
+ LockerWrapper<std::shared_lock<std::shared_mutex>>>);
+#endif
#if defined __cpp_lib_shared_timed_mutex
QTest::newRow("std::shared_timed_mutex") << FunctionPtrHolder(
testReadOnly<std::shared_timed_mutex,
@@ -179,5 +195,66 @@ void tst_QReadWriteLock::readOnly()
holder.value();
}
+static QString global_string;
+
+template <typename Mutex, typename Locker>
+void testWriteOnly()
+{
+ struct Thread : QThread
+ {
+ Mutex *lock;
+ void run() override
+ {
+ for (int i = 0; i < Iterations; ++i) {
+ QString s = QString::number(i); // Do something outside the lock
+ Locker locker(lock);
+ global_string = s;
+ }
+ }
+ };
+ Mutex lock;
+ std::vector<std::unique_ptr<Thread>> threads;
+ for (int i = 0; i < threadCount; ++i) {
+ auto t = qt_make_unique<Thread>();
+ t->lock = &lock;
+ threads.push_back(std::move(t));
+ }
+ QBENCHMARK {
+ for (auto &t : threads) {
+ t->start();
+ }
+ for (auto &t : threads) {
+ t->wait();
+ }
+ }
+}
+
+void tst_QReadWriteLock::writeOnly_data()
+{
+ QTest::addColumn<FunctionPtrHolder>("holder");
+
+ // QTest::newRow("nothing") << FunctionPtrHolder(testWriteOnly<int, FakeLock>);
+ QTest::newRow("QMutex") << FunctionPtrHolder(testWriteOnly<QMutex, QMutexLocker>);
+ QTest::newRow("QReadWriteLock") << FunctionPtrHolder(testWriteOnly<QReadWriteLock, QWriteLocker>);
+ QTest::newRow("std::mutex") << FunctionPtrHolder(
+ testWriteOnly<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
+#ifdef __cpp_lib_shared_mutex
+ QTest::newRow("std::shared_mutex") << FunctionPtrHolder(
+ testWriteOnly<std::shared_mutex,
+ LockerWrapper<std::unique_lock<std::shared_mutex>>>);
+#endif
+#if defined __cpp_lib_shared_timed_mutex
+ QTest::newRow("std::shared_timed_mutex") << FunctionPtrHolder(
+ testWriteOnly<std::shared_timed_mutex,
+ LockerWrapper<std::unique_lock<std::shared_timed_mutex>>>);
+#endif
+}
+
+void tst_QReadWriteLock::writeOnly()
+{
+ QFETCH(FunctionPtrHolder, holder);
+ holder.value();
+}
+
QTEST_MAIN(tst_QReadWriteLock)
#include "tst_qreadwritelock.moc"
diff --git a/tests/benchmarks/corelib/time/qdate/qdate.pro b/tests/benchmarks/corelib/time/qdate/qdate.pro
new file mode 100644
index 0000000000..a655917135
--- /dev/null
+++ b/tests/benchmarks/corelib/time/qdate/qdate.pro
@@ -0,0 +1,4 @@
+TARGET = tst_bench_qdate
+QT = core testlib
+
+SOURCES += tst_bench_qdate.cpp
diff --git a/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp b/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp
new file mode 100644
index 0000000000..10c013c080
--- /dev/null
+++ b/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module 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 <QDate>
+#include <QTest>
+#include <QVector>
+
+class tst_QDate : public QObject
+{
+ Q_OBJECT
+
+ enum : qint64
+ {
+ JULIAN_DAY_2010 = 2455198,
+ JULIAN_DAY_2011 = 2455563,
+ JULIAN_DAY_2020 = 2458850,
+ };
+
+ static QVector<QDate> daily(qint64 start, qint64 end);
+ static QVector<QDate> yearly(qint32 first, qint32 last);
+
+private Q_SLOTS:
+ void create();
+ void year();
+ void month();
+ void day();
+ void dayOfWeek();
+ void dayOfYear();
+ void monthLengths(); // isValid() and daysInMonth()
+ void daysInYear();
+ void isLeapYear();
+ void getSetDate();
+ void addDays();
+ void addMonths();
+ void addYears();
+};
+
+QVector<QDate> tst_QDate::daily(qint64 start, qint64 end)
+{
+ QVector<QDate> list;
+ list.reserve(end - start);
+ for (qint64 jd = start; jd < end; ++jd)
+ list.append(QDate::fromJulianDay(jd));
+ return list;
+}
+
+QVector<QDate> tst_QDate::yearly(qint32 first, qint32 last)
+{
+ QVector<QDate> list;
+ list.reserve(last + 1 - first);
+ for (qint32 year = first; year <= last; ++year)
+ list.append(QDate(year, 3, 21));
+ return list;
+}
+
+void tst_QDate::create()
+{
+ QDate test;
+ QBENCHMARK {
+ for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
+ test = QDate::fromJulianDay(jd);
+ }
+ Q_UNUSED(test);
+}
+
+void tst_QDate::year()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDate &test : list)
+ test.year();
+ }
+}
+
+void tst_QDate::month()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDate &test : list)
+ test.month();
+ }
+}
+
+void tst_QDate::day()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDate &test : list)
+ test.day();
+ }
+}
+
+void tst_QDate::dayOfWeek()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDate &test : list)
+ test.dayOfWeek();
+ }
+}
+
+void tst_QDate::dayOfYear()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDate &test : list)
+ test.dayOfYear();
+ }
+}
+
+void tst_QDate::monthLengths()
+{
+ bool check = true;
+ QBENCHMARK {
+ for (int year = 1900; year <= 2100; year++) {
+ for (int month = 1; month <= 12; month++)
+ check = QDate::isValid(year, month, QDate(year, month, 1).daysInMonth());
+ }
+ }
+ Q_UNUSED(check);
+}
+
+void tst_QDate::daysInYear()
+{
+ const auto list = yearly(1601, 2401);
+ QBENCHMARK {
+ for (const QDate date : list)
+ date.daysInYear();
+ }
+}
+
+void tst_QDate::isLeapYear()
+{
+ QBENCHMARK {
+ for (qint32 year = 1601; year <= 2401; year++)
+ QDate::isLeapYear(year);
+ }
+}
+
+void tst_QDate::getSetDate()
+{
+ QDate store;
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const auto test : list) {
+ int year, month, day;
+ test.getDate(&year, &month, &day);
+ store.setDate(year, month, day);
+ }
+ }
+ Q_UNUSED(store);
+}
+
+void tst_QDate::addDays()
+{
+ QDate store;
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const auto test : list)
+ store = test.addDays(17);
+ }
+ Q_UNUSED(store);
+}
+
+void tst_QDate::addMonths()
+{
+ QDate store;
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const auto test : list)
+ store = test.addMonths(17);
+ }
+ Q_UNUSED(store);
+}
+
+void tst_QDate::addYears()
+{
+ QDate store;
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const auto test : list)
+ store = test.addYears(17);
+ }
+ Q_UNUSED(store);
+}
+
+QTEST_MAIN(tst_QDate)
+#include "tst_bench_qdate.moc"
diff --git a/tests/benchmarks/corelib/time/qdatetime/main.cpp b/tests/benchmarks/corelib/time/qdatetime/main.cpp
new file mode 100644
index 0000000000..740e08cc46
--- /dev/null
+++ b/tests/benchmarks/corelib/time/qdatetime/main.cpp
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module 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 <QDateTime>
+#include <QTimeZone>
+#include <QTest>
+#include <QVector>
+#include <qdebug.h>
+
+class tst_QDateTime : public QObject
+{
+ Q_OBJECT
+
+ enum : qint64
+ {
+ SECS_PER_DAY = 86400,
+ MSECS_PER_DAY = 86400000,
+ JULIAN_DAY_1950 = 2433283,
+ JULIAN_DAY_1960 = 2436935,
+ JULIAN_DAY_1970 = 2440588, // Epoch
+ JULIAN_DAY_2010 = 2455198,
+ JULIAN_DAY_2011 = 2455563,
+ JULIAN_DAY_2020 = 2458850,
+ JULIAN_DAY_2050 = 2469808,
+ JULIAN_DAY_2060 = 2473460
+ };
+
+ static QVector<QDateTime> daily(qint64 start, qint64 end);
+ static QVector<QDateTime> norse(qint64 start, qint64 end);
+
+private Q_SLOTS:
+ void create();
+ void isNull();
+ void isValid();
+ void date();
+ void time();
+ void timeSpec();
+ void offsetFromUtc();
+ void timeZoneAbbreviation();
+ void toMSecsSinceEpoch();
+ void toMSecsSinceEpoch1950();
+ void toMSecsSinceEpoch2050();
+ void toMSecsSinceEpochTz();
+ void toMSecsSinceEpoch1950Tz();
+ void toMSecsSinceEpoch2050Tz();
+ void setDate();
+ void setTime();
+ void setTimeSpec();
+ void setOffsetFromUtc();
+ void setMSecsSinceEpoch();
+ void setMSecsSinceEpochTz();
+ void toString();
+ void toStringTextFormat();
+ void toStringIsoFormat();
+ void addDays();
+ void addDaysTz();
+ void addMSecs();
+ void addMSecsTz();
+ void toTimeSpec();
+ void toOffsetFromUtc();
+ void daysTo();
+ void msecsTo();
+ void equivalent();
+ void equivalentUtc();
+ void lessThan();
+ void lessThanUtc();
+ void currentDateTime();
+ void currentDate();
+ void currentTime();
+ void currentDateTimeUtc();
+ void currentMSecsSinceEpoch();
+ void fromString();
+ void fromStringText();
+ void fromStringIso();
+ void fromMSecsSinceEpoch();
+ void fromMSecsSinceEpochUtc();
+ void fromMSecsSinceEpochTz();
+};
+
+QVector<QDateTime> tst_QDateTime::daily(qint64 start, qint64 end)
+{
+ QVector<QDateTime> list;
+ list.reserve(end - start);
+ for (int jd = start; jd < end; ++jd)
+ list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
+ return list;
+}
+
+QVector<QDateTime> tst_QDateTime::norse(qint64 start, qint64 end)
+{
+ const QTimeZone cet("Europe/Oslo");
+ QVector<QDateTime> list;
+ list.reserve(end - start);
+ for (int jd = start; jd < end; ++jd)
+ list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
+ return list;
+}
+
+void tst_QDateTime::create()
+{
+ QBENCHMARK {
+ for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd) {
+ QDateTime test(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0));
+ Q_UNUSED(test)
+ }
+ }
+}
+
+void tst_QDateTime::isNull()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.isNull();
+ }
+}
+
+void tst_QDateTime::isValid()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.isValid();
+ }
+}
+
+void tst_QDateTime::date()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.date();
+ }
+}
+
+void tst_QDateTime::time()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.time();
+ }
+}
+
+void tst_QDateTime::timeSpec()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.timeSpec();
+ }
+}
+
+void tst_QDateTime::offsetFromUtc()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.offsetFromUtc();
+ }
+}
+
+void tst_QDateTime::timeZoneAbbreviation()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.timeZoneAbbreviation();
+ }
+}
+
+void tst_QDateTime::toMSecsSinceEpoch()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toMSecsSinceEpoch();
+ }
+}
+
+void tst_QDateTime::toMSecsSinceEpoch1950()
+{
+ const auto list = daily(JULIAN_DAY_1950, JULIAN_DAY_1960);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toMSecsSinceEpoch();
+ }
+}
+
+void tst_QDateTime::toMSecsSinceEpoch2050()
+{
+ const auto list = daily(JULIAN_DAY_2050, JULIAN_DAY_2060);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toMSecsSinceEpoch();
+ }
+}
+
+void tst_QDateTime::toMSecsSinceEpochTz()
+{
+ qint64 result;
+ const auto list = norse(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = test.toMSecsSinceEpoch();
+ }
+ Q_UNUSED(result);
+}
+
+void tst_QDateTime::toMSecsSinceEpoch1950Tz()
+{
+ qint64 result;
+ const auto list = norse(JULIAN_DAY_1950, JULIAN_DAY_1960);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = test.toMSecsSinceEpoch();
+ }
+ Q_UNUSED(result);
+}
+
+void tst_QDateTime::toMSecsSinceEpoch2050Tz()
+{
+ qint64 result;
+ const auto list = norse(JULIAN_DAY_2050, JULIAN_DAY_2060);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = test.toMSecsSinceEpoch();
+ }
+ Q_UNUSED(result);
+}
+
+void tst_QDateTime::setDate()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (QDateTime test : list)
+ test.setDate(QDate::fromJulianDay(JULIAN_DAY_2010));
+ }
+}
+
+void tst_QDateTime::setTime()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (QDateTime test : list)
+ test.setTime(QTime(12, 0, 0));
+ }
+}
+
+void tst_QDateTime::setTimeSpec()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (QDateTime test : list)
+ test.setTimeSpec(Qt::UTC);
+ }
+}
+
+void tst_QDateTime::setOffsetFromUtc()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (QDateTime test : list)
+ test.setOffsetFromUtc(3600);
+ }
+}
+
+void tst_QDateTime::setMSecsSinceEpoch()
+{
+ qint64 msecs = qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970 + 180) * MSECS_PER_DAY;
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (QDateTime test : list)
+ test.setMSecsSinceEpoch(msecs);
+ }
+}
+
+void tst_QDateTime::setMSecsSinceEpochTz()
+{
+ const qint64 msecs = qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970 + 180) * MSECS_PER_DAY;
+ const auto list = norse(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (QDateTime test : list)
+ test.setMSecsSinceEpoch(msecs);
+ }
+}
+
+void tst_QDateTime::toString()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2011);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toString(QStringLiteral("yyy-MM-dd hh:mm:ss.zzz t"));
+ }
+}
+
+void tst_QDateTime::toStringTextFormat()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2011);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toString(Qt::TextDate);
+ }
+}
+
+void tst_QDateTime::toStringIsoFormat()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2011);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toString(Qt::ISODate);
+ }
+}
+
+void tst_QDateTime::addDays()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QDateTime next;
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ next = test.addDays(1);
+ }
+ Q_UNUSED(next);
+}
+
+void tst_QDateTime::addDaysTz()
+{
+ const auto list = norse(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ QDateTime result = test.addDays(1);
+ }
+}
+
+void tst_QDateTime::addMSecs()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QDateTime next;
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ next = test.addMSecs(1);
+ }
+ Q_UNUSED(next);
+}
+
+void tst_QDateTime::addMSecsTz()
+{
+ const auto list = norse(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ QDateTime result = test.addMSecs(1);
+ }
+}
+
+void tst_QDateTime::toTimeSpec()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toTimeSpec(Qt::UTC);
+ }
+}
+
+void tst_QDateTime::toOffsetFromUtc()
+{
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.toOffsetFromUtc(3600);
+ }
+}
+
+void tst_QDateTime::daysTo()
+{
+ const QDateTime other = QDateTime::fromMSecsSinceEpoch(
+ qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970) * MSECS_PER_DAY);
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.daysTo(other);
+ }
+}
+
+void tst_QDateTime::msecsTo()
+{
+ const QDateTime other = QDateTime::fromMSecsSinceEpoch(
+ qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970) * MSECS_PER_DAY);
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ test.msecsTo(other);
+ }
+}
+
+void tst_QDateTime::equivalent()
+{
+ bool result;
+ const QDateTime other = QDateTime::fromMSecsSinceEpoch(
+ qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970) * MSECS_PER_DAY);
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = (test == other);
+ }
+ Q_UNUSED(result)
+}
+
+void tst_QDateTime::equivalentUtc()
+{
+ bool result = false;
+ const QDateTime other = QDateTime::fromMSecsSinceEpoch(
+ qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970) * MSECS_PER_DAY, Qt::UTC);
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = (test == other);
+ }
+ Q_UNUSED(result)
+}
+
+void tst_QDateTime::lessThan()
+{
+ bool result = false;
+ const QDateTime other = QDateTime::fromMSecsSinceEpoch(
+ qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970) * MSECS_PER_DAY);
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = (test < other);
+ }
+ Q_UNUSED(result)
+}
+
+void tst_QDateTime::lessThanUtc()
+{
+ bool result = false;
+ const QDateTime other = QDateTime::fromMSecsSinceEpoch(
+ qint64(JULIAN_DAY_2010 - JULIAN_DAY_1970) * MSECS_PER_DAY, Qt::UTC);
+ const auto list = daily(JULIAN_DAY_2010, JULIAN_DAY_2020);
+ QBENCHMARK {
+ for (const QDateTime &test : list)
+ result = (test < other);
+ }
+ Q_UNUSED(result)
+}
+
+void tst_QDateTime::currentDateTime()
+{
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDateTime::currentDateTime();
+ }
+}
+
+void tst_QDateTime::currentDate()
+{
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDate::currentDate();
+ }
+}
+
+void tst_QDateTime::currentTime()
+{
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QTime::currentTime();
+ }
+}
+
+void tst_QDateTime::currentDateTimeUtc()
+{
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDateTime::currentDateTimeUtc();
+ }
+}
+
+void tst_QDateTime::currentMSecsSinceEpoch()
+{
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDateTime::currentMSecsSinceEpoch();
+ }
+}
+
+void tst_QDateTime::fromString()
+{
+ QString format = "yyyy-MM-dd hh:mm:ss.zzz";
+ QString input = "2010-01-01 13:12:11.999";
+ QVERIFY(QDateTime::fromString(input, format).isValid());
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDateTime::fromString(input, format);
+ }
+}
+
+void tst_QDateTime::fromStringText()
+{
+ QString input = "Wed Jan 2 01:02:03.000 2013 GMT";
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDateTime::fromString(input, Qt::TextDate);
+ }
+}
+
+void tst_QDateTime::fromStringIso()
+{
+ QString input = "2010-01-01T13:28:34.999Z";
+ QBENCHMARK {
+ for (int i = 0; i < 1000; ++i)
+ QDateTime::fromString(input, Qt::ISODate);
+ }
+}
+
+void tst_QDateTime::fromMSecsSinceEpoch()
+{
+ const int start = JULIAN_DAY_2010 - JULIAN_DAY_1970;
+ const int end = JULIAN_DAY_2020 - JULIAN_DAY_1970;
+ QBENCHMARK {
+ for (int jd = start; jd < end; ++jd)
+ QDateTime::fromMSecsSinceEpoch(jd * MSECS_PER_DAY, Qt::LocalTime);
+ }
+}
+
+void tst_QDateTime::fromMSecsSinceEpochUtc()
+{
+ const int start = JULIAN_DAY_2010 - JULIAN_DAY_1970;
+ const int end = JULIAN_DAY_2020 - JULIAN_DAY_1970;
+ QBENCHMARK {
+ for (int jd = start; jd < end; ++jd)
+ QDateTime::fromMSecsSinceEpoch(jd * MSECS_PER_DAY, Qt::UTC);
+ }
+}
+
+void tst_QDateTime::fromMSecsSinceEpochTz()
+{
+ const int start = JULIAN_DAY_2010 - JULIAN_DAY_1970;
+ const int end = JULIAN_DAY_2020 - JULIAN_DAY_1970;
+ const QTimeZone cet("Europe/Oslo");
+ QBENCHMARK {
+ for (int jd = start; jd < end; ++jd)
+ QDateTime test = QDateTime::fromMSecsSinceEpoch(jd * MSECS_PER_DAY, cet);
+ }
+}
+
+QTEST_MAIN(tst_QDateTime)
+
+#include "main.moc"
diff --git a/tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro
index a85e7346c6..a85e7346c6 100644
--- a/tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro
+++ b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro
diff --git a/tests/benchmarks/corelib/tools/qtimezone/main.cpp b/tests/benchmarks/corelib/time/qtimezone/main.cpp
index 65455a7261..65455a7261 100644
--- a/tests/benchmarks/corelib/tools/qtimezone/main.cpp
+++ b/tests/benchmarks/corelib/time/qtimezone/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro
index d0531b568b..d0531b568b 100644
--- a/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro
+++ b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro
diff --git a/tests/benchmarks/corelib/time/time.pro b/tests/benchmarks/corelib/time/time.pro
new file mode 100644
index 0000000000..b5184845d9
--- /dev/null
+++ b/tests/benchmarks/corelib/time/time.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qdate \
+ qdatetime \
+ qtimezone
diff --git a/tests/benchmarks/corelib/tools/qdatetime/main.cpp b/tests/benchmarks/corelib/tools/qdatetime/main.cpp
deleted file mode 100644
index 2c1e3d97ae..0000000000
--- a/tests/benchmarks/corelib/tools/qdatetime/main.cpp
+++ /dev/null
@@ -1,604 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module 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 <QDateTime>
-#include <QTimeZone>
-#include <QTest>
-#include <qdebug.h>
-
-class tst_QDateTime : public QObject
-{
- Q_OBJECT
-
- enum
-#if defined(Q_COMPILER_CLASS_ENUM) || (defined(Q_CC_MSVC) && _MSC_VER >= 1700)
- : qint64
-#endif
- {
- SECS_PER_DAY = 86400,
- MSECS_PER_DAY = 86400000,
- JULIAN_DAY_1950 = 2433283,
- JULIAN_DAY_1960 = 2436935,
- JULIAN_DAY_2010 = 2455198,
- JULIAN_DAY_2011 = 2455563,
- JULIAN_DAY_2020 = 2458850,
- JULIAN_DAY_2050 = 2469808,
- JULIAN_DAY_2060 = 2473460
- };
-
-private Q_SLOTS:
- void create();
- void isNull();
- void isValid();
- void date();
- void time();
- void timeSpec();
- void offsetFromUtc();
- void timeZoneAbbreviation();
- void toMSecsSinceEpoch();
- void toMSecsSinceEpoch1950();
- void toMSecsSinceEpoch2050();
- void toMSecsSinceEpochTz();
- void toMSecsSinceEpoch1950Tz();
- void toMSecsSinceEpoch2050Tz();
- void setDate();
- void setTime();
- void setTimeSpec();
- void setOffsetFromUtc();
- void setMSecsSinceEpoch();
- void setMSecsSinceEpochTz();
- void toString();
- void toStringTextFormat();
- void toStringIsoFormat();
- void addDays();
- void addDaysTz();
- void addMSecs();
- void addMSecsTz();
- void toTimeSpec();
- void toOffsetFromUtc();
- void daysTo();
- void msecsTo();
- void equivalent();
- void equivalentUtc();
- void lessThan();
- void lessThanUtc();
- void currentDateTime();
- void currentDate();
- void currentTime();
- void currentDateTimeUtc();
- void currentMSecsSinceEpoch();
- void fromString();
- void fromStringText();
- void fromStringIso();
- void fromMSecsSinceEpoch();
- void fromMSecsSinceEpochUtc();
- void fromMSecsSinceEpochTz();
-};
-
-void tst_QDateTime::create()
-{
- QBENCHMARK {
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd) {
- QDateTime test(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0));
- Q_UNUSED(test)
- }
- }
-}
-
-void tst_QDateTime::isNull()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.isNull();
- }
-}
-
-void tst_QDateTime::isValid()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.isValid();
- }
-}
-
-void tst_QDateTime::date()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.date();
- }
-}
-
-void tst_QDateTime::time()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.time();
- }
-}
-
-void tst_QDateTime::timeSpec()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.timeSpec();
- }
-}
-
-void tst_QDateTime::offsetFromUtc()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.offsetFromUtc();
- }
-}
-
-void tst_QDateTime::timeZoneAbbreviation()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.timeZoneAbbreviation();
- }
-}
-
-void tst_QDateTime::toMSecsSinceEpoch()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::toMSecsSinceEpoch1950()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_1950; jd < JULIAN_DAY_1960; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::toMSecsSinceEpoch2050()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2050; jd < JULIAN_DAY_2060; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::toMSecsSinceEpochTz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- qint64 result = test.toMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::toMSecsSinceEpoch1950Tz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_1950; jd < JULIAN_DAY_1960; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- qint64 result = test.toMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::toMSecsSinceEpoch2050Tz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2050; jd < JULIAN_DAY_2060; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- qint64 result = test.toMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::setDate()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (QDateTime test, list)
- test.setDate(QDate::fromJulianDay(JULIAN_DAY_2010));
- }
-}
-
-void tst_QDateTime::setTime()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (QDateTime test, list)
- test.setTime(QTime(12, 0, 0));
- }
-}
-
-void tst_QDateTime::setTimeSpec()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (QDateTime test, list)
- test.setTimeSpec(Qt::UTC);
- }
-}
-
-void tst_QDateTime::setOffsetFromUtc()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (QDateTime test, list)
- test.setOffsetFromUtc(3600);
- }
-}
-
-void tst_QDateTime::setMSecsSinceEpoch()
-{
- qint64 msecs = qint64(JULIAN_DAY_2010 + 180) * MSECS_PER_DAY;
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (QDateTime test, list)
- test.setMSecsSinceEpoch(msecs);
- }
-}
-
-void tst_QDateTime::setMSecsSinceEpochTz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
- QBENCHMARK {
- foreach (QDateTime test, list)
- test.setMSecsSinceEpoch((JULIAN_DAY_2010 + 180) * MSECS_PER_DAY);
- }
-}
-
-void tst_QDateTime::toString()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2011; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toString(QStringLiteral("yyy-MM-dd hh:mm:ss.zzz t"));
- }
-}
-
-void tst_QDateTime::toStringTextFormat()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2011; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toString(Qt::TextDate);
- }
-}
-
-void tst_QDateTime::toStringIsoFormat()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2011; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toString(Qt::ISODate);
- }
-}
-
-void tst_QDateTime::addDays()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.addDays(1);
- }
-}
-
-void tst_QDateTime::addDaysTz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- QDateTime result = test.addDays(1);
- }
-}
-
-void tst_QDateTime::addMSecs()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.addMSecs(1);
- }
-}
-
-void tst_QDateTime::addMSecsTz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0), cet));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- QDateTime result = test.addMSecs(1);
- }
-}
-
-void tst_QDateTime::toTimeSpec()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toTimeSpec(Qt::UTC);
- }
-}
-
-void tst_QDateTime::toOffsetFromUtc()
-{
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.toOffsetFromUtc(3600);
- }
-}
-
-void tst_QDateTime::daysTo()
-{
- QDateTime other = QDateTime::fromMSecsSinceEpoch(qint64(JULIAN_DAY_2010) * MSECS_PER_DAY);
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.daysTo(other);
- }
-}
-
-void tst_QDateTime::msecsTo()
-{
- QDateTime other = QDateTime::fromMSecsSinceEpoch(qint64(JULIAN_DAY_2010) * MSECS_PER_DAY);
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- test.msecsTo(other);
- }
-}
-
-void tst_QDateTime::equivalent()
-{
- bool result;
- QDateTime other = QDateTime::fromMSecsSinceEpoch(qint64(JULIAN_DAY_2010) * MSECS_PER_DAY);
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- result = (test == other);
- }
- Q_UNUSED(result)
-}
-
-void tst_QDateTime::equivalentUtc()
-{
- bool result = false;
- QDateTime other = QDateTime::fromMSecsSinceEpoch(qint64(JULIAN_DAY_2010) * MSECS_PER_DAY, Qt::UTC);
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- result = (test == other);
- }
- Q_UNUSED(result)
-}
-
-void tst_QDateTime::lessThan()
-{
- bool result = false;
- QDateTime other = QDateTime::fromMSecsSinceEpoch(qint64(JULIAN_DAY_2010) * MSECS_PER_DAY);
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- result = (test < other);
- }
- Q_UNUSED(result)
-}
-
-void tst_QDateTime::lessThanUtc()
-{
- bool result = false;
- QDateTime other = QDateTime::fromMSecsSinceEpoch(qint64(JULIAN_DAY_2010) * MSECS_PER_DAY, Qt::UTC);
- QList<QDateTime> list;
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- list.append(QDateTime(QDate::fromJulianDay(jd), QTime::fromMSecsSinceStartOfDay(0)));
- QBENCHMARK {
- foreach (const QDateTime &test, list)
- result = (test < other);
- }
- Q_UNUSED(result)
-}
-
-void tst_QDateTime::currentDateTime()
-{
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDateTime::currentDateTime();
- }
-}
-
-void tst_QDateTime::currentDate()
-{
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDate::currentDate();
- }
-}
-
-void tst_QDateTime::currentTime()
-{
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QTime::currentTime();
- }
-}
-
-void tst_QDateTime::currentDateTimeUtc()
-{
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDateTime::currentDateTimeUtc();
- }
-}
-
-void tst_QDateTime::currentMSecsSinceEpoch()
-{
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDateTime::currentMSecsSinceEpoch();
- }
-}
-
-void tst_QDateTime::fromString()
-{
- QString format = "yyyy-MM-dd hh:mm:ss.zzz";
- QString input = "2010-01-01 13:12:11.999";
- QVERIFY(QDateTime::fromString(input, format).isValid());
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDateTime::fromString(input, format);
- }
-}
-
-void tst_QDateTime::fromStringText()
-{
- QString input = "Wed Jan 2 01:02:03.000 2013 GMT";
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDateTime::fromString(input, Qt::TextDate);
- }
-}
-
-void tst_QDateTime::fromStringIso()
-{
- QString input = "2010-01-01T13:28:34.999Z";
- QBENCHMARK {
- for (int i = 0; i < 1000; ++i)
- QDateTime::fromString(input, Qt::ISODate);
- }
-}
-
-void tst_QDateTime::fromMSecsSinceEpoch()
-{
- QBENCHMARK {
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- QDateTime::fromMSecsSinceEpoch(jd * MSECS_PER_DAY, Qt::LocalTime);
- }
-}
-
-void tst_QDateTime::fromMSecsSinceEpochUtc()
-{
- QBENCHMARK {
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- QDateTime::fromMSecsSinceEpoch(jd * MSECS_PER_DAY, Qt::UTC);
- }
-}
-
-void tst_QDateTime::fromMSecsSinceEpochTz()
-{
- QTimeZone cet = QTimeZone("Europe/Oslo");
- QBENCHMARK {
- for (int jd = JULIAN_DAY_2010; jd < JULIAN_DAY_2020; ++jd)
- QDateTime test = QDateTime::fromMSecsSinceEpoch(jd * MSECS_PER_DAY, cet);
- }
-}
-
-QTEST_MAIN(tst_QDateTime)
-
-#include "main.moc"
diff --git a/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt b/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt
index d5acd28820..662285296f 100644
--- a/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt
+++ b/tests/benchmarks/corelib/tools/qhash/paths_small_data.txt
@@ -47,13 +47,38 @@
./codecs/.obj/debug-shared
./.pch
./.pch/debug-shared
+./text
+./text/text.pro
+./text/qregexp
+./text/qregexp/qregexp.qrc
+./text/qregexp/main.cpp
+./text/qregexp/Makefile
+./text/qregexp/qregexp.pro
+./text/qstringbuilder
+./text/qstringbuilder/main.cpp
+./text/qstringbuilder/Makefile
+./text/qstringbuilder/qstringbuilder.pro
+./text/qstring
+./text/qstring/generatelist.pl
+./text/qstring/data.h
+./text/qstring/qstring.pro
+./text/qstring/main.cpp
+./text/qstring/data.cpp
+./text/qstring/Makefile
+./text/qstring/utf-8.txt
+./text/qstringlist
+./text/qstringlist/qstringlist.pro
+./text/qstringlist/main.cpp
+./text/qstringlist/.gitignore
+./text/qstringlist/Makefile
+./text/qbytearray
+./text/qbytearray/qbytearray.pro
+./text/qbytearray/main.cpp
+./text/qbytearray/Makefile
+./text/.pch
+./text/.pch/debug-shared
./tools
./tools/tools.pro
-./tools/qregexp
-./tools/qregexp/qregexp.qrc
-./tools/qregexp/main.cpp
-./tools/qregexp/Makefile
-./tools/qregexp/qregexp.pro
./tools/qvector
./tools/qvector/tst_vector
./tools/qvector/.pch
@@ -72,31 +97,10 @@
./tools/qvector/qvector.pro
./tools/.pch
./tools/.pch/debug-shared
-./tools/qstringbuilder
-./tools/qstringbuilder/main.cpp
-./tools/qstringbuilder/Makefile
-./tools/qstringbuilder/qstringbuilder.pro
./tools/containers-sequential
./tools/containers-sequential/containers-sequential.pro
./tools/containers-sequential/main.cpp
./tools/containers-sequential/Makefile
-./tools/qstring
-./tools/qstring/generatelist.pl
-./tools/qstring/data.h
-./tools/qstring/qstring.pro
-./tools/qstring/main.cpp
-./tools/qstring/data.cpp
-./tools/qstring/Makefile
-./tools/qstring/utf-8.txt
-./tools/qstringlist
-./tools/qstringlist/qstringlist.pro
-./tools/qstringlist/main.cpp
-./tools/qstringlist/.gitignore
-./tools/qstringlist/Makefile
-./tools/qbytearray
-./tools/qbytearray/qbytearray.pro
-./tools/qbytearray/main.cpp
-./tools/qbytearray/Makefile
./tools/containers-associative
./tools/containers-associative/containers-associative.pro
./tools/containers-associative/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qvector/qrawvector.h b/tests/benchmarks/corelib/tools/qvector/qrawvector.h
index c7173b5b8d..16a911c63a 100644
--- a/tests/benchmarks/corelib/tools/qvector/qrawvector.h
+++ b/tests/benchmarks/corelib/tools/qvector/qrawvector.h
@@ -32,7 +32,6 @@
#include <QtCore/qiterator.h>
#include <QtCore/qdebug.h>
#include <QtCore/qatomic.h>
-#include <QtCore/qalgorithms.h>
#include <QtCore/qlist.h>
#include <QtCore/private/qtools_p.h>
@@ -263,9 +262,9 @@ public:
//static QRawVector<T> fromList(const QList<T> &list);
static inline QRawVector<T> fromStdVector(const std::vector<T> &vector)
- { QRawVector<T> tmp; qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
+ { QRawVector<T> tmp; std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
inline std::vector<T> toStdVector() const
- { std::vector<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+ { std::vector<T> tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
private:
T *allocate(int alloc);
@@ -568,7 +567,7 @@ typename QRawVector<T>::iterator QRawVector<T>::erase(iterator abegin, iterator
int l = int(aend - m_begin);
int n = l - f;
if (QTypeInfo<T>::isComplex) {
- qCopy(m_begin + l, m_begin + m_size, m_begin + f);
+ std::copy(m_begin + l, m_begin + m_size, m_begin + f);
T *i = m_begin + m_size;
T *b = m_begin + m_size - n;
while (i != b) {
diff --git a/tests/benchmarks/corelib/tools/tools.pro b/tests/benchmarks/corelib/tools/tools.pro
index ca9c0a6f89..b4ee0520a6 100644
--- a/tests/benchmarks/corelib/tools/tools.pro
+++ b/tests/benchmarks/corelib/tools/tools.pro
@@ -2,21 +2,12 @@ TEMPLATE = subdirs
SUBDIRS = \
containers-associative \
containers-sequential \
- qbytearray \
qcontiguouscache \
qcryptographichash \
- qdatetime \
qlist \
- qlocale \
qmap \
qrect \
qringbuffer \
qstack \
- qstring \
- qstringbuilder \
- qstringlist \
- qtimezone \
qvector \
qalgorithms
-
-!*g++*: SUBDIRS -= qstring
diff --git a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp
index 605df100ee..b8afb3bc05 100644
--- a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp
+++ b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp
@@ -183,6 +183,7 @@ void tst_QImageConversion::convertRgb32_data()
QTest::newRow("rgb32 -> rgb30") << rgb32 << QImage::Format_RGB30;
QTest::newRow("rgb32 -> a2bgr30") << rgb32 << QImage::Format_A2BGR30_Premultiplied;
QTest::newRow("rgb32 -> rgb888") << rgb32 << QImage::Format_RGB888;
+ QTest::newRow("rgb32 -> bgr888") << rgb32 << QImage::Format_BGR888;
QTest::newRow("rgb32 -> rgb666") << rgb32 << QImage::Format_RGB666;
QTest::newRow("rgb32 -> rgb555") << rgb32 << QImage::Format_RGB555;
QTest::newRow("rgb32 -> argb8565pm") << rgb32 << QImage::Format_ARGB8565_Premultiplied;
@@ -196,6 +197,7 @@ void tst_QImageConversion::convertRgb32_data()
QTest::newRow("argb32 -> rgb30") << argb32 << QImage::Format_RGB30;
QTest::newRow("argb32 -> a2bgr30") << argb32 << QImage::Format_A2BGR30_Premultiplied;
QTest::newRow("argb32 -> rgb888") << argb32 << QImage::Format_RGB888;
+ QTest::newRow("argb32 -> bgr888") << argb32 << QImage::Format_BGR888;
QTest::newRow("argb32 -> rgb666") << argb32 << QImage::Format_RGB666;
QTest::newRow("argb32 -> argb8565pm") << argb32 << QImage::Format_ARGB8565_Premultiplied;
QTest::newRow("argb32 -> argb4444pm") << argb32 << QImage::Format_ARGB4444_Premultiplied;
@@ -212,6 +214,7 @@ void tst_QImageConversion::convertRgb32_data()
QTest::newRow("argb32pm -> rgb30") << argb32pm << QImage::Format_RGB30;
QTest::newRow("argb32pm -> a2bgr30") << argb32pm << QImage::Format_A2BGR30_Premultiplied;
QTest::newRow("argb32pm -> rgb888") << argb32pm << QImage::Format_RGB888;
+ QTest::newRow("argb32pm -> bgr888") << argb32pm << QImage::Format_BGR888;
QTest::newRow("argb32pm -> rgb666") << argb32pm << QImage::Format_RGB666;
QTest::newRow("argb32pm -> argb8565pm") << argb32pm << QImage::Format_ARGB8565_Premultiplied;
QTest::newRow("argb32pm -> argb4444pm") << argb32pm << QImage::Format_ARGB4444_Premultiplied;
@@ -242,6 +245,8 @@ void tst_QImageConversion::convertGeneric_data()
QImage rgb666 = rgb32.convertToFormat(QImage::Format_RGB666);
QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied);
QImage rgba64pm = argb32.convertToFormat(QImage::Format_RGBA64_Premultiplied);
+ QImage rgb888 = rgb32.convertToFormat(QImage::Format_RGB888);
+ QImage bgr888 = rgb32.convertToFormat(QImage::Format_BGR888);
QTest::newRow("indexed8 -> rgb32") << i8 << QImage::Format_RGB32;
QTest::newRow("indexed8 -> argb32") << i8 << QImage::Format_ARGB32;
@@ -299,6 +304,20 @@ void tst_QImageConversion::convertGeneric_data()
QTest::newRow("rgba64pm -> rgb30") << rgba64pm << QImage::Format_RGB30;
QTest::newRow("rgba64pm -> a2bgr30") << rgba64pm << QImage::Format_A2BGR30_Premultiplied;
QTest::newRow("rgba64pm -> rgba64") << rgba64pm << QImage::Format_RGBA64;
+
+ QTest::newRow("rgb888 -> rgb32") << rgb888 << QImage::Format_RGB32;
+ QTest::newRow("rgb888 -> argb32") << rgb888 << QImage::Format_ARGB32;
+ QTest::newRow("rgb888 -> argb32pm") << rgb888 << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("rgb888 -> rgbx8888") << rgb888 << QImage::Format_RGBX8888;
+ QTest::newRow("rgb888 -> rgba8888pm") << rgb888 << QImage::Format_RGBA8888_Premultiplied;
+ QTest::newRow("rgb888 -> bgr888") << rgb888 << QImage::Format_BGR888;
+
+ QTest::newRow("bgr888 -> rgb32") << bgr888 << QImage::Format_RGB32;
+ QTest::newRow("bgr888 -> argb32") << bgr888 << QImage::Format_ARGB32;
+ QTest::newRow("bgr888 -> argb32pm") << bgr888 << QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("bgr888 -> rgbx8888") << bgr888 << QImage::Format_RGBX8888;
+ QTest::newRow("bgr888 -> rgba8888pm") << bgr888 << QImage::Format_RGBA8888_Premultiplied;
+ QTest::newRow("bgr888 -> rgb888") << bgr888 << QImage::Format_RGB888;
}
void tst_QImageConversion::convertGeneric()
@@ -323,6 +342,8 @@ void tst_QImageConversion::convertGenericInplace_data()
QImage argb6666 = argb32.convertToFormat(QImage::Format_ARGB6666_Premultiplied);
QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied);
QImage rgb16 = argb32.convertToFormat(QImage::Format_RGB16);
+ QImage rgb30 = argb32.convertToFormat(QImage::Format_RGB30);
+ QImage rgb888 = argb32.convertToFormat(QImage::Format_RGB888);
QTest::newRow("argb32 -> argb32pm -> argb32") << argb32 << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("argb32 -> rgb32 -> argb32") << argb32 << QImage::Format_RGB32;
@@ -349,6 +370,9 @@ void tst_QImageConversion::convertGenericInplace_data()
QTest::newRow("rgb16 -> rgb555 -> rgb16") << rgb16 << QImage::Format_RGB555;
QTest::newRow("rgb16 -> rgb444 -> rgb16") << rgb16 << QImage::Format_RGB444;
QTest::newRow("rgb16 -> argb4444pm -> rgb16") << rgb16 << QImage::Format_ARGB4444_Premultiplied;
+
+ QTest::newRow("rgb30 -> bgr30 -> rgb30") << rgb30 << QImage::Format_BGR30;
+ QTest::newRow("rgb888 -> bgr888 -> rgb888") << rgb888 << QImage::Format_BGR888;
}
void tst_QImageConversion::convertGenericInplace()
@@ -357,10 +381,10 @@ void tst_QImageConversion::convertGenericInplace()
QFETCH(QImage::Format, outputFormat);
QImage::Format inputFormat = inputImage.format();
- QImage tmpImage = qMove(inputImage);
+ QImage tmpImage = std::move(inputImage);
QBENCHMARK {
- tmpImage = (qMove(tmpImage).convertToFormat(outputFormat)).convertToFormat(inputFormat);
+ tmpImage = (std::move(tmpImage).convertToFormat(outputFormat)).convertToFormat(inputFormat);
}
}
diff --git a/tests/benchmarks/gui/image/qimagereader/qimagereader.pro b/tests/benchmarks/gui/image/qimagereader/qimagereader.pro
index 29f7f6b16e..3454cf1474 100644
--- a/tests/benchmarks/gui/image/qimagereader/qimagereader.pro
+++ b/tests/benchmarks/gui/image/qimagereader/qimagereader.pro
@@ -8,3 +8,5 @@ SOURCES += tst_qimagereader.cpp
qtConfig(gif): DEFINES += QTEST_HAVE_GIF
qtConfig(jpeg): DEFINES += QTEST_HAVE_JPEG
+
+TESTDATA += images/*
diff --git a/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp b/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp
index d81d5bb01a..48e838148f 100644
--- a/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp
+++ b/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp
@@ -51,6 +51,7 @@ public:
virtual ~tst_QImageReader();
public slots:
+ void initTestCase();
void init();
void cleanup();
@@ -69,6 +70,7 @@ private slots:
private:
QList< QPair<QString, QByteArray> > images; // filename, format
+ QString prefix;
};
tst_QImageReader::tst_QImageReader()
@@ -102,6 +104,13 @@ tst_QImageReader::~tst_QImageReader()
{
}
+void tst_QImageReader::initTestCase()
+{
+ prefix = QFINDTESTDATA("images/");
+ if (prefix.isEmpty())
+ QFAIL("Can't find images directory!");
+}
+
void tst_QImageReader::init()
{
}
@@ -128,7 +137,7 @@ void tst_QImageReader::readImage()
QFETCH(QByteArray, format);
QBENCHMARK {
- QImageReader io("images/" + fileName, format);
+ QImageReader io(prefix + fileName, format);
QImage image = io.read();
QVERIFY(!image.isNull());
}
@@ -159,7 +168,7 @@ void tst_QImageReader::setScaledSize()
QFETCH(QByteArray, format);
QBENCHMARK {
- QImageReader reader("images/" + fileName, format);
+ QImageReader reader(prefix + fileName, format);
reader.setScaledSize(newSize);
QImage image = reader.read();
QCOMPARE(image.size(), newSize);
@@ -186,7 +195,7 @@ void tst_QImageReader::setClipRect()
QFETCH(QByteArray, format);
QBENCHMARK {
- QImageReader reader("images/" + fileName, format);
+ QImageReader reader(prefix + fileName, format);
reader.setClipRect(newRect);
QImage image = reader.read();
QCOMPARE(image.rect(), newRect);
@@ -205,7 +214,7 @@ void tst_QImageReader::setScaledClipRect()
QFETCH(QByteArray, format);
QBENCHMARK {
- QImageReader reader("images/" + fileName, format);
+ QImageReader reader(prefix + fileName, format);
reader.setScaledSize(QSize(300, 300));
reader.setScaledClipRect(newRect);
QImage image = reader.read();
diff --git a/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp
index d4be85b5ad..2ded426cdd 100644
--- a/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp
+++ b/tests/benchmarks/gui/image/qpixmapcache/tst_qpixmapcache.cpp
@@ -106,7 +106,7 @@ void tst_QPixmapCache::find()
if (cacheType) {
QBENCHMARK {
for (int i = 0 ; i <= 10000 ; i++)
- QPixmapCache::find(QString::asprintf("my-key-%d", i), p);
+ QPixmapCache::find(QString::asprintf("my-key-%d", i), &p);
}
} else {
QBENCHMARK {
@@ -155,7 +155,7 @@ void tst_QPixmapCache::styleUseCaseComplexKey()
QPixmapCache::insert(QString::asprintf("%s-%d-%d-%d-%d-%d-%d", QString("my-progressbar-%1").arg(i).toLatin1().constData(), 5, 3, 0, 358, 100, 200), p);
for (int i = 0 ; i <= 10000 ; i++)
- QPixmapCache::find(QString::asprintf("%s-%d-%d-%d-%d-%d-%d", QString("my-progressbar-%1").arg(i).toLatin1().constData(), 5, 3, 0, 358, 100, 200), p);
+ QPixmapCache::find(QString::asprintf("%s-%d-%d-%d-%d-%d-%d", QString("my-progressbar-%1").arg(i).toLatin1().constData(), 5, 3, 0, 358, 100, 200), &p);
}
} else {
QHash<styleStruct, QPixmapCache::Key> hash;
diff --git a/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp b/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
index d7a7f383ac..12e85d4842 100644
--- a/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
+++ b/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
@@ -167,9 +167,7 @@ void tst_QTransform::func##_data() \
{ \
QTest::addColumn<QTransform>("transform"); \
QMap<const char *, QTransform> x = generateTransforms(); \
- QMapIterator<const char *, QTransform> it(x); \
- while (it.hasNext()) { \
- it.next(); \
+ for (auto it = x.begin(), end = x.end(); it != end; ++it) { \
QTest::newRow(it.key()) << it.value(); \
} \
}
@@ -180,14 +178,10 @@ void tst_QTransform::func##_data() \
QTest::addColumn<QTransform>("x1"); \
QTest::addColumn<QTransform>("x2"); \
QMap<const char *, QTransform> x = generateTransforms(); \
- QMapIterator<const char *, QTransform> it(x); \
- while (it.hasNext()) { \
- it.next(); \
+ for (auto it = x.cbegin(), end = x.cend(); it != end; ++it) { \
const char *key1 = it.key(); \
QTransform x1 = it.value(); \
- QMapIterator<const char *, QTransform> it2(x); \
- while (it2.hasNext()) { \
- it2.next(); \
+ for (auto it2 = x.cbegin(), end = x.cend(); it2 != end; ++it2) { \
QTest::newRow(QString("%1 + %2").arg(key1).arg(it2.key()).toLatin1().constData()) \
<< x1 << it2.value(); \
} \
diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp
index b2f4cbd7ba..c182ef7ebf 100644
--- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -908,7 +908,7 @@ void tst_qnetworkreply::httpsRequestChain()
qint64 average = (elapsed / count);
- qSort(helper.timeList);
+ std::sort(helper.timeList.begin(), helper.timeList.end());
qint64 median = helper.timeList.at(5);
qDebug() << "Total:" << elapsed << " Average:" << average << " Median:" << median;
diff --git a/tests/benchmarks/opengl/main.cpp b/tests/benchmarks/opengl/main.cpp
index 5008f1592b..0886c0e55b 100644
--- a/tests/benchmarks/opengl/main.cpp
+++ b/tests/benchmarks/opengl/main.cpp
@@ -76,7 +76,6 @@ void OpenGLBench::initTestCase()
QPainter p(pb);
p.setRenderHint(QPainter::Antialiasing);
- p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawImage(0, 0, QImage(256, 256, QImage::Format_ARGB32_Premultiplied));
}
@@ -120,7 +119,6 @@ void OpenGLBench::imageDrawing()
QPainter p(pb);
p.setRenderHint(QPainter::SmoothPixmapTransform, smoothPixmapTransform);
p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
- p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
QBENCHMARK {
if (pixmap) {
@@ -182,7 +180,6 @@ void OpenGLBench::pathDrawing()
dummy.addRect(-1, -1, 2, 2);
QPainter p(pb);
p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
- p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
p.translate(pb->width() / 2, pb->height() / 2);
p.rotate(30);
p.drawPath(dummy);
@@ -196,7 +193,6 @@ void OpenGLBench::pathDrawing()
QBENCHMARK {
p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
- p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
p.rotate(0.01);
p.drawPath(path);
@@ -227,7 +223,6 @@ void OpenGLBench::startupCost()
QGLPixelBuffer buffer(512, 512);
QPainter p(&buffer);
p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
- p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
p.translate(buffer.width() / 2, buffer.height() / 2);
p.drawPath(path);
diff --git a/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
index c8ccb60dbb..8f7736010d 100644
--- a/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
@@ -270,7 +270,6 @@ void MainView::construct()
// Turn off automatic background
setAttribute(Qt::WA_OpaquePaintEvent);
- setAttribute(Qt::WA_NoBackground);
setAttribute(Qt::WA_NoSystemBackground);
setAutoFillBackground(false);
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
index b15aad04cd..e0c5a7f683 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
@@ -60,7 +60,7 @@ public:
{
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->drawRoundRect(rect());
+ painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize);
painter->drawLine(rect().topLeft(), rect().bottomRight());
painter->drawLine(rect().bottomLeft(), rect().topRight());
}
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
index 5c97d7f738..caf5455a80 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
@@ -53,7 +53,7 @@ public:
{
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->drawRoundRect(rect());
+ painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize);
painter->drawLine(rect().topLeft(), rect().bottomRight());
painter->drawLine(rect().bottomLeft(), rect().topRight());
}
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp
index 57ab62b1c3..2277ae0f14 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp
@@ -38,7 +38,7 @@ Chip::Chip(const QColor &color, int x, int y)
setZValue((x + y) % 2);
setFlags(ItemIsSelectable | ItemIsMovable);
- setAcceptsHoverEvents(true);
+ setAcceptHoverEvents(true);
}
QRectF Chip::boundingRect() const
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp
index de4e9e5ad7..6e0ac445a6 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp
@@ -30,12 +30,7 @@
#include <QtGui>
-#if 0 // Used to be included in Qt4 for Q_WS_WIN
-#define CALLGRIND_START_INSTRUMENTATION {}
-#define CALLGRIND_STOP_INSTRUMENTATION {}
-#else
#include "valgrind/callgrind.h"
-#endif
#ifndef QT_NO_OPENGL
#include <QtOpenGL>
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp
index e0cc0f8eb4..140278b8f6 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp
@@ -27,16 +27,7 @@
****************************************************************************/
#include <QtGui>
-#if 0 // Used to be included in Qt4 for Q_WS_WIN
-#define CALLGRIND_START_INSTRUMENTATION {}
-#define CALLGRIND_STOP_INSTRUMENTATION {}
-#else
#include "valgrind/callgrind.h"
-#endif
-
-#if 0 // Used to be included in Qt4 for Q_WS_X11
-extern void qt_x11_wait_for_window_manager(QWidget *);
-#endif
class View : public QGraphicsView
{
@@ -89,9 +80,6 @@ int main(int argc, char *argv[])
View view(&scene, item);
view.resize(300, 300);
view.show();
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- qt_x11_wait_for_window_manager(&view);
-#endif
return app.exec();
}
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp
index 1fbb229cd8..566d16ca51 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp
@@ -27,12 +27,7 @@
****************************************************************************/
#include <QtGui>
-#if 0 // Used to be included in Qt4 for Q_WS_WIN
-#define CALLGRIND_START_INSTRUMENTATION {}
-#define CALLGRIND_STOP_INSTRUMENTATION {}
-#else
#include "valgrind/callgrind.h"
-#endif
class ItemMover : public QObject
{
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp
index cf82282bfe..21eb622f15 100644
--- a/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp
@@ -57,9 +57,9 @@ void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
{
Q_UNUSED(widget);
- QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color;
+ QColor fillColor = (option->state & QStyle::State_Selected) ? color.darker(150) : color;
if (option->state & QStyle::State_MouseOver)
- fillColor = fillColor.light(125);
+ fillColor = fillColor.lighter(125);
if (option->levelOfDetail < 0.2) {
if (option->levelOfDetail < 0.125) {
@@ -82,7 +82,7 @@ void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
pen.setWidth(width);
QBrush b = painter->brush();
- painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100)));
+ painter->setBrush(QBrush(fillColor.darker(option->state & QStyle::State_Sunken ? 120 : 100)));
painter->drawRect(QRect(14, 14, 79, 39));
painter->setBrush(b);
diff --git a/tests/libfuzzer/gui/iccparser/iccparser.pro b/tests/libfuzzer/gui/iccparser/iccparser.pro
new file mode 100644
index 0000000000..bf4037eae7
--- /dev/null
+++ b/tests/libfuzzer/gui/iccparser/iccparser.pro
@@ -0,0 +1,3 @@
+QT += gui
+SOURCES += main.cpp
+LIBS += -fsanitize=fuzzer
diff --git a/tests/libfuzzer/gui/iccparser/main.cpp b/tests/libfuzzer/gui/iccparser/main.cpp
new file mode 100644
index 0000000000..ba4f70ef3b
--- /dev/null
+++ b/tests/libfuzzer/gui/iccparser/main.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QGuiApplication>
+#include <QColorSpace>
+
+extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+ static int c = 0;
+ static QGuiApplication a(c, nullptr);
+ QColorSpace cs = QColorSpace::fromIccProfile(QByteArray(data, size));
+ return 0;
+}
diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri
index 9f10167136..b57ee75841 100644
--- a/tests/manual/diaglib/diaglib.pri
+++ b/tests/manual/diaglib/diaglib.pri
@@ -12,7 +12,7 @@ HEADERS += \
win32:!winrt: {
SOURCES += $$PWD/nativewindowdump_win.cpp
- LIBS *= -luser32
+ QMAKE_USE += user32
} else {
SOURCES += $$PWD/nativewindowdump.cpp
}
diff --git a/tests/manual/diaglib/textdump.cpp b/tests/manual/diaglib/textdump.cpp
index 8bb899783b..383ec4edb0 100644
--- a/tests/manual/diaglib/textdump.cpp
+++ b/tests/manual/diaglib/textdump.cpp
@@ -44,6 +44,9 @@ static const EnumLookup specialCharactersEnumLookup[] =
#if QT_VERSION >= 0x050000
{QChar::Tabulation, "Tabulation"},
{QChar::LineFeed, "LineFeed"},
+# if QT_VERSION >= 0x050e00
+ {QChar::FormFeed, "FormFeed"},
+# endif
{QChar::CarriageReturn, "CarriageReturn"},
{QChar::Space, "Space"},
#endif
diff --git a/tests/manual/highdpi/dragwidget.cpp b/tests/manual/highdpi/dragwidget.cpp
index 46a8ea8090..11bbc1d127 100644
--- a/tests/manual/highdpi/dragwidget.cpp
+++ b/tests/manual/highdpi/dragwidget.cpp
@@ -110,7 +110,7 @@ void DragWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasText()) {
const QMimeData *mime = event->mimeData();
- QStringList pieces = mime->text().split(QRegExp("\\s+"),
+ QStringList pieces = mime->text().split(QRegularExpression("\\s+"),
QString::SkipEmptyParts);
QPoint position = event->pos();
QPoint hotSpot;
diff --git a/tests/manual/highdpi/highdpi.pro b/tests/manual/highdpi/highdpi.pro
index 9db083cd82..2de8ed3bb5 100644
--- a/tests/manual/highdpi/highdpi.pro
+++ b/tests/manual/highdpi/highdpi.pro
@@ -15,3 +15,4 @@ HEADERS += \
RESOURCES += \
highdpi.qrc
+DEFINES += HAVE_SCREEN_BASE_DPI
diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp
index 7225587ac0..8884c5feed 100644
--- a/tests/manual/highdpi/main.cpp
+++ b/tests/manual/highdpi/main.cpp
@@ -37,10 +37,12 @@
#include <QPushButton>
#include <QButtonGroup>
#include <QLineEdit>
+#include <QPlainTextEdit>
#include <QScrollBar>
#include <QSlider>
#include <QSpinBox>
#include <QTabBar>
+#include <QTextBrowser>
#include <QIcon>
#include <QPainter>
#include <QWindow>
@@ -55,9 +57,16 @@
#include <QCommandLineOption>
#include <QDebug>
#include <private/qhighdpiscaling_p.h>
+#include <qpa/qplatformscreen.h>
#include "dragwidget.h"
+static QTextStream &operator<<(QTextStream &str, const QRect &r)
+{
+ str << r.width() << 'x' << r.height() << forcesign << r.x() << r.y() << noforcesign;
+ return str;
+}
+
class DemoContainerBase
{
public:
@@ -1176,6 +1185,85 @@ public:
}
};
+class MetricsTest : public QWidget
+{
+ QPlainTextEdit *m_textEdit;
+
+public:
+ MetricsTest()
+ {
+ qDebug() << R"(
+MetricsTest
+Relevant environment variables are:
+QT_FONT_DPI=N
+QT_SCALE_FACTOR=n
+QT_ENABLE_HIGHDPI_SCALING=0|1
+QT_USE_PHYSICAL_DPI=0|1
+QT_SCREEN_SCALE_FACTORS=N;N;N or QT_SCREEN_SCALE_FACTORS=name:N
+QT_SCALE_FACTOR_ROUNDING_POLICY=Round|Ceil|Floor|RoundPreferFloor|PassThrough
+QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
+
+ resize(480, 360);
+
+ QVBoxLayout *layout = new QVBoxLayout();
+ setLayout(layout);
+
+ m_textEdit = new QPlainTextEdit;
+ m_textEdit->setReadOnly(true);
+ layout->addWidget(m_textEdit);
+ }
+
+ void updateMetrics()
+ {
+ QString text;
+ QTextStream str(&text);
+
+ auto currentScreen = windowHandle()->screen();
+ const auto screens = QGuiApplication::screens();
+ for (int i = 0, size = screens.size(); i < size; ++i) {
+ auto screen = screens.at(i);
+ auto platformScreen = screen->handle();
+ str << "Screen #" << i << " \"" << screen->name() << '"';
+ if (screen == currentScreen)
+ str << " [current]";
+ if (screen == QGuiApplication::primaryScreen())
+ str << " [primary]";
+ str << "\n screen geometry: " << screen->geometry()
+ << "\n platform screen geometry: " << platformScreen->geometry()
+ << "\n platform screen logicalDpi: " << platformScreen->logicalDpi().first;
+
+#ifdef HAVE_SCREEN_BASE_DPI
+ str << "\n platform screen logicalBaseDpi: " << platformScreen->logicalBaseDpi().first;
+#endif
+ str << "\n platform screen devicePixelRatio: " <<platformScreen->devicePixelRatio()
+ << "\n platform screen physicalDpi: " << screen->physicalDotsPerInch()
+ << "\n\n";
+ }
+
+ str << "widget devicePixelRatio: " << this->devicePixelRatioF()
+ << "\nwidget logicalDpi: " << this->logicalDpiX()
+ << "\n\nQT_FONT_DPI: " << qgetenv("QT_FONT_DPI")
+ << "\nQT_SCALE_FACTOR: " << qgetenv("QT_SCALE_FACTOR")
+ << "\nQT_ENABLE_HIGHDPI_SCALING: " << qgetenv("QT_ENABLE_HIGHDPI_SCALING")
+ << "\nQT_SCREEN_SCALE_FACTORS: " << qgetenv("QT_SCREEN_SCALE_FACTORS")
+ << "\nQT_USE_PHYSICAL_DPI: " << qgetenv("QT_USE_PHYSICAL_DPI")
+ << "\nQT_SCALE_FACTOR_ROUNDING_POLICY: " << qgetenv("QT_SCALE_FACTOR_ROUNDING_POLICY")
+ << "\nQT_DPI_ADJUSTMENT_POLICY: " << qgetenv("QT_DPI_ADJUSTMENT_POLICY")
+ << '\n';
+
+ m_textEdit->setPlainText(text);
+ }
+
+ void paintEvent(QPaintEvent *ev)
+ {
+ // We get a paint event on screen change, so this is a convenient place
+ // to update the metrics, at the possible risk of doing something else
+ // than painting in a paint event.
+ updateMetrics();
+ QWidget::paintEvent(ev);
+ }
+};
+
int main(int argc, char **argv)
{
QApplication app(argc, argv);
@@ -1212,6 +1300,7 @@ int main(int argc, char **argv)
demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning");
demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch");
demoList << new DemoContainer<GraphicsViewCaching>("graphicsview", "Test QGraphicsView caching");
+ demoList << new DemoContainer<MetricsTest>("metrics", "Show display metrics");
foreach (DemoContainerBase *demo, demoList)
parser.addOption(demo->option());
diff --git a/tests/manual/keypadnavigation/main.cpp b/tests/manual/keypadnavigation/main.cpp
index 67986a9cc9..dad4376514 100644
--- a/tests/manual/keypadnavigation/main.cpp
+++ b/tests/manual/keypadnavigation/main.cpp
@@ -33,7 +33,6 @@
#include <QFontDialog>
#include <QInputDialog>
#include <QMessageBox>
-#include <QSignalMapper>
#include "ui_keypadnavigation.h"
class KeypadNavigation : public QMainWindow
@@ -48,7 +47,7 @@ public:
ui->setupUi(this);
const struct {
- QObject *action;
+ QAction *action;
QWidget *page;
} layoutMappings[] = {
{ui->m_actionLayoutVerticalSimple, ui->m_pageVerticalSimple},
@@ -58,15 +57,16 @@ public:
{ui->m_actionLayoutChaos, ui->m_pageChaos},
{ui->m_actionLayoutDialogs, ui->m_pageDialogs}
};
- for (int i = 0; i < int(sizeof layoutMappings / sizeof layoutMappings[0]); ++i) {
- connect(layoutMappings[i].action, SIGNAL(triggered()), &m_layoutSignalMapper, SLOT(map()));
- m_layoutSignalMapper.setMapping(layoutMappings[i].action, layoutMappings[i].page);
+ for (auto layoutMapping : layoutMappings) {
+ const auto page = layoutMapping.page;
+ connect(layoutMapping.action, &QAction::triggered, ui->m_stackWidget,
+ [this, page]()
+ { ui->m_stackWidget->setCurrentWidget(page); });
}
- connect(&m_layoutSignalMapper, SIGNAL(mapped(QWidget*)), ui->m_stackWidget, SLOT(setCurrentWidget(QWidget*)));
#ifdef QT_KEYPAD_NAVIGATION
const struct {
- QObject *action;
+ QAction *action;
Qt::NavigationMode mode;
} modeMappings[] = {
{ui->m_actionModeNone, Qt::NavigationModeNone},
@@ -75,17 +75,17 @@ public:
{ui->m_actionModeCursorAuto, Qt::NavigationModeCursorAuto},
{ui->m_actionModeCursorForceVisible, Qt::NavigationModeCursorForceVisible}
};
- for (int i = 0; i < int(sizeof modeMappings / sizeof modeMappings[0]); ++i) {
- connect(modeMappings[i].action, SIGNAL(triggered()), &m_modeSignalMapper, SLOT(map()));
- m_modeSignalMapper.setMapping(modeMappings[i].action, int(modeMappings[i].mode));
+ for (auto modeMapping : modeMappings) {
+ const auto mode = modeMapping.mode;
+ connect(modeMapping.action, &QAction::triggered, this,
+ [this, mode]() { setNavigationMode(mode); });
}
- connect(&m_modeSignalMapper, SIGNAL(mapped(int)), SLOT(setNavigationMode(int)));
#else // QT_KEYPAD_NAVIGATION
ui->m_menuNavigation_mode->deleteLater();
#endif // QT_KEYPAD_NAVIGATION
const struct {
- QObject *button;
+ QPushButton *button;
Dialog dialog;
} openDialogMappings[] = {
{ui->m_buttonGetOpenFileName, DialogGetOpenFileName},
@@ -97,11 +97,11 @@ public:
{ui->m_buttonAboutQt, DialogAboutQt},
{ui->m_buttonGetItem, DialogGetItem}
};
- for (int i = 0; i < int(sizeof openDialogMappings / sizeof openDialogMappings[0]); ++i) {
- connect(openDialogMappings[i].button, SIGNAL(clicked()), &m_dialogSignalMapper, SLOT(map()));
- m_dialogSignalMapper.setMapping(openDialogMappings[i].button, int(openDialogMappings[i].dialog));
+ for (auto openDialogMapping : openDialogMappings) {
+ const auto dialog = openDialogMapping.dialog;
+ connect(openDialogMapping.button, &QPushButton::clicked, this,
+ [this, dialog]() { openDialog(dialog); });
}
- connect(&m_dialogSignalMapper, SIGNAL(mapped(int)), SLOT(openDialog(int)));
}
~KeypadNavigation()
@@ -162,11 +162,6 @@ private:
};
Ui_KeypadNavigation *ui;
- QSignalMapper m_layoutSignalMapper;
-#ifdef QT_KEYPAD_NAVIGATION
- QSignalMapper m_modeSignalMapper;
-#endif // QT_KEYPAD_NAVIGATION
- QSignalMapper m_dialogSignalMapper;
};
int main(int argc, char *argv[])
diff --git a/tests/manual/lance/main.cpp b/tests/manual/lance/main.cpp
index 7f5af2d908..6dc5e2076a 100644
--- a/tests/manual/lance/main.cpp
+++ b/tests/manual/lance/main.cpp
@@ -334,20 +334,7 @@ int main(int argc, char **argv)
checkers_background = false;
}
} else {
-#if 0 // Used to be included in Qt4 for Q_WS_WIN
- QString input = QString::fromLocal8Bit(argv[i]);
- if (input.indexOf('*') >= 0) {
- QFileInfo info(input);
- QDir dir = info.dir();
- QFileInfoList infos = dir.entryInfoList(QStringList(info.fileName()));
- for (int ii=0; ii<infos.size(); ++ii)
- files.append(infos.at(ii).absoluteFilePath());
- } else {
- files.append(input);
- }
-#else
files.append(QString(argv[i]));
-#endif
}
}
scaledWidth = int(width * scalefactor);
diff --git a/tests/manual/lance/widgets.h b/tests/manual/lance/widgets.h
index 46c55f4c16..09b2c3e667 100644
--- a/tests/manual/lance/widgets.h
+++ b/tests/manual/lance/widgets.h
@@ -43,7 +43,6 @@
#include <QFileDialog>
#include <QTextStream>
#include <QPaintEngine>
-#include <QSignalMapper>
#include <QAction>
#include <QDebug>
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index ab00a5ef60..42f9878e44 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -23,6 +23,7 @@ qimagereader \
qlayout \
qlocale \
qmimedatabase \
+qnetconmonitor \
qnetworkaccessmanager/qget \
qnetworkconfigurationmanager \
qnetworkconfiguration \
@@ -34,6 +35,7 @@ qsslsocket \
qsysinfo \
qtabletevent \
qtexteditlist \
+qtexttableborders \
qtbug-8933 \
qtbug-52641 \
qtouchevent \
@@ -53,7 +55,8 @@ shortcuts \
dialogs \
windowtransparency \
unc \
-qtabbar
+qtabbar \
+rhi
!qtConfig(openssl): SUBDIRS -= qssloptions
diff --git a/tests/manual/markdown/html2md.cpp b/tests/manual/markdown/html2md.cpp
new file mode 100644
index 0000000000..19d6ff06af
--- /dev/null
+++ b/tests/manual/markdown/html2md.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2019 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 <QCommandLineParser>
+#include <QDebug>
+#include <QFile>
+#include <QGuiApplication>
+#include <QTextDocument>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+ QGuiApplication::setApplicationVersion(QT_VERSION_STR);
+ QCommandLineParser parser;
+ parser.setApplicationDescription("Converts the Qt-supported subset of HTML to Markdown.");
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.addPositionalArgument(QGuiApplication::translate("main", "input"),
+ QGuiApplication::translate("main", "input file"));
+ parser.addPositionalArgument(QGuiApplication::translate("main", "output"),
+ QGuiApplication::translate("main", "output file"));
+ parser.process(app);
+ if (parser.positionalArguments().count() != 2)
+ parser.showHelp(1);
+
+ QFile inFile(parser.positionalArguments().first());
+ if (!inFile.open(QIODevice::ReadOnly)) {
+ qFatal("failed to open %s for reading", parser.positionalArguments().first().toLocal8Bit().data());
+ exit(2);
+ }
+ QFile outFile(parser.positionalArguments().at(1));
+ if (!outFile.open(QIODevice::WriteOnly)) {
+ qFatal("failed to open %s for writing", parser.positionalArguments().at(1).toLocal8Bit().data());
+ exit(2);
+ }
+ QTextDocument doc;
+ doc.setHtml(QString::fromUtf8(inFile.readAll()));
+ outFile.write(doc.toMarkdown().toUtf8());
+}
diff --git a/tests/manual/markdown/html2md.pro b/tests/manual/markdown/html2md.pro
new file mode 100644
index 0000000000..4d6254e5a0
--- /dev/null
+++ b/tests/manual/markdown/html2md.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+TARGET = html2md
+INCLUDEPATH += .
+#QT += gui-private
+SOURCES += html2md.cpp
+
diff --git a/tests/manual/qcursor/qcursorhighdpi/main.cpp b/tests/manual/qcursor/qcursorhighdpi/main.cpp
index 4a7646c39d..3b18bff91c 100644
--- a/tests/manual/qcursor/qcursorhighdpi/main.cpp
+++ b/tests/manual/qcursor/qcursorhighdpi/main.cpp
@@ -183,7 +183,7 @@ private:
void DraggableLabel::mousePressEvent(QMouseEvent *)
{
QMimeData *mimeData = new QMimeData;
- mimeData->setImageData(qVariantFromValue(m_pixmap));
+ mimeData->setImageData(QVariant::fromValue(m_pixmap));
QDrag *drag = new QDrag(this);
QPixmap pixmap = m_pixmap;
if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
diff --git a/tests/manual/qgraphicslayout/flicker/window.h b/tests/manual/qgraphicslayout/flicker/window.h
index 22a53585d1..c49b82704e 100644
--- a/tests/manual/qgraphicslayout/flicker/window.h
+++ b/tests/manual/qgraphicslayout/flicker/window.h
@@ -107,7 +107,7 @@ public:
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setBrush(m_brush);
- painter->drawRoundRect(rect());
+ painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize);
painter->drawLine(rect().topLeft(), rect().bottomRight());
painter->drawLine(rect().bottomLeft(), rect().topRight());
}
diff --git a/tests/manual/qnetconmonitor/qnetconmonitor.pro b/tests/manual/qnetconmonitor/qnetconmonitor.pro
new file mode 100644
index 0000000000..dda88c4cd7
--- /dev/null
+++ b/tests/manual/qnetconmonitor/qnetconmonitor.pro
@@ -0,0 +1,4 @@
+TEMPLATE = app
+QT = network-private testlib
+CONFIG += console
+SOURCES += tst_qnetconmonitor.cpp
diff --git a/tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp b/tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp
new file mode 100644
index 0000000000..92daee3348
--- /dev/null
+++ b/tests/manual/qnetconmonitor/tst_qnetconmonitor.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdeadlinetimer.h>
+
+#include <QtNetwork/qhostinfo.h>
+#include <QtNetwork/private/qnetconmonitor_p.h>
+
+#include <QtTest/qsignalspy.h>
+
+void testDetectDisconnection();
+void testDetectRouteDisrupted();
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ if (!QNetworkStatusMonitor::isEnabled()) {
+ qWarning("QNetworkStatusMonitor is not enabled for this platform!");
+ return 0;
+ }
+
+ while (true) {
+
+ QByteArray indent(" ");
+ {
+ QTextStream writer(stdout);
+ writer << "Manual test for QNetwork{Status|Connection}Monitor\n"
+ << "The tests are grouped by what they test. Run them in any order\n"
+ << "- QNetworkStatusMonitor tests:\n"
+ << indent << "c" << indent << "Test connection and disconnection detection.\n"
+ << "- QNetworkConnectionMonitor tests:\n"
+ << indent << "r" << indent << "Test detection of disruption of route to target.\n"
+ << "- General\n"
+ << indent << "q" << indent << "Quit the test.\n"
+ << "> ";
+ }
+
+ auto getCommand = []() {
+ char ch;
+ QTextStream reader(stdin);
+ reader >> ch;
+ return ch;
+ };
+
+ switch (getCommand()) {
+ case 'c':
+ testDetectDisconnection();
+ break;
+ case 'r':
+ testDetectRouteDisrupted();
+ break;
+ case 'q':
+ return 0;
+ }
+ }
+ Q_UNREACHABLE();
+ return 0;
+}
+
+bool ensureNetworkAccessible(QNetworkStatusMonitor &status, QTextStream &writer)
+{
+ if (!status.isNetworkAccessible()) {
+ writer << "Network currently not accessible, please make sure you have an internet "
+ "connection. Will wait for a connection for 20 seconds.\n";
+ writer.flush();
+ QDeadlineTimer timer{ 20 * 1000 };
+ while (!timer.hasExpired() && !status.isNetworkAccessible())
+ QCoreApplication::processEvents();
+ if (!status.isNetworkAccessible()) {
+ writer << "Error: No network in 20 seconds, ending now!\n";
+ return false;
+ }
+ writer << "Network successfully connected, thanks!\n";
+ }
+ return true;
+}
+
+void testDetectDisconnection()
+{
+ QTextStream writer(stdout);
+ QNetworkStatusMonitor status;
+
+ if (!status.start()) {
+ writer << "Error: Failed to start";
+ return;
+ }
+
+ if (!ensureNetworkAccessible(status, writer))
+ return;
+
+ QSignalSpy onlineStateSpy(&status, &QNetworkStatusMonitor::onlineStateChanged);
+
+ writer << "Please disconnect from the internet within 20 seconds\n";
+ writer.flush();
+ QDeadlineTimer timer{ 20 * 1000 };
+ while (!timer.hasExpired() && status.isNetworkAccessible())
+ QCoreApplication::processEvents();
+ if (status.isNetworkAccessible()) {
+ writer << "Error: Still connected after 20 seconds, ending now!\n";
+ return;
+ }
+ if (onlineStateSpy.count() == 0) {
+ writer << "Error: There was a disconnection but there was no signal emitted!\n";
+ return;
+ }
+ // Get the final parameter of the final signal emission and make sure it is false.
+ if (onlineStateSpy.last().last().toBool()) {
+ writer << "Error: There was a disconnection but the latest signal emitted says we are online!\n";
+ return;
+ }
+ writer << "Success, connection loss was detected!\n";
+}
+
+void testDetectRouteDisrupted()
+{
+ QTextStream writer(stdout);
+
+ {
+ QNetworkStatusMonitor status;
+ if (!status.start()) {
+ writer << "Error: Failed to start";
+ return;
+ }
+ if (!ensureNetworkAccessible(status, writer))
+ return;
+ }
+
+ QNetworkConnectionMonitor connection;
+
+ auto readLineFromStdin = []() -> QString {
+ QTextStream in(stdin);
+ return in.readLine();
+ };
+
+ writer << "Type your local IP address: ";
+ writer.flush();
+ const QHostAddress local{ readLineFromStdin() };
+ if (local.isNull()) {
+ writer << "Error: The address is invalid!\n";
+ return;
+ }
+
+ const QHostAddress defaultAddress{ QString::fromLatin1("1.1.1.1") };
+ QHostAddress remote;
+ do {
+ writer << "Type a remote IP address [" << defaultAddress.toString() << "]: ";
+ writer.flush();
+ QString address = readLineFromStdin();
+ if (address.isEmpty()) {
+ remote = defaultAddress;
+ } else {
+ QHostAddress remoteTemp{ address };
+ if (remoteTemp.isNull()) {
+ writer << "Invalid address\n";
+ } else {
+ remote = remoteTemp;
+ }
+ }
+ } while (remote.isNull());
+
+ if (!connection.setTargets(local, remote)) {
+ writer << "Error: Failed to set the targets!\n";
+ return;
+ }
+ if (!connection.isReachable()) {
+ writer << "Error: Target is not reachable!\n";
+ return;
+ }
+ if (!connection.startMonitoring()) {
+ writer << "Error: Failed to start monitoring!\n";
+ return;
+ }
+
+ QSignalSpy reachabilitySpy(&connection, &QNetworkConnectionMonitor::reachabilityChanged);
+
+ writer << "QNetworkConnectionMonitor might assume the target is initially reachable.\n"
+ "If it is not reachable then this test might not work correctly.\n"
+ "Please disrupt the connection between your machine and the target within 20 "
+ "seconds\n";
+ writer.flush();
+ reachabilitySpy.wait(20 * 1000);
+ if (reachabilitySpy.count() == 0) {
+ writer << "Error: There was a disconnection but there was no signal emitted!\n";
+ return;
+ }
+ // Get the final parameter of the final signal emission and make sure it is false.
+ if (reachabilitySpy.last().last().toBool()) {
+ writer << "Error: There was a disconnection but the latest signal emitted says the target is "
+ "reachable!\n";
+ return;
+ }
+ writer << "Success, connection disruption was detected!\n";
+}
diff --git a/tests/manual/qtexttableborders/main.cpp b/tests/manual/qtexttableborders/main.cpp
new file mode 100644
index 0000000000..a8fdf7becc
--- /dev/null
+++ b/tests/manual/qtexttableborders/main.cpp
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "widget.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ Widget w;
+ w.show();
+
+ return a.exec();
+}
diff --git a/tests/manual/qtexttableborders/qtexttableborders.pro b/tests/manual/qtexttableborders/qtexttableborders.pro
new file mode 100644
index 0000000000..7e454f978d
--- /dev/null
+++ b/tests/manual/qtexttableborders/qtexttableborders.pro
@@ -0,0 +1,10 @@
+#This project can be used to verify QTBUG-36152 case.
+QT += core gui printsupport
+CONFIG += c++11
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+TARGET = qtexttableborders
+TEMPLATE = app
+SOURCES += main.cpp widget.cpp
+HEADERS += widget.h
+FORMS += widget.ui
+RESOURCES += resources.qrc
diff --git a/tests/manual/qtexttableborders/resources.qrc b/tests/manual/qtexttableborders/resources.qrc
new file mode 100644
index 0000000000..a7000a73e3
--- /dev/null
+++ b/tests/manual/qtexttableborders/resources.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>table-border-test-header.html</file>
+ <file>table-border-test.html</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/qtexttableborders/table-border-test-header.html b/tests/manual/qtexttableborders/table-border-test-header.html
new file mode 100644
index 0000000000..cb29d0a41d
--- /dev/null
+++ b/tests/manual/qtexttableborders/table-border-test-header.html
@@ -0,0 +1,129 @@
+<html>
+ <body>
+
+ <h2>Printable table with repeated header</h2>
+
+ <p>
+ Please print (to PDF, save the trees) this table and compare this to the
+ print results of Chrome/Firefox.
+ <ul>
+ <li>Firefox fails to render the first repeated header correctly
+ <li>Chrome fails to render the Cell B top edge (should be red, except the first row after header
+ <li>Qt: Could do slightly better with the last row on each page (although both Firefox and Chrome don't work perfect here as well)
+ </ul>
+ </p>
+
+ <table border=1 bordercolor="#aaaaaa" style="border-collapse:collapse">
+ <thead>
+ <tr>
+ <th style="border-bottom: 1px solid blue">Header A</th>
+ <th style="border-bottom: 4px solid blue">Header B</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ <tr><td>Cell A</td><td style="border-top: 1px solid red">Cell B</td></tr>
+ </tbody>
+ </table>
+
+ </body>
+</html>
diff --git a/tests/manual/qtexttableborders/table-border-test.html b/tests/manual/qtexttableborders/table-border-test.html
new file mode 100644
index 0000000000..0339f80d0f
--- /dev/null
+++ b/tests/manual/qtexttableborders/table-border-test.html
@@ -0,0 +1,171 @@
+<html>
+ <body>
+
+ <h1>Working Test Cases</h1>
+
+ <h2>border-collapse: separate</h2>
+
+ <h3>TC-A1: table no border</h3>
+ <table>
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-A2: table attribute controlled border (1px, red)</h3>
+ <table border=1 bordercolor="red">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-A3: table attribute controlled border (4px, blue)</h3>
+ <table border=4 bordercolor="blue">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+ Note: Real browsers render the inner cells border with 1px, but QTextDocument's rendering has always been like this.
+
+ <h2>border-collapse: collapse</h2>
+
+ <h3>TC-B1: table no border</h3>
+ <table style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-B2: table attribute + css controlled grid (outer border 1px)</h3>
+ <table border=1 bordercolor="red" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-B3: table attribute + css controlled grid (outer border 4px)</h3>
+ <table border=4 bordercolor="red" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-B4: table attribute + css controlled grid (one cell with custom edge)</h3>
+ <table border=4 bordercolor="red" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td style="border-right: 8px solid green">Cell 1B (border-right: 8px solid green)</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-B5: table with single decorated cell</h3>
+ <table style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td style="border: 2px solid red">Cell 1B (border: 2px solid red)</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>cells with competing rules</h3>
+
+ <h4>TC-C1: vertical edge (pink, 6px) wins over horizontal edge (red|blue, 6px)</h4>
+ <table border=1 bordercolor="#999999" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td style="border-right: 4px solid green; border-bottom: 6px solid red">Cell 1A</td>
+ <td style="border-left: 6px solid pink; border-bottom: 6px solid blue">Cell 2B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h4>TC-C2: vertical edge (pink, 6px) loses over horizontal edge (red|blue, 8px)</h4>
+ <table border=1 bordercolor="#999999" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td style="border-right: 4px solid green; border-bottom: 8px solid red">Cell 1A</td>
+ <td style="border-left: 6px solid pink; border-bottom: 8px solid blue">Cell 2B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h4>TC-C3: cells with span and competing rules</h4>
+ <table border=1 bordercolor="#999999" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td colspan=2 style="border-bottom: 4px solid red">Cell 1A/B spans over two columns (border-bottom: red)</td>
+ </tr>
+ <tr>
+ <td style="border-top: 1px solid green">Cell 2A (border-top loses -> red)</td>
+ <td style="border-top: 10px solid green">Cell 2B (border-top wins -> green)</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h1>Non-Working Test Cases</h1>
+
+ <h2>border-collapse: separate</h2>
+
+ <h3>TC-X1: table css border (red via style)</h3>
+ <table style="border: 1px solid red">
+ <tbody>
+ <tr>
+ <td>Cell 1A</td>
+ <td>Cell 1B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h2>border-collapse: collapse</h2>
+
+ <h3>TC-X2: tr css border</h3>
+ <table border=1 style="border-collapse: collapse">
+ <tbody>
+ <tr style="border-bottom: 2px solid red">
+ <td>Cell 1A (border-bottom should be red)</td>
+ <td>Cell 1B (border-bottom should be red)</td>
+ </tr>
+ <tr style="border-left: 2px solid red">
+ <td>Cell 2A (border-left should be red)</td>
+ <td>Cell 2B</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>TC-X3: cells with competing rules and colspan</h3>
+ <table border=1 bordercolor="#999999" style="border-collapse: collapse">
+ <tbody>
+ <tr>
+ <td colspan=2 style="border-bottom: 4px solid red; border-right: 15px solid pink">Cell 1A/B spans over two columns (border-bottom: red, border-right pink)</td>
+ </tr>
+ <tr>
+ <td style="border-top: 1px solid green">Cell 2A (border-top loses -> red)</td>
+ <td style="border-top: 10px solid green">Cell 2B (border-top wins -> green)</td>
+ </tr>
+ </tbody>
+ </table>
+ This is currently not 100% correct but admittedly a constructed corner case (and Chrome failes here, too).
+
+ </body>
+</html>
diff --git a/tests/manual/qtexttableborders/widget.cpp b/tests/manual/qtexttableborders/widget.cpp
new file mode 100644
index 0000000000..21d958ce81
--- /dev/null
+++ b/tests/manual/qtexttableborders/widget.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "widget.h"
+#include "ui_widget.h"
+
+#include <QScrollBar>
+#include <QFile>
+#include <QDir>
+#include <QTemporaryFile>
+
+#ifndef QT_NO_DESKTOPSERVICES
+#include <QDesktopServices>
+#endif
+
+#ifndef QT_NO_PRINTER
+#include <QPrinter>
+#include <QPrintDialog>
+#include <QPrintPreviewDialog>
+#endif
+
+// This manual test allows checking the QTextTable border logic (QTBUG-36152)
+
+Widget::Widget(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::Widget)
+{
+ ui->setupUi(this);
+ resize(1400, 800);
+
+ connect(ui->docComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Widget::onDocumentSelected);
+ connect(ui->printButton, &QPushButton::clicked, this, &Widget::onPrint);
+ connect(ui->previewButton, &QPushButton::clicked, this, &Widget::onPreview);
+ connect(ui->openBrowserButton, &QPushButton::clicked, this, &Widget::onOpenBrowser);
+
+ connect(ui->sourceEdit, &QTextEdit::textChanged, this,
+ [this]() {
+ // make this a world class HTML IDE
+ auto pos = ui->htmlEdit->verticalScrollBar()->value();
+ ui->htmlEdit->setHtml(ui->sourceEdit->toPlainText());
+ ui->htmlEdit->verticalScrollBar()->setValue(pos);
+ });
+
+ ui->docComboBox->addItem(tr("Table Border Test"), ":/table-border-test.html");
+ ui->docComboBox->addItem(tr("Table Border Header Test"), ":/table-border-test-header.html");
+
+ ui->docComboBox->setCurrentIndex(0);
+}
+
+Widget::~Widget()
+{
+ delete ui;
+}
+
+void Widget::onDocumentSelected()
+{
+ QString url = ui->docComboBox->itemData(ui->docComboBox->currentIndex()).toString();
+ QFile f(url);
+ if (f.open(QFile::ReadOnly)) {
+ ui->sourceEdit->setPlainText(QString::fromUtf8(f.readAll()));
+ // preview HTML is set via textChanged signal
+ }
+}
+
+void Widget::onPrint()
+{
+#ifndef QT_NO_PRINTER
+ QPrinter printer(QPrinter::HighResolution);
+ QPrintDialog dlg(&printer, this);
+ if (ui->htmlEdit->textCursor().hasSelection())
+ dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
+ dlg.setWindowTitle(tr("Print Document"));
+ if (dlg.exec() == QDialog::Accepted) {
+ ui->htmlEdit->print(&printer);
+ }
+#endif
+}
+
+void Widget::onPreview()
+{
+#ifndef QT_NO_PRINTER
+ QPrinter printer(QPrinter::HighResolution);
+ QPrintPreviewDialog preview(&printer, this);
+ connect(&preview, &QPrintPreviewDialog::paintRequested, ui->htmlEdit, &QTextEdit::print);
+ preview.exec();
+#endif
+}
+
+void Widget::onOpenBrowser()
+{
+ // write the current html to a temp file and open the system browser
+#ifndef QT_NO_DESKTOPSERVICES
+ auto tf = new QTemporaryFile(QDir::tempPath() + "/XXXXXX.html", this);
+ if (tf->open()) {
+ tf->write(ui->sourceEdit->toPlainText().toUtf8());
+ tf->close();
+ QDesktopServices::openUrl(QUrl::fromLocalFile(tf->fileName()));
+ }
+#endif
+}
diff --git a/tests/manual/qtexttableborders/widget.h b/tests/manual/qtexttableborders/widget.h
new file mode 100644
index 0000000000..9cf459e1cd
--- /dev/null
+++ b/tests/manual/qtexttableborders/widget.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 WIDGET_H
+#define WIDGET_H
+
+#include <QWidget>
+
+namespace Ui {
+class Widget;
+}
+
+class Widget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit Widget(QWidget *parent = nullptr);
+ ~Widget();
+
+private slots:
+ void onDocumentSelected();
+ void onPrint();
+ void onPreview();
+ void onOpenBrowser();
+
+private:
+ Ui::Widget *ui;
+};
+
+#endif // WIDGET_H
diff --git a/tests/manual/qtexttableborders/widget.ui b/tests/manual/qtexttableborders/widget.ui
new file mode 100644
index 0000000000..95c23be69e
--- /dev/null
+++ b/tests/manual/qtexttableborders/widget.ui
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Widget</class>
+ <widget class="QWidget" name="Widget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>606</width>
+ <height>522</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>QTextTable Border Manual Test</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="docComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="printButton">
+ <property name="text">
+ <string>Print</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="previewButton">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="openBrowserButton">
+ <property name="text">
+ <string>Open Browser</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QTextEdit" name="htmlEdit"/>
+ <widget class="QTextEdit" name="sourceEdit"/>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+ <tabstop>docComboBox</tabstop>
+ <tabstop>printButton</tabstop>
+ <tabstop>previewButton</tabstop>
+ <tabstop>openBrowserButton</tabstop>
+ <tabstop>htmlEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp
new file mode 100644
index 0000000000..27dd8097ad
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include "../shared/cube.h"
+#include "../shared/dds_bc1.h"
+
+struct {
+ QRhiBuffer *vbuf = nullptr;
+ bool vbufReady = false;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+
+ float rotation = 0;
+
+ QByteArrayList compressedData;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::BC1))
+ qFatal("This backend does not support BC1");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.vbufReady = false;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+
+ QSize imageSize;
+ d.compressedData = loadBC1(QLatin1String(":/qt256_bc1_9mips.dds"), &imageSize);
+ qDebug() << d.compressedData.count() << imageSize << m_r->mipLevelsForSize(imageSize);
+
+ d.tex = m_r->newTexture(QRhiTexture::BC1, imageSize, 1, QRhiTexture::MipMapped);
+ d.tex->build();
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ const QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ delete d.ps;
+ d.ps = nullptr;
+
+ delete d.srb;
+ d.srb = nullptr;
+
+ delete d.ubuf;
+ d.ubuf = nullptr;
+
+ delete d.vbuf;
+ d.vbuf = nullptr;
+
+ delete d.sampler;
+ d.sampler = nullptr;
+
+ delete d.tex;
+ d.tex = nullptr;
+}
+
+void Window::customRender()
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (!d.vbufReady) {
+ d.vbufReady = true;
+ u->uploadStaticBuffer(d.vbuf, cube);
+ qint32 flip = 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ }
+ if (!d.compressedData.isEmpty()) {
+ QRhiTextureUploadDescription desc;
+ for (int i = 0; i < d.compressedData.count(); ++i) {
+ QRhiTextureSubresourceUploadDescription image(d.compressedData[i].constData(), d.compressedData[i].size());
+ desc.append({ 0, i, image });
+ }
+ u->uploadTexture(d.tex, desc);
+ d.compressedData.clear();
+ }
+ d.rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(d.rotation, 0, 1, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { d.vbuf, 0 },
+ { d.vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro
new file mode 100644
index 0000000000..d185aa6b9a
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ compressedtexture_bc1.cpp
+
+RESOURCES = compressedtexture_bc1.qrc
diff --git a/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc
new file mode 100644
index 0000000000..a83259a7d3
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256_bc1_9mips.dds">../shared/qt256_bc1_9mips.dds</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp
new file mode 100644
index 0000000000..87d1e7646a
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include "../shared/cube.h"
+#include "../shared/dds_bc1.h"
+
+struct {
+ QRhiBuffer *vbuf = nullptr;
+ bool vbufReady = false;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+
+ float rotation = 0;
+
+ QByteArrayList compressedData;
+ QByteArrayList compressedData2;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::BC1))
+ qFatal("This backend does not support BC1");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.vbufReady = false;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+
+ QSize imageSize;
+ d.compressedData = loadBC1(QLatin1String(":/qt256_bc1_9mips.dds"), &imageSize);
+ Q_ASSERT(imageSize == QSize(256, 256));
+
+ d.tex = m_r->newTexture(QRhiTexture::BC1, imageSize);
+ d.tex->build();
+
+ d.compressedData2 = loadBC1(QLatin1String(":/bwqt224_64_nomips.dds"), &imageSize);
+ Q_ASSERT(imageSize == QSize(224, 64));
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, // no mipmapping here
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ const QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ delete d.ps;
+ d.ps = nullptr;
+
+ delete d.srb;
+ d.srb = nullptr;
+
+ delete d.ubuf;
+ d.ubuf = nullptr;
+
+ delete d.vbuf;
+ d.vbuf = nullptr;
+
+ delete d.sampler;
+ d.sampler = nullptr;
+
+ delete d.tex;
+ d.tex = nullptr;
+}
+
+void Window::customRender()
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (!d.vbufReady) {
+ d.vbufReady = true;
+ u->uploadStaticBuffer(d.vbuf, cube);
+ qint32 flip = 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ }
+ if (!d.compressedData.isEmpty()) {
+ {
+ QRhiTextureUploadDescription desc({ 0, 0, { d.compressedData[0].constData(), d.compressedData[0].size() } });
+ u->uploadTexture(d.tex, desc);
+ d.compressedData.clear();
+ }
+
+ // now exercise uploading a smaller compressed image into the same texture
+ {
+ QRhiTextureSubresourceUploadDescription image(d.compressedData2[0].constData(), d.compressedData2[0].size());
+ // positions and sizes must be multiples of 4 here (for BC1)
+ image.setDestinationTopLeft(QPoint(16, 32));
+ // the image is smaller than the subresource size (224x64 vs
+ // 256x256) so the size must be specified manually
+ image.setSourceSize(QSize(224, 64));
+ QRhiTextureUploadDescription desc({ 0, 0, image });
+ u->uploadTexture(d.tex, desc);
+ d.compressedData2.clear();
+ }
+ }
+ d.rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(d.rotation, 0, 1, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { d.vbuf, 0 },
+ { d.vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro
new file mode 100644
index 0000000000..a1184fc754
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ compressedtexture_bc1_subupload.cpp
+
+RESOURCES = compressedtexture_bc1_subupload.qrc
diff --git a/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc
new file mode 100644
index 0000000000..859a0a79f6
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256_bc1_9mips.dds">../shared/qt256_bc1_9mips.dds</file>
+ <file alias="bwqt224_64_nomips.dds">../shared/bwqt224_64_nomips.dds</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/computebuffer/buffer.comp b/tests/manual/rhi/computebuffer/buffer.comp
new file mode 100644
index 0000000000..a0d0350e37
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/buffer.comp
@@ -0,0 +1,41 @@
+#version 440
+
+layout (local_size_x = 256) in;
+
+struct Data
+{
+ vec2 pos;
+ float dir;
+};
+
+layout(std140, binding = 0) buffer StorageBuffer
+{
+ Data d[];
+} buf;
+
+layout(std140, binding = 1) uniform UniformBuffer
+{
+ float step;
+ uint count;
+} ubuf;
+
+void main()
+{
+ uint index = gl_GlobalInvocationID.x;
+ if (index < ubuf.count) {
+ vec2 p = buf.d[index].pos;
+ float dir = buf.d[index].dir;
+
+ p.x += dir * ubuf.step * 0.01;
+ if (p.x > 1.0) {
+ p.x = 1.0;
+ buf.d[index].dir *= -1.0;
+ }
+ if (p.x < -1.0) {
+ p.x = -1.0;
+ buf.d[index].dir *= -1.0;
+ }
+
+ buf.d[index].pos = p;
+ }
+}
diff --git a/tests/manual/rhi/computebuffer/buffer.comp.qsb b/tests/manual/rhi/computebuffer/buffer.comp.qsb
new file mode 100644
index 0000000000..b1a666f185
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/buffer.comp.qsb
Binary files differ
diff --git a/tests/manual/rhi/computebuffer/buildshaders.bat b/tests/manual/rhi/computebuffer/buildshaders.bat
new file mode 100755
index 0000000000..2768273b70
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/buildshaders.bat
@@ -0,0 +1,3 @@
+qsb --glsl "310 es,430" --hlsl 50 --msl 12 buffer.comp -o buffer.comp.qsb
+qsb --glsl "310 es,430" --hlsl 50 --msl 12 main.vert -o main.vert.qsb
+qsb --glsl "310 es,430" --hlsl 50 --msl 12 main.frag -o main.frag.qsb
diff --git a/tests/manual/rhi/computebuffer/computebuffer.cpp b/tests/manual/rhi/computebuffer/computebuffer.cpp
new file mode 100644
index 0000000000..2a3e0b92b5
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/computebuffer.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include <QRandomGenerator>
+
+// Compute shader example. Writes to a storage buffer from a compute shader,
+// then uses the same buffer as vertex buffer in the vertex stage. This would
+// be typical when implementing particles for example. Here we just simply move
+// the positions back and forth along the X axis.
+
+// Note that the example relies on gl_PointSize which is not supported
+// everywhere. So in some cases the points will be of size 1.
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *sbuf = nullptr;
+ QRhiBuffer *computeUniBuf = nullptr;
+ QRhiShaderResourceBindings *computeBindings = nullptr;
+ QRhiComputePipeline *computePipeline = nullptr;
+ QRhiShaderResourceBindings *graphicsBindings = nullptr;
+ QRhiGraphicsPipeline *graphicsPipeline = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ float step = 0.2f;
+} d;
+
+// these struct must match the std140 packing rules
+struct Data {
+ float pos[2];
+ float dir;
+ quint32 pad[1];
+};
+struct ComputeUBuf {
+ float step;
+ quint32 count;
+};
+
+const int DATA_COUNT = 256 * 128;
+
+const int COMPUTE_UBUF_SIZE = 8;
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::Compute))
+ qFatal("Compute is not supported");
+
+ if (!m_r->isFeatureSupported(QRhi::VertexShaderPointSize))
+ qWarning("Point sizes other than 1 not supported");
+
+ // compute pass
+
+ d.sbuf = m_r->newBuffer(QRhiBuffer::Immutable,
+ QRhiBuffer::StorageBuffer | QRhiBuffer::VertexBuffer,
+ sizeof(Data) * DATA_COUNT);
+ d.sbuf->build();
+ d.releasePool << d.sbuf;
+
+ d.computeUniBuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, COMPUTE_UBUF_SIZE);
+ d.computeUniBuf->build();
+ d.releasePool << d.computeUniBuf;
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+
+ QByteArray data;
+ data.resize(sizeof(Data) * DATA_COUNT);
+ Data *p = reinterpret_cast<Data *>(data.data());
+ QRandomGenerator *rgen = QRandomGenerator::global();
+ for (int i = 0; i < DATA_COUNT; ++i) {
+ p->pos[0] = rgen->bounded(1000) / 500.0f - 1.0f;
+ p->pos[1] = rgen->bounded(1000) / 500.0f - 1.0f;
+ p->dir = rgen->bounded(2) ? 1 : -1;
+ ++p;
+ }
+ d.initialUpdates->uploadStaticBuffer(d.sbuf, data.constData());
+
+ ComputeUBuf ud;
+ ud.step = d.step;
+ ud.count = DATA_COUNT;
+ d.initialUpdates->updateDynamicBuffer(d.computeUniBuf, 0, COMPUTE_UBUF_SIZE, &ud);
+
+ d.computeBindings = m_r->newShaderResourceBindings();
+ d.computeBindings->setBindings({
+ QRhiShaderResourceBinding::bufferLoadStore(0, QRhiShaderResourceBinding::ComputeStage, d.sbuf),
+ QRhiShaderResourceBinding::uniformBuffer(1, QRhiShaderResourceBinding::ComputeStage, d.computeUniBuf)
+ });
+ d.computeBindings->build();
+ d.releasePool << d.computeBindings;
+
+ d.computePipeline = m_r->newComputePipeline();
+ d.computePipeline->setShaderResourceBindings(d.computeBindings);
+ d.computePipeline->setShaderStage({ QRhiShaderStage::Compute, getShader(QLatin1String(":/buffer.comp.qsb")) });
+ d.computePipeline->build();
+ d.releasePool << d.computePipeline;
+
+ // graphics pass
+
+ d.graphicsBindings = m_r->newShaderResourceBindings();
+ d.graphicsBindings->build();
+ d.releasePool << d.graphicsBindings;
+
+ d.graphicsPipeline = m_r->newGraphicsPipeline();
+ d.graphicsPipeline->setTopology(QRhiGraphicsPipeline::Points);
+ d.graphicsPipeline->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/main.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/main.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ });
+ d.graphicsPipeline->setVertexInputLayout(inputLayout);
+ d.graphicsPipeline->setShaderResourceBindings(d.graphicsBindings);
+ d.graphicsPipeline->setRenderPassDescriptor(m_rp);
+ d.graphicsPipeline->build();
+ d.releasePool << d.graphicsPipeline;
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+#if 0
+ u->updateDynamicBuffer(d.computeUniBuf, 0, sizeof(float), &d.step);
+ d.step += 0.01f;
+#endif
+
+ // compute pass
+ cb->beginComputePass(u);
+ cb->setComputePipeline(d.computePipeline);
+ cb->setShaderResources();
+ cb->dispatch(DATA_COUNT / 256, 1, 1);
+ cb->endComputePass();
+
+ // graphics pass
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.graphicsPipeline);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ QRhiCommandBuffer::VertexInput vbufBinding(d.sbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(DATA_COUNT);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/computebuffer/computebuffer.pro b/tests/manual/rhi/computebuffer/computebuffer.pro
new file mode 100644
index 0000000000..ab3c8001f1
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/computebuffer.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ computebuffer.cpp
+
+RESOURCES = computebuffer.qrc
diff --git a/tests/manual/rhi/computebuffer/computebuffer.qrc b/tests/manual/rhi/computebuffer/computebuffer.qrc
new file mode 100644
index 0000000000..d9e877a15d
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/computebuffer.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>buffer.comp.qsb</file>
+ <file>main.vert.qsb</file>
+ <file>main.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/computebuffer/main.frag b/tests/manual/rhi/computebuffer/main.frag
new file mode 100644
index 0000000000..4785a404d3
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/main.frag
@@ -0,0 +1,8 @@
+#version 440
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(1.0);
+}
diff --git a/tests/manual/rhi/computebuffer/main.frag.qsb b/tests/manual/rhi/computebuffer/main.frag.qsb
new file mode 100644
index 0000000000..f05da411e5
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/main.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/computebuffer/main.vert b/tests/manual/rhi/computebuffer/main.vert
new file mode 100644
index 0000000000..5dfb778d2e
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/main.vert
@@ -0,0 +1,11 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };
+
+void main()
+{
+ gl_PointSize = 4.0; // required with Vulkan when drawing points
+ gl_Position = position;
+}
diff --git a/tests/manual/rhi/computebuffer/main.vert.qsb b/tests/manual/rhi/computebuffer/main.vert.qsb
new file mode 100644
index 0000000000..944645ffbf
--- /dev/null
+++ b/tests/manual/rhi/computebuffer/main.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/computeimage/buildshaders.bat b/tests/manual/rhi/computeimage/buildshaders.bat
new file mode 100755
index 0000000000..41a324d2b2
--- /dev/null
+++ b/tests/manual/rhi/computeimage/buildshaders.bat
@@ -0,0 +1 @@
+qsb --glsl "310 es,430" --hlsl 50 --msl 12 image.comp -o image.comp.qsb
diff --git a/tests/manual/rhi/computeimage/computeimage.cpp b/tests/manual/rhi/computeimage/computeimage.cpp
new file mode 100644
index 0000000000..51bf216c5a
--- /dev/null
+++ b/tests/manual/rhi/computeimage/computeimage.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+
+// Compute shader example with image load/store. The texture sampled in the
+// fragment shader is generated by the compute shader.
+
+struct {
+ QVector<QRhiResource *> releasePool;
+
+ QRhiTexture *texIn = nullptr;
+ QRhiTexture *texOut = nullptr;
+ QRhiBuffer *computeUBuf = nullptr;
+ QRhiShaderResourceBindings *computeBindings = nullptr;
+ QRhiComputePipeline *computePipeline = nullptr;
+
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QSize imageSize;
+ QMatrix4x4 winProj;
+ float factor = 1.0f;
+} d;
+
+static float quadVertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 quadIndexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::Compute))
+ qFatal("Compute is not supported");
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+
+ // compute pass
+
+ const QImage image = QImage(QLatin1String(":/qt256.png")).convertToFormat(QImage::Format_RGBA8888);
+ d.imageSize = image.size();
+ d.texIn = m_r->newTexture(QRhiTexture::RGBA8, d.imageSize, 1, QRhiTexture::UsedWithLoadStore);
+ d.texIn->build();
+ d.releasePool << d.texIn;
+
+ d.texOut = m_r->newTexture(QRhiTexture::RGBA8, d.imageSize, 1, QRhiTexture::UsedWithLoadStore);
+ d.texOut->build();
+ d.releasePool << d.texOut;
+
+ d.initialUpdates->uploadTexture(d.texIn, image);
+
+ d.computeUBuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 4);
+ d.computeUBuf->build();
+ d.releasePool << d.computeUBuf;
+
+ d.computeBindings = m_r->newShaderResourceBindings();
+ d.computeBindings->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::ComputeStage, d.computeUBuf),
+ QRhiShaderResourceBinding::imageLoad(1, QRhiShaderResourceBinding::ComputeStage, d.texIn, 0),
+ QRhiShaderResourceBinding::imageStore(2, QRhiShaderResourceBinding::ComputeStage, d.texOut, 0)
+ });
+ d.computeBindings->build();
+ d.releasePool << d.computeBindings;
+
+ d.computePipeline = m_r->newComputePipeline();
+ d.computePipeline->setShaderResourceBindings(d.computeBindings);
+ d.computePipeline->setShaderStage({ QRhiShaderStage::Compute, getShader(QLatin1String(":/image.comp.qsb")) });
+ d.computePipeline->build();
+ d.releasePool << d.computePipeline;
+
+ // graphics pass
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(quadVertexData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, quadVertexData);
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(quadIndexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, quadIndexData);
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ qint32 flip = 0; // regardless of isYUpInFramebuffer() since the input is not flipped so the end result is good for GL too
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.texOut, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2.5f);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ }
+
+ u->updateDynamicBuffer(d.computeUBuf, 0, 4, &d.factor);
+ d.factor += 0.1f;
+ if (d.factor >= 50.0f)
+ d.factor = 1.0f;
+
+ cb->beginComputePass(u);
+ cb->setComputePipeline(d.computePipeline);
+ cb->setShaderResources();
+ cb->dispatch(d.imageSize.width() / 16, d.imageSize.height() / 16, 1);
+ cb->endComputePass();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/computeimage/computeimage.pro b/tests/manual/rhi/computeimage/computeimage.pro
new file mode 100644
index 0000000000..291a4e91b1
--- /dev/null
+++ b/tests/manual/rhi/computeimage/computeimage.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ computeimage.cpp
+
+RESOURCES = computeimage.qrc
diff --git a/tests/manual/rhi/computeimage/computeimage.qrc b/tests/manual/rhi/computeimage/computeimage.qrc
new file mode 100644
index 0000000000..5299e1ae22
--- /dev/null
+++ b/tests/manual/rhi/computeimage/computeimage.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>image.comp.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="qt256.png">../shared/qt256.png</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/computeimage/image.comp b/tests/manual/rhi/computeimage/image.comp
new file mode 100644
index 0000000000..9826ed7c6c
--- /dev/null
+++ b/tests/manual/rhi/computeimage/image.comp
@@ -0,0 +1,20 @@
+#version 440
+
+layout (local_size_x = 16, local_size_y = 16) in;
+
+layout(std140, binding = 0) uniform UniformBuffer
+{
+ float factor;
+} ubuf;
+
+layout (binding = 1, rgba8) uniform readonly image2D texIn;
+layout (binding = 2, rgba8) uniform writeonly image2D texOut;
+
+void main()
+{
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ ivec2 d = ivec2(1, 1);
+ vec4 diff = imageLoad(texIn, pos + d) - imageLoad(texIn, pos - d);
+ float c = (diff.x + diff.y + diff.z) / ubuf.factor + 0.5f;
+ imageStore(texOut, pos, vec4(c, c, c, 1.0));
+}
diff --git a/tests/manual/rhi/computeimage/image.comp.qsb b/tests/manual/rhi/computeimage/image.comp.qsb
new file mode 100644
index 0000000000..725629f7ab
--- /dev/null
+++ b/tests/manual/rhi/computeimage/image.comp.qsb
Binary files differ
diff --git a/tests/manual/rhi/cubemap/buildshaders.bat b/tests/manual/rhi/cubemap/buildshaders.bat
new file mode 100644
index 0000000000..ebf673875d
--- /dev/null
+++ b/tests/manual/rhi/cubemap/buildshaders.bat
@@ -0,0 +1,2 @@
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c cubemap.vert -o cubemap.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c cubemap.frag -o cubemap.frag.qsb
diff --git a/tests/manual/rhi/cubemap/c.png b/tests/manual/rhi/cubemap/c.png
new file mode 100644
index 0000000000..7b00455e53
--- /dev/null
+++ b/tests/manual/rhi/cubemap/c.png
Binary files differ
diff --git a/tests/manual/rhi/cubemap/cubemap.cpp b/tests/manual/rhi/cubemap/cubemap.cpp
new file mode 100644
index 0000000000..df302736a2
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include "../shared/cube.h"
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+} d;
+
+void Window::customInit()
+{
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ const QSize cubeMapSize(512, 512);
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, cubeMapSize, 1, QRhiTexture::CubeMap);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, cube);
+
+ QImage img = QImage(":/c.png").mirrored().convertToFormat(QImage::Format_RGBA8888);
+ // just use the same image for all faces for now
+ QRhiTextureSubresourceUploadDescription subresDesc(img);
+ QRhiTextureUploadDescription desc({
+ { 0, 0, subresDesc }, // +X
+ { 1, 0, subresDesc }, // -X
+ { 2, 0, subresDesc }, // +Y
+ { 3, 0, subresDesc }, // -Y
+ { 4, 0, subresDesc }, // +Z
+ { 5, 0, subresDesc } // -Z
+ });
+ d.initialUpdates->uploadTexture(d.tex, desc);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::Repeat, QRhiSampler::Repeat);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::LessOrEqual);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Front); // we are inside the cube so cull front, not back
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW); // front is ccw in the cube data
+
+ QShader vs = getShader(QLatin1String(":/cubemap.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/cubemap.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ QMatrix4x4 mvp = m_r->clipSpaceCorrMatrix();
+ mvp.perspective(90.0f, outputSizeInPixels.width() / (float) outputSizeInPixels.height(), 0.01f, 1000.0f);
+ // cube vertices go from -1..1
+ mvp.scale(10);
+ static float rx = 0;
+ mvp.rotate(rx, 1, 0, 0);
+ rx += 0.5f;
+ // no translation
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(36);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/cubemap/cubemap.frag b/tests/manual/rhi/cubemap/cubemap.frag
new file mode 100644
index 0000000000..13a365ed0c
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec3 v_coord;
+layout(location = 0) out vec4 fragColor;
+layout(binding = 1) uniform samplerCube tex;
+
+void main()
+{
+ fragColor = vec4(texture(tex, v_coord).rgb, 1.0);
+}
diff --git a/tests/manual/rhi/cubemap/cubemap.frag.qsb b/tests/manual/rhi/cubemap/cubemap.frag.qsb
new file mode 100644
index 0000000000..d7cc025554
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/cubemap/cubemap.pro b/tests/manual/rhi/cubemap/cubemap.pro
new file mode 100644
index 0000000000..61910ffe20
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ cubemap.cpp
+
+RESOURCES = cubemap.qrc
diff --git a/tests/manual/rhi/cubemap/cubemap.qrc b/tests/manual/rhi/cubemap/cubemap.qrc
new file mode 100644
index 0000000000..bacd15446c
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>cubemap.vert.qsb</file>
+ <file>cubemap.frag.qsb</file>
+ <file>c.png</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/cubemap/cubemap.vert b/tests/manual/rhi/cubemap/cubemap.vert
new file mode 100644
index 0000000000..65216dd6b0
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.vert
@@ -0,0 +1,15 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 0) out vec3 v_coord;
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_coord = position.xyz;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/cubemap/cubemap.vert.qsb b/tests/manual/rhi/cubemap/cubemap.vert.qsb
new file mode 100644
index 0000000000..fae136337c
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/floattexture/floattexture.cpp b/tests/manual/rhi/floattexture/floattexture.cpp
new file mode 100644
index 0000000000..16e58ff00f
--- /dev/null
+++ b/tests/manual/rhi/floattexture/floattexture.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include <qmath.h>
+
+QByteArray loadHdr(const QString &fn, QSize *size)
+{
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return QByteArray();
+ }
+
+ char sig[256];
+ f.read(sig, 11);
+ if (strncmp(sig, "#?RADIANCE\n", 11))
+ return QByteArray();
+
+ QByteArray buf = f.readAll();
+ const char *p = buf.constData();
+ const char *pEnd = p + buf.size();
+
+ // Process lines until the empty one.
+ QByteArray line;
+ while (p < pEnd) {
+ char c = *p++;
+ if (c == '\n') {
+ if (line.isEmpty())
+ break;
+ if (line.startsWith(QByteArrayLiteral("FORMAT="))) {
+ const QByteArray format = line.mid(7).trimmed();
+ if (format != QByteArrayLiteral("32-bit_rle_rgbe")) {
+ qWarning("HDR format '%s' is not supported", format.constData());
+ return QByteArray();
+ }
+ }
+ line.clear();
+ } else {
+ line.append(c);
+ }
+ }
+ if (p == pEnd) {
+ qWarning("Malformed HDR image data at property strings");
+ return QByteArray();
+ }
+
+ // Get the resolution string.
+ while (p < pEnd) {
+ char c = *p++;
+ if (c == '\n')
+ break;
+ line.append(c);
+ }
+ if (p == pEnd) {
+ qWarning("Malformed HDR image data at resolution string");
+ return QByteArray();
+ }
+
+ int w = 0, h = 0;
+ // We only care about the standard orientation.
+ if (!sscanf(line.constData(), "-Y %d +X %d", &h, &w)) {
+ qWarning("Unsupported HDR resolution string '%s'", line.constData());
+ return QByteArray();
+ }
+ if (w <= 0 || h <= 0) {
+ qWarning("Invalid HDR resolution");
+ return QByteArray();
+ }
+
+ // output is RGBA32F
+ const int blockSize = 4 * sizeof(float);
+ QByteArray data;
+ data.resize(w * h * blockSize);
+
+ typedef unsigned char RGBE[4];
+ RGBE *scanline = new RGBE[w];
+
+ for (int y = 0; y < h; ++y) {
+ if (pEnd - p < 4) {
+ qWarning("Unexpected end of HDR data");
+ delete[] scanline;
+ return QByteArray();
+ }
+
+ scanline[0][0] = *p++;
+ scanline[0][1] = *p++;
+ scanline[0][2] = *p++;
+ scanline[0][3] = *p++;
+
+ if (scanline[0][0] == 2 && scanline[0][1] == 2 && scanline[0][2] < 128) {
+ // new rle, the first pixel was a dummy
+ for (int channel = 0; channel < 4; ++channel) {
+ for (int x = 0; x < w && p < pEnd; ) {
+ unsigned char c = *p++;
+ if (c > 128) { // run
+ if (p < pEnd) {
+ int repCount = c & 127;
+ c = *p++;
+ while (repCount--)
+ scanline[x++][channel] = c;
+ }
+ } else { // not a run
+ while (c-- && p < pEnd)
+ scanline[x++][channel] = *p++;
+ }
+ }
+ }
+ } else {
+ // old rle
+ scanline[0][0] = 2;
+ int bitshift = 0;
+ int x = 1;
+ while (x < w && pEnd - p >= 4) {
+ scanline[x][0] = *p++;
+ scanline[x][1] = *p++;
+ scanline[x][2] = *p++;
+ scanline[x][3] = *p++;
+
+ if (scanline[x][0] == 1 && scanline[x][1] == 1 && scanline[x][2] == 1) { // run
+ int repCount = scanline[x][3] << bitshift;
+ while (repCount--) {
+ memcpy(scanline[x], scanline[x - 1], 4);
+ ++x;
+ }
+ bitshift += 8;
+ } else { // not a run
+ ++x;
+ bitshift = 0;
+ }
+ }
+ }
+
+ // adjust for -Y orientation
+ float *fp = reinterpret_cast<float *>(data.data() + (h - 1 - y) * blockSize * w);
+ for (int x = 0; x < w; ++x) {
+ float d = qPow(2.0f, float(scanline[x][3]) - 128.0f);
+ // r, g, b, a
+ *fp++ = scanline[x][0] / 256.0f * d;
+ *fp++ = scanline[x][1] / 256.0f * d;
+ *fp++ = scanline[x][2] / 256.0f * d;
+ *fp++ = 1.0f;
+ }
+ }
+
+ delete[] scanline;
+
+ if (size)
+ *size = QSize(w, h);
+
+ return data;
+}
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::RGBA32F))
+ qWarning("RGBA32F texture format is not supported");
+
+ QSize size;
+ QByteArray floatData = loadHdr(QLatin1String(":/OpenfootageNET_fieldairport-512.hdr"), &size);
+ Q_ASSERT(!floatData.isEmpty());
+ qDebug() << size;
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.tex = m_r->newTexture(QRhiTexture::RGBA32F, size);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ qint32 flip = 1;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+
+ QRhiTextureUploadDescription desc({ 0, 0, { floatData.constData(), floatData.size() } });
+ d.initialUpdates->uploadTexture(d.tex, desc);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2.5f);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ }
+
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/floattexture/floattexture.pro b/tests/manual/rhi/floattexture/floattexture.pro
new file mode 100644
index 0000000000..e566da2b94
--- /dev/null
+++ b/tests/manual/rhi/floattexture/floattexture.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ floattexture.cpp
+
+RESOURCES = floattexture.qrc
diff --git a/tests/manual/rhi/floattexture/floattexture.qrc b/tests/manual/rhi/floattexture/floattexture.qrc
new file mode 100644
index 0000000000..fefb56b910
--- /dev/null
+++ b/tests/manual/rhi/floattexture/floattexture.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="OpenfootageNET_fieldairport-512.hdr">../shared/OpenfootageNET_fieldairport-512.hdr</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp
new file mode 100644
index 0000000000..3c39ff1719
--- /dev/null
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is a compact, minimal, single-file demo of deciding the backend at
+// runtime while using the exact same shaders and rendering code without any
+// branching whatsoever once the QWindow is up and the RHI is initialized.
+
+#include <QGuiApplication>
+#include <QCommandLineParser>
+#include <QWindow>
+#include <QPlatformSurfaceEvent>
+#include <QElapsedTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+
+#include <QtGui/private/qrhinull_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+static float vertexData[] = {
+ // Y up (note clipSpaceCorrMatrix in m_proj), CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal,
+ Null
+};
+
+static GraphicsApi graphicsApi;
+
+static QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ case Null:
+ return QLatin1String("Null");
+ default:
+ break;
+ }
+ return QString();
+}
+
+class Window : public QWindow
+{
+public:
+ Window();
+ ~Window();
+
+ void init();
+ void releaseResources();
+ void resizeSwapChain();
+ void releaseSwapChain();
+ void render();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+private:
+ bool m_running = false;
+ bool m_notExposed = false;
+ bool m_newlyExposed = false;
+
+ QRhi *m_r = nullptr;
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+ QVector<QRhiResource *> releasePool;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ float m_opacity = 1;
+ int m_opacityDir = -1;
+
+ QElapsedTimer m_timer;
+ qint64 m_elapsedMs;
+ int m_elapsedCount;
+
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *m_fallbackSurface = nullptr;
+#endif
+};
+
+Window::Window()
+{
+ // Tell the platform plugin what we want.
+ switch (graphicsApi) {
+ case OpenGL:
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ setFormat(QRhiGles2InitParams::adjustedFormat());
+#endif
+ break;
+ case Vulkan:
+ setSurfaceType(VulkanSurface);
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+Window::~Window()
+{
+ releaseResources();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !m_running) {
+ m_running = true;
+ init();
+ resizeSwapChain();
+ }
+
+ // stop pushing frames when not exposed (or size is 0)
+ if ((!isExposed() || (m_hasSwapChain && m_sc->surfacePixelSize().isEmpty())) && m_running)
+ m_notExposed = true;
+
+ // continue when exposed again and the surface has a valid size.
+ // note that the surface size can be (0, 0) even though size() reports a valid one...
+ if (isExposed() && m_running && m_notExposed && !m_sc->surfacePixelSize().isEmpty()) {
+ m_notExposed = false;
+ m_newlyExposed = true;
+ }
+
+ // always render a frame on exposeEvent() (when exposed) in order to update
+ // immediately on window resize.
+ if (isExposed() && !m_sc->surfacePixelSize().isEmpty())
+ render();
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void Window::init()
+{
+ if (graphicsApi == Null) {
+ QRhiNullInitParams params;
+ m_r = QRhi::create(QRhi::Null, &params);
+ }
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ m_fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = m_fallbackSurface;
+ params.window = this;
+ m_r = QRhi::create(QRhi::OpenGLES2, &params);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = vulkanInstance();
+ params.window = this;
+ m_r = QRhi::create(QRhi::Vulkan, &params);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ m_r = QRhi::create(QRhi::D3D11, &params);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ m_r = QRhi::create(QRhi::Metal, &params);
+ }
+#endif
+
+ if (!m_r)
+ qFatal("Failed to create RHI backend");
+
+ // now onto the backend-independent init
+
+ m_sc = m_r->newSwapChain();
+ // allow depth-stencil, although we do not actually enable depth test/write for the triangle
+ m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ releasePool << m_ds;
+ m_sc->setWindow(this);
+ m_sc->setDepthStencil(m_ds);
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ releasePool << m_rp;
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ releasePool << m_vbuf;
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ releasePool << m_ubuf;
+ m_ubuf->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ releasePool << m_srb;
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+ releasePool << m_ps;
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ m_ps->setTargetBlends({ premulAlphaBlend });
+
+ const QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ m_ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(m_rp);
+
+ m_ps->build();
+}
+
+void Window::releaseResources()
+{
+ qDeleteAll(releasePool);
+ releasePool.clear();
+
+ delete m_sc; // native swapchain is likely released already
+ m_sc = nullptr;
+
+ delete m_r;
+
+#ifndef QT_NO_OPENGL
+ delete m_fallbackSurface;
+#endif
+}
+
+void Window::resizeSwapChain()
+{
+ const QSize outputSize = m_sc->surfacePixelSize();
+
+ m_ds->setPixelSize(outputSize);
+ m_ds->build(); // == m_ds->release(); m_ds->build();
+
+ m_hasSwapChain = m_sc->buildOrResize();
+
+ m_elapsedMs = 0;
+ m_elapsedCount = 0;
+
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void Window::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Window::render()
+{
+ if (!m_hasSwapChain || m_notExposed)
+ return;
+
+ // If the window got resized or got newly exposed, resize the swapchain.
+ // (the newly-exposed case is not actually required by some
+ // platforms/backends, but f.ex. Vulkan on Windows seems to need it)
+ if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ m_newlyExposed = false;
+ }
+
+ // Start a new frame. This is where we block when too far ahead of
+ // GPU/present, and that's what throttles the thread to the refresh rate.
+ // (except for OpenGL where it happens either in endFrame or somewhere else
+ // depending on the GL implementation)
+ QRhi::FrameOpResult r = m_r->beginFrame(m_sc);
+ if (r == QRhi::FrameOpSwapChainOutOfDate) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ r = m_r->beginFrame(m_sc);
+ }
+ if (r != QRhi::FrameOpSuccess) {
+ requestUpdate();
+ return;
+ }
+
+ if (m_elapsedCount)
+ m_elapsedMs += m_timer.elapsed();
+ m_timer.restart();
+ m_elapsedCount += 1;
+ if (m_elapsedMs >= 4000) {
+ qDebug("%f", m_elapsedCount / 4.0f);
+ m_elapsedMs = 0;
+ m_elapsedCount = 0;
+ }
+
+ // Set up buffer updates.
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ u->uploadStaticBuffer(m_vbuf, vertexData);
+ }
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.rotate(m_rotation, 0, 1, 0);
+ u->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+ m_opacity += m_opacityDir * 0.005f;
+ if (m_opacity < 0.0f || m_opacity > 1.0f) {
+ m_opacityDir *= -1;
+ m_opacity = qBound(0.0f, m_opacity, 1.0f);
+ }
+ u->updateDynamicBuffer(m_ubuf, 64, 4, &m_opacity);
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ // Apply buffer updates, clear, start the renderpass (where applicable).
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+
+ cb->endPass();
+
+ // Submit.
+ m_r->endFrame(m_sc);
+
+ requestUpdate(); // render continuously, throttled by the presentation rate (due to beginFrame above)
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ // Defaults.
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ // Allow overriding via the command line.
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
+ cmdLineParser.addOption(nullOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+ if (cmdLineParser.isSet(nullOption))
+ graphicsApi = Null;
+
+ // Vulkan setup.
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+ if (graphicsApi == Vulkan) {
+ if (!inst.create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ // Create and show the window.
+ Window w;
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan)
+ w.setVulkanInstance(&inst);
+#endif
+ w.resize(1280, 720);
+ w.setTitle(graphicsApiName());
+ w.show();
+
+ // Window::event() will not get invoked when the
+ // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow
+ // destruction. That happens only when exiting via app::quit() instead of
+ // the more common QWindow::close(). Take care of it: if the
+ // QPlatformWindow is still around (there was no close() yet), get rid of
+ // the swapchain while it's not too late.
+ if (w.handle())
+ w.releaseSwapChain();
+
+ return app.exec();
+}
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro
new file mode 100644
index 0000000000..eeef33ff6a
--- /dev/null
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ hellominimalcrossgfxtriangle.cpp
+
+RESOURCES = hellominimalcrossgfxtriangle.qrc
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc
new file mode 100644
index 0000000000..8cec4fa9ec
--- /dev/null
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/instancing/buildshaders.bat b/tests/manual/rhi/instancing/buildshaders.bat
new file mode 100644
index 0000000000..9053a1c54a
--- /dev/null
+++ b/tests/manual/rhi/instancing/buildshaders.bat
@@ -0,0 +1,2 @@
+qsb --glsl "330,300 es" --hlsl 50 --msl 12 inst.vert -o inst.vert.qsb
+qsb --glsl "330,300 es" --hlsl 50 --msl 12 inst.frag -o inst.frag.qsb
diff --git a/tests/manual/rhi/instancing/inst.frag b/tests/manual/rhi/instancing/inst.frag
new file mode 100644
index 0000000000..719fd79ff5
--- /dev/null
+++ b/tests/manual/rhi/instancing/inst.frag
@@ -0,0 +1,9 @@
+#version 440
+
+layout(location = 0) in vec3 vColor;
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(vColor, 1.0);
+}
diff --git a/tests/manual/rhi/instancing/inst.frag.qsb b/tests/manual/rhi/instancing/inst.frag.qsb
new file mode 100644
index 0000000000..f19a2f0a71
--- /dev/null
+++ b/tests/manual/rhi/instancing/inst.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/instancing/inst.vert b/tests/manual/rhi/instancing/inst.vert
new file mode 100644
index 0000000000..3e1b117d58
--- /dev/null
+++ b/tests/manual/rhi/instancing/inst.vert
@@ -0,0 +1,25 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+// Instanced attributes to variate the translation and color of the cube
+layout(location = 1) in vec3 instTranslate;
+layout(location = 2) in vec3 instColor;
+
+layout(location = 0) out vec3 vColor;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+void main()
+{
+ vColor = instColor;
+ mat4 t = mat4(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ instTranslate.x, instTranslate.y, instTranslate.z, 1);
+ gl_Position = ubuf.mvp * t * position;
+}
diff --git a/tests/manual/rhi/instancing/inst.vert.qsb b/tests/manual/rhi/instancing/inst.vert.qsb
new file mode 100644
index 0000000000..de05eae80f
--- /dev/null
+++ b/tests/manual/rhi/instancing/inst.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/instancing/instancing.cpp b/tests/manual/rhi/instancing/instancing.cpp
new file mode 100644
index 0000000000..87029e541c
--- /dev/null
+++ b/tests/manual/rhi/instancing/instancing.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include "../shared/cube.h"
+#include <QRandomGenerator>
+
+// Instanced draw example. When running with OpenGL, at least 3.3 or ES 3.0 is
+// needed.
+
+const int INSTANCE_COUNT = 1024;
+
+struct {
+ QVector<QRhiResource *> releasePool;
+
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *instBuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::Instancing))
+ qFatal("Instanced drawing is not supported");
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, cube);
+
+ // translation + color (vec3 + vec3), interleaved, for each instance
+ d.instBuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, INSTANCE_COUNT * 6 * sizeof(float));
+ d.instBuf->build();
+ d.releasePool << d.instBuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 12);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, d.ubuf)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/inst.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/inst.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }, // cube vertices
+ { 6 * sizeof(float), QRhiVertexInputBinding::PerInstance } // per-instance translation and color
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 }, // position
+ { 1, 1, QRhiVertexInputAttribute::Float3, 0 }, // instTranslate
+ { 1, 2, QRhiVertexInputAttribute::Float3, 3 * sizeof(float) } // instColor
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ QByteArray instData;
+ instData.resize(INSTANCE_COUNT * 6 * sizeof(float));
+ float *p = reinterpret_cast<float *>(instData.data());
+ QRandomGenerator *rgen = QRandomGenerator::global();
+ for (int i = 0; i < INSTANCE_COUNT; ++i) {
+ // translation
+ *p++ = rgen->bounded(8000) / 100.0f - 40.0f;
+ *p++ = rgen->bounded(8000) / 100.0f - 40.0f;
+ *p++ = 0.0f;
+ // color
+ *p++ = i / float(INSTANCE_COUNT);
+ *p++ = 0.0f;
+ *p++ = 0.0f;
+ }
+ d.initialUpdates->uploadStaticBuffer(d.instBuf, instData.constData());
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.05f);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ }
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding[] = {
+ { d.vbuf, 0 },
+ { d.instBuf, 0 }
+ };
+ cb->setVertexInput(0, 2, vbufBinding);
+ cb->draw(36, INSTANCE_COUNT);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/instancing/instancing.pro b/tests/manual/rhi/instancing/instancing.pro
new file mode 100644
index 0000000000..416c79f28a
--- /dev/null
+++ b/tests/manual/rhi/instancing/instancing.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ instancing.cpp
+
+RESOURCES = instancing.qrc
diff --git a/tests/manual/rhi/instancing/instancing.qrc b/tests/manual/rhi/instancing/instancing.qrc
new file mode 100644
index 0000000000..db21a9d8aa
--- /dev/null
+++ b/tests/manual/rhi/instancing/instancing.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>inst.vert.qsb</file>
+ <file>inst.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/mrt/buildshaders.bat b/tests/manual/rhi/mrt/buildshaders.bat
new file mode 100644
index 0000000000..75741448b1
--- /dev/null
+++ b/tests/manual/rhi/mrt/buildshaders.bat
@@ -0,0 +1,2 @@
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c mrt.vert -o mrt.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c mrt.frag -o mrt.frag.qsb
diff --git a/tests/manual/rhi/mrt/mrt.cpp b/tests/manual/rhi/mrt/mrt.cpp
new file mode 100644
index 0000000000..b80af7ac87
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+
+// Exercises MRT, by attaching 4 textures to a single QRhiTextureRenderTarget.
+// The fragment shader outputs to all four targets.
+// The textures are then used to render 4 quads, so their contents can be confirmed.
+
+const int ATTCOUNT = 4;
+
+static float quadVertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 quadIndexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+static float triangleData[] =
+{ // Y up, CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+ struct PerColorBuffer {
+ QRhiTexture *tex = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ };
+ PerColorBuffer colData[ATTCOUNT];
+
+ QRhiBuffer *triUbuf = nullptr;
+ QRhiShaderResourceBindings *triSrb = nullptr;
+ QRhiGraphicsPipeline *triPs = nullptr;
+ float triRot = 0;
+ QMatrix4x4 triBaseMvp;
+} d;
+
+void Window::customInit()
+{
+ qDebug("Max color attachments: %d", m_r->resourceLimit(QRhi::MaxColorAttachments));
+ if (m_r->resourceLimit(QRhi::MaxColorAttachments) < 4)
+ qWarning("MRT is not supported");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(quadVertexData) + sizeof(triangleData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(quadIndexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(68);
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, oneRoundedUniformBlockSize * ATTCOUNT);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ QRhiTexture *tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+ d.releasePool << tex;
+ tex->build();
+
+ QRhiShaderResourceBindings *srb = m_r->newShaderResourceBindings();
+ d.releasePool << srb;
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
+ d.ubuf, i * oneRoundedUniformBlockSize, 68),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, tex, d.sampler)
+ });
+ srb->build();
+
+ d.colData[i].tex = tex;
+ d.colData[i].srb = srb;
+ }
+
+ QRhiTextureRenderTargetDescription rtDesc;
+ QVector<QRhiColorAttachment> att;
+ for (int i = 0; i < ATTCOUNT; ++i)
+ att.append(QRhiColorAttachment(d.colData[i].tex));
+ rtDesc.setColorAttachments(att);
+ d.rt = m_r->newTextureRenderTarget(rtDesc);
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.colData[0].srb); // all of them are layout-compatible
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(quadVertexData), quadVertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(quadVertexData), sizeof(triangleData), triangleData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, quadIndexData);
+
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ for (int i = 0; i < ATTCOUNT; ++i)
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, i * oneRoundedUniformBlockSize + 64, 4, &flip);
+
+ // triangle
+ d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.triUbuf;
+ d.triUbuf->build();
+
+ d.triSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.triSrb;
+ d.triSrb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf)
+ });
+ d.triSrb->build();
+
+ d.triPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.triPs;
+ d.triPs->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/mrt.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/mrt.frag.qsb")) }
+ });
+ QVector<QRhiGraphicsPipeline::TargetBlend> blends;
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ QRhiGraphicsPipeline::TargetBlend blend;
+ blends.append(blend);
+ }
+ d.triPs->setTargetBlends(blends);
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ d.triPs->setVertexInputLayout(inputLayout);
+ d.triPs->setShaderResourceBindings(d.triSrb);
+ d.triPs->setRenderPassDescriptor(d.rtRp);
+ d.triPs->build();
+
+ d.triBaseMvp = m_r->clipSpaceCorrMatrix();
+ d.triBaseMvp.perspective(45.0f, d.rt->pixelSize().width() / float(d.rt->pixelSize().height()), 0.01f, 1000.0f);
+ d.triBaseMvp.translate(0, 0, -2);
+ float opacity = 1.0f;
+ d.initialUpdates->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ QMatrix4x4 triMvp = d.triBaseMvp;
+ triMvp.rotate(d.triRot, 0, 1, 0);
+ d.triRot += 1;
+ u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
+
+ cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.triPs);
+ cb->setViewport({ 0, 0, float(d.rt->pixelSize().width()), float(d.rt->pixelSize().height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, sizeof(quadVertexData));
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ u = m_r->nextResourceUpdateBatch();
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(68);
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ QMatrix4x4 mvp = m_proj;
+ switch (i) {
+ case 0:
+ mvp.translate(-2.0f, 0, 0);
+ break;
+ case 1:
+ mvp.translate(-0.8f, 0, 0);
+ break;
+ case 2:
+ mvp.translate(0.4f, 0, 0);
+ break;
+ case 3:
+ mvp.translate(1.6f, 0, 0);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ u->updateDynamicBuffer(d.ubuf, i * oneRoundedUniformBlockSize, 64, mvp.constData());
+ }
+ }
+
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ vbufBinding.second = 0;
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ cb->setShaderResources(d.colData[i].srb);
+ cb->drawIndexed(6);
+ }
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/mrt/mrt.frag b/tests/manual/rhi/mrt/mrt.frag
new file mode 100644
index 0000000000..9166b552b9
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.frag
@@ -0,0 +1,22 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 c0;
+layout(location = 1) out vec4 c1;
+layout(location = 2) out vec4 c2;
+layout(location = 3) out vec4 c3;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+void main()
+{
+ vec4 c = vec4(v_color * ubuf.opacity, ubuf.opacity);
+ c0 = vec4(c.r, 0, 0, c.a);
+ c1 = vec4(0, c.g, 0, c.a);
+ c2 = vec4(0, 0, c.b, c.a);
+ c3 = c;
+}
diff --git a/tests/manual/rhi/mrt/mrt.frag.qsb b/tests/manual/rhi/mrt/mrt.frag.qsb
new file mode 100644
index 0000000000..389b6affa3
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/mrt/mrt.pro b/tests/manual/rhi/mrt/mrt.pro
new file mode 100644
index 0000000000..7cde425488
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ mrt.cpp
+
+RESOURCES = mrt.qrc
diff --git a/tests/manual/rhi/mrt/mrt.qrc b/tests/manual/rhi/mrt/mrt.qrc
new file mode 100644
index 0000000000..275f476013
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>mrt.vert.qsb</file>
+ <file>mrt.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/mrt/mrt.vert b/tests/manual/rhi/mrt/mrt.vert
new file mode 100644
index 0000000000..43af543f44
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.vert
@@ -0,0 +1,19 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/mrt/mrt.vert.qsb b/tests/manual/rhi/mrt/mrt.vert.qsb
new file mode 100644
index 0000000000..ff8c0e50bb
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp
new file mode 100644
index 0000000000..b77a27b1b5
--- /dev/null
+++ b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+
+// Uses a multisample renderbuffer (whatever that may be on a given backend) to
+// render to and then resolves the samples into a non-multisample texture.
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+static float triangleData[] =
+{ // Y up, CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiRenderBuffer *rb = nullptr;
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiBuffer *triUbuf = nullptr;
+ QRhiShaderResourceBindings *triSrb = nullptr;
+ QRhiGraphicsPipeline *triPs = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 triBaseMvp;
+ float triRot = 0;
+ QMatrix4x4 winProj;
+} d;
+
+void Window::customInit()
+{
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData) + sizeof(triangleData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.rb = m_r->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
+ d.rb->build();
+ d.releasePool << d.rb;
+
+ // the non-msaa texture that will be the destination in the resolve
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, d.rb->pixelSize(), 1, QRhiTexture::RenderTarget);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ // rb is multisample, instead of writing out the msaa data into it,
+ // resolve into d.tex at the end of each render pass
+ QRhiTextureRenderTargetDescription rtDesc;
+ QRhiColorAttachment rtAtt(d.rb);
+ rtAtt.setResolveTexture(d.tex);
+ rtDesc.setColorAttachments({ rtAtt });
+
+ d.rt = m_r->newTextureRenderTarget(rtDesc);
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+
+ d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.triUbuf;
+ d.triUbuf->build();
+
+ d.triSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.triSrb;
+ d.triSrb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf)
+ });
+ d.triSrb->build();
+
+ d.triPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.triPs;
+ d.triPs->setSampleCount(4); // must match the render target
+ d.triPs->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ d.triPs->setVertexInputLayout(inputLayout);
+ d.triPs->setShaderResourceBindings(d.triSrb);
+ d.triPs->setRenderPassDescriptor(d.rtRp);
+ d.triPs->build();
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(vertexData), vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(vertexData), sizeof(triangleData), triangleData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ d.triBaseMvp = m_r->clipSpaceCorrMatrix();
+ d.triBaseMvp.perspective(45.0f, d.rb->pixelSize().width() / float(d.rb->pixelSize().height()), 0.01f, 1000.0f);
+ d.triBaseMvp.translate(0, 0, -2);
+ float opacity = 1.0f;
+ d.initialUpdates->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
+
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ QMatrix4x4 triMvp = d.triBaseMvp;
+ triMvp.rotate(d.triRot, 0, 1, 0);
+ d.triRot += 1;
+ u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2.5f);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ }
+
+ // offscreen (triangle, msaa)
+ cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.triPs);
+ cb->setViewport({ 0, 0, float(d.rb->pixelSize().width()), float(d.rb->pixelSize().height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, sizeof(vertexData));
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ // onscreen (quad)
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ vbufBinding.second = 0;
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro
new file mode 100644
index 0000000000..4b31e39e7d
--- /dev/null
+++ b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ msaarenderbuffer.cpp
+
+RESOURCES = msaarenderbuffer.qrc
diff --git a/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc
new file mode 100644
index 0000000000..c7a2380a42
--- /dev/null
+++ b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/msaatexture/msaatexture.cpp b/tests/manual/rhi/msaatexture/msaatexture.cpp
new file mode 100644
index 0000000000..46a9b2830c
--- /dev/null
+++ b/tests/manual/rhi/msaatexture/msaatexture.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+
+// Renders into a non-multisample and a multisample (4x) texture, and then uses
+// those textures to draw two quads. Note that this uses an MSAA sampler in the
+// shader, not resolves. Not supported on the GL(ES) backend atm.
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+static float triangleData[] =
+{ // Y up, CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+};
+
+const int UBUFSZ = 68;
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiTexture *msaaTex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srbLeft = nullptr;
+ QRhiShaderResourceBindings *srbRight = nullptr;
+ QRhiGraphicsPipeline *psLeft = nullptr;
+ QRhiGraphicsPipeline *psRight = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ int rightOfs;
+ QMatrix4x4 winProj;
+ QMatrix4x4 triBaseMvp;
+ float triRot = 0;
+
+ QRhiShaderResourceBindings *triSrb = nullptr;
+ QRhiGraphicsPipeline *msaaTriPs = nullptr;
+ QRhiGraphicsPipeline *triPs = nullptr;
+ QRhiBuffer *triUbuf = nullptr;
+ QRhiTextureRenderTarget *msaaRt = nullptr;
+ QRhiRenderPassDescriptor *msaaRtRp = nullptr;
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+} d;
+
+//#define NO_MSAA
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::MultisampleTexture))
+ qFatal("Multisample textures not supported by this backend");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData) + sizeof(triangleData));
+ d.releasePool << d.vbuf;
+ d.vbuf->build();
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.releasePool << d.ibuf;
+ d.ibuf->build();
+
+ d.rightOfs = m_r->ubufAligned(UBUFSZ);
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, d.rightOfs + UBUFSZ);
+ d.releasePool << d.ubuf;
+ d.ubuf->build();
+
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+ d.releasePool << d.tex;
+ d.tex->build();
+#ifndef NO_MSAA
+ d.msaaTex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 4, QRhiTexture::RenderTarget);
+#else
+ d.msaaTex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+#endif
+ d.releasePool << d.msaaTex;
+ d.msaaTex->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(vertexData), vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(vertexData), sizeof(triangleData), triangleData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srbLeft = m_r->newShaderResourceBindings();
+ d.releasePool << d.srbLeft;
+ d.srbLeft->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUFSZ),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srbLeft->build();
+
+ d.srbRight = m_r->newShaderResourceBindings();
+ d.releasePool << d.srbRight;
+ d.srbRight->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, d.rightOfs, UBUFSZ),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.msaaTex, d.sampler)
+ });
+ d.srbRight->build();
+
+ d.psLeft = m_r->newGraphicsPipeline();
+ d.releasePool << d.psLeft;
+ d.psLeft->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 4 * sizeof(float) } });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.psLeft->setVertexInputLayout(inputLayout);
+ d.psLeft->setShaderResourceBindings(d.srbLeft);
+ d.psLeft->setRenderPassDescriptor(m_rp);
+ d.psLeft->build();
+
+ d.psRight = m_r->newGraphicsPipeline();
+ d.releasePool << d.psRight;
+ d.psRight->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+#ifndef NO_MSAA
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture_ms4.frag.qsb")) }
+#else
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+#endif
+ });
+ d.psRight->setVertexInputLayout(d.psLeft->vertexInputLayout());
+ d.psRight->setShaderResourceBindings(d.srbRight);
+ d.psRight->setRenderPassDescriptor(m_rp);
+ d.psRight->build();
+
+ // set up the offscreen triangle that goes into tex and msaaTex
+ d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.triUbuf;
+ d.triUbuf->build();
+ d.triSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.triSrb;
+ d.triSrb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf)
+ });
+ d.triSrb->build();
+ d.rt = m_r->newTextureRenderTarget({ d.tex });
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+ d.msaaRt = m_r->newTextureRenderTarget({ d.msaaTex });
+ d.releasePool << d.msaaRt;
+ d.msaaRtRp = d.msaaRt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.msaaRtRp;
+ d.msaaRt->setRenderPassDescriptor(d.msaaRtRp);
+ d.msaaRt->build();
+ d.triPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.triPs;
+ d.triPs->setSampleCount(1);
+ d.triPs->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
+ });
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ d.triPs->setVertexInputLayout(inputLayout);
+ d.triPs->setShaderResourceBindings(d.triSrb);
+ d.triPs->setRenderPassDescriptor(d.rtRp);
+ d.triPs->build();
+ d.msaaTriPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.msaaTriPs;
+#ifndef NO_MSAA
+ d.msaaTriPs->setSampleCount(4);
+#else
+ d.msaaTriPs->setSampleCount(1);
+#endif
+ d.msaaTriPs->setShaderStages(d.triPs->shaderStages());
+ d.msaaTriPs->setVertexInputLayout(d.triPs->vertexInputLayout());
+ d.msaaTriPs->setShaderResourceBindings(d.triSrb);
+ d.msaaTriPs->setRenderPassDescriptor(d.msaaRtRp);
+ d.msaaTriPs->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+
+ // onscreen ubuf
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ u->updateDynamicBuffer(d.ubuf, d.rightOfs + 64, 4, &flip);
+
+ // offscreen ubuf
+ d.triBaseMvp = m_r->clipSpaceCorrMatrix();
+ d.triBaseMvp.perspective(45.0f, d.msaaTex->pixelSize().width() / float(d.msaaTex->pixelSize().height()), 0.01f, 1000.0f);
+ d.triBaseMvp.translate(0, 0, -2);
+ float opacity = 1.0f;
+ u->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
+ }
+
+ if (d.winProj != m_proj) {
+ // onscreen buf, window size dependent
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2);
+ mvp.translate(-0.8f, 0, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ mvp.translate(1.6f, 0, 0);
+ u->updateDynamicBuffer(d.ubuf, d.rightOfs, 64, mvp.constData());
+ }
+
+ // offscreen buf, apply the rotation on every frame
+ QMatrix4x4 triMvp = d.triBaseMvp;
+ triMvp.rotate(d.triRot, 0, 1, 0);
+ d.triRot += 1;
+ u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
+
+ cb->resourceUpdate(u); // could have passed u to beginPass but exercise this one too
+
+ // offscreen
+ cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.triPs);
+ cb->setViewport({ 0, 0, float(d.msaaTex->pixelSize().width()), float(d.msaaTex->pixelSize().height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, sizeof(vertexData));
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ // offscreen msaa
+ cb->beginPass(d.msaaRt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.msaaTriPs);
+ cb->setViewport({ 0, 0, float(d.msaaTex->pixelSize().width()), float(d.msaaTex->pixelSize().height()) });
+ cb->setShaderResources();
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ // onscreen
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.psLeft); // showing the non-msaa version
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ vbufBinding.second = 0;
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->setGraphicsPipeline(d.psRight); // showing the msaa version, resolved in the shader
+ cb->setShaderResources();
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/msaatexture/msaatexture.pro b/tests/manual/rhi/msaatexture/msaatexture.pro
new file mode 100644
index 0000000000..0467e4dc9d
--- /dev/null
+++ b/tests/manual/rhi/msaatexture/msaatexture.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ msaatexture.cpp
+
+RESOURCES = msaatexture.qrc
diff --git a/tests/manual/rhi/msaatexture/msaatexture.qrc b/tests/manual/rhi/msaatexture/msaatexture.qrc
new file mode 100644
index 0000000000..ecd968481c
--- /dev/null
+++ b/tests/manual/rhi/msaatexture/msaatexture.qrc
@@ -0,0 +1,9 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="texture_ms4.frag.qsb">../shared/texture_ms4.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/multiwindow/multiwindow.cpp b/tests/manual/rhi/multiwindow/multiwindow.cpp
new file mode 100644
index 0000000000..4c5d5c345a
--- /dev/null
+++ b/tests/manual/rhi/multiwindow/multiwindow.cpp
@@ -0,0 +1,644 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QWidget>
+#include <QLabel>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QVBoxLayout>
+
+#include <QCommandLineParser>
+#include <QWindow>
+#include <QPlatformSurfaceEvent>
+#include <QElapsedTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal
+};
+
+static GraphicsApi graphicsApi;
+
+static QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ default:
+ break;
+ }
+ return QString();
+}
+
+static struct {
+#if QT_CONFIG(vulkan)
+ QVulkanInstance *instance = nullptr;
+#endif
+ QRhi *r = nullptr;
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *fallbackSurface = nullptr;
+#endif
+} r;
+
+void createRhi()
+{
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ r.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = r.fallbackSurface;
+ //params.window = this;
+ r.r = QRhi::create(QRhi::OpenGLES2, &params);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = r.instance;
+ //params.window = this;
+ r.r = QRhi::create(QRhi::Vulkan, &params);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ r.r = QRhi::create(QRhi::D3D11, &params);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ r.r = QRhi::create(QRhi::Metal, &params);
+ }
+#endif
+
+ if (!r.r)
+ qFatal("Failed to create RHI backend");
+}
+
+void destroyRhi()
+{
+ delete r.r;
+
+#ifndef QT_NO_OPENGL
+ delete r.fallbackSurface;
+#endif
+}
+
+struct {
+ QVector<QWindow *> windows;
+
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+} d;
+
+static float vertexData[] = {
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+// can use just one rpd from whichever window comes first since they are
+// actually compatible due to all windows using the same config (have
+// depth-stencil, sample count 1, same format). this means the same pso can be
+// reused too.
+void ensureSharedResources(QRhiRenderPassDescriptor *rp)
+{
+ if (!d.vbuf) {
+ d.vbuf = r.r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ d.vbuf->build();
+ d.initialUpdates = r.r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, vertexData);
+ }
+
+ if (!d.ubuf) {
+ d.ubuf = r.r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ }
+
+ if (!d.srb) {
+ d.srb = r.r->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf)
+ });
+ d.srb->build();
+ }
+
+ if (!d.ps) {
+ d.ps = r.r->newGraphicsPipeline();
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ d.ps->setTargetBlends({ premulAlphaBlend });
+
+ const QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(rp);
+
+ d.ps->build();
+ }
+}
+
+void destroySharedResources()
+{
+ delete d.ps;
+ d.ps = nullptr;
+
+ delete d.srb;
+ d.srb = nullptr;
+
+ delete d.vbuf;
+ d.vbuf = nullptr;
+
+ delete d.ubuf;
+ d.ubuf = nullptr;
+}
+
+class Window : public QWindow
+{
+public:
+ Window(const QString &title, const QColor &bgColor, int axis, bool noVSync);
+ ~Window();
+
+protected:
+ void init();
+ void releaseResources();
+ void resizeSwapChain();
+ void releaseSwapChain();
+ void render();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+ QColor m_bgColor;
+ int m_rotationAxis;
+ bool m_noVSync;
+
+ bool m_running = false;
+ bool m_notExposed = false;
+ bool m_newlyExposed = false;
+
+ QMatrix4x4 m_proj;
+ QVector<QRhiResource *> m_releasePool;
+
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+
+ float m_rotation = 0;
+ float m_opacity = 1;
+ int m_opacityDir = -1;
+};
+
+Window::Window(const QString &title, const QColor &bgColor, int axis, bool noVSync)
+ : m_bgColor(bgColor),
+ m_rotationAxis(axis),
+ m_noVSync(noVSync)
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ {
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ QSurfaceFormat fmt = QRhiGles2InitParams::adjustedFormat(); // default + depth/stencil
+ fmt.setSwapInterval(noVSync ? 0 : 1); // + swap interval
+ setFormat(fmt);
+#endif
+ }
+ break;
+ case Vulkan:
+#if QT_CONFIG(vulkan)
+ setSurfaceType(VulkanSurface);
+ setVulkanInstance(r.instance);
+#endif
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ resize(800, 600);
+ setTitle(title);
+}
+
+Window::~Window()
+{
+ releaseResources();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !m_running) {
+ m_running = true;
+ init();
+ resizeSwapChain();
+ }
+
+ // stop pushing frames when not exposed (or size is 0)
+ if ((!isExposed() || (m_hasSwapChain && m_sc->surfacePixelSize().isEmpty())) && m_running)
+ m_notExposed = true;
+
+ // continue when exposed again and the surface has a valid size.
+ // note that the surface size can be (0, 0) even though size() reports a valid one...
+ if (isExposed() && m_running && m_notExposed && !m_sc->surfacePixelSize().isEmpty()) {
+ m_notExposed = false;
+ m_newlyExposed = true;
+ }
+
+ // always render a frame on exposeEvent() (when exposed) in order to update
+ // immediately on window resize.
+ if (isExposed() && !m_sc->surfacePixelSize().isEmpty())
+ render();
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void Window::init()
+{
+ m_sc = r.r->newSwapChain();
+ m_ds = r.r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ m_releasePool << m_ds;
+ m_sc->setWindow(this);
+ m_sc->setDepthStencil(m_ds);
+ if (m_noVSync)
+ m_sc->setFlags(QRhiSwapChain::NoVSync);
+
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ m_releasePool << m_rp;
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ ensureSharedResources(m_rp);
+}
+
+void Window::releaseResources()
+{
+ qDeleteAll(m_releasePool);
+ m_releasePool.clear();
+
+ delete m_sc;
+ m_sc = nullptr;
+}
+
+void Window::resizeSwapChain()
+{
+ const QSize outputSize = m_sc->surfacePixelSize();
+
+ m_ds->setPixelSize(outputSize);
+ m_ds->build();
+
+ m_hasSwapChain = m_sc->buildOrResize();
+
+ m_proj = r.r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void Window::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Window::render()
+{
+ if (!m_hasSwapChain || m_notExposed)
+ return;
+
+ // If the window got resized or got newly exposed, resize the swapchain.
+ // (the newly-exposed case is not actually required by some
+ // platforms/backends, but f.ex. Vulkan on Windows seems to need it)
+ if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ m_newlyExposed = false;
+ }
+
+ QRhi::FrameOpResult result = r.r->beginFrame(m_sc);
+ if (result == QRhi::FrameOpSwapChainOutOfDate) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ result = r.r->beginFrame(m_sc);
+ }
+ if (result != QRhi::FrameOpSuccess) {
+ requestUpdate();
+ return;
+ }
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ QRhiResourceUpdateBatch *u = r.r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.rotate(m_rotation, m_rotationAxis == 0 ? 1 : 0, m_rotationAxis == 1 ? 1 : 0, m_rotationAxis == 2 ? 1 : 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ m_opacity += m_opacityDir * 0.005f;
+ if (m_opacity < 0.0f || m_opacity > 1.0f) {
+ m_opacityDir *= -1;
+ m_opacity = qBound(0.0f, m_opacity, 1.0f);
+ }
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &m_opacity);
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(),
+ QColor::fromRgbF(float(m_bgColor.redF()), float(m_bgColor.greenF()), float(m_bgColor.blueF()), 1.0f),
+ { 1.0f, 0 },
+ u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+
+ cb->endPass();
+
+ r.r->endFrame(m_sc);
+
+ requestUpdate();
+}
+
+void createWindow(bool noVSync)
+{
+ static QColor colors[] = { Qt::red, Qt::green, Qt::blue, Qt::yellow, Qt::cyan, Qt::gray };
+ const int n = d.windows.count();
+ d.windows.append(new Window(QString::asprintf("Window #%d%s", n, noVSync ? " (no vsync)" : ""), colors[n % 6], n % 3, noVSync));
+ d.windows.last()->show();
+}
+
+void closeWindow()
+{
+ delete d.windows.takeLast();
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication app(argc, argv);
+
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+#if QT_CONFIG(vulkan)
+ r.instance = new QVulkanInstance;
+ if (graphicsApi == Vulkan) {
+#ifndef Q_OS_ANDROID
+ r.instance->setLayers({ "VK_LAYER_LUNARG_standard_validation" });
+#else
+ r.instance->setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ if (!r.instance->create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ createRhi();
+
+ int winCount = 0;
+ QWidget w;
+ w.resize(800, 600);
+ w.setWindowTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName());
+ QVBoxLayout *layout = new QVBoxLayout(&w);
+
+ QPlainTextEdit *info = new QPlainTextEdit(
+ QLatin1String("This application tests rendering with the same QRhi instance (and so the same Vulkan/Metal/D3D device or OpenGL context) "
+ "to multiple windows via multiple QRhiSwapChain objects, from the same one thread. Some resources are shared across all windows.\n"
+ "\nNote that the behavior may differ depending on the underlying graphics API implementation and the number of windows. "
+ "One challenge here is the vsync throttling: with the default vsync/fifo presentation mode the behavior may differ between "
+ "platforms, drivers, and APIs as we present different swapchains' images in a row on the same thread. As a potential solution, "
+ "setting NoVSync on the second, third, and later window swapchains is offered as an option.\n"
+ "\n\nUsing API: ") + graphicsApiName());
+ info->setReadOnly(true);
+ layout->addWidget(info);
+ QLabel *label = new QLabel(QLatin1String("Window count: 0"));
+ layout->addWidget(label);
+ QCheckBox *vsCb = new QCheckBox(QLatin1String("Set NoVSync on all swapchains except the first"));
+ vsCb->setChecked(false);
+ layout->addWidget(vsCb);
+ QPushButton *btn = new QPushButton(QLatin1String("New window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, vsCb, &winCount] {
+ winCount += 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ const bool noVSync = vsCb->isChecked() && winCount > 1;
+ createWindow(noVSync);
+ });
+ layout->addWidget(btn);
+ btn = new QPushButton(QLatin1String("Close window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, &winCount] {
+ if (winCount > 0) {
+ winCount -= 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ closeWindow();
+ }
+ });
+ layout->addWidget(btn);
+ w.show();
+
+ int result = app.exec();
+
+ qDeleteAll(d.windows);
+
+ destroySharedResources();
+ destroyRhi();
+
+#if QT_CONFIG(vulkan)
+ delete r.instance;
+#endif
+
+ return result;
+}
diff --git a/tests/manual/rhi/multiwindow/multiwindow.pro b/tests/manual/rhi/multiwindow/multiwindow.pro
new file mode 100644
index 0000000000..b9c3867bf8
--- /dev/null
+++ b/tests/manual/rhi/multiwindow/multiwindow.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private widgets
+
+SOURCES = \
+ multiwindow.cpp
+
+RESOURCES = multiwindow.qrc
diff --git a/tests/manual/rhi/multiwindow/multiwindow.qrc b/tests/manual/rhi/multiwindow/multiwindow.qrc
new file mode 100644
index 0000000000..8cec4fa9ec
--- /dev/null
+++ b/tests/manual/rhi/multiwindow/multiwindow.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp
new file mode 100644
index 0000000000..53185bddb2
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp
@@ -0,0 +1,833 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QWidget>
+#include <QLabel>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QVBoxLayout>
+
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QQueue>
+#include <QEvent>
+#include <QCommandLineParser>
+#include <QElapsedTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+#include <QtGui/private/qrhiprofiler_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+#include "window.h"
+
+#include "../shared/cube.h"
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+static GraphicsApi graphicsApi;
+
+static QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ default:
+ break;
+ }
+ return QString();
+}
+
+#if QT_CONFIG(vulkan)
+QVulkanInstance *instance = nullptr;
+#endif
+
+// Window (main thread) emit signals -> Renderer::send* (main thread) -> event queue (add on main, process on render thread) -> Renderer::renderEvent (render thread)
+
+// event queue is taken from the Qt Quick scenegraph as-is
+// all this below is conceptually the same as the QSG threaded render loop
+class RenderThreadEventQueue : public QQueue<QEvent *>
+{
+public:
+ RenderThreadEventQueue()
+ : waiting(false)
+ {
+ }
+
+ void addEvent(QEvent *e) {
+ mutex.lock();
+ enqueue(e);
+ if (waiting)
+ condition.wakeOne();
+ mutex.unlock();
+ }
+
+ QEvent *takeEvent(bool wait) {
+ mutex.lock();
+ if (isEmpty() && wait) {
+ waiting = true;
+ condition.wait(&mutex);
+ waiting = false;
+ }
+ QEvent *e = dequeue();
+ mutex.unlock();
+ return e;
+ }
+
+ bool hasMoreEvents() {
+ mutex.lock();
+ bool has = !isEmpty();
+ mutex.unlock();
+ return has;
+ }
+
+private:
+ QMutex mutex;
+ QWaitCondition condition;
+ bool waiting;
+};
+
+struct Renderer;
+
+struct Thread : public QThread
+{
+ Thread(Renderer *renderer_)
+ : renderer(renderer_)
+ {
+ active = true;
+ start();
+ }
+ void run() override;
+
+ Renderer *renderer;
+ bool active;
+ RenderThreadEventQueue eventQueue;
+ bool sleeping = false;
+ bool stopEventProcessing = false;
+ bool pendingRender = false;
+ bool pendingRenderIsNewExpose = false;
+ // mutex and cond used to allow the main thread waiting until something completes on the render thread
+ QMutex mutex;
+ QWaitCondition cond;
+};
+
+class RenderThreadEvent : public QEvent
+{
+public:
+ RenderThreadEvent(QEvent::Type type) : QEvent(type) { }
+};
+
+class InitEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 1);
+ InitEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+class RequestRenderEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 2);
+ RequestRenderEvent(bool newlyExposed_) : RenderThreadEvent(TYPE), newlyExposed(newlyExposed_)
+ { }
+ bool newlyExposed;
+};
+
+class SurfaceCleanupEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 3);
+ SurfaceCleanupEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+class CloseEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 4);
+ CloseEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+class SyncSurfaceSizeEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 5);
+ SyncSurfaceSizeEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+struct Renderer
+{
+ // ctor and dtor and send* are called main thread, rest on the render thread
+
+ Renderer(QWindow *w, const QColor &bgColor, int rotationAxis);
+ ~Renderer();
+
+ void sendInit();
+ void sendRender(bool newlyExposed);
+ void sendSurfaceGoingAway();
+ void sendSyncSurfaceSize();
+
+ QWindow *window;
+ Thread *thread;
+ QRhi *r = nullptr;
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *fallbackSurface = nullptr;
+#endif
+
+ void createRhi();
+ void destroyRhi();
+ void renderEvent(QEvent *e);
+ void init();
+ void releaseSwapChain();
+ void releaseResources();
+ void render(bool newlyExposed, bool wakeBeforePresent);
+
+ QColor m_bgColor;
+ int m_rotationAxis;
+
+ QVector<QRhiResource *> m_releasePool;
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiTexture *m_tex = nullptr;
+ QRhiSampler *m_sampler = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+ QRhiResourceUpdateBatch *m_initialUpdates = nullptr;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_frameCount = 0;
+};
+
+void Thread::run()
+{
+ while (active) {
+#ifdef Q_OS_DARWIN
+ QMacAutoReleasePool autoReleasePool;
+#endif
+
+ if (pendingRender) {
+ pendingRender = false;
+ renderer->render(pendingRenderIsNewExpose, false);
+ }
+
+ while (eventQueue.hasMoreEvents()) {
+ QEvent *e = eventQueue.takeEvent(false);
+ renderer->renderEvent(e);
+ delete e;
+ }
+
+ if (active && !pendingRender) {
+ sleeping = true;
+ stopEventProcessing = false;
+ while (!stopEventProcessing) {
+ QEvent *e = eventQueue.takeEvent(true);
+ renderer->renderEvent(e);
+ delete e;
+ }
+ sleeping = false;
+ }
+ }
+}
+
+Renderer::Renderer(QWindow *w, const QColor &bgColor, int rotationAxis)
+ : window(w),
+ m_bgColor(bgColor),
+ m_rotationAxis(rotationAxis)
+{ // main thread
+ thread = new Thread(this);
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL)
+ fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+#endif
+}
+
+Renderer::~Renderer()
+{ // main thread
+ thread->eventQueue.addEvent(new CloseEvent);
+ thread->wait();
+ delete thread;
+
+#ifndef QT_NO_OPENGL
+ delete fallbackSurface;
+#endif
+}
+
+void Renderer::createRhi()
+{
+ if (r)
+ return;
+
+ qDebug() << "renderer" << this << "creating rhi";
+ QRhi::Flags rhiFlags = QRhi::EnableProfiling;
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ QRhiGles2InitParams params;
+ params.fallbackSurface = fallbackSurface;
+ params.window = window;
+ r = QRhi::create(QRhi::OpenGLES2, &params, rhiFlags);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = instance;
+ params.window = window;
+ r = QRhi::create(QRhi::Vulkan, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ r = QRhi::create(QRhi::D3D11, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ r = QRhi::create(QRhi::Metal, &params, rhiFlags);
+ }
+#endif
+
+ if (!r)
+ qFatal("Failed to create RHI backend");
+}
+
+void Renderer::destroyRhi()
+{
+ qDebug() << "renderer" << this << "destroying rhi";
+ delete r;
+ r = nullptr;
+}
+
+void Renderer::renderEvent(QEvent *e)
+{
+ Q_ASSERT(QThread::currentThread() == thread);
+
+ if (thread->sleeping)
+ thread->stopEventProcessing = true;
+
+ switch (int(e->type())) {
+ case InitEvent::TYPE:
+ qDebug() << "renderer" << this << "for window" << window << "is initializing";
+ createRhi();
+ init();
+ break;
+ case RequestRenderEvent::TYPE:
+ thread->pendingRender = true;
+ thread->pendingRenderIsNewExpose = static_cast<RequestRenderEvent *>(e)->newlyExposed;
+ break;
+ case SurfaceCleanupEvent::TYPE: // when the QWindow is closed, before QPlatformWindow goes away
+ thread->mutex.lock();
+ qDebug() << "renderer" << this << "for window" << window << "is destroying swapchain";
+ thread->pendingRender = false;
+ releaseSwapChain();
+ thread->cond.wakeOne();
+ thread->mutex.unlock();
+ break;
+ case CloseEvent::TYPE: // when destroying the window+renderer (NB not the same as hitting X on the window, that's just QWindow close)
+ qDebug() << "renderer" << this << "for window" << window << "is shutting down";
+ thread->pendingRender = false;
+ thread->active = false;
+ thread->stopEventProcessing = true;
+ releaseResources();
+ destroyRhi();
+ break;
+ case SyncSurfaceSizeEvent::TYPE:
+ thread->mutex.lock();
+ thread->pendingRender = false;
+ render(false, true);
+ break;
+ default:
+ break;
+ }
+}
+
+void Renderer::init()
+{
+ m_sc = r->newSwapChain();
+ m_ds = r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ m_releasePool << m_ds;
+ m_sc->setWindow(window);
+ m_sc->setDepthStencil(m_ds);
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ m_releasePool << m_rp;
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ m_vbuf = r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ m_releasePool << m_vbuf;
+ m_vbuf->build();
+
+ m_ubuf = r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
+ m_releasePool << m_ubuf;
+ m_ubuf->build();
+
+ QImage image = QImage(QLatin1String(":/qt256.png")).convertToFormat(QImage::Format_RGBA8888);
+ m_tex = r->newTexture(QRhiTexture::RGBA8, image.size());
+ m_releasePool << m_tex;
+ m_tex->build();
+
+ m_sampler = r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ m_releasePool << m_sampler;
+ m_sampler->build();
+
+ m_srb = r->newShaderResourceBindings();
+ m_releasePool << m_srb;
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, m_tex, m_sampler)
+ });
+ m_srb->build();
+
+ m_ps = r->newGraphicsPipeline();
+ m_releasePool << m_ps;
+
+ m_ps->setDepthTest(true);
+ m_ps->setDepthWrite(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ m_ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ m_ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(m_rp);
+
+ m_ps->build();
+
+ m_initialUpdates = r->nextResourceUpdateBatch();
+
+ m_initialUpdates->uploadStaticBuffer(m_vbuf, cube);
+
+ qint32 flip = 0;
+ m_initialUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &flip);
+
+ m_initialUpdates->uploadTexture(m_tex, image);
+}
+
+void Renderer::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Renderer::releaseResources()
+{
+ qDeleteAll(m_releasePool);
+ m_releasePool.clear();
+
+ delete m_sc;
+ m_sc = nullptr;
+}
+
+void Renderer::render(bool newlyExposed, bool wakeBeforePresent)
+{
+ // This function handles both resizing and rendering. Resizes have some
+ // complications due to the threaded model (check exposeEvent and
+ // sendSyncSurfaceSize) but don't have to worry about that in here.
+
+ auto buildOrResizeSwapChain = [this] {
+ qDebug() << "renderer" << this << "build or resize swapchain for window" << window;
+ const QSize outputSize = m_sc->surfacePixelSize();
+ qDebug() << " size is" << outputSize;
+ m_ds->setPixelSize(outputSize);
+ m_ds->build();
+ m_hasSwapChain = m_sc->buildOrResize();
+ m_proj = r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+ };
+
+ auto wakeUpIfNeeded = [wakeBeforePresent, this] {
+ // make sure the main/gui thread is not blocked when issuing the Present (or equivalent)
+ if (wakeBeforePresent) {
+ thread->cond.wakeOne();
+ thread->mutex.unlock();
+ }
+ };
+
+ const QSize surfaceSize = m_sc->surfacePixelSize();
+ if (surfaceSize.isEmpty()) {
+ wakeUpIfNeeded();
+ return;
+ }
+
+ if (newlyExposed || m_sc->currentPixelSize() != surfaceSize)
+ buildOrResizeSwapChain();
+
+ if (!m_hasSwapChain) {
+ wakeUpIfNeeded();
+ return;
+ }
+
+ QRhi::FrameOpResult result = r->beginFrame(m_sc);
+ if (result == QRhi::FrameOpSwapChainOutOfDate) {
+ buildOrResizeSwapChain();
+ if (!m_hasSwapChain) {
+ wakeUpIfNeeded();
+ return;
+ }
+ result = r->beginFrame(m_sc);
+ }
+ if (result != QRhi::FrameOpSuccess) {
+ wakeUpIfNeeded();
+ return;
+ }
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSize = m_sc->currentPixelSize();
+
+ QRhiResourceUpdateBatch *u = r->nextResourceUpdateBatch();
+ if (m_initialUpdates) {
+ u->merge(m_initialUpdates);
+ m_initialUpdates->release();
+ m_initialUpdates = nullptr;
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(m_rotation, m_rotationAxis == 0 ? 1 : 0, m_rotationAxis == 1 ? 1 : 0, m_rotationAxis == 2 ? 1 : 0);
+ u->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(),
+ QColor::fromRgbF(float(m_bgColor.redF()), float(m_bgColor.greenF()), float(m_bgColor.blueF()), 1.0f),
+ { 1.0f, 0 },
+ u);
+
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { m_vbuf, 0 },
+ { m_vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+
+ wakeUpIfNeeded();
+
+ r->endFrame(m_sc);
+
+ m_frameCount += 1;
+ if ((m_frameCount % 300) == 0) {
+ const QRhiProfiler::CpuTime ff = r->profiler()->frameToFrameTimes(m_sc);
+ const QRhiProfiler::CpuTime be = r->profiler()->frameBuildTimes(m_sc);
+ const QRhiProfiler::GpuTime gp = r->profiler()->gpuFrameTimes(m_sc);
+ if (r->isFeatureSupported(QRhi::Timestamps)) {
+ qDebug("[renderer %p] frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. "
+ "gpu frame time: min %f max %f avg %f",
+ this,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime,
+ gp.minTime, gp.maxTime, gp.avgTime);
+ } else {
+ qDebug("[renderer %p] frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. ",
+ this,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime);
+ }
+ }
+}
+
+void Renderer::sendInit()
+{ // main thread
+ InitEvent *e = new InitEvent;
+ thread->eventQueue.addEvent(e);
+}
+
+void Renderer::sendRender(bool newlyExposed)
+{ // main thread
+ RequestRenderEvent *e = new RequestRenderEvent(newlyExposed);
+ thread->eventQueue.addEvent(e);
+}
+
+void Renderer::sendSurfaceGoingAway()
+{ // main thread
+ SurfaceCleanupEvent *e = new SurfaceCleanupEvent;
+
+ // cannot let this thread to proceed with tearing down the native window
+ // before the render thread completes the swapchain release
+ thread->mutex.lock();
+
+ thread->eventQueue.addEvent(e);
+
+ thread->cond.wait(&thread->mutex);
+ thread->mutex.unlock();
+}
+
+void Renderer::sendSyncSurfaceSize()
+{ // main thread
+ SyncSurfaceSizeEvent *e = new SyncSurfaceSizeEvent;
+ // must block to prevent surface size mess. the render thread will do a
+ // full rendering round before it unlocks which is good since it can thus
+ // pick up and the surface (window) size atomically.
+ thread->mutex.lock();
+ thread->eventQueue.addEvent(e);
+ thread->cond.wait(&thread->mutex);
+ thread->mutex.unlock();
+}
+
+struct WindowAndRenderer
+{
+ QWindow *window;
+ Renderer *renderer;
+};
+
+QVector<WindowAndRenderer> windows;
+
+void createWindow()
+{
+ static QColor colors[] = { Qt::red, Qt::green, Qt::blue, Qt::yellow, Qt::cyan, Qt::gray };
+ const int n = windows.count();
+ Window *w = new Window(QString::asprintf("Window+Thread #%d (%s)", n, qPrintable(graphicsApiName())), graphicsApi);
+ Renderer *renderer = new Renderer(w, colors[n % 6], n % 3);;
+ QObject::connect(w, &Window::initRequested, w, [renderer] {
+ renderer->sendInit();
+ });
+ QObject::connect(w, &Window::renderRequested, w, [w, renderer](bool newlyExposed) {
+ renderer->sendRender(newlyExposed);
+ w->requestUpdate();
+ });
+ QObject::connect(w, &Window::surfaceGoingAway, w, [renderer] {
+ renderer->sendSurfaceGoingAway();
+ });
+ QObject::connect(w, &Window::syncSurfaceSizeRequested, w, [renderer] {
+ renderer->sendSyncSurfaceSize();
+ });
+ windows.append({ w, renderer });
+ w->show();
+}
+
+void closeWindow()
+{
+ WindowAndRenderer wr = windows.takeLast();
+ delete wr.renderer;
+ delete wr.window;
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication app(argc, argv);
+
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+#if QT_CONFIG(vulkan)
+ instance = new QVulkanInstance;
+ if (graphicsApi == Vulkan) {
+#ifndef Q_OS_ANDROID
+ instance->setLayers({ "VK_LAYER_LUNARG_standard_validation" });
+#else
+ instance->setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ if (!instance->create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ int winCount = 0;
+ QWidget w;
+ w.resize(800, 600);
+ w.setWindowTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName());
+ QVBoxLayout *layout = new QVBoxLayout(&w);
+
+ QPlainTextEdit *info = new QPlainTextEdit(
+ QLatin1String("This application tests rendering on a separate thread per window, with dedicated QRhi instances and resources. "
+ "\n\nThis is the same concept as the Qt Quick Scenegraph's threaded render loop. This should allow rendering to the different windows "
+ "without unintentionally throttling each other's threads."
+ "\n\nUsing API: ") + graphicsApiName());
+ info->setReadOnly(true);
+ layout->addWidget(info);
+ QLabel *label = new QLabel(QLatin1String("Window and thread count: 0"));
+ layout->addWidget(label);
+ QPushButton *btn = new QPushButton(QLatin1String("New window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, &winCount] {
+ winCount += 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ createWindow();
+ });
+ layout->addWidget(btn);
+ btn = new QPushButton(QLatin1String("Close window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, &winCount] {
+ if (winCount > 0) {
+ winCount -= 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ closeWindow();
+ }
+ });
+ layout->addWidget(btn);
+ w.show();
+
+ int result = app.exec();
+
+ for (const WindowAndRenderer &wr : windows) {
+ delete wr.renderer;
+ delete wr.window;
+ }
+
+#if QT_CONFIG(vulkan)
+ delete instance;
+#endif
+
+ return result;
+}
diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro
new file mode 100644
index 0000000000..0b78518b9b
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+QT += gui-private widgets
+
+SOURCES = \
+ multiwindow_threaded.cpp \
+ window.cpp
+
+HEADERS = \
+ window.h
+
+RESOURCES = multiwindow_threaded.qrc
diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc
new file mode 100644
index 0000000000..742b2b77af
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256.png">../shared/qt256.png</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/multiwindow_threaded/window.cpp b/tests/manual/rhi/multiwindow_threaded/window.cpp
new file mode 100644
index 0000000000..aa7b479047
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/window.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+#include <QPlatformSurfaceEvent>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#endif
+
+#if QT_CONFIG(vulkan)
+extern QVulkanInstance *instance;
+#endif
+
+Window::Window(const QString &title, GraphicsApi api)
+{
+ switch (api) {
+ case OpenGL:
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ setFormat(QRhiGles2InitParams::adjustedFormat());
+#endif
+ break;
+ case Vulkan:
+#if QT_CONFIG(vulkan)
+ setSurfaceType(VulkanSurface);
+ setVulkanInstance(instance);
+#endif
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ resize(800, 600);
+ setTitle(title);
+}
+
+Window::~Window()
+{
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ if (isExposed()) {
+ if (!m_running) {
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ m_running = true;
+ m_notExposed = false;
+ emit initRequested();
+ emit renderRequested(true);
+ } else {
+ // continue when exposed again
+ if (m_notExposed) {
+ m_notExposed = false;
+ emit renderRequested(true);
+ } else {
+ // resize generates exposes - this is very important here (unlike in a single-threaded renderer)
+ emit syncSurfaceSizeRequested();
+ }
+ }
+ } else {
+ // stop pushing frames when not exposed (on some platforms this is essential, optional on others)
+ if (m_running)
+ m_notExposed = true;
+ }
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ if (!m_notExposed)
+ emit renderRequested(false);
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ emit surfaceGoingAway();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
diff --git a/tests/manual/rhi/multiwindow_threaded/window.h b/tests/manual/rhi/multiwindow_threaded/window.h
new file mode 100644
index 0000000000..7810858d0a
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/window.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <QWindow>
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal
+};
+
+class Window : public QWindow
+{
+ Q_OBJECT
+
+public:
+ Window(const QString &title, GraphicsApi api);
+ ~Window();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+signals:
+ void initRequested();
+ void renderRequested(bool newlyExposed);
+ void surfaceGoingAway();
+ void syncSurfaceSizeRequested();
+
+protected:
+ bool m_running = false;
+ bool m_notExposed = true;
+};
+
+#endif
diff --git a/tests/manual/rhi/offscreen/offscreen.cpp b/tests/manual/rhi/offscreen/offscreen.cpp
new file mode 100644
index 0000000000..79e50d3dd4
--- /dev/null
+++ b/tests/manual/rhi/offscreen/offscreen.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QImage>
+#include <QFileInfo>
+#include <QFile>
+#include <QLoggingCategory>
+#include <QCommandLineParser>
+#include <QtGui/private/qshader_p.h>
+
+#include <QtGui/private/qrhinull_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+//#define TEST_FINISH
+
+static float vertexData[] = { // Y up (note m_proj), CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal,
+ Null
+};
+
+GraphicsApi graphicsApi;
+
+QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ case Null:
+ return QLatin1String("Null");
+ default:
+ break;
+ }
+ return QString();
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
+ cmdLineParser.addOption(nullOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+ if (cmdLineParser.isSet(nullOption))
+ graphicsApi = Null;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+ QRhi *r = nullptr;
+
+ if (graphicsApi == Null) {
+ QRhiNullInitParams params;
+ r = QRhi::create(QRhi::Null, &params);
+ }
+
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+ if (graphicsApi == Vulkan) {
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ if (inst.create()) {
+ QRhiVulkanInitParams params;
+ params.inst = &inst;
+ r = QRhi::create(QRhi::Vulkan, &params);
+ } else {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+#ifndef QT_NO_OPENGL
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+ if (graphicsApi == OpenGL) {
+ offscreenSurface.reset(QRhiGles2InitParams::newFallbackSurface());
+ QRhiGles2InitParams params;
+ params.fallbackSurface = offscreenSurface.data();
+ r = QRhi::create(QRhi::OpenGLES2, &params);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ r = QRhi::create(QRhi::D3D11, &params);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ r = QRhi::create(QRhi::Metal, &params);
+ }
+#endif
+
+ if (!r)
+ qFatal("Failed to initialize RHI");
+
+ QRhiTexture *tex = r->newTexture(QRhiTexture::RGBA8, QSize(1280, 720), 1, QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ tex->build();
+ QRhiTextureRenderTarget *rt = r->newTextureRenderTarget({ tex });
+ QRhiRenderPassDescriptor *rp = rt->newCompatibleRenderPassDescriptor();
+ rt->setRenderPassDescriptor(rp);
+ rt->build();
+
+ QMatrix4x4 proj = r->clipSpaceCorrMatrix();
+ proj.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f);
+ proj.translate(0, 0, -4);
+
+ QRhiBuffer *vbuf = r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ vbuf->build();
+
+ QRhiBuffer *ubuf = r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ ubuf->build();
+
+ QRhiShaderResourceBindings *srb = r->newShaderResourceBindings();
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
+ });
+ srb->build();
+
+ QRhiGraphicsPipeline *ps = r->newGraphicsPipeline();
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ ps->setTargetBlends({ premulAlphaBlend });
+
+ const QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ ps->setVertexInputLayout(inputLayout);
+ ps->setShaderResourceBindings(srb);
+ ps->setRenderPassDescriptor(rp);
+ ps->build();
+
+ int frame = 0;
+ for (; frame < 20; ++frame) {
+ QRhiCommandBuffer *cb;
+ if (r->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess)
+ break;
+
+ qDebug("Generating offscreen frame %d", frame);
+ QRhiResourceUpdateBatch *u = r->nextResourceUpdateBatch();
+ if (frame == 0)
+ u->uploadStaticBuffer(vbuf, vertexData);
+
+ static float rotation = 0.0f;
+ QMatrix4x4 mvp = proj;
+ mvp.rotate(rotation, 0, 1, 0);
+ u->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
+ rotation += 5.0f;
+ static float opacity = 1.0f;
+ static int opacityDir= 1;
+ u->updateDynamicBuffer(ubuf, 64, 4, &opacity);
+ opacity += opacityDir * 0.005f;
+ if (opacity < 0.0f || opacity > 1.0f) {
+ opacityDir *= -1;
+ opacity = qBound(0.0f, opacity, 1.0f);
+ }
+
+ cb->beginPass(rt, QColor::fromRgbF(0.0f, 1.0f, 0.0f, 1.0f), { 1, 0 }, u);
+ cb->setGraphicsPipeline(ps);
+ cb->setViewport({ 0, 0, 1280, 720 });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+
+ u = r->nextResourceUpdateBatch();
+ QRhiReadbackDescription rb(tex);
+ QRhiReadbackResult rbResult;
+ rbResult.completed = [frame] { qDebug(" - readback %d completed", frame); };
+ u->readBackTexture(rb, &rbResult);
+
+ cb->endPass(u);
+
+ qDebug("Submit and wait");
+#ifdef TEST_FINISH
+ r->finish();
+#else
+ r->endOffscreenFrame();
+#endif
+ // The data should be ready either because endOffscreenFrame() waits
+ // for completion or because finish() did.
+ if (!rbResult.data.isEmpty()) {
+ const uchar *p = reinterpret_cast<const uchar *>(rbResult.data.constData());
+ QImage image(p, rbResult.pixelSize.width(), rbResult.pixelSize.height(), QImage::Format_RGBA8888);
+ QString fn = QString::asprintf("frame%d.png", frame);
+ fn = QFileInfo(fn).absoluteFilePath();
+ qDebug("Saving into %s", qPrintable(fn));
+ if (r->isYUpInFramebuffer())
+ image.mirrored().save(fn);
+ else
+ image.save(fn);
+ } else {
+ qWarning("Readback failed!");
+ }
+#ifdef TEST_FINISH
+ r->endOffscreenFrame();
+#endif
+ }
+
+ delete ps;
+ delete srb;
+ delete ubuf;
+ delete vbuf;
+
+ delete rt;
+ delete rp;
+ delete tex;
+
+ delete r;
+
+ qDebug("\nRendered and read back %d frames using %s", frame, qPrintable(graphicsApiName()));
+
+ return 0;
+}
diff --git a/tests/manual/rhi/offscreen/offscreen.pro b/tests/manual/rhi/offscreen/offscreen.pro
new file mode 100644
index 0000000000..ae040a4b6c
--- /dev/null
+++ b/tests/manual/rhi/offscreen/offscreen.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+CONFIG += console
+
+QT += gui-private
+
+SOURCES = \
+ offscreen.cpp
+
+RESOURCES = offscreen.qrc
diff --git a/tests/manual/rhi/offscreen/offscreen.qrc b/tests/manual/rhi/offscreen/offscreen.qrc
new file mode 100644
index 0000000000..8cec4fa9ec
--- /dev/null
+++ b/tests/manual/rhi/offscreen/offscreen.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/qrhiprof/qrhiprof.cpp b/tests/manual/rhi/qrhiprof/qrhiprof.cpp
new file mode 100644
index 0000000000..7e3027a951
--- /dev/null
+++ b/tests/manual/rhi/qrhiprof/qrhiprof.cpp
@@ -0,0 +1,671 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Simple QRhiProfiler receiver app. Start it and then in a QRhi-based
+// application connect with a QTcpSocket to 127.0.0.1:30667 and set that as the
+// QRhiProfiler's device.
+
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QApplication>
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QTextEdit>
+#include <QLabel>
+#include <QTime>
+#include <QtGui/private/qrhiprofiler_p.h>
+
+const int MIN_KNOWN_OP = 1;
+const int MAX_KNOWN_OP = 18;
+
+class Parser : public QObject
+{
+ Q_OBJECT
+
+public:
+ void feed(const QByteArray &line);
+
+ struct Event {
+ QRhiProfiler::StreamOp op;
+ qint64 timestamp;
+ quint64 resource;
+ QByteArray resourceName;
+
+ struct Param {
+ enum ValueType {
+ Int64,
+ Float
+ };
+ QByteArray key;
+ ValueType valueType;
+ union {
+ qint64 intValue;
+ float floatValue;
+ };
+ };
+
+ QVector<Param> params;
+
+ const Param *param(const char *key) const {
+ auto it = std::find_if(params.cbegin(), params.cend(), [key](const Param &p) {
+ return !strcmp(p.key.constData(), key);
+ });
+ return it == params.cend() ? nullptr : &*it;
+ }
+ };
+
+signals:
+ void eventReceived(const Event &e);
+};
+
+void Parser::feed(const QByteArray &line)
+{
+ const QList<QByteArray> elems = line.split(',');
+ if (elems.count() < 4) {
+ qWarning("Malformed line '%s'", line.constData());
+ return;
+ }
+ bool ok = false;
+ const int op = elems[0].toInt(&ok);
+ if (!ok) {
+ qWarning("Invalid op %s", elems[0].constData());
+ return;
+ }
+ if (op < MIN_KNOWN_OP || op > MAX_KNOWN_OP) {
+ qWarning("Unknown op %d", op);
+ return;
+ }
+
+ Event e;
+ e.op = QRhiProfiler::StreamOp(op);
+ e.timestamp = elems[1].toLongLong();
+ e.resource = elems[2].toULongLong();
+ e.resourceName = elems[3];
+
+ const int elemCount = elems.count();
+ for (int i = 4; i < elemCount; i += 2) {
+ if (i + 1 < elemCount && !elems[i].isEmpty() && !elems[i + 1].isEmpty()) {
+ QByteArray key = elems[i];
+ if (key.startsWith('F')) {
+ key = key.mid(1);
+ bool ok = false;
+ const float value = elems[i + 1].toFloat(&ok);
+ if (!ok) {
+ qWarning("Failed to parse float %s in line '%s'", elems[i + 1].constData(), line.constData());
+ continue;
+ }
+ Event::Param param;
+ param.key = key;
+ param.valueType = Event::Param::Float;
+ param.floatValue = value;
+ e.params.append(param);
+ } else {
+ const qint64 value = elems[i + 1].toLongLong();
+ Event::Param param;
+ param.key = key;
+ param.valueType = Event::Param::Int64;
+ param.intValue = value;
+ e.params.append(param);
+ }
+ }
+ }
+
+ emit eventReceived(e);
+}
+
+class Tracker : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void handleEvent(const Parser::Event &e);
+
+signals:
+ void buffersTouched();
+ void texturesTouched();
+ void swapchainsTouched();
+ void frameTimeTouched();
+ void gpuFrameTimeTouched();
+ void gpuMemAllocStatsTouched();
+
+public:
+ Tracker() {
+ reset();
+ }
+
+ static const int MAX_STAGING_SLOTS = 3;
+
+ struct Buffer {
+ Buffer()
+ {
+ memset(stagingExtraSize, 0, sizeof(stagingExtraSize));
+ }
+ quint64 lastTimestamp;
+ QByteArray resourceName;
+ qint64 effectiveSize = 0;
+ int backingGpuBufCount = 1;
+ qint64 stagingExtraSize[MAX_STAGING_SLOTS];
+ };
+ QHash<qint64, Buffer> m_buffers;
+ qint64 m_totalBufferApproxByteSize;
+ qint64 m_peakBufferApproxByteSize;
+ qint64 m_totalStagingBufferApproxByteSize;
+ qint64 m_peakStagingBufferApproxByteSize;
+
+ struct Texture {
+ Texture()
+ {
+ memset(stagingExtraSize, 0, sizeof(stagingExtraSize));
+ }
+ quint64 lastTimestamp;
+ QByteArray resourceName;
+ qint64 approxByteSize = 0;
+ bool ownsNativeResource = true;
+ qint64 stagingExtraSize[MAX_STAGING_SLOTS];
+ };
+ QHash<qint64, Texture> m_textures;
+ qint64 m_totalTextureApproxByteSize;
+ qint64 m_peakTextureApproxByteSize;
+ qint64 m_totalTextureStagingBufferApproxByteSize;
+ qint64 m_peakTextureStagingBufferApproxByteSize;
+
+ struct SwapChain {
+ quint64 lastTimestamp;
+ QByteArray resourceName;
+ qint64 approxByteSize = 0;
+ };
+ QHash<qint64, SwapChain> m_swapchains;
+ qint64 m_totalSwapChainApproxByteSize;
+ qint64 m_peakSwapChainApproxByteSize;
+
+ struct FrameTime {
+ qint64 framesSinceResize = 0;
+ int minDelta = 0;
+ int maxDelta = 0;
+ float avgDelta = 0;
+ };
+ FrameTime m_lastFrameTime;
+
+ struct GpuFrameTime {
+ float minTime = 0;
+ float maxTime = 0;
+ float avgTime = 0;
+ };
+ GpuFrameTime m_lastGpuFrameTime;
+
+ struct GpuMemAllocStats {
+ qint64 realAllocCount;
+ qint64 subAllocCount;
+ qint64 totalSize;
+ qint64 unusedSize;
+ };
+ GpuMemAllocStats m_lastGpuMemAllocStats;
+
+ void reset() {
+ m_buffers.clear();
+ m_textures.clear();
+ m_totalBufferApproxByteSize = 0;
+ m_peakBufferApproxByteSize = 0;
+ m_totalStagingBufferApproxByteSize = 0;
+ m_peakStagingBufferApproxByteSize = 0;
+ m_totalTextureApproxByteSize = 0;
+ m_peakTextureApproxByteSize = 0;
+ m_totalTextureStagingBufferApproxByteSize = 0;
+ m_peakTextureStagingBufferApproxByteSize = 0;
+ m_totalSwapChainApproxByteSize = 0;
+ m_peakSwapChainApproxByteSize = 0;
+ m_lastFrameTime = FrameTime();
+ m_lastGpuFrameTime = GpuFrameTime();
+ m_lastGpuMemAllocStats = GpuMemAllocStats();
+ emit buffersTouched();
+ emit texturesTouched();
+ emit swapchainsTouched();
+ emit frameTimeTouched();
+ emit gpuFrameTimeTouched();
+ emit gpuMemAllocStatsTouched();
+ }
+};
+
+Q_DECLARE_TYPEINFO(Tracker::Buffer, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracker::Texture, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracker::FrameTime, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracker::GpuFrameTime, Q_MOVABLE_TYPE);
+
+void Tracker::handleEvent(const Parser::Event &e)
+{
+ switch (e.op) {
+ case QRhiProfiler::NewBuffer:
+ {
+ Buffer b;
+ b.lastTimestamp = e.timestamp;
+ b.resourceName = e.resourceName;
+ // type,0,usage,1,logical_size,84,effective_size,84,backing_gpu_buf_count,1,backing_cpu_buf_count,0
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("effective_size"))
+ b.effectiveSize = p.intValue;
+ else if (p.key == QByteArrayLiteral("backing_gpu_buf_count"))
+ b.backingGpuBufCount = p.intValue;
+ }
+ m_totalBufferApproxByteSize += b.effectiveSize * b.backingGpuBufCount;
+ m_peakBufferApproxByteSize = qMax(m_peakBufferApproxByteSize, m_totalBufferApproxByteSize);
+ m_buffers.insert(e.resource, b);
+ emit buffersTouched();
+ }
+ break;
+ case QRhiProfiler::ReleaseBuffer:
+ {
+ auto it = m_buffers.find(e.resource);
+ if (it != m_buffers.end()) {
+ m_totalBufferApproxByteSize -= it->effectiveSize * it->backingGpuBufCount;
+ m_buffers.erase(it);
+ emit buffersTouched();
+ }
+ }
+ break;
+
+ case QRhiProfiler::NewBufferStagingArea:
+ {
+ qint64 slot = -1;
+ qint64 size = 0;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ else if (p.key == QByteArrayLiteral("size"))
+ size = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_buffers.find(e.resource);
+ if (it != m_buffers.end()) {
+ it->stagingExtraSize[slot] = size;
+ m_totalStagingBufferApproxByteSize += size;
+ m_peakStagingBufferApproxByteSize = qMax(m_peakStagingBufferApproxByteSize, m_totalStagingBufferApproxByteSize);
+ emit buffersTouched();
+ }
+ }
+ }
+ break;
+ case QRhiProfiler::ReleaseBufferStagingArea:
+ {
+ qint64 slot = -1;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_buffers.find(e.resource);
+ if (it != m_buffers.end()) {
+ m_totalStagingBufferApproxByteSize -= it->stagingExtraSize[slot];
+ it->stagingExtraSize[slot] = 0;
+ emit buffersTouched();
+ }
+ }
+ }
+ break;
+
+ case QRhiProfiler::NewTexture:
+ {
+ Texture t;
+ t.lastTimestamp = e.timestamp;
+ t.resourceName = e.resourceName;
+ // width,256,height,256,format,1,owns_native_resource,1,mip_count,9,layer_count,1,effective_sample_count,1,approx_byte_size,349524
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("approx_byte_size"))
+ t.approxByteSize = p.intValue;
+ else if (p.key == QByteArrayLiteral("owns_native_resource"))
+ t.ownsNativeResource = p.intValue;
+ }
+ if (t.ownsNativeResource) {
+ m_totalTextureApproxByteSize += t.approxByteSize;
+ m_peakTextureApproxByteSize = qMax(m_peakTextureApproxByteSize, m_totalTextureApproxByteSize);
+ }
+ m_textures.insert(e.resource, t);
+ emit texturesTouched();
+ }
+ break;
+ case QRhiProfiler::ReleaseTexture:
+ {
+ auto it = m_textures.find(e.resource);
+ if (it != m_textures.end()) {
+ if (it->ownsNativeResource)
+ m_totalTextureApproxByteSize -= it->approxByteSize;
+ m_textures.erase(it);
+ emit texturesTouched();
+ }
+ }
+ break;
+
+ case QRhiProfiler::NewTextureStagingArea:
+ {
+ qint64 slot = -1;
+ qint64 size = 0;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ else if (p.key == QByteArrayLiteral("size"))
+ size = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_textures.find(e.resource);
+ if (it != m_textures.end()) {
+ it->stagingExtraSize[slot] = size;
+ m_totalTextureStagingBufferApproxByteSize += size;
+ m_peakTextureStagingBufferApproxByteSize = qMax(m_peakTextureStagingBufferApproxByteSize, m_totalTextureStagingBufferApproxByteSize);
+ emit texturesTouched();
+ }
+ }
+ }
+ break;
+ case QRhiProfiler::ReleaseTextureStagingArea:
+ {
+ qint64 slot = -1;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_textures.find(e.resource);
+ if (it != m_textures.end()) {
+ m_totalTextureStagingBufferApproxByteSize -= it->stagingExtraSize[slot];
+ it->stagingExtraSize[slot] = 0;
+ emit texturesTouched();
+ }
+ }
+ }
+ break;
+
+ case QRhiProfiler::ResizeSwapChain:
+ {
+ auto it = m_swapchains.find(e.resource);
+ if (it != m_swapchains.end())
+ m_totalSwapChainApproxByteSize -= it->approxByteSize;
+
+ SwapChain s;
+ s.lastTimestamp = e.timestamp;
+ s.resourceName = e.resourceName;
+ // width,1280,height,720,buffer_count,2,msaa_buffer_count,0,effective_sample_count,1,approx_total_byte_size,7372800
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("approx_total_byte_size"))
+ s.approxByteSize = p.intValue;
+ }
+ m_totalSwapChainApproxByteSize += s.approxByteSize;
+ m_peakSwapChainApproxByteSize = qMax(m_peakSwapChainApproxByteSize, m_totalSwapChainApproxByteSize);
+ m_swapchains.insert(e.resource, s);
+ emit swapchainsTouched();
+ }
+ break;
+ case QRhiProfiler::ReleaseSwapChain:
+ {
+ auto it = m_swapchains.find(e.resource);
+ if (it != m_swapchains.end()) {
+ m_totalSwapChainApproxByteSize -= it->approxByteSize;
+ m_swapchains.erase(it);
+ emit swapchainsTouched();
+ }
+ }
+ break;
+
+ case QRhiProfiler::GpuFrameTime:
+ {
+ // Fmin_ms_gpu_frame_time,0.15488,Fmax_ms_gpu_frame_time,0.494592,Favg_ms_gpu_frame_time,0.33462
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("min_ms_gpu_frame_time"))
+ m_lastGpuFrameTime.minTime = p.floatValue;
+ else if (p.key == QByteArrayLiteral("max_ms_gpu_frame_time"))
+ m_lastGpuFrameTime.maxTime = p.floatValue;
+ else if (p.key == QByteArrayLiteral("avg_ms_gpu_frame_time"))
+ m_lastGpuFrameTime.avgTime = p.floatValue;
+ }
+ emit gpuFrameTimeTouched();
+ }
+ break;
+ case QRhiProfiler::FrameToFrameTime:
+ {
+ // frames_since_resize,121,min_ms_frame_delta,9,max_ms_frame_delta,33,Favg_ms_frame_delta,16.1167
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("frames_since_resize"))
+ m_lastFrameTime.framesSinceResize = p.intValue;
+ else if (p.key == QByteArrayLiteral("min_ms_frame_delta"))
+ m_lastFrameTime.minDelta = p.intValue;
+ else if (p.key == QByteArrayLiteral("max_ms_frame_delta"))
+ m_lastFrameTime.maxDelta = p.intValue;
+ else if (p.key == QByteArrayLiteral("avg_ms_frame_delta"))
+ m_lastFrameTime.avgDelta = p.floatValue;
+ }
+ emit frameTimeTouched();
+ }
+ break;
+
+ case QRhiProfiler::GpuMemAllocStats:
+ {
+ // real_alloc_count,2,sub_alloc_count,154,total_size,10752,unused_size,50320896
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("real_alloc_count"))
+ m_lastGpuMemAllocStats.realAllocCount = p.intValue;
+ else if (p.key == QByteArrayLiteral("sub_alloc_count"))
+ m_lastGpuMemAllocStats.subAllocCount = p.intValue;
+ else if (p.key == QByteArrayLiteral("total_size"))
+ m_lastGpuMemAllocStats.totalSize = p.intValue;
+ else if (p.key == QByteArrayLiteral("unused_size"))
+ m_lastGpuMemAllocStats.unusedSize = p.intValue;
+ }
+ emit gpuMemAllocStatsTouched();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+class Server : public QTcpServer
+{
+ Q_OBJECT
+
+protected:
+ void incomingConnection(qintptr socketDescriptor) override;
+
+signals:
+ void clientConnected();
+ void clientDisconnected();
+ void receiveStarted();
+ void lineReceived(const QByteArray &line);
+
+private:
+ bool m_valid = false;
+ QTcpSocket m_socket;
+ QByteArray m_buf;
+};
+
+void Server::incomingConnection(qintptr socketDescriptor)
+{
+ if (m_valid)
+ return;
+
+ m_socket.setSocketDescriptor(socketDescriptor);
+ m_valid = true;
+ emit clientConnected();
+ connect(&m_socket, &QAbstractSocket::readyRead, this, [this] {
+ bool receiveStartedSent = false;
+ m_buf += m_socket.readAll();
+ while (m_buf.contains('\n')) {
+ const int lfpos = m_buf.indexOf('\n');
+ const QByteArray line = m_buf.left(lfpos).trimmed();
+ m_buf = m_buf.mid(lfpos + 1);
+ if (!receiveStartedSent) {
+ receiveStartedSent = true;
+ emit receiveStarted();
+ }
+ emit lineReceived(line);
+ }
+ });
+ connect(&m_socket, &QAbstractSocket::disconnected, this, [this] {
+ if (m_valid) {
+ m_valid = false;
+ emit clientDisconnected();
+ }
+ });
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ Tracker tracker;
+ Parser parser;
+ QObject::connect(&parser, &Parser::eventReceived, &tracker, &Tracker::handleEvent);
+
+ Server server;
+ if (!server.listen(QHostAddress::Any, 30667))
+ qFatal("Failed to start server: %s", qPrintable(server.errorString()));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+
+ QLabel *infoLabel = new QLabel(QLatin1String("<i>Launch a Qt Quick application with QSG_RHI_PROFILE=1 and QSG_RHI_PROFILE_HOST set to the IP address.<br>"
+ "(resource memory usage reporting works best with the Vulkan backend)</i>"));
+ layout->addWidget(infoLabel);
+
+ QGroupBox *groupBox = new QGroupBox(QLatin1String("RHI statistics"));
+ QVBoxLayout *groupLayout = new QVBoxLayout;
+
+ QLabel *buffersLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::buffersTouched, buffersLabel, [buffersLabel, &tracker] {
+ const QString msg = QString::asprintf("%d buffers with ca. %lld bytes of current memory (sub)allocations (peak %lld) + %lld bytes of known staging buffers (peak %lld)",
+ tracker.m_buffers.count(),
+ tracker.m_totalBufferApproxByteSize, tracker.m_peakBufferApproxByteSize,
+ tracker.m_totalStagingBufferApproxByteSize, tracker.m_peakStagingBufferApproxByteSize);
+ buffersLabel->setText(msg);
+ });
+ groupLayout->addWidget(buffersLabel);
+
+ QLabel *texturesLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::texturesTouched, texturesLabel, [texturesLabel, &tracker] {
+ const QString msg = QString::asprintf("%d textures with ca. %lld bytes of current memory (sub)allocations (peak %lld) + %lld bytes of known staging buffers (peak %lld)",
+ tracker.m_textures.count(),
+ tracker.m_totalTextureApproxByteSize, tracker.m_peakTextureApproxByteSize,
+ tracker.m_totalTextureStagingBufferApproxByteSize, tracker.m_peakTextureStagingBufferApproxByteSize);
+ texturesLabel->setText(msg);
+ });
+ groupLayout->addWidget(texturesLabel);
+
+ QLabel *swapchainsLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::swapchainsTouched, swapchainsLabel, [swapchainsLabel, &tracker] {
+ const QString msg = QString::asprintf("Estimated total swapchain color buffer size is %lld bytes (peak %lld)",
+ tracker.m_totalSwapChainApproxByteSize, tracker.m_peakSwapChainApproxByteSize);
+ swapchainsLabel->setText(msg);
+ });
+ groupLayout->addWidget(swapchainsLabel);
+
+ QLabel *frameTimeLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::frameTimeTouched, frameTimeLabel, [frameTimeLabel, &tracker] {
+ const QString msg = QString::asprintf("Frames since resize %lld Frame delta min %d ms max %d ms avg %f ms",
+ tracker.m_lastFrameTime.framesSinceResize,
+ tracker.m_lastFrameTime.minDelta,
+ tracker.m_lastFrameTime.maxDelta,
+ tracker.m_lastFrameTime.avgDelta);
+ frameTimeLabel->setText(msg);
+ });
+ groupLayout->addWidget(frameTimeLabel);
+
+ QLabel *gpuFrameTimeLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::gpuFrameTimeTouched, gpuFrameTimeLabel, [gpuFrameTimeLabel, &tracker] {
+ const QString msg = QString::asprintf("GPU frame time min %f ms max %f ms avg %f ms",
+ tracker.m_lastGpuFrameTime.minTime,
+ tracker.m_lastGpuFrameTime.maxTime,
+ tracker.m_lastGpuFrameTime.avgTime);
+ gpuFrameTimeLabel->setText(msg);
+ });
+ groupLayout->addWidget(gpuFrameTimeLabel);
+
+ QLabel *gpuMemAllocStatsLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::gpuMemAllocStatsTouched, gpuMemAllocStatsLabel, [gpuMemAllocStatsLabel, &tracker] {
+ const QString msg = QString::asprintf("GPU memory allocator status: %lld real allocations %lld sub-allocations %lld total bytes %lld unused bytes",
+ tracker.m_lastGpuMemAllocStats.realAllocCount,
+ tracker.m_lastGpuMemAllocStats.subAllocCount,
+ tracker.m_lastGpuMemAllocStats.totalSize,
+ tracker.m_lastGpuMemAllocStats.unusedSize);
+ gpuMemAllocStatsLabel->setText(msg);
+ });
+ groupLayout->addWidget(gpuMemAllocStatsLabel);
+
+ groupBox->setLayout(groupLayout);
+ layout->addWidget(groupBox);
+
+ QTextEdit *rawLog = new QTextEdit;
+ rawLog->setReadOnly(true);
+ layout->addWidget(rawLog);
+
+ QObject::connect(&server, &Server::clientConnected, rawLog, [rawLog] {
+ rawLog->append(QLatin1String("\nCONNECTED\n"));
+ });
+ QObject::connect(&server, &Server::clientDisconnected, rawLog, [rawLog, &tracker] {
+ rawLog->append(QLatin1String("\nDISCONNECTED\n"));
+ tracker.reset();
+ });
+ QObject::connect(&server, &Server::receiveStarted, rawLog, [rawLog] {
+ rawLog->setFontItalic(true);
+ rawLog->append(QLatin1String("[") + QTime::currentTime().toString() + QLatin1String("]"));
+ rawLog->setFontItalic(false);
+ });
+
+ QObject::connect(&server, &Server::lineReceived, rawLog, [rawLog, &parser](const QByteArray &line) {
+ rawLog->append(QString::fromUtf8(line));
+ parser.feed(line);
+ });
+
+ QWidget w;
+ w.resize(800, 600);
+ w.setLayout(layout);
+ w.show();
+
+ return app.exec();
+}
+
+#include "qrhiprof.moc"
diff --git a/tests/manual/rhi/qrhiprof/qrhiprof.pro b/tests/manual/rhi/qrhiprof/qrhiprof.pro
new file mode 100644
index 0000000000..2939dd7ce2
--- /dev/null
+++ b/tests/manual/rhi/qrhiprof/qrhiprof.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+QT += network widgets gui-private
+
+SOURCES = \
+ qrhiprof.cpp
diff --git a/tests/manual/rhi/rhi.pro b/tests/manual/rhi/rhi.pro
new file mode 100644
index 0000000000..d3661ff169
--- /dev/null
+++ b/tests/manual/rhi/rhi.pro
@@ -0,0 +1,25 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ hellominimalcrossgfxtriangle \
+ compressedtexture_bc1 \
+ compressedtexture_bc1_subupload \
+ texuploads \
+ msaatexture \
+ msaarenderbuffer \
+ cubemap \
+ multiwindow \
+ multiwindow_threaded \
+ triquadcube \
+ offscreen \
+ floattexture \
+ mrt \
+ shadowmap \
+ computebuffer \
+ computeimage \
+ instancing
+
+qtConfig(widgets) {
+ SUBDIRS += \
+ qrhiprof
+}
diff --git a/tests/manual/rhi/shadowmap/buildshaders.bat b/tests/manual/rhi/shadowmap/buildshaders.bat
new file mode 100644
index 0000000000..7b84cc0952
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/buildshaders.bat
@@ -0,0 +1,4 @@
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c shadowmap.vert -o shadowmap.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c shadowmap.frag -o shadowmap.frag.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c main.vert -o main.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c main.frag -o main.frag.qsb
diff --git a/tests/manual/rhi/shadowmap/buildshaders.sh b/tests/manual/rhi/shadowmap/buildshaders.sh
new file mode 100755
index 0000000000..c4d17841e6
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/buildshaders.sh
@@ -0,0 +1,4 @@
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 shadowmap.vert -o shadowmap.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 shadowmap.frag -o shadowmap.frag.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 main.vert -o main.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 main.frag -o main.frag.qsb
diff --git a/tests/manual/rhi/shadowmap/main.frag b/tests/manual/rhi/shadowmap/main.frag
new file mode 100644
index 0000000000..8fefe2bb42
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.frag
@@ -0,0 +1,30 @@
+#version 440
+
+layout(location = 0) in vec4 vLCVertPos;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2DShadow shadowMap;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ mat4 lightMvp;
+ mat4 shadowBias;
+ int useShadow;
+} ubuf;
+
+void main()
+{
+ vec4 adjustedLcVertPos = vLCVertPos;
+ adjustedLcVertPos.z -= 0.0001; // bias to avoid acne
+
+ // no textureProj, that seems to end up not doing the perspective divide for z (?)
+ vec3 v = adjustedLcVertPos.xyz / adjustedLcVertPos.w;
+ float sc = texture(shadowMap, v); // sampler is comparison enabled so compares to z
+
+ float shadowFactor = 0.2;
+ if (sc > 0 || ubuf.useShadow == 0)
+ shadowFactor = 1.0;
+
+ fragColor = vec4(0.5, 0.3 + ubuf.useShadow * 0.2, 0.7, 1.0) * shadowFactor;
+}
diff --git a/tests/manual/rhi/shadowmap/main.frag.qsb b/tests/manual/rhi/shadowmap/main.frag.qsb
new file mode 100644
index 0000000000..3001908b85
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shadowmap/main.vert b/tests/manual/rhi/shadowmap/main.vert
new file mode 100644
index 0000000000..9d6cade634
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.vert
@@ -0,0 +1,20 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ mat4 lightMvp;
+ mat4 shadowBias;
+ int useShadow;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+layout(location = 0) out vec4 vLCVertPos;
+
+void main()
+{
+ vLCVertPos = ubuf.shadowBias * ubuf.lightMvp * position;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shadowmap/main.vert.qsb b/tests/manual/rhi/shadowmap/main.vert.qsb
new file mode 100644
index 0000000000..8b81a93c00
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shadowmap/shadowmap.cpp b/tests/manual/rhi/shadowmap/shadowmap.cpp
new file mode 100644
index 0000000000..9146be5cc9
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include "../shared/cube.h"
+
+// Depth texture / shadow sampler / shadow map example.
+// Not available on GLES 2.0.
+
+static float quadVertexData[] =
+{ // Y up, CCW, x-y-z
+ -0.5f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f,
+ 0.5f, 0.5f, 0.0f,
+};
+
+static quint16 quadIndexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiSampler *shadowSampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+ float cubeRot = 0;
+
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+ QRhiTexture *shadowMap = nullptr;
+ QRhiShaderResourceBindings *shadowSrb = nullptr;
+ QRhiGraphicsPipeline *shadowPs = nullptr;
+} d;
+
+const int UBLOCK_SIZE = 64 * 3 + 4;
+const int SHADOW_UBLOCK_SIZE = 64 * 1;
+const int UBUF_SLOTS = 4; // 2 objects * 2 passes with different cameras
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::D32F))
+ qFatal("Depth texture is not supported");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(quadVertexData) + sizeof(cube));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(quadIndexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(UBLOCK_SIZE);
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SLOTS * oneRoundedUniformBlockSize);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.shadowMap = m_r->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
+ d.releasePool << d.shadowMap;
+ d.shadowMap->build();
+
+ d.shadowSampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.shadowSampler;
+ d.shadowSampler->setTextureCompareOp(QRhiSampler::Less);
+ d.shadowSampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ const QRhiShaderResourceBinding::StageFlags stages = QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage;
+ d.srb->setBindings({ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, stages, d.ubuf, UBLOCK_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.shadowMap, d.shadowSampler) });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/main.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/main.frag.qsb")) }
+ });
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ // fits both the quad and cube vertex data
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(quadVertexData), quadVertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(quadVertexData), sizeof(cube), cube);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, quadIndexData);
+
+ QRhiTextureRenderTargetDescription rtDesc;
+ rtDesc.setDepthTexture(d.shadowMap);
+ d.rt = m_r->newTextureRenderTarget(rtDesc);
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+
+ d.shadowSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.shadowSrb;
+ d.shadowSrb->setBindings({ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, stages, d.ubuf, SHADOW_UBLOCK_SIZE) });
+ d.shadowSrb->build();
+
+ d.shadowPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.shadowPs;
+ d.shadowPs->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/shadowmap.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/shadowmap.frag.qsb")) }
+ });
+ d.shadowPs->setDepthTest(true);
+ d.shadowPs->setDepthWrite(true);
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 }
+ });
+ d.shadowPs->setVertexInputLayout(inputLayout);
+ d.shadowPs->setShaderResourceBindings(d.shadowSrb);
+ d.shadowPs->setRenderPassDescriptor(d.rtRp);
+ d.shadowPs->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+static void enqueueScene(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int oneRoundedUniformBlockSize, int firstUbufSlot)
+{
+ QRhiCommandBuffer::DynamicOffset ubufOffset(0, quint32(firstUbufSlot * oneRoundedUniformBlockSize));
+ // draw the ground (the quad)
+ cb->setShaderResources(srb, 1, &ubufOffset);
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+
+ // Draw the object (the cube). Both vertex and uniform data are in the same
+ // buffer, right after the quad's.
+ ubufOffset.second += oneRoundedUniformBlockSize;
+ cb->setShaderResources(srb, 1, &ubufOffset);
+ vbufBinding.second = sizeof(quadVertexData);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(36);
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(UBLOCK_SIZE);
+
+ QMatrix4x4 shadowBias;
+ // fill it in column-major order to keep our sanity (ctor would take row-major)
+ float *sbp = shadowBias.data();
+ if (m_r->isClipDepthZeroToOne()) {
+ // convert x, y [-1, 1] -> [0, 1]
+ *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = m_r->isYUpInNDC() ? -0.5f : 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 1.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.5f; *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 1.0f;
+ } else {
+ // convert x, y, z [-1, 1] -> [0, 1]
+ *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 0.5f; *sbp++ = 0.0f;
+ *sbp++ = 0.5f; *sbp++ = 0.5f; *sbp++ = 0.5f; *sbp++ = 1.0f;
+ }
+
+ const QVector3D lightPos(5, 10, 10);
+ QMatrix4x4 lightViewProj = m_r->clipSpaceCorrMatrix();
+ lightViewProj.perspective(45.0f, 1, 0.1f, 100.0f);
+ lightViewProj.lookAt(lightPos, QVector3D(0, 0, 0), QVector3D(0, 1, 0));
+
+ // uniform data for the ground
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+
+ QMatrix4x4 m;
+ m.scale(4.0f);
+ m.rotate(-60, 1, 0, 0);
+
+ // for the main pass
+ const QMatrix4x4 mvp = m_proj * m; // m_proj is in fact projection * view
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ const QMatrix4x4 shadowMvp = lightViewProj * m;
+ u->updateDynamicBuffer(d.ubuf, 64, 64, shadowMvp.constData());
+ u->updateDynamicBuffer(d.ubuf, 128, 64, shadowBias.constData());
+ qint32 useShadows = 1;
+ u->updateDynamicBuffer(d.ubuf, 192, 4, &useShadows);
+
+ // for the shadow pass
+ u->updateDynamicBuffer(d.ubuf, 2 * oneRoundedUniformBlockSize, 64, shadowMvp.constData());
+ }
+
+ // uniform data for the rotating cube
+ QMatrix4x4 m;
+ m.translate(0, 0.5f, 2);
+ m.scale(0.2f);
+ m.rotate(d.cubeRot, 0, 1, 0);
+ m.rotate(45, 1, 0, 0);
+ d.cubeRot += 1;
+
+ // for the main pass
+ const QMatrix4x4 mvp = m_proj * m;
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize, 64, mvp.constData());
+ const QMatrix4x4 shadowMvp = lightViewProj * m;
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize + 64, 64, shadowMvp.constData());
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize + 128, 64, shadowBias.constData());
+ qint32 useShadows = 0;
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize + 192, 4, &useShadows);
+
+ // for the shadow pass
+ u->updateDynamicBuffer(d.ubuf, 3 * oneRoundedUniformBlockSize, 64, shadowMvp.constData());
+
+ cb->resourceUpdate(u);
+
+ // shadow pass
+ const QSize shadowMapSize = d.shadowMap->pixelSize();
+ cb->beginPass(d.rt, QColor(), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.shadowPs);
+ cb->setViewport({ 0, 0, float(shadowMapSize.width()), float(shadowMapSize.height()) });
+ enqueueScene(cb, d.shadowSrb, oneRoundedUniformBlockSize, 2);
+ cb->endPass();
+
+ // main pass
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ enqueueScene(cb, d.srb, oneRoundedUniformBlockSize, 0);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/shadowmap/shadowmap.frag b/tests/manual/rhi/shadowmap/shadowmap.frag
new file mode 100644
index 0000000000..fa868f31a2
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.frag
@@ -0,0 +1,5 @@
+#version 440
+
+void main()
+{
+}
diff --git a/tests/manual/rhi/shadowmap/shadowmap.frag.qsb b/tests/manual/rhi/shadowmap/shadowmap.frag.qsb
new file mode 100644
index 0000000000..3cad114cf4
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shadowmap/shadowmap.pro b/tests/manual/rhi/shadowmap/shadowmap.pro
new file mode 100644
index 0000000000..baf740927c
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ shadowmap.cpp
+
+RESOURCES = shadowmap.qrc
diff --git a/tests/manual/rhi/shadowmap/shadowmap.qrc b/tests/manual/rhi/shadowmap/shadowmap.qrc
new file mode 100644
index 0000000000..8256d5ca25
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>shadowmap.vert.qsb</file>
+ <file>shadowmap.frag.qsb</file>
+ <file>main.vert.qsb</file>
+ <file>main.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/shadowmap/shadowmap.vert b/tests/manual/rhi/shadowmap/shadowmap.vert
new file mode 100644
index 0000000000..72b5370aec
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.vert
@@ -0,0 +1,14 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shadowmap/shadowmap.vert.qsb b/tests/manual/rhi/shadowmap/shadowmap.vert.qsb
new file mode 100644
index 0000000000..37a5e6ecbf
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdr b/tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdr
new file mode 100644
index 0000000000..abdebdb74b
--- /dev/null
+++ b/tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdr
Binary files differ
diff --git a/tests/manual/rhi/shared/buildshaders.bat b/tests/manual/rhi/shared/buildshaders.bat
new file mode 100644
index 0000000000..dde5f7b3d2
--- /dev/null
+++ b/tests/manual/rhi/shared/buildshaders.bat
@@ -0,0 +1,5 @@
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c color.vert -o color.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c color.frag -o color.frag.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c texture.vert -o texture.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c texture.frag -o texture.frag.qsb
+qsb --hlsl 50 --msl 12 -c texture_ms4.frag -o texture_ms4.frag.qsb
diff --git a/tests/manual/rhi/shared/bwqt224_64.png b/tests/manual/rhi/shared/bwqt224_64.png
new file mode 100644
index 0000000000..8020cbb2a8
--- /dev/null
+++ b/tests/manual/rhi/shared/bwqt224_64.png
Binary files differ
diff --git a/tests/manual/rhi/shared/bwqt224_64_nomips.dds b/tests/manual/rhi/shared/bwqt224_64_nomips.dds
new file mode 100644
index 0000000000..393cfec9db
--- /dev/null
+++ b/tests/manual/rhi/shared/bwqt224_64_nomips.dds
Binary files differ
diff --git a/tests/manual/rhi/shared/color.frag b/tests/manual/rhi/shared/color.frag
new file mode 100644
index 0000000000..bb94a5a605
--- /dev/null
+++ b/tests/manual/rhi/shared/color.frag
@@ -0,0 +1,15 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+void main()
+{
+ fragColor = vec4(v_color * ubuf.opacity, ubuf.opacity);
+}
diff --git a/tests/manual/rhi/shared/color.frag.qsb b/tests/manual/rhi/shared/color.frag.qsb
new file mode 100644
index 0000000000..3a965682eb
--- /dev/null
+++ b/tests/manual/rhi/shared/color.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/color.vert b/tests/manual/rhi/shared/color.vert
new file mode 100644
index 0000000000..43af543f44
--- /dev/null
+++ b/tests/manual/rhi/shared/color.vert
@@ -0,0 +1,19 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shared/color.vert.qsb b/tests/manual/rhi/shared/color.vert.qsb
new file mode 100644
index 0000000000..e34eae79a0
--- /dev/null
+++ b/tests/manual/rhi/shared/color.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/cube.h b/tests/manual/rhi/shared/cube.h
new file mode 100644
index 0000000000..252e80c56c
--- /dev/null
+++ b/tests/manual/rhi/shared/cube.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Chia-I Wu <olv@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Ian Elliott <ian@LunarG.com>
+ * Author: Ian Elliott <ianelliott@google.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Gwan-gyeong Mun <elongbug@gmail.com>
+ * Author: Tony Barbour <tony@LunarG.com>
+ * Author: Bill Hollings <bill.hollings@brenwill.com>
+ */
+
+#ifndef CUBE_H
+#define CUBE_H
+
+// clang-format off
+static const float cube[] = {
+ -1.0f,-1.0f,-1.0f, // -X side
+ -1.0f,-1.0f, 1.0f,
+ -1.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f,-1.0f,
+ -1.0f,-1.0f,-1.0f,
+
+ -1.0f,-1.0f,-1.0f, // -Z side
+ 1.0f, 1.0f,-1.0f,
+ 1.0f,-1.0f,-1.0f,
+ -1.0f,-1.0f,-1.0f,
+ -1.0f, 1.0f,-1.0f,
+ 1.0f, 1.0f,-1.0f,
+
+ -1.0f,-1.0f,-1.0f, // -Y side
+ 1.0f,-1.0f,-1.0f,
+ 1.0f,-1.0f, 1.0f,
+ -1.0f,-1.0f,-1.0f,
+ 1.0f,-1.0f, 1.0f,
+ -1.0f,-1.0f, 1.0f,
+
+ -1.0f, 1.0f,-1.0f, // +Y side
+ -1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f,-1.0f,
+ 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f,-1.0f,
+
+ 1.0f, 1.0f,-1.0f, // +X side
+ 1.0f, 1.0f, 1.0f,
+ 1.0f,-1.0f, 1.0f,
+ 1.0f,-1.0f, 1.0f,
+ 1.0f,-1.0f,-1.0f,
+ 1.0f, 1.0f,-1.0f,
+
+ -1.0f, 1.0f, 1.0f, // +Z side
+ -1.0f,-1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ -1.0f,-1.0f, 1.0f,
+ 1.0f,-1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+
+ 0.0f, 1.0f, // -X side
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+
+ 1.0f, 1.0f, // -Z side
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+
+ 1.0f, 0.0f, // -Y side
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+
+ 1.0f, 0.0f, // +Y side
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+
+ 1.0f, 0.0f, // +X side
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+
+ 0.0f, 0.0f, // +Z side
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+};
+// clang-format on
+
+#endif
diff --git a/tests/manual/rhi/shared/dds_bc1.h b/tests/manual/rhi/shared/dds_bc1.h
new file mode 100644
index 0000000000..3c98a94cfc
--- /dev/null
+++ b/tests/manual/rhi/shared/dds_bc1.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+static const quint32 DDS_MAGIC = 0x20534444; // 'DDS '
+static const quint32 DDS_FOURCC = 4;
+
+#define FOURCC(c0, c1, c2, c3) ((c0) | ((c1) << 8) | ((c2) << 16) | ((c3 << 24)))
+
+struct DDS_PIXELFORMAT {
+ quint32 size;
+ quint32 flags;
+ quint32 fourCC;
+ quint32 rgbBitCount;
+ quint32 rBitMask;
+ quint32 gBitMask;
+ quint32 bBitMask;
+ quint32 aBitMask;
+};
+
+struct DDS_HEADER {
+ quint32 size;
+ quint32 flags;
+ quint32 height;
+ quint32 width;
+ quint32 pitch;
+ quint32 depth;
+ quint32 mipMapCount;
+ quint32 reserved1[11];
+ DDS_PIXELFORMAT pixelFormat;
+ quint32 caps;
+ quint32 caps2;
+ quint32 caps3;
+ quint32 caps4;
+ quint32 reserved2;
+};
+
+static quint32 bc1size(const QSize &size)
+{
+ static const quint32 blockSize = 8; // 8 bytes for BC1
+ const quint32 bytesPerLine = qMax<quint32>(1, (size.width() + 3) / 4) * blockSize;
+ const quint32 ySize = qMax<quint32>(1, (size.height() + 3) / 4);
+ return bytesPerLine * ySize;
+}
+
+static QByteArrayList loadBC1(const QString &filename, QSize *size)
+{
+ QFile f(filename);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(filename));
+ return QByteArrayList();
+ }
+
+ quint32 magic = 0;
+ f.read(reinterpret_cast<char *>(&magic), sizeof(magic));
+ if (magic != DDS_MAGIC) {
+ qWarning("%s is not a DDS file", qPrintable(filename));
+ return QByteArrayList();
+ }
+ DDS_HEADER header;
+ f.read(reinterpret_cast<char *>(&header), sizeof(header));
+ if (header.size != sizeof(DDS_HEADER)) {
+ qWarning("Invalid DDS header size");
+ return QByteArrayList();
+ }
+ if (header.pixelFormat.size != sizeof(DDS_PIXELFORMAT)) {
+ qWarning("Invalid DDS pixel format size");
+ return QByteArrayList();
+ }
+ if (!(header.pixelFormat.flags & DDS_FOURCC)) {
+ qWarning("Invalid DDS pixel format");
+ return QByteArrayList();
+ }
+ if (header.pixelFormat.fourCC != FOURCC('D', 'X', 'T', '1')) {
+ qWarning("Only DXT1 (BC1) is supported");
+ return QByteArrayList();
+ }
+
+ QByteArrayList data;
+ QSize sz(header.width, header.height);
+ for (quint32 level = 0; level < header.mipMapCount; ++level) {
+ data.append(f.read(bc1size(sz)));
+ sz.setWidth(qMax(1, sz.width() / 2));
+ sz.setHeight(qMax(1, sz.height() / 2));
+ }
+
+ if (size)
+ *size = QSize(header.width, header.height);
+
+ return data;
+}
diff --git a/tests/manual/rhi/shared/examplefw.h b/tests/manual/rhi/shared/examplefw.h
new file mode 100644
index 0000000000..4bd087473b
--- /dev/null
+++ b/tests/manual/rhi/shared/examplefw.h
@@ -0,0 +1,569 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Adapted from hellominimalcrossgfxtriangle with the frame rendering stripped out.
+// Include this file and implement Window::customInit, release and render.
+// Debug/validation layer is enabled for D3D and Vulkan.
+
+#include <QGuiApplication>
+#include <QCommandLineParser>
+#include <QWindow>
+#include <QPlatformSurfaceEvent>
+#include <QElapsedTimer>
+#include <QTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+#include <QtGui/private/qrhiprofiler_p.h>
+#include <QtGui/private/qrhinull_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+enum GraphicsApi
+{
+ Null,
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal
+};
+
+GraphicsApi graphicsApi;
+
+QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case Null:
+ return QLatin1String("Null (no output)");
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ default:
+ break;
+ }
+ return QString();
+}
+
+QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers;
+int sampleCount = 1;
+QRhiSwapChain::Flags scFlags = 0;
+QRhi::BeginFrameFlags beginFrameFlags = 0;
+QRhi::EndFrameFlags endFrameFlags = 0;
+int framesUntilTdr = -1;
+
+class Window : public QWindow
+{
+public:
+ Window();
+ ~Window();
+
+protected:
+ void init();
+ void releaseResources();
+ void resizeSwapChain();
+ void releaseSwapChain();
+ void render();
+
+ void customInit();
+ void customRelease();
+ void customRender();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+ bool m_running = false;
+ bool m_notExposed = false;
+ bool m_newlyExposed = false;
+
+ QRhi *m_r = nullptr;
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+
+ QMatrix4x4 m_proj;
+
+ QElapsedTimer m_timer;
+ int m_frameCount;
+
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *m_fallbackSurface = nullptr;
+#endif
+
+ friend int main(int, char**);
+};
+
+Window::Window()
+{
+ // Tell the platform plugin what we want.
+ switch (graphicsApi) {
+ case OpenGL:
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ setFormat(QRhiGles2InitParams::adjustedFormat());
+#endif
+ break;
+ case Vulkan:
+ setSurfaceType(VulkanSurface);
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+Window::~Window()
+{
+ releaseResources();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !m_running) {
+ m_running = true;
+ init();
+ resizeSwapChain();
+ }
+
+ const QSize surfaceSize = m_hasSwapChain ? m_sc->surfacePixelSize() : QSize();
+
+ // stop pushing frames when not exposed (or size is 0)
+ if ((!isExposed() || (m_hasSwapChain && surfaceSize.isEmpty())) && m_running)
+ m_notExposed = true;
+
+ // continue when exposed again and the surface has a valid size.
+ // note that the surface size can be (0, 0) even though size() reports a valid one...
+ if (isExposed() && m_running && m_notExposed && !surfaceSize.isEmpty()) {
+ m_notExposed = false;
+ m_newlyExposed = true;
+ }
+
+ // always render a frame on exposeEvent() (when exposed) in order to update
+ // immediately on window resize.
+ if (isExposed() && !surfaceSize.isEmpty())
+ render();
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void Window::init()
+{
+ if (graphicsApi == Null) {
+ QRhiNullInitParams params;
+ m_r = QRhi::create(QRhi::Null, &params, rhiFlags);
+ }
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ m_fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = m_fallbackSurface;
+ params.window = this;
+ m_r = QRhi::create(QRhi::OpenGLES2, &params, rhiFlags);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = vulkanInstance();
+ params.window = this;
+ m_r = QRhi::create(QRhi::Vulkan, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ if (framesUntilTdr > 0) {
+ params.framesUntilKillingDeviceViaTdr = framesUntilTdr;
+ params.repeatDeviceKill = true;
+ }
+ m_r = QRhi::create(QRhi::D3D11, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ m_r = QRhi::create(QRhi::Metal, &params, rhiFlags);
+ }
+#endif
+
+ if (!m_r)
+ qFatal("Failed to create RHI backend");
+
+ // now onto the backend-independent init
+
+ m_sc = m_r->newSwapChain();
+ // allow depth-stencil, although we do not actually enable depth test/write for the triangle
+ m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ sampleCount,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ m_sc->setWindow(this);
+ m_sc->setDepthStencil(m_ds);
+ m_sc->setSampleCount(sampleCount);
+ m_sc->setFlags(scFlags);
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ customInit();
+}
+
+void Window::releaseResources()
+{
+ customRelease();
+
+ delete m_rp;
+ m_rp = nullptr;
+
+ delete m_ds;
+ m_ds = nullptr;
+
+ delete m_sc;
+ m_sc = nullptr;
+
+ delete m_r;
+ m_r = nullptr;
+
+#ifndef QT_NO_OPENGL
+ delete m_fallbackSurface;
+ m_fallbackSurface = nullptr;
+#endif
+}
+
+void Window::resizeSwapChain()
+{
+ const QSize outputSize = m_sc->surfacePixelSize();
+
+ m_ds->setPixelSize(outputSize);
+ m_ds->build(); // == m_ds->release(); m_ds->build();
+
+ m_hasSwapChain = m_sc->buildOrResize();
+
+ m_frameCount = 0;
+ m_timer.restart();
+
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void Window::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Window::render()
+{
+ if (!m_hasSwapChain || m_notExposed)
+ return;
+
+ // If the window got resized or got newly exposed, resize the swapchain.
+ // (the newly-exposed case is not actually required by some
+ // platforms/backends, but f.ex. Vulkan on Windows seems to need it)
+ if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ m_newlyExposed = false;
+ }
+
+ // Start a new frame. This is where we block when too far ahead of
+ // GPU/present, and that's what throttles the thread to the refresh rate.
+ // (except for OpenGL where it happens either in endFrame or somewhere else
+ // depending on the GL implementation)
+ QRhi::FrameOpResult r = m_r->beginFrame(m_sc, beginFrameFlags);
+ if (r == QRhi::FrameOpSwapChainOutOfDate) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ r = m_r->beginFrame(m_sc);
+ }
+ if (r != QRhi::FrameOpSuccess) {
+ requestUpdate();
+ return;
+ }
+
+ m_frameCount += 1;
+ if (m_timer.elapsed() > 1000) {
+ if (rhiFlags.testFlag(QRhi::EnableProfiling)) {
+ const QRhiProfiler::CpuTime ff = m_r->profiler()->frameToFrameTimes(m_sc);
+ const QRhiProfiler::CpuTime be = m_r->profiler()->frameBuildTimes(m_sc);
+ const QRhiProfiler::GpuTime gp = m_r->profiler()->gpuFrameTimes(m_sc);
+ if (m_r->isFeatureSupported(QRhi::Timestamps)) {
+ qDebug("ca. %d fps. "
+ "frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. "
+ "gpu frame time: min %f max %f avg %f",
+ m_frameCount,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime,
+ gp.minTime, gp.maxTime, gp.avgTime);
+ } else {
+ qDebug("ca. %d fps. "
+ "frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. ",
+ m_frameCount,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime);
+ }
+ } else {
+ qDebug("ca. %d fps", m_frameCount);
+ }
+
+ m_timer.restart();
+ m_frameCount = 0;
+ }
+
+ customRender();
+
+ m_r->endFrame(m_sc, endFrameFlags);
+
+ if (!scFlags.testFlag(QRhiSwapChain::NoVSync))
+ requestUpdate();
+ else // try prevent all delays when NoVSync
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ // Defaults.
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ // Allow overriding via the command line.
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
+ cmdLineParser.addOption(nullOption);
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ // Testing cleanup both with QWindow::close() (hitting X or Alt-F4) and
+ // QCoreApplication::quit() (e.g. what a menu widget would do) is important.
+ // Use this parameter for the latter.
+ QCommandLineOption sdOption({ "s", "self-destruct" }, QLatin1String("Self-destruct after 5 seconds."));
+ cmdLineParser.addOption(sdOption);
+ // Attempt testing device lost situations on D3D at least.
+ QCommandLineOption tdrOption(QLatin1String("curse"), QLatin1String("Curse the graphics device. "
+ "(generate a device reset every <count> frames when on D3D11)"),
+ QLatin1String("count"));
+ cmdLineParser.addOption(tdrOption);
+ // Allow testing preferring the software adapter (D3D).
+ QCommandLineOption swOption(QLatin1String("software"), QLatin1String("Prefer a software renderer when choosing the adapter. "
+ "Only applicable with some APIs and platforms."));
+ cmdLineParser.addOption(swOption);
+
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(nullOption))
+ graphicsApi = Null;
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+#ifdef EXAMPLEFW_PREINIT
+ void preInit();
+ preInit();
+#endif
+
+ // OpenGL specifics.
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+ fmt.setStencilBufferSize(8);
+ if (sampleCount > 1)
+ fmt.setSamples(sampleCount);
+ if (scFlags.testFlag(QRhiSwapChain::NoVSync))
+ fmt.setSwapInterval(0);
+ if (scFlags.testFlag(QRhiSwapChain::sRGB))
+ fmt.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+ QSurfaceFormat::setDefaultFormat(fmt);
+
+ // Vulkan setup.
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+ if (graphicsApi == Vulkan) {
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ inst.setExtensions(QByteArrayList()
+ << "VK_KHR_get_physical_device_properties2");
+ if (!inst.create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ if (cmdLineParser.isSet(tdrOption))
+ framesUntilTdr = cmdLineParser.value(tdrOption).toInt();
+
+ if (cmdLineParser.isSet(swOption))
+ rhiFlags |= QRhi::PreferSoftwareRenderer;
+
+ // Create and show the window.
+ Window w;
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan)
+ w.setVulkanInstance(&inst);
+#endif
+ w.resize(1280, 720);
+ w.setTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName());
+ w.show();
+
+ if (cmdLineParser.isSet(sdOption))
+ QTimer::singleShot(5000, qGuiApp, SLOT(quit()));
+
+ int ret = app.exec();
+
+ // Window::event() will not get invoked when the
+ // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow
+ // destruction. That happens only when exiting via app::quit() instead of
+ // the more common QWindow::close(). Take care of it: if the
+ // QPlatformWindow is still around (there was no close() yet), get rid of
+ // the swapchain while it's not too late.
+ if (w.handle())
+ w.releaseSwapChain();
+
+ return ret;
+}
diff --git a/tests/manual/rhi/shared/qt256.png b/tests/manual/rhi/shared/qt256.png
new file mode 100644
index 0000000000..30c621c9c6
--- /dev/null
+++ b/tests/manual/rhi/shared/qt256.png
Binary files differ
diff --git a/tests/manual/rhi/shared/qt256_bc1_9mips.dds b/tests/manual/rhi/shared/qt256_bc1_9mips.dds
new file mode 100644
index 0000000000..734a5d184f
--- /dev/null
+++ b/tests/manual/rhi/shared/qt256_bc1_9mips.dds
Binary files differ
diff --git a/tests/manual/rhi/shared/texture.frag b/tests/manual/rhi/shared/texture.frag
new file mode 100644
index 0000000000..5405444c68
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.frag
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+} ubuf;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ vec4 c = texture(tex, v_texcoord);
+ fragColor = vec4(c.rgb * c.a, c.a);
+}
diff --git a/tests/manual/rhi/shared/texture.frag.qsb b/tests/manual/rhi/shared/texture.frag.qsb
new file mode 100644
index 0000000000..31bcd7105e
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/texture.vert b/tests/manual/rhi/shared/texture.vert
new file mode 100644
index 0000000000..ad7e783dfb
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.vert
@@ -0,0 +1,21 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = vec2(texcoord.x, texcoord.y);
+ if (ubuf.flip != 0)
+ v_texcoord.y = 1.0 - v_texcoord.y;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shared/texture.vert.qsb b/tests/manual/rhi/shared/texture.vert.qsb
new file mode 100644
index 0000000000..1b9e52890d
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/texture_ms4.frag b/tests/manual/rhi/shared/texture_ms4.frag
new file mode 100644
index 0000000000..d4f2bd3654
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_ms4.frag
@@ -0,0 +1,20 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+} ubuf;
+
+layout(binding = 1) uniform sampler2DMS tex;
+
+void main()
+{
+ ivec2 tc = ivec2(floor(vec2(textureSize(tex)) * v_texcoord));
+ vec4 c = texelFetch(tex, tc, 0) + texelFetch(tex, tc, 1) + texelFetch(tex, tc, 2) + texelFetch(tex, tc, 3);
+ c /= 4.0;
+ fragColor = vec4(c.rgb * c.a, c.a);
+}
diff --git a/tests/manual/rhi/shared/texture_ms4.frag.qsb b/tests/manual/rhi/shared/texture_ms4.frag.qsb
new file mode 100644
index 0000000000..7f187ce7f0
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_ms4.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/texuploads/texuploads.cpp b/tests/manual/rhi/texuploads/texuploads.cpp
new file mode 100644
index 0000000000..dc20ffb1fc
--- /dev/null
+++ b/tests/manual/rhi/texuploads/texuploads.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/examplefw.h"
+#include "../shared/cube.h"
+#include <QPainter>
+
+struct {
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QVector<QRhiResource *> releasePool;
+
+ float rotation = 0;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ int frameCount = 0;
+ QImage customImage;
+ QRhiTexture *newTex = nullptr;
+ QRhiTexture *importedTex = nullptr;
+ int testStage = 0;
+} d;
+
+void Window::customInit()
+{
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.releasePool << d.vbuf;
+ d.vbuf->build();
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.ubuf;
+ d.ubuf->build();
+
+ QImage baseImage(QLatin1String(":/qt256.png"));
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, baseImage.size(), 1, QRhiTexture::UsedAsTransferSource);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ // As an alternative to what some of the other examples do, prepare an
+ // update batch right here instead of relying on vbufReady and similar flags.
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, cube);
+ qint32 flip = 0;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ d.initialUpdates->uploadTexture(d.tex, baseImage);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ const QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+
+ d.customImage = QImage(128, 64, QImage::Format_RGBA8888);
+ d.customImage.fill(Qt::red);
+ QPainter painter(&d.customImage);
+ // the text may look different on different platforms, so no guarantee the
+ // output on the screen will be identical everywhere
+ painter.drawText(5, 25, "Hello world");
+ painter.end();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+
+ // take the initial set of updates, if this is the first frame
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ d.rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(d.rotation, 0, 1, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ if (d.frameCount > 0 && (d.frameCount % 100) == 0) {
+ d.testStage += 1;
+ qDebug("testStage = %d", d.testStage);
+
+ // Partially change the texture.
+ if (d.testStage == 1) {
+ QRhiTextureSubresourceUploadDescription mipDesc(d.customImage);
+ // The image here is smaller than the original. Use a non-zero position
+ // to make it more interesting.
+ mipDesc.setDestinationTopLeft(QPoint(100, 20));
+ QRhiTextureUploadDescription desc({ 0, 0, mipDesc });
+ u->uploadTexture(d.tex, desc);
+ }
+
+ // Exercise image copying.
+ if (d.testStage == 2) {
+ const QSize sz = d.tex->pixelSize();
+ d.newTex = m_r->newTexture(QRhiTexture::RGBA8, sz);
+ d.releasePool << d.newTex;
+ d.newTex->build();
+
+ QImage empty(sz.width(), sz.height(), QImage::Format_RGBA8888);
+ empty.fill(Qt::blue);
+ u->uploadTexture(d.newTex, empty);
+
+ // Copy the left-half of tex to the right-half of newTex, while
+ // leaving the left-half of newTex blue. Keep a 20 pixel gap at
+ // the top.
+ QRhiTextureCopyDescription desc;
+ desc.setSourceTopLeft(QPoint(0, 20));
+ desc.setPixelSize(QSize(sz.width() / 2, sz.height() - 20));
+ desc.setDestinationTopLeft(QPoint(sz.width() / 2, 20));
+ u->copyTexture(d.newTex, d.tex, desc);
+
+ // Now replace d.tex with d.newTex as the shader resource.
+ auto bindings = d.srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.newTex, d.sampler);
+ d.srb->setBindings(bindings);
+ // "rebuild", whatever that means for a given backend. This srb is
+ // already live as the ps in the setGraphicsPipeline references it,
+ // but that's fine. Changes will be picked up automatically.
+ d.srb->build();
+ }
+
+ // Exercise simple, full texture copy.
+ if (d.testStage == 4)
+ u->copyTexture(d.newTex, d.tex);
+
+ // Now again upload customImage but this time only a part of it.
+ if (d.testStage == 5) {
+ QRhiTextureSubresourceUploadDescription mipDesc(d.customImage);
+ mipDesc.setDestinationTopLeft(QPoint(10, 120));
+ mipDesc.setSourceSize(QSize(50, 40));
+ mipDesc.setSourceTopLeft(QPoint(20, 10));
+ QRhiTextureUploadDescription desc({ 0, 0, mipDesc });
+ u->uploadTexture(d.newTex, desc);
+ }
+
+ // Exercise texture object export/import.
+ if (d.testStage == 6) {
+ const QRhiNativeHandles *h = d.tex->nativeHandles();
+ if (h) {
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ qDebug() << "Metal texture: " << static_cast<const QRhiMetalTextureNativeHandles *>(h)->texture;
+ // Now could cast to id<MTLTexture> and do something with
+ // it, keeping in mind that copy operations are only done
+ // in beginPass, while rendering into a texture may only
+ // have proper results in current_frame + 2, or after a
+ // finish(). The QRhiTexture still owns the native object.
+ }
+#endif
+ // omit for other backends, the idea is the same
+
+ d.importedTex = m_r->newTexture(QRhiTexture::RGBA8, d.tex->pixelSize());
+ d.releasePool << d.importedTex;
+ if (!d.importedTex->buildFrom(h))
+ qWarning("Texture import failed");
+
+ // now d.tex and d.importedTex use the same MTLTexture
+ // underneath (owned by d.tex)
+
+ // switch to showing d.importedTex
+ auto bindings = d.srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.importedTex, d.sampler);
+ d.srb->setBindings(bindings);
+ d.srb->build();
+ } else {
+ qWarning("Accessing native texture object is not supported");
+ }
+ }
+
+ // Exercise uploading uncompressed data without a QImage.
+ if (d.testStage == 7) {
+ auto bindings = d.srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.newTex, d.sampler);
+ d.srb->setBindings(bindings);
+ d.srb->build();
+
+ const QSize sz(221, 139);
+ QByteArray data;
+ data.resize(sz.width() * sz.height() * 4);
+ for (int y = 0; y < sz.height(); ++y) {
+ uchar *p = reinterpret_cast<uchar *>(data.data()) + y * sz.width() * 4;
+ for (int x = 0; x < sz.width(); ++x) {
+ *p++ = 0; *p++ = 0; *p++ = y * (255 / sz.height());
+ *p++ = 255;
+ }
+ }
+ QRhiTextureSubresourceUploadDescription mipDesc(data.constData(), data.size());
+ mipDesc.setSourceSize(sz);
+ mipDesc.setDestinationTopLeft(QPoint(5, 25));
+ QRhiTextureUploadDescription desc({ 0, 0, mipDesc });
+ u->uploadTexture(d.newTex, desc);
+ }
+ }
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { d.vbuf, 0 },
+ { d.vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+
+ d.frameCount += 1;
+}
diff --git a/tests/manual/rhi/texuploads/texuploads.pro b/tests/manual/rhi/texuploads/texuploads.pro
new file mode 100644
index 0000000000..64f204fb32
--- /dev/null
+++ b/tests/manual/rhi/texuploads/texuploads.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ texuploads.cpp
+
+RESOURCES = texuploads.qrc
diff --git a/tests/manual/rhi/texuploads/texuploads.qrc b/tests/manual/rhi/texuploads/texuploads.qrc
new file mode 100644
index 0000000000..742b2b77af
--- /dev/null
+++ b/tests/manual/rhi/texuploads/texuploads.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256.png">../shared/qt256.png</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/triquadcube/quadrenderer.cpp b/tests/manual/rhi/triquadcube/quadrenderer.cpp
new file mode 100644
index 0000000000..6137fb1b9a
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/quadrenderer.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quadrenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+// Renders a quad using indexed drawing. No QRhiGraphicsPipeline is created, it
+// expects to reuse the one created by TriangleRenderer. A separate
+// QRhiShaderResourceBindings is still needed, this will override the one the
+// QRhiGraphicsPipeline references.
+
+static float vertexData[] =
+{ // Y up (note m_proj), CCW
+ -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+void QuadRenderer::initResources(QRhiRenderPassDescriptor *)
+{
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ m_ibuf->build();
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ m_ubuf->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf)
+ });
+ m_srb->build();
+}
+
+void QuadRenderer::setPipeline(QRhiGraphicsPipeline *ps)
+{
+ m_ps = ps;
+}
+
+void QuadRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void QuadRenderer::releaseResources()
+{
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_ibuf;
+ m_ibuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void QuadRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ resourceUpdates->uploadStaticBuffer(m_vbuf, vertexData);
+ resourceUpdates->uploadStaticBuffer(m_ibuf, indexData);
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.rotate(m_rotation, 0, 1, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ if (!m_opacityReady) {
+ m_opacityReady = true;
+ const float opacity = 1.0f;
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &opacity);
+ }
+}
+
+void QuadRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &/*outputSizeInPixels*/)
+{
+ cb->setGraphicsPipeline(m_ps);
+ //cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources(m_srb);
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, m_ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+}
diff --git a/tests/manual/rhi/triquadcube/quadrenderer.h b/tests/manual/rhi/triquadcube/quadrenderer.h
new file mode 100644
index 0000000000..79d5b8209d
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/quadrenderer.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUADRENDERER_H
+#define QUADRENDERER_H
+
+#include <QtGui/private/qrhi_p.h>
+
+class QuadRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ int sampleCount() const { return m_sampleCount; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void setPipeline(QRhiGraphicsPipeline *ps);
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ibuf = nullptr;
+ bool m_opacityReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+
+ QVector3D m_translation;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_sampleCount = 1; // no MSAA by default
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/texturedcuberenderer.cpp b/tests/manual/rhi/triquadcube/texturedcuberenderer.cpp
new file mode 100644
index 0000000000..3f15881e2d
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/texturedcuberenderer.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "texturedcuberenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+#include "../shared/cube.h"
+
+const bool MIPMAP = true;
+const bool AUTOGENMIPMAP = true;
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void TexturedCubeRenderer::initResources(QRhiRenderPassDescriptor *rp)
+{
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ m_vbuf->setName(QByteArrayLiteral("Cube vbuf (textured)"));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
+ m_ubuf->setName(QByteArrayLiteral("Cube ubuf (textured)"));
+ m_ubuf->build();
+
+ m_image = QImage(QLatin1String(":/qt256.png")).convertToFormat(QImage::Format_RGBA8888);
+ QRhiTexture::Flags texFlags = 0;
+ if (MIPMAP)
+ texFlags |= QRhiTexture::MipMapped;
+ if (AUTOGENMIPMAP)
+ texFlags |= QRhiTexture::UsedWithGenerateMips;
+ m_tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(m_image.width(), m_image.height()), 1, texFlags);
+ m_tex->setName(QByteArrayLiteral("Qt texture"));
+ m_tex->build();
+
+ m_sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, MIPMAP ? QRhiSampler::Linear : QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ m_sampler->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, m_tex, m_sampler)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+
+ // No blending but the texture has alpha which we do not want to write out.
+ // Be nice. (would not matter for an onscreen window but makes a difference
+ // when reading back and saving into image files f.ex.)
+ QRhiGraphicsPipeline::TargetBlend blend;
+ blend.colorWrite = QRhiGraphicsPipeline::R | QRhiGraphicsPipeline::G | QRhiGraphicsPipeline::B;
+ m_ps->setTargetBlends({ blend });
+
+ m_ps->setDepthTest(true);
+ m_ps->setDepthWrite(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ m_ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ m_ps->setSampleCount(m_sampleCount);
+
+ QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ m_ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(rp);
+
+ m_ps->build();
+}
+
+void TexturedCubeRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TexturedCubeRenderer::releaseResources()
+{
+ delete m_ps;
+ m_ps = nullptr;
+
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_sampler;
+ m_sampler = nullptr;
+
+ delete m_tex;
+ m_tex = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void TexturedCubeRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ resourceUpdates->uploadStaticBuffer(m_vbuf, cube);
+ qint32 flip = 0;
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &flip);
+ }
+
+ if (!m_image.isNull()) {
+ if (MIPMAP) {
+ QRhiTextureUploadDescription desc;
+ if (!AUTOGENMIPMAP) {
+ // the ghetto mipmap generator...
+ for (int i = 0, ie = m_r->mipLevelsForSize(m_image.size()); i != ie; ++i) {
+ QImage image = m_image.scaled(m_r->sizeForMipLevel(i, m_image.size()));
+ desc.append({ 0, i, image });
+ }
+ } else {
+ desc.append({ 0, 0, m_image });
+ }
+ resourceUpdates->uploadTexture(m_tex, desc);
+ if (AUTOGENMIPMAP)
+ resourceUpdates->generateMips(m_tex);
+ } else {
+ resourceUpdates->uploadTexture(m_tex, m_image);
+ }
+ m_image = QImage();
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.scale(0.5f);
+ mvp.rotate(m_rotation, 0, 1, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+}
+
+void TexturedCubeRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels)
+{
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { m_vbuf, 0 },
+ { m_vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+}
diff --git a/tests/manual/rhi/triquadcube/texturedcuberenderer.h b/tests/manual/rhi/triquadcube/texturedcuberenderer.h
new file mode 100644
index 0000000000..879f875209
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/texturedcuberenderer.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTUREDCUBERENDERER_H
+#define TEXTUREDCUBERENDERER_H
+
+#include <QtGui/private/qrhi_p.h>
+
+class TexturedCubeRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QImage m_image;
+ QRhiTexture *m_tex = nullptr;
+ QRhiSampler *m_sampler = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+
+ QVector3D m_translation;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_sampleCount = 1; // no MSAA by default
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp b/tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp
new file mode 100644
index 0000000000..250ae3a2ee
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "triangleoncuberenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+// toggle to test the preserved content (no clear) path
+const bool IMAGE_UNDER_OFFSCREEN_RENDERING = false;
+const bool UPLOAD_UNDERLAY_ON_EVERY_FRAME = false;
+
+const bool DS_ATT = false; // have a depth-stencil attachment for the offscreen pass
+
+const bool DEPTH_TEXTURE = false; // offscreen pass uses a depth texture (verify with renderdoc etc., ignore valid.layer about ps slot 0)
+const bool MRT = false; // two textures, the second is just cleared as the shader does not write anything (valid.layer may warn but for testing that's ok)
+
+#include "../shared/cube.h"
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+static const QSize OFFSCREEN_SIZE(512, 512);
+
+void TriangleOnCubeRenderer::initResources(QRhiRenderPassDescriptor *rp)
+{
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ m_vbuf->setName(QByteArrayLiteral("Cube vbuf (textured with offscreen)"));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
+ m_ubuf->setName(QByteArrayLiteral("Cube ubuf (textured with offscreen)"));
+ m_ubuf->build();
+
+ if (IMAGE_UNDER_OFFSCREEN_RENDERING) {
+ m_image = QImage(QLatin1String(":/qt256.png")).scaled(OFFSCREEN_SIZE).convertToFormat(QImage::Format_RGBA8888);
+ if (m_r->isYUpInFramebuffer())
+ m_image = m_image.mirrored(); // just cause we'll flip texcoord Y when y up so accommodate our static background image as well
+ }
+
+ m_tex = m_r->newTexture(QRhiTexture::RGBA8, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget);
+ m_tex->setName(QByteArrayLiteral("Texture for offscreen content"));
+ m_tex->build();
+
+ if (MRT) {
+ m_tex2 = m_r->newTexture(QRhiTexture::RGBA8, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget);
+ m_tex2->build();
+ }
+
+ if (DS_ATT) {
+ m_offscreenTriangle.setDepthWrite(true);
+ m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil, m_tex->pixelSize());
+ m_ds->build();
+ }
+
+ if (DEPTH_TEXTURE) {
+ m_offscreenTriangle.setDepthWrite(true);
+ m_depthTex = m_r->newTexture(QRhiTexture::D32F, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget);
+ m_depthTex->build();
+ }
+
+ m_sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ m_sampler->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, m_tex, m_sampler)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+
+ m_ps->setDepthTest(true);
+ m_ps->setDepthWrite(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ m_ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ m_ps->setSampleCount(m_sampleCount);
+
+ QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ m_ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(rp);
+
+ m_ps->build();
+
+ QRhiTextureRenderTarget::Flags rtFlags = 0;
+ if (IMAGE_UNDER_OFFSCREEN_RENDERING)
+ rtFlags |= QRhiTextureRenderTarget::PreserveColorContents;
+
+ if (DEPTH_TEXTURE) {
+ QRhiTextureRenderTargetDescription desc;
+ desc.setDepthTexture(m_depthTex);
+ m_rt = m_r->newTextureRenderTarget(desc, rtFlags);
+ } else {
+ QRhiTextureRenderTargetDescription desc;
+ QRhiColorAttachment color0 { m_tex };
+ if (DS_ATT)
+ desc.setDepthStencilBuffer(m_ds);
+ if (MRT) {
+ m_offscreenTriangle.setColorAttCount(2);
+ QRhiColorAttachment color1 { m_tex2 };
+ desc.setColorAttachments({ color0, color1 });
+ } else {
+ desc.setColorAttachments({ color0 });
+ }
+ m_rt = m_r->newTextureRenderTarget(desc, rtFlags);
+ }
+
+ m_rp = m_rt->newCompatibleRenderPassDescriptor();
+ m_rt->setRenderPassDescriptor(m_rp);
+
+ m_rt->build();
+
+ m_offscreenTriangle.setRhi(m_r);
+ m_offscreenTriangle.initResources(m_rp);
+ m_offscreenTriangle.setScale(2);
+ // m_tex and the offscreen triangle are never multisample
+}
+
+void TriangleOnCubeRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+
+ m_offscreenTriangle.resize(pixelSize);
+}
+
+void TriangleOnCubeRenderer::releaseResources()
+{
+ m_offscreenTriangle.releaseResources();
+
+ delete m_ps;
+ m_ps = nullptr;
+
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_rt;
+ m_rt = nullptr;
+
+ delete m_rp;
+ m_rp = nullptr;
+
+ delete m_sampler;
+ m_sampler = nullptr;
+
+ delete m_depthTex;
+ m_depthTex = nullptr;
+
+ delete m_tex2;
+ m_tex2 = nullptr;
+
+ delete m_tex;
+ m_tex = nullptr;
+
+ delete m_ds;
+ m_ds = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void TriangleOnCubeRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ resourceUpdates->uploadStaticBuffer(m_vbuf, cube);
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &flip);
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.scale(0.5f);
+ mvp.rotate(m_rotation, 1, 0, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ // ###
+// if (DEPTH_TEXTURE) {
+// // m_tex is basically undefined here, be nice and transition the layout properly at least
+// resourceUpdates->prepareTextureForUse(m_tex, QRhiResourceUpdateBatch::TextureRead);
+// }
+}
+
+void TriangleOnCubeRenderer::queueOffscreenPass(QRhiCommandBuffer *cb)
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ m_offscreenTriangle.queueResourceUpdates(u);
+
+ if (IMAGE_UNDER_OFFSCREEN_RENDERING && !m_image.isNull()) {
+ u->uploadTexture(m_tex, m_image);
+ if (!UPLOAD_UNDERLAY_ON_EVERY_FRAME)
+ m_image = QImage();
+ }
+
+ cb->beginPass(m_rt, QColor::fromRgbF(0.0f, 0.4f, 0.7f, 1.0f), { 1.0f, 0 }, u);
+ m_offscreenTriangle.queueDraw(cb, OFFSCREEN_SIZE);
+ cb->endPass();
+}
+
+void TriangleOnCubeRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels)
+{
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { m_vbuf, 0 },
+ { m_vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+}
diff --git a/tests/manual/rhi/triquadcube/triangleoncuberenderer.h b/tests/manual/rhi/triquadcube/triangleoncuberenderer.h
new file mode 100644
index 0000000000..5a56bf6bd1
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triangleoncuberenderer.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRIANGLEONCUBERENDERER_H
+#define TRIANGLEONCUBERENDERER_H
+
+#include "trianglerenderer.h"
+
+class TriangleOnCubeRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueOffscreenPass(QRhiCommandBuffer *cb);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiTexture *m_tex = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiTexture *m_tex2 = nullptr;
+ QRhiTexture *m_depthTex = nullptr;
+ QRhiSampler *m_sampler = nullptr;
+ QRhiTextureRenderTarget *m_rt = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+
+ QVector3D m_translation;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_sampleCount = 1; // no MSAA by default
+
+ TriangleRenderer m_offscreenTriangle;
+
+ QImage m_image;
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/trianglerenderer.cpp b/tests/manual/rhi/triquadcube/trianglerenderer.cpp
new file mode 100644
index 0000000000..0980acca49
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/trianglerenderer.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "trianglerenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+//#define VBUF_IS_DYNAMIC
+
+static float vertexData[] = { // Y up (note m_proj), CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void TriangleRenderer::initResources(QRhiRenderPassDescriptor *rp)
+{
+#ifdef VBUF_IS_DYNAMIC
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+#else
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+#endif
+ m_vbuf->setName(QByteArrayLiteral("Triangle vbuf"));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ m_ubuf->setName(QByteArrayLiteral("Triangle ubuf"));
+ m_ubuf->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend; // convenient defaults...
+ premulAlphaBlend.enable = true;
+ QVector<QRhiGraphicsPipeline::TargetBlend> rtblends;
+ for (int i = 0; i < m_colorAttCount; ++i)
+ rtblends << premulAlphaBlend;
+
+ m_ps->setTargetBlends(rtblends);
+ m_ps->setSampleCount(m_sampleCount);
+
+ if (m_depthWrite) { // TriangleOnCube may want to exercise this
+ m_ps->setDepthTest(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Always);
+ m_ps->setDepthWrite(true);
+ }
+
+ QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ m_ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 7 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(rp);
+
+ m_ps->build();
+}
+
+void TriangleRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TriangleRenderer::releaseResources()
+{
+ delete m_ps;
+ m_ps = nullptr;
+
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void TriangleRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+#if 0
+ static int messWithBufferTrigger = 0;
+ // recreate the underlying VkBuffer every second frame
+ // to exercise setShaderResources' built-in smartness
+ if (!(messWithBufferTrigger & 1)) {
+ m_ubuf->release();
+ m_ubuf->build();
+ }
+ ++messWithBufferTrigger;
+#endif
+
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+#ifdef VBUF_IS_DYNAMIC
+ resourceUpdates->updateDynamicBuffer(m_vbuf, 0, m_vbuf->size(), vertexData);
+#else
+ resourceUpdates->uploadStaticBuffer(m_vbuf, vertexData);
+#endif
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.scale(m_scale);
+ mvp.rotate(m_rotation, 0, 1, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ m_opacity += m_opacityDir * 0.005f;
+ if (m_opacity < 0.0f || m_opacity > 1.0f) {
+ m_opacityDir *= -1;
+ m_opacity = qBound(0.0f, m_opacity, 1.0f);
+ }
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &m_opacity);
+}
+
+void TriangleRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels)
+{
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+}
diff --git a/tests/manual/rhi/triquadcube/trianglerenderer.h b/tests/manual/rhi/triquadcube/trianglerenderer.h
new file mode 100644
index 0000000000..53d6926a62
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/trianglerenderer.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRIANGLERENDERER_H
+#define TRIANGLERENDERER_H
+
+#include <QtGui/private/qrhi_p.h>
+
+class TriangleRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ int sampleCount() const { return m_sampleCount; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void setScale(float f) { m_scale = f; }
+ void setDepthWrite(bool enable) { m_depthWrite = enable; }
+ void setColorAttCount(int count) { m_colorAttCount = count; }
+ QRhiGraphicsPipeline *pipeline() const { return m_ps; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+
+ QVector3D m_translation;
+ float m_scale = 1;
+ bool m_depthWrite = false;
+ int m_colorAttCount = 1;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ float m_opacity = 1;
+ int m_opacityDir = -1;
+ int m_sampleCount = 1; // no MSAA by default
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/triquadcube.cpp b/tests/manual/rhi/triquadcube/triquadcube.cpp
new file mode 100644
index 0000000000..76dbe558ab
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triquadcube.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// An example exercising more than a single feature. Enables profiling
+// (resource logging to a file) and inserts debug markers and sets some
+// object names. Can also be used to test MSAA swapchains, swapchain image
+// readback, requesting an sRGB swapchain, and some texture features.
+
+#define EXAMPLEFW_PREINIT
+#include "../shared/examplefw.h"
+#include "trianglerenderer.h"
+#include "quadrenderer.h"
+#include "texturedcuberenderer.h"
+#include "triangleoncuberenderer.h"
+
+#include <QFileInfo>
+#include <QFile>
+#include <QtGui/private/qrhiprofiler_p.h>
+
+#define PROFILE_TO_FILE
+//#define SKIP_PRESENT
+//#define USE_MSAA
+//#define USE_SRGB_SWAPCHAIN
+//#define READBACK_SWAPCHAIN
+//#define NO_VSYNC
+//#define USE_MIN_SWAPCHAIN_BUFFERS
+//#define DECLARE_EXT_CONTENTS
+
+struct {
+ TriangleRenderer triRenderer;
+ QuadRenderer quadRenderer;
+ TexturedCubeRenderer cubeRenderer;
+ TriangleOnCubeRenderer liveTexCubeRenderer;
+ bool onScreenOnly = false;
+ bool triangleOnly = false;
+ QSize lastOutputSize;
+ int frameCount = 0;
+ QFile profOut;
+} d;
+
+void preInit()
+{
+#ifdef PROFILE_TO_FILE
+ rhiFlags |= QRhi::EnableProfiling;
+ const QString profFn = QFileInfo(QLatin1String("rhiprof.txt")).absoluteFilePath();
+ qDebug("Writing profiling output to %s", qPrintable(profFn));
+ d.profOut.setFileName(profFn);
+ d.profOut.open(QIODevice::WriteOnly);
+#endif
+
+#ifdef SKIP_PRESENT
+ endFrameFlags |= QRhi::SkipPresent;
+#endif
+
+#ifdef USE_MSAA
+ sampleCount = 4; // enable 4x MSAA (except for the render-to-texture pass)
+#endif
+
+#ifdef READBACK_SWAPCHAIN
+ scFlags |= QRhiSwapChain::UsedAsTransferSource;
+#endif
+
+#ifdef USE_SRGB_SWAPCHAIN
+ scFlags |= QRhiSwapChain::sRGB;
+#endif
+
+#ifdef NO_VSYNC
+ scFlags |= QRhiSwapChain::NoVSync;
+#endif
+
+#ifdef USE_MIN_SWAPCHAIN_BUFFERS
+ scFlags |= QRhiSwapChain::MinimalBufferCount;
+#endif
+
+#ifdef DECLARE_EXT_CONTENTS
+ beginFrameFlags |= QRhi::ExternalContentsInPass;
+#endif
+
+ // For OpenGL some of these are incorporated into the QSurfaceFormat by
+ // examplefw.h after returning from here as that is out of the RHI's control.
+}
+
+void Window::customInit()
+{
+#ifdef PROFILE_TO_FILE
+ m_r->profiler()->setDevice(&d.profOut);
+#endif
+
+ d.triRenderer.setRhi(m_r);
+ d.triRenderer.setSampleCount(sampleCount);
+ d.triRenderer.initResources(m_rp);
+
+ if (!d.triangleOnly) {
+ d.triRenderer.setTranslation(QVector3D(0, 0.5f, 0));
+
+ d.quadRenderer.setRhi(m_r);
+ d.quadRenderer.setSampleCount(sampleCount);
+ d.quadRenderer.setPipeline(d.triRenderer.pipeline());
+ d.quadRenderer.initResources(m_rp);
+ d.quadRenderer.setTranslation(QVector3D(1.5f, -0.5f, 0));
+
+ d.cubeRenderer.setRhi(m_r);
+ d.cubeRenderer.setSampleCount(sampleCount);
+ d.cubeRenderer.initResources(m_rp);
+ d.cubeRenderer.setTranslation(QVector3D(0, -0.5f, 0));
+ }
+
+ if (!d.onScreenOnly) {
+ d.liveTexCubeRenderer.setRhi(m_r);
+ d.liveTexCubeRenderer.setSampleCount(sampleCount);
+ d.liveTexCubeRenderer.initResources(m_rp);
+ d.liveTexCubeRenderer.setTranslation(QVector3D(-2.0f, 0, 0));
+ }
+
+ // Put the gpu mem allocator statistics to the profiling stream after doing
+ // all the init. (where applicable)
+ m_r->profiler()->addVMemAllocatorStats();
+
+ // Check some features/limits.
+ qDebug("isFeatureSupported(MultisampleTexture): %d", m_r->isFeatureSupported(QRhi::MultisampleTexture));
+ qDebug("isFeatureSupported(MultisampleRenderBuffer): %d", m_r->isFeatureSupported(QRhi::MultisampleRenderBuffer));
+ qDebug("isFeatureSupported(DebugMarkers): %d", m_r->isFeatureSupported(QRhi::DebugMarkers));
+ qDebug("isFeatureSupported(Timestamps): %d", m_r->isFeatureSupported(QRhi::Timestamps));
+ qDebug("isFeatureSupported(Instancing): %d", m_r->isFeatureSupported(QRhi::Instancing));
+ qDebug("isFeatureSupported(CustomInstanceStepRate): %d", m_r->isFeatureSupported(QRhi::CustomInstanceStepRate));
+ qDebug("isFeatureSupported(PrimitiveRestart): %d", m_r->isFeatureSupported(QRhi::PrimitiveRestart));
+ qDebug("isFeatureSupported(NonDynamicUniformBuffers): %d", m_r->isFeatureSupported(QRhi::NonDynamicUniformBuffers));
+ qDebug("isFeatureSupported(NonFourAlignedEffectiveIndexBufferOffset): %d", m_r->isFeatureSupported(QRhi::NonFourAlignedEffectiveIndexBufferOffset));
+ qDebug("isFeatureSupported(NPOTTextureRepeat): %d", m_r->isFeatureSupported(QRhi::NPOTTextureRepeat));
+ qDebug("isFeatureSupported(RedOrAlpha8IsRed): %d", m_r->isFeatureSupported(QRhi::RedOrAlpha8IsRed));
+ qDebug("isFeatureSupported(ElementIndexUint): %d", m_r->isFeatureSupported(QRhi::ElementIndexUint));
+ qDebug("isFeatureSupported(Compute): %d", m_r->isFeatureSupported(QRhi::Compute));
+ qDebug("isFeatureSupported(WideLines): %d", m_r->isFeatureSupported(QRhi::WideLines));
+ qDebug("isFeatureSupported(VertexShaderPointSize): %d", m_r->isFeatureSupported(QRhi::VertexShaderPointSize));
+ qDebug("isFeatureSupported(BaseVertex): %d", m_r->isFeatureSupported(QRhi::BaseVertex));
+ qDebug("isFeatureSupported(BaseInstance): %d", m_r->isFeatureSupported(QRhi::BaseInstance));
+ qDebug("Min 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMin));
+ qDebug("Max 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMax));
+ qDebug("Max color attachment count: %d", m_r->resourceLimit(QRhi::MaxColorAttachments));
+}
+
+void Window::customRelease()
+{
+ d.triRenderer.releaseResources();
+
+ if (!d.triangleOnly) {
+ d.quadRenderer.releaseResources();
+ d.cubeRenderer.releaseResources();
+ }
+
+ if (!d.onScreenOnly)
+ d.liveTexCubeRenderer.releaseResources();
+}
+
+void Window::customRender()
+{
+ const QSize outputSize = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+
+ if (outputSize != d.lastOutputSize) {
+ d.triRenderer.resize(outputSize);
+ if (!d.triangleOnly) {
+ d.quadRenderer.resize(outputSize);
+ d.cubeRenderer.resize(outputSize);
+ }
+ if (!d.onScreenOnly)
+ d.liveTexCubeRenderer.resize(outputSize);
+ d.lastOutputSize = outputSize;
+ }
+
+ if (!d.onScreenOnly) {
+ cb->debugMarkBegin("Offscreen triangle pass");
+ d.liveTexCubeRenderer.queueOffscreenPass(cb);
+ cb->debugMarkEnd();
+ }
+
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ d.triRenderer.queueResourceUpdates(u);
+ if (!d.triangleOnly) {
+ d.quadRenderer.queueResourceUpdates(u);
+ d.cubeRenderer.queueResourceUpdates(u);
+ }
+ if (!d.onScreenOnly)
+ d.liveTexCubeRenderer.queueResourceUpdates(u);
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->debugMarkBegin(QByteArrayLiteral("Triangle"));
+ d.triRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ if (!d.triangleOnly) {
+ cb->debugMarkMsg(QByteArrayLiteral("More stuff"));
+ cb->debugMarkBegin(QByteArrayLiteral("Quad"));
+ d.quadRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ cb->debugMarkBegin(QByteArrayLiteral("Cube"));
+ d.cubeRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ }
+ if (!d.onScreenOnly) {
+ cb->debugMarkMsg(QByteArrayLiteral("Even more stuff"));
+ cb->debugMarkBegin(QByteArrayLiteral("Cube with offscreen triangle"));
+ d.liveTexCubeRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ }
+
+ QRhiResourceUpdateBatch *passEndUpdates = nullptr;
+#ifdef READBACK_SWAPCHAIN
+ passEndUpdates = m_r->nextResourceUpdateBatch();
+ QRhiReadbackDescription rb; // no texture given -> backbuffer
+ QRhiReadbackResult *rbResult = new QRhiReadbackResult;
+ int frameNo = d.frameCount;
+ rbResult->completed = [this, rbResult, frameNo] {
+ {
+ QImage::Format fmt = rbResult->format == QRhiTexture::BGRA8 ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_RGBA8888_Premultiplied;
+ const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
+ QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
+ QString fn = QString::asprintf("frame%d.png", frameNo);
+ fn = QFileInfo(fn).absoluteFilePath();
+ qDebug("Saving into %s", qPrintable(fn));
+ if (m_r->isYUpInFramebuffer())
+ image.mirrored().save(fn);
+ else
+ image.save(fn);
+ }
+ delete rbResult;
+ };
+ passEndUpdates->readBackTexture(rb, rbResult);
+#endif
+
+ cb->endPass(passEndUpdates);
+
+ d.frameCount += 1;
+}
diff --git a/tests/manual/rhi/triquadcube/triquadcube.pro b/tests/manual/rhi/triquadcube/triquadcube.pro
new file mode 100644
index 0000000000..0002b3cad1
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triquadcube.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ triquadcube.cpp \
+ trianglerenderer.cpp \
+ quadrenderer.cpp \
+ texturedcuberenderer.cpp \
+ triangleoncuberenderer.cpp
+
+HEADERS = \
+ trianglerenderer.h \
+ quadrenderer.h \
+ texturedcuberenderer.h \
+ triangleoncuberenderer.h
+
+RESOURCES = triquadcube.qrc
diff --git a/tests/manual/rhi/triquadcube/triquadcube.qrc b/tests/manual/rhi/triquadcube/triquadcube.qrc
new file mode 100644
index 0000000000..41b72edc41
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triquadcube.qrc
@@ -0,0 +1,9 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="qt256.png">../shared/qt256.png</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/socketengine/main.cpp b/tests/manual/socketengine/main.cpp
index 0d491e7350..3e3e7e53e5 100644
--- a/tests/manual/socketengine/main.cpp
+++ b/tests/manual/socketengine/main.cpp
@@ -83,7 +83,7 @@ int main(int argc, char**argv)
// disconnected
exit(0);
}
- qFill(buf, buf + bufsize, 0);
+ std::fill(buf, buf + bufsize, 0);
ret = socketEngine->read(buf, available);
if (ret > 0) {
printf("%s", buf);
diff --git a/tests/manual/textrendering/glyphshaping/main.cpp b/tests/manual/textrendering/glyphshaping/main.cpp
index c3acda953d..c1e49b3b7e 100644
--- a/tests/manual/textrendering/glyphshaping/main.cpp
+++ b/tests/manual/textrendering/glyphshaping/main.cpp
@@ -160,8 +160,6 @@ bool dumpHtml(const QString &pathName)
QString platformName = QString::fromLatin1(
#if defined(Q_OS_WIN)
"Win32"
-#elif 0 // Used to be included in Qt4 for Q_WS_X11
- "X11"
#else
""
#endif
diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h
index 9f4527a992..0e7e6ba867 100644
--- a/tests/shared/filesystem.h
+++ b/tests/shared/filesystem.h
@@ -79,7 +79,7 @@ public:
return file.isNull() ? qint64(-1) : file->write(relativeFileName.toUtf8());
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
static DWORD createNtfsJunction(QString target, QString linkName, QString *errorMessage)
{
typedef struct {
diff --git a/tests/testserver/apache2/apache2.sh b/tests/testserver/apache2/apache2.sh
index 4b0c74e2c4..d5075c7096 100755
--- a/tests/testserver/apache2/apache2.sh
+++ b/tests/testserver/apache2/apache2.sh
@@ -73,5 +73,8 @@ touch -d "2007-05-22 12:04:57 GMT" /home/$USER/www/htdocs/fluke.gif
# Create 10MB file for use by tst_Q*::downloadBigFile and interruption tests:
su $USER -c "/bin/dd if=/dev/zero of=~/www/htdocs/mediumfile bs=1 count=0 seek=10000000"
+# Emulate test server's hierarchy:
+su $USER -c "ln -s ~/www/htdocs/rfcs/rfc2616.html ~/www/htdocs/deflate/"
+
# enable service with installed configurations
service apache2 restart
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi
new file mode 100755
index 0000000000..7dc506fc1e
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi
@@ -0,0 +1,7 @@
+#!/bin/bash
+# cache control takes precedence over expires
+echo "Cache-Control: max-age=-1"
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi
new file mode 100755
index 0000000000..f2edfc161f
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi
@@ -0,0 +1,13 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_MODIFIED_SINCE} ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+cc=`echo "${QUERY_STRING}" | sed -e s/%20/\ /g`
+echo "Cache-Control: $cc"
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi
new file mode 100755
index 0000000000..e44d5ed570
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi
@@ -0,0 +1,9 @@
+#!/bin/bash
+cc=`echo "${QUERY_STRING}" | sed -e s/%20/\ /g`
+echo "Status: 200"
+echo "Cache-Control: $cc"
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo "X-Script: $0"
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi
new file mode 100755
index 0000000000..0966abfdd1
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "ETag: foo"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi
new file mode 100755
index 0000000000..91a4b922bd
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_NONE_MATCH} ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "ETag: foo"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi
new file mode 100755
index 0000000000..e18ebc86ad
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "Expires: Sat, 31 Oct 1981 6:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi
new file mode 100755
index 0000000000..1c7de1cd77
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ${HTTP_IF_MODIFIED_SINCE} == "Mon, 30 Oct 2028 14:19:41 GMT" ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi
new file mode 100755
index 0000000000..5dc219b1e7
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "Last-Modified: Sat, 31 Oct 1981 6:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi
new file mode 100755
index 0000000000..bdf23bed2f
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ${HTTP_IF_MODIFIED_SINCE} == "Sat, 31 Oct 1981 06:00:00 GMT" ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes b/tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes
new file mode 100644
index 0000000000..1d09ee726e
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes
@@ -0,0 +1 @@
+rfc2616.html binary
diff --git a/tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html b/tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html
new file mode 100644
index 0000000000..0e3282fb8d
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html
@@ -0,0 +1,8380 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html><head><title>RFC 2616 (rfc2616) - Hypertext Transfer Protocol -- HTTP/1.1</title>
+
+
+
+<meta name="description" content="RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1">
+<meta name="obsoletes" content="RFC2068">
+<script language="JavaScript1.2">
+function erfc(s)
+{document.write("<A href=\"/rfccomment.php?rfcnum="+s+"\" target=\"_blank\" onclick=\"window.open('/rfccomment.php?rfcnum="+s+"','Popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=680,height=530,left=30,top=43'); return false;\")>Comment on RFC "+s+"</A>\n");}
+//-->
+</script></head><body bgcolor="#ffffff" text="#000000">
+<p align="center"><img src="rfc2616_files/library.htm" alt="" align="middle" border="0" height="62" width="150"></p>
+<h1 align="center">RFC 2616 (RFC2616)</h1>
+<p align="center">Internet RFC/STD/FYI/BCP Archives</p>
+
+<div align="center">[ <a href="http://firefly.troll.no/rfcs/">RFC Index</a> | <a href="http://firefly.troll.no/rfcs/rfcsearch.html">RFC Search</a> | <a href="http://firefly.troll.no/faqs/">Usenet FAQs</a> | <a href="http://firefly.troll.no/contrib/">Web FAQs</a> | <a href="http://firefly.troll.no/docs/">Documents</a> | <a href="http://www.city-data.com/">Cities</a> ]
+<p>
+<strong>Alternate Formats:</strong>
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.txt">rfc2616.txt</a> |
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.ps">rfc2616.ps</a> |
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.pdf">rfc2616.pdf</a></p></div>
+<p align="center"><script language="JavaScript"><!--
+erfc("2616");
+// --></script><a href="http://firefly.troll.no/rfccomment.php?rfcnum=2616" target="_blank" onclick="window.open('/rfccomment.php?rfcnum=2616','Popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=680,height=530,left=30,top=43'); return false;" )="">Comment on RFC 2616</a>
+</p>
+<h3 align="center">RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1</h3>
+<hr noshade="noshade" size="2">
+<pre>
+Network Working Group R. Fielding
+Request for Comments: 2616 UC Irvine
+Obsoletes: 2068 J. Gettys
+Category: Standards Track Compaq/W3C
+ J. Mogul
+ Compaq
+ H. Frystyk
+ W3C/MIT
+ L. Masinter
+ Xerox
+ P. Leach
+ Microsoft
+ T. Berners-Lee
+ W3C/MIT
+ June 1999
+
+ Hypertext Transfer Protocol -- HTTP/1.1
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ The Hypertext Transfer Protocol (HTTP) is an application-level
+ protocol for distributed, collaborative, hypermedia information
+ systems. It is a generic, stateless, protocol which can be used for
+ many tasks beyond its use for hypertext, such as name servers and
+ distributed object management systems, through extension of its
+ request methods, error codes and headers [47]. A feature of HTTP is
+ the typing and negotiation of data representation, allowing systems
+ to be built independently of the data being transferred.
+
+ HTTP has been in use by the World-Wide Web global information
+ initiative since 1990. This specification defines the protocol
+ referred to as "HTTP/1.1", and is an update to <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> [33].
+
+Table of Contents
+
+ 1 Introduction ...................................................7
+ 1.1 Purpose......................................................7
+ 1.2 Requirements .................................................8
+ 1.3 Terminology ..................................................8
+ 1.4 Overall Operation ...........................................12
+ 2 Notational Conventions and Generic Grammar ....................14
+ 2.1 Augmented BNF ...............................................14
+ 2.2 Basic Rules .................................................15
+ 3 Protocol Parameters ...........................................17
+ 3.1 HTTP Version ................................................17
+ 3.2 Uniform Resource Identifiers ................................18
+ 3.2.1 General Syntax ...........................................19
+ 3.2.2 http URL .................................................19
+ 3.2.3 URI Comparison ...........................................20
+ 3.3 Date/Time Formats ...........................................20
+ 3.3.1 Full Date ................................................20
+ 3.3.2 Delta Seconds ............................................21
+ 3.4 Character Sets ..............................................21
+ 3.4.1 Missing Charset ..........................................22
+ 3.5 Content Codings .............................................23
+ 3.6 Transfer Codings ............................................24
+ 3.6.1 Chunked Transfer Coding ..................................25
+ 3.7 Media Types .................................................26
+ 3.7.1 Canonicalization and Text Defaults .......................27
+ 3.7.2 Multipart Types ..........................................27
+ 3.8 Product Tokens ..............................................28
+ 3.9 Quality Values ..............................................29
+ 3.10 Language Tags ...............................................29
+ 3.11 Entity Tags .................................................30
+ 3.12 Range Units .................................................30
+ 4 HTTP Message ..................................................31
+ 4.1 Message Types ...............................................31
+ 4.2 Message Headers .............................................31
+ 4.3 Message Body ................................................32
+ 4.4 Message Length ..............................................33
+ 4.5 General Header Fields .......................................34
+ 5 Request .......................................................35
+ 5.1 Request-Line ................................................35
+ 5.1.1 Method ...................................................36
+ 5.1.2 Request-URI ..............................................36
+ 5.2 The Resource Identified by a Request ........................38
+ 5.3 Request Header Fields .......................................38
+ 6 Response ......................................................39
+ 6.1 Status-Line .................................................39
+ 6.1.1 Status Code and Reason Phrase ............................39
+ 6.2 Response Header Fields ......................................41
+
+ 7 Entity ........................................................42
+ 7.1 Entity Header Fields ........................................42
+ 7.2 Entity Body .................................................43
+ 7.2.1 Type .....................................................43
+ 7.2.2 Entity Length ............................................43
+ 8 Connections ...................................................44
+ 8.1 Persistent Connections ......................................44
+ 8.1.1 Purpose ..................................................44
+ 8.1.2 Overall Operation ........................................45
+ 8.1.3 Proxy Servers ............................................46
+ 8.1.4 Practical Considerations .................................46
+ 8.2 Message Transmission Requirements ...........................47
+ 8.2.1 Persistent Connections and Flow Control ..................47
+ 8.2.2 Monitoring Connections for Error Status Messages .........48
+ 8.2.3 Use of the 100 (Continue) Status .........................48
+ 8.2.4 Client Behavior if Server Prematurely Closes Connection ..50
+ 9 Method Definitions ............................................51
+ 9.1 Safe and Idempotent Methods .................................51
+ 9.1.1 Safe Methods .............................................51
+ 9.1.2 Idempotent Methods .......................................51
+ 9.2 OPTIONS .....................................................52
+ 9.3 GET .........................................................53
+ 9.4 HEAD ........................................................54
+ 9.5 POST ........................................................54
+ 9.6 PUT .........................................................55
+ 9.7 DELETE ......................................................56
+ 9.8 TRACE .......................................................56
+ 9.9 CONNECT .....................................................57
+ 10 Status Code Definitions ......................................57
+ 10.1 Informational 1xx ...........................................57
+ 10.1.1 100 Continue .............................................58
+ 10.1.2 101 Switching Protocols ..................................58
+ 10.2 Successful 2xx ..............................................58
+ 10.2.1 200 OK ...................................................58
+ 10.2.2 201 Created ..............................................59
+ 10.2.3 202 Accepted .............................................59
+ 10.2.4 203 Non-Authoritative Information ........................59
+ 10.2.5 204 No Content ...........................................60
+ 10.2.6 205 Reset Content ........................................60
+ 10.2.7 206 Partial Content ......................................60
+ 10.3 Redirection 3xx .............................................61
+ 10.3.1 300 Multiple Choices .....................................61
+ 10.3.2 301 Moved Permanently ....................................62
+ 10.3.3 302 Found ................................................62
+ 10.3.4 303 See Other ............................................63
+ 10.3.5 304 Not Modified .........................................63
+ 10.3.6 305 Use Proxy ............................................64
+ 10.3.7 306 (Unused) .............................................64
+
+ 10.3.8 307 Temporary Redirect ...................................65
+ 10.4 Client Error 4xx ............................................65
+ 10.4.1 400 Bad Request .........................................65
+ 10.4.2 401 Unauthorized ........................................66
+ 10.4.3 402 Payment Required ....................................66
+ 10.4.4 403 Forbidden ...........................................66
+ 10.4.5 404 Not Found ...........................................66
+ 10.4.6 405 Method Not Allowed ..................................66
+ 10.4.7 406 Not Acceptable ......................................67
+ 10.4.8 407 Proxy Authentication Required .......................67
+ 10.4.9 408 Request Timeout .....................................67
+ 10.4.10 409 Conflict ............................................67
+ 10.4.11 410 Gone ................................................68
+ 10.4.12 411 Length Required .....................................68
+ 10.4.13 412 Precondition Failed .................................68
+ 10.4.14 413 Request Entity Too Large ............................69
+ 10.4.15 414 Request-URI Too Long ................................69
+ 10.4.16 415 Unsupported Media Type ..............................69
+ 10.4.17 416 Requested Range Not Satisfiable .....................69
+ 10.4.18 417 Expectation Failed ..................................70
+ 10.5 Server Error 5xx ............................................70
+ 10.5.1 500 Internal Server Error ................................70
+ 10.5.2 501 Not Implemented ......................................70
+ 10.5.3 502 Bad Gateway ..........................................70
+ 10.5.4 503 Service Unavailable ..................................70
+ 10.5.5 504 Gateway Timeout ......................................71
+ 10.5.6 505 HTTP Version Not Supported ...........................71
+ 11 Access Authentication ........................................71
+ 12 Content Negotiation ..........................................71
+ 12.1 Server-driven Negotiation ...................................72
+ 12.2 Agent-driven Negotiation ....................................73
+ 12.3 Transparent Negotiation .....................................74
+ 13 Caching in HTTP ..............................................74
+ 13.1.1 Cache Correctness ........................................75
+ 13.1.2 Warnings .................................................76
+ 13.1.3 Cache-control Mechanisms .................................77
+ 13.1.4 Explicit User Agent Warnings .............................78
+ 13.1.5 Exceptions to the Rules and Warnings .....................78
+ 13.1.6 Client-controlled Behavior ...............................79
+ 13.2 Expiration Model ............................................79
+ 13.2.1 Server-Specified Expiration ..............................79
+ 13.2.2 Heuristic Expiration .....................................80
+ 13.2.3 Age Calculations .........................................80
+ 13.2.4 Expiration Calculations ..................................83
+ 13.2.5 Disambiguating Expiration Values .........................84
+ 13.2.6 Disambiguating Multiple Responses ........................84
+ 13.3 Validation Model ............................................85
+ 13.3.1 Last-Modified Dates ......................................86
+
+ 13.3.2 Entity Tag Cache Validators ..............................86
+ 13.3.3 Weak and Strong Validators ...............................86
+ 13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates.89
+ 13.3.5 Non-validating Conditionals ..............................90
+ 13.4 Response Cacheability .......................................91
+ 13.5 Constructing Responses From Caches ..........................92
+ 13.5.1 End-to-end and Hop-by-hop Headers ........................92
+ 13.5.2 Non-modifiable Headers ...................................92
+ 13.5.3 Combining Headers ........................................94
+ 13.5.4 Combining Byte Ranges ....................................95
+ 13.6 Caching Negotiated Responses ................................95
+ 13.7 Shared and Non-Shared Caches ................................96
+ 13.8 Errors or Incomplete Response Cache Behavior ................97
+ 13.9 Side Effects of GET and HEAD ................................97
+ 13.10 Invalidation After Updates or Deletions ...................97
+ 13.11 Write-Through Mandatory ...................................98
+ 13.12 Cache Replacement .........................................99
+ 13.13 History Lists .............................................99
+ 14 Header Field Definitions ....................................100
+ 14.1 Accept .....................................................100
+ 14.2 Accept-Charset .............................................102
+ 14.3 Accept-Encoding ............................................102
+ 14.4 Accept-Language ............................................104
+ 14.5 Accept-Ranges ..............................................105
+ 14.6 Age ........................................................106
+ 14.7 Allow ......................................................106
+ 14.8 Authorization ..............................................107
+ 14.9 Cache-Control ..............................................108
+ 14.9.1 What is Cacheable .......................................109
+ 14.9.2 What May be Stored by Caches ............................110
+ 14.9.3 Modifications of the Basic Expiration Mechanism .........111
+ 14.9.4 Cache Revalidation and Reload Controls ..................113
+ 14.9.5 No-Transform Directive ..................................115
+ 14.9.6 Cache Control Extensions ................................116
+ 14.10 Connection ...............................................117
+ 14.11 Content-Encoding .........................................118
+ 14.12 Content-Language .........................................118
+ 14.13 Content-Length ...........................................119
+ 14.14 Content-Location .........................................120
+ 14.15 Content-MD5 ..............................................121
+ 14.16 Content-Range ............................................122
+ 14.17 Content-Type .............................................124
+ 14.18 Date .....................................................124
+ 14.18.1 Clockless Origin Server Operation ......................125
+ 14.19 ETag .....................................................126
+ 14.20 Expect ...................................................126
+ 14.21 Expires ..................................................127
+ 14.22 From .....................................................128
+
+ 14.23 Host .....................................................128
+ 14.24 If-Match .................................................129
+ 14.25 If-Modified-Since ........................................130
+ 14.26 If-None-Match ............................................132
+ 14.27 If-Range .................................................133
+ 14.28 If-Unmodified-Since ......................................134
+ 14.29 Last-Modified ............................................134
+ 14.30 Location .................................................135
+ 14.31 Max-Forwards .............................................136
+ 14.32 Pragma ...................................................136
+ 14.33 Proxy-Authenticate .......................................137
+ 14.34 Proxy-Authorization ......................................137
+ 14.35 Range ....................................................138
+ 14.35.1 Byte Ranges ...........................................138
+ 14.35.2 Range Retrieval Requests ..............................139
+ 14.36 Referer ..................................................140
+ 14.37 Retry-After ..............................................141
+ 14.38 Server ...................................................141
+ 14.39 TE .......................................................142
+ 14.40 Trailer ..................................................143
+ 14.41 Transfer-Encoding..........................................143
+ 14.42 Upgrade ..................................................144
+ 14.43 User-Agent ...............................................145
+ 14.44 Vary .....................................................145
+ 14.45 Via ......................................................146
+ 14.46 Warning ..................................................148
+ 14.47 WWW-Authenticate .........................................150
+ 15 Security Considerations .......................................150
+ 15.1 Personal Information....................................151
+ 15.1.1 Abuse of Server Log Information .........................151
+ 15.1.2 Transfer of Sensitive Information .......................151
+ 15.1.3 Encoding Sensitive Information in URI's .................152
+ 15.1.4 Privacy Issues Connected to Accept Headers ..............152
+ 15.2 Attacks Based On File and Path Names .......................153
+ 15.3 DNS Spoofing ...............................................154
+ 15.4 Location Headers and Spoofing ..............................154
+ 15.5 Content-Disposition Issues .................................154
+ 15.6 Authentication Credentials and Idle Clients ................155
+ 15.7 Proxies and Caching ........................................155
+ 15.7.1 Denial of Service Attacks on Proxies....................156
+ 16 Acknowledgments .............................................156
+ 17 References ..................................................158
+ 18 Authors' Addresses ..........................................162
+ 19 Appendices ..................................................164
+ 19.1 Internet Media Type message/http and application/http ......164
+ 19.2 Internet Media Type multipart/byteranges ...................165
+ 19.3 Tolerant Applications ......................................166
+ 19.4 Differences Between HTTP Entities and <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> Entities ....167
+
+ 19.4.1 MIME-Version ............................................167
+ 19.4.2 Conversion to Canonical Form ............................167
+ 19.4.3 Conversion of Date Formats ..............................168
+ 19.4.4 Introduction of Content-Encoding ........................168
+ 19.4.5 No Content-Transfer-Encoding ............................168
+ 19.4.6 Introduction of Transfer-Encoding .......................169
+ 19.4.7 MHTML and Line Length Limitations .......................169
+ 19.5 Additional Features ........................................169
+ 19.5.1 Content-Disposition .....................................170
+ 19.6 Compatibility with Previous Versions .......................170
+ 19.6.1 Changes from HTTP/1.0 ...................................171
+ 19.6.2 Compatibility with HTTP/1.0 Persistent Connections ......172
+ 19.6.3 Changes from <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> ...................................172
+ 20 Index .......................................................175
+ 21 Full Copyright Statement ....................................176
+
+1 Introduction
+
+1.1 Purpose
+
+ The Hypertext Transfer Protocol (HTTP) is an application-level
+ protocol for distributed, collaborative, hypermedia information
+ systems. HTTP has been in use by the World-Wide Web global
+ information initiative since 1990. The first version of HTTP,
+ referred to as HTTP/0.9, was a simple protocol for raw data transfer
+ across the Internet. HTTP/1.0, as defined by <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a> [6], improved
+ the protocol by allowing messages to be in the format of MIME-like
+ messages, containing metainformation about the data transferred and
+ modifiers on the request/response semantics. However, HTTP/1.0 does
+ not sufficiently take into consideration the effects of hierarchical
+ proxies, caching, the need for persistent connections, or virtual
+ hosts. In addition, the proliferation of incompletely-implemented
+ applications calling themselves "HTTP/1.0" has necessitated a
+ protocol version change in order for two communicating applications
+ to determine each other's true capabilities.
+
+ This specification defines the protocol referred to as "HTTP/1.1".
+ This protocol includes more stringent requirements than HTTP/1.0 in
+ order to ensure reliable implementation of its features.
+
+ Practical information systems require more functionality than simple
+ retrieval, including search, front-end update, and annotation. HTTP
+ allows an open-ended set of methods and headers that indicate the
+ purpose of a request [47]. It builds on the discipline of reference
+ provided by the Uniform Resource Identifier (URI) [3], as a location
+ (URL) [4] or name (URN) [20], for indicating the resource to which a
+
+ method is to be applied. Messages are passed in a format similar to
+ that used by Internet mail [9] as defined by the Multipurpose
+ Internet Mail Extensions (MIME) [7].
+
+ HTTP is also used as a generic protocol for communication between
+ user agents and proxies/gateways to other Internet systems, including
+ those supported by the SMTP [16], NNTP [13], FTP [18], Gopher [2],
+ and WAIS [10] protocols. In this way, HTTP allows basic hypermedia
+ access to resources available from diverse applications.
+
+1.2 Requirements
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in <a href="http://firefly.troll.no/rfcs/rfc2119.html">RFC 2119</a> [34].
+
+ An implementation is not compliant if it fails to satisfy one or more
+ of the MUST or REQUIRED level requirements for the protocols it
+ implements. An implementation that satisfies all the MUST or REQUIRED
+ level and all the SHOULD level requirements for its protocols is said
+ to be "unconditionally compliant"; one that satisfies all the MUST
+ level requirements but not all the SHOULD level requirements for its
+ protocols is said to be "conditionally compliant."
+
+1.3 Terminology
+
+ This specification uses a number of terms to refer to the roles
+ played by participants in, and objects of, the HTTP communication.
+
+ connection
+ A transport layer virtual circuit established between two programs
+ for the purpose of communication.
+
+ message
+ The basic unit of HTTP communication, consisting of a structured
+ sequence of octets matching the syntax defined in section 4 and
+ transmitted via the connection.
+
+ request
+ An HTTP request message, as defined in section 5.
+
+ response
+ An HTTP response message, as defined in section 6.
+
+ resource
+ A network data object or service that can be identified by a URI,
+ as defined in section 3.2. Resources may be available in multiple
+ representations (e.g. multiple languages, data formats, size, and
+ resolutions) or vary in other ways.
+
+ entity
+ The information transferred as the payload of a request or
+ response. An entity consists of metainformation in the form of
+ entity-header fields and content in the form of an entity-body, as
+ described in section 7.
+
+ representation
+ An entity included with a response that is subject to content
+ negotiation, as described in section 12. There may exist multiple
+ representations associated with a particular response status.
+
+ content negotiation
+ The mechanism for selecting the appropriate representation when
+ servicing a request, as described in section 12. The
+ representation of entities in any response can be negotiated
+ (including error responses).
+
+ variant
+ A resource may have one, or more than one, representation(s)
+ associated with it at any given instant. Each of these
+ representations is termed a `varriant'. Use of the term `variant'
+ does not necessarily imply that the resource is subject to content
+ negotiation.
+
+ client
+ A program that establishes connections for the purpose of sending
+ requests.
+
+ user agent
+ The client which initiates a request. These are often browsers,
+ editors, spiders (web-traversing robots), or other end user tools.
+
+ server
+ An application program that accepts connections in order to
+ service requests by sending back responses. Any given program may
+ be capable of being both a client and a server; our use of these
+ terms refers only to the role being performed by the program for a
+ particular connection, rather than to the program's capabilities
+ in general. Likewise, any server may act as an origin server,
+ proxy, gateway, or tunnel, switching behavior based on the nature
+ of each request.
+
+ origin server
+ The server on which a given resource resides or is to be created.
+
+ proxy
+ An intermediary program which acts as both a server and a client
+ for the purpose of making requests on behalf of other clients.
+ Requests are serviced internally or by passing them on, with
+ possible translation, to other servers. A proxy MUST implement
+ both the client and server requirements of this specification. A
+ "transparent proxy" is a proxy that does not modify the request or
+ response beyond what is required for proxy authentication and
+ identification. A "non-transparent proxy" is a proxy that modifies
+ the request or response in order to provide some added service to
+ the user agent, such as group annotation services, media type
+ transformation, protocol reduction, or anonymity filtering. Except
+ where either transparent or non-transparent behavior is explicitly
+ stated, the HTTP proxy requirements apply to both types of
+ proxies.
+
+ gateway
+ A server which acts as an intermediary for some other server.
+ Unlike a proxy, a gateway receives requests as if it were the
+ origin server for the requested resource; the requesting client
+ may not be aware that it is communicating with a gateway.
+
+ tunnel
+ An intermediary program which is acting as a blind relay between
+ two connections. Once active, a tunnel is not considered a party
+ to the HTTP communication, though the tunnel may have been
+ initiated by an HTTP request. The tunnel ceases to exist when both
+ ends of the relayed connections are closed.
+
+ cache
+ A program's local store of response messages and the subsystem
+ that controls its message storage, retrieval, and deletion. A
+ cache stores cacheable responses in order to reduce the response
+ time and network bandwidth consumption on future, equivalent
+ requests. Any client or server may include a cache, though a cache
+ cannot be used by a server that is acting as a tunnel.
+
+ cacheable
+ A response is cacheable if a cache is allowed to store a copy of
+ the response message for use in answering subsequent requests. The
+ rules for determining the cacheability of HTTP responses are
+ defined in section 13. Even if a resource is cacheable, there may
+ be additional constraints on whether a cache can use the cached
+ copy for a particular request.
+
+ first-hand
+ A response is first-hand if it comes directly and without
+ unnecessary delay from the origin server, perhaps via one or more
+ proxies. A response is also first-hand if its validity has just
+ been checked directly with the origin server.
+
+ explicit expiration time
+ The time at which the origin server intends that an entity should
+ no longer be returned by a cache without further validation.
+
+ heuristic expiration time
+ An expiration time assigned by a cache when no explicit expiration
+ time is available.
+
+ age
+ The age of a response is the time since it was sent by, or
+ successfully validated with, the origin server.
+
+ freshness lifetime
+ The length of time between the generation of a response and its
+ expiration time.
+
+ fresh
+ A response is fresh if its age has not yet exceeded its freshness
+ lifetime.
+
+ stale
+ A response is stale if its age has passed its freshness lifetime.
+
+ semantically transparent
+ A cache behaves in a "semantically transparent" manner, with
+ respect to a particular response, when its use affects neither the
+ requesting client nor the origin server, except to improve
+ performance. When a cache is semantically transparent, the client
+ receives exactly the same response (except for hop-by-hop headers)
+ that it would have received had its request been handled directly
+ by the origin server.
+
+ validator
+ A protocol element (e.g., an entity tag or a Last-Modified time)
+ that is used to find out whether a cache entry is an equivalent
+ copy of an entity.
+
+ upstream/downstream
+ Upstream and downstream describe the flow of a message: all
+ messages flow from upstream to downstream.
+
+ inbound/outbound
+ Inbound and outbound refer to the request and response paths for
+ messages: "inbound" means "traveling toward the origin server",
+ and "outbound" means "traveling toward the user agent"
+
+1.4 Overall Operation
+
+ The HTTP protocol is a request/response protocol. A client sends a
+ request to the server in the form of a request method, URI, and
+ protocol version, followed by a MIME-like message containing request
+ modifiers, client information, and possible body content over a
+ connection with a server. The server responds with a status line,
+ including the message's protocol version and a success or error code,
+ followed by a MIME-like message containing server information, entity
+ metainformation, and possible entity-body content. The relationship
+ between HTTP and MIME is described in appendix 19.4.
+
+ Most HTTP communication is initiated by a user agent and consists of
+ a request to be applied to a resource on some origin server. In the
+ simplest case, this may be accomplished via a single connection (v)
+ between the user agent (UA) and the origin server (O).
+
+ request chain ------------------------&gt;
+ UA -------------------v------------------- O
+ &lt;----------------------- response chain
+
+ A more complicated situation occurs when one or more intermediaries
+ are present in the request/response chain. There are three common
+ forms of intermediary: proxy, gateway, and tunnel. A proxy is a
+ forwarding agent, receiving requests for a URI in its absolute form,
+ rewriting all or part of the message, and forwarding the reformatted
+ request toward the server identified by the URI. A gateway is a
+ receiving agent, acting as a layer above some other server(s) and, if
+ necessary, translating the requests to the underlying server's
+ protocol. A tunnel acts as a relay point between two connections
+ without changing the messages; tunnels are used when the
+ communication needs to pass through an intermediary (such as a
+ firewall) even when the intermediary cannot understand the contents
+ of the messages.
+
+ request chain --------------------------------------&gt;
+ UA -----v----- A -----v----- B -----v----- C -----v----- O
+ &lt;------------------------------------- response chain
+
+ The figure above shows three intermediaries (A, B, and C) between the
+ user agent and origin server. A request or response message that
+ travels the whole chain will pass through four separate connections.
+ This distinction is important because some HTTP communication options
+
+ may apply only to the connection with the nearest, non-tunnel
+ neighbor, only to the end-points of the chain, or to all connections
+ along the chain. Although the diagram is linear, each participant may
+ be engaged in multiple, simultaneous communications. For example, B
+ may be receiving requests from many clients other than A, and/or
+ forwarding requests to servers other than C, at the same time that it
+ is handling A's request.
+
+ Any party to the communication which is not acting as a tunnel may
+ employ an internal cache for handling requests. The effect of a cache
+ is that the request/response chain is shortened if one of the
+ participants along the chain has a cached response applicable to that
+ request. The following illustrates the resulting chain if B has a
+ cached copy of an earlier response from O (via C) for a request which
+ has not been cached by UA or A.
+
+ request chain ----------&gt;
+ UA -----v----- A -----v----- B - - - - - - C - - - - - - O
+ &lt;--------- response chain
+
+ Not all responses are usefully cacheable, and some requests may
+ contain modifiers which place special requirements on cache behavior.
+ HTTP requirements for cache behavior and cacheable responses are
+ defined in section 13.
+
+ In fact, there are a wide variety of architectures and configurations
+ of caches and proxies currently being experimented with or deployed
+ across the World Wide Web. These systems include national hierarchies
+ of proxy caches to save transoceanic bandwidth, systems that
+ broadcast or multicast cache entries, organizations that distribute
+ subsets of cached data via CD-ROM, and so on. HTTP systems are used
+ in corporate intranets over high-bandwidth links, and for access via
+ PDAs with low-power radio links and intermittent connectivity. The
+ goal of HTTP/1.1 is to support the wide diversity of configurations
+ already deployed while introducing protocol constructs that meet the
+ needs of those who build web applications that require high
+ reliability and, failing that, at least reliable indications of
+ failure.
+
+ HTTP communication usually takes place over TCP/IP connections. The
+ default port is TCP 80 [19], but other ports can be used. This does
+ not preclude HTTP from being implemented on top of any other protocol
+ on the Internet, or on other networks. HTTP only presumes a reliable
+ transport; any protocol that provides such guarantees can be used;
+ the mapping of the HTTP/1.1 request and response structures onto the
+ transport data units of the protocol in question is outside the scope
+ of this specification.
+
+ In HTTP/1.0, most implementations used a new connection for each
+ request/response exchange. In HTTP/1.1, a connection may be used for
+ one or more request/response exchanges, although connections may be
+ closed for a variety of reasons (see section 8.1).
+
+2 Notational Conventions and Generic Grammar
+
+2.1 Augmented BNF
+
+ All of the mechanisms specified in this document are described in
+ both prose and an augmented Backus-Naur Form (BNF) similar to that
+ used by <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]. Implementors will need to be familiar with the
+ notation in order to understand this specification. The augmented BNF
+ includes the following constructs:
+
+ name = definition
+ The name of a rule is simply the name itself (without any
+ enclosing "&lt;" and "&gt;") and is separated from its definition by the
+ equal "=" character. White space is only significant in that
+ indentation of continuation lines is used to indicate a rule
+ definition that spans more than one line. Certain basic rules are
+ in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle
+ brackets are used within definitions whenever their presence will
+ facilitate discerning the use of rule names.
+
+ "literal"
+ Quotation marks surround literal text. Unless stated otherwise,
+ the text is case-insensitive.
+
+ rule1 | rule2
+ Elements separated by a bar ("|") are alternatives, e.g., "yes |
+ no" will accept yes or no.
+
+ (rule1 rule2)
+ Elements enclosed in parentheses are treated as a single element.
+ Thus, "(elem (foo | bar) elem)" allows the token sequences "elem
+ foo elem" and "elem bar elem".
+
+ *rule
+ The character "*" preceding an element indicates repetition. The
+ full form is "&lt;n&gt;*&lt;m&gt;element" indicating at least &lt;n&gt; and at most
+ &lt;m&gt; occurrences of element. Default values are 0 and infinity so
+ that "*(element)" allows any number, including zero; "1*element"
+ requires at least one; and "1*2element" allows one or two.
+
+ [rule]
+ Square brackets enclose optional elements; "[foo bar]" is
+ equivalent to "*1(foo bar)".
+
+ N rule
+ Specific repetition: "&lt;n&gt;(element)" is equivalent to
+ "&lt;n&gt;*&lt;n&gt;(element)"; that is, exactly &lt;n&gt; occurrences of (element).
+ Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three
+ alphabetic characters.
+
+ #rule
+ A construct "#" is defined, similar to "*", for defining lists of
+ elements. The full form is "&lt;n&gt;#&lt;m&gt;element" indicating at least
+ &lt;n&gt; and at most &lt;m&gt; elements, each separated by one or more commas
+ (",") and OPTIONAL linear white space (LWS). This makes the usual
+ form of lists very easy; a rule such as
+ ( *LWS element *( *LWS "," *LWS element ))
+ can be shown as
+ 1#element
+ Wherever this construct is used, null elements are allowed, but do
+ not contribute to the count of elements present. That is,
+ "(element), , (element) " is permitted, but counts as only two
+ elements. Therefore, where at least one element is required, at
+ least one non-null element MUST be present. Default values are 0
+ and infinity so that "#element" allows any number, including zero;
+ "1#element" requires at least one; and "1#2element" allows one or
+ two.
+
+ ; comment
+ A semi-colon, set off some distance to the right of rule text,
+ starts a comment that continues to the end of line. This is a
+ simple way of including useful notes in parallel with the
+ specifications.
+
+ implied *LWS
+ The grammar described by this specification is word-based. Except
+ where noted otherwise, linear white space (LWS) can be included
+ between any two adjacent words (token or quoted-string), and
+ between adjacent words and separators, without changing the
+ interpretation of a field. At least one delimiter (LWS and/or
+
+ separators) MUST exist between any two tokens (for the definition
+ of "token" below), since they would otherwise be interpreted as a
+ single token.
+
+2.2 Basic Rules
+
+ The following rules are used throughout this specification to
+ describe basic parsing constructs. The US-ASCII coded character set
+ is defined by ANSI X3.4-1986 [21].
+
+ OCTET = &lt;any 8-bit sequence of data&gt;
+ CHAR = &lt;any US-ASCII character (octets 0 - 127)&gt;
+ UPALPHA = &lt;any US-ASCII uppercase letter "A".."Z"&gt;
+ LOALPHA = &lt;any US-ASCII lowercase letter "a".."z"&gt;
+ ALPHA = UPALPHA | LOALPHA
+ DIGIT = &lt;any US-ASCII digit "0".."9"&gt;
+ CTL = &lt;any US-ASCII control character
+ (octets 0 - 31) and DEL (127)&gt;
+ CR = &lt;US-ASCII CR, carriage return (13)&gt;
+ LF = &lt;US-ASCII LF, linefeed (10)&gt;
+ SP = &lt;US-ASCII SP, space (32)&gt;
+ HT = &lt;US-ASCII HT, horizontal-tab (9)&gt;
+ &lt;"&gt; = &lt;US-ASCII double-quote mark (34)&gt;
+
+ HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
+ protocol elements except the entity-body (see appendix 19.3 for
+ tolerant applications). The end-of-line marker within an entity-body
+ is defined by its associated media type, as described in section 3.7.
+
+ CRLF = CR LF
+
+ HTTP/1.1 header field values can be folded onto multiple lines if the
+ continuation line begins with a space or horizontal tab. All linear
+ white space, including folding, has the same semantics as SP. A
+ recipient MAY replace any linear white space with a single SP before
+ interpreting the field value or forwarding the message downstream.
+
+ LWS = [CRLF] 1*( SP | HT )
+
+ The TEXT rule is only used for descriptive field contents and values
+ that are not intended to be interpreted by the message parser. Words
+ of *TEXT MAY contain characters from character sets other than ISO-
+ 8859-1 [22] only when encoded according to the rules of <a href="http://firefly.troll.no/rfcs/rfc2047.html">RFC 2047</a>
+ [14].
+
+ TEXT = &lt;any OCTET except CTLs,
+ but including LWS&gt;
+
+ A CRLF is allowed in the definition of TEXT only as part of a header
+ field continuation. It is expected that the folding LWS will be
+ replaced with a single SP before interpretation of the TEXT value.
+
+ Hexadecimal numeric characters are used in several protocol elements.
+
+ HEX = "A" | "B" | "C" | "D" | "E" | "F"
+ | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
+
+ Many HTTP/1.1 header field values consist of words separated by LWS
+ or special characters. These special characters MUST be in a quoted
+ string to be used within a parameter value (as defined in section
+ 3.6).
+
+ token = 1*&lt;any CHAR except CTLs or separators&gt;
+ separators = "(" | ")" | "&lt;" | "&gt;" | "@"
+ | "," | ";" | ":" | "\" | &lt;"&gt;
+ | "/" | "[" | "]" | "?" | "="
+ | "{" | "}" | SP | HT
+
+ Comments can be included in some HTTP header fields by surrounding
+ the comment text with parentheses. Comments are only allowed in
+ fields containing "comment" as part of their field value definition.
+ In all other fields, parentheses are considered part of the field
+ value.
+
+ comment = "(" *( ctext | quoted-pair | comment ) ")"
+ ctext = &lt;any TEXT excluding "(" and ")"&gt;
+
+ A string of text is parsed as a single word if it is quoted using
+ double-quote marks.
+
+ quoted-string = ( &lt;"&gt; *(qdtext | quoted-pair ) &lt;"&gt; )
+ qdtext = &lt;any TEXT except &lt;"&gt;&gt;
+
+ The backslash character ("\") MAY be used as a single-character
+ quoting mechanism only within quoted-string and comment constructs.
+
+ quoted-pair = "\" CHAR
+
+3 Protocol Parameters
+
+3.1 HTTP Version
+
+ HTTP uses a "&lt;major&gt;.&lt;minor&gt;" numbering scheme to indicate versions
+ of the protocol. The protocol versioning policy is intended to allow
+ the sender to indicate the format of a message and its capacity for
+ understanding further HTTP communication, rather than the features
+ obtained via that communication. No change is made to the version
+ number for the addition of message components which do not affect
+ communication behavior or which only add to extensible field values.
+ The &lt;minor&gt; number is incremented when the changes made to the
+ protocol add features which do not change the general message parsing
+ algorithm, but which may add to the message semantics and imply
+ additional capabilities of the sender. The &lt;major&gt; number is
+ incremented when the format of a message within the protocol is
+ changed. See <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a> [36] for a fuller explanation.
+
+ The version of an HTTP message is indicated by an HTTP-Version field
+ in the first line of the message.
+
+ HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+
+ Note that the major and minor numbers MUST be treated as separate
+ integers and that each MAY be incremented higher than a single digit.
+ Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is
+ lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and
+ MUST NOT be sent.
+
+ An application that sends a request or response message that includes
+ HTTP-Version of "HTTP/1.1" MUST be at least conditionally compliant
+ with this specification. Applications that are at least conditionally
+ compliant with this specification SHOULD use an HTTP-Version of
+ "HTTP/1.1" in their messages, and MUST do so for any message that is
+ not compatible with HTTP/1.0. For more details on when to send
+ specific HTTP-Version values, see <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a> [36].
+
+ The HTTP version of an application is the highest HTTP version for
+ which the application is at least conditionally compliant.
+
+ Proxy and gateway applications need to be careful when forwarding
+ messages in protocol versions different from that of the application.
+ Since the protocol version indicates the protocol capability of the
+ sender, a proxy/gateway MUST NOT send a message with a version
+ indicator which is greater than its actual version. If a higher
+ version request is received, the proxy/gateway MUST either downgrade
+ the request version, or respond with an error, or switch to tunnel
+ behavior.
+
+ Due to interoperability problems with HTTP/1.0 proxies discovered
+ since the publication of <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>[33], caching proxies MUST, gateways
+ MAY, and tunnels MUST NOT upgrade the request to the highest version
+ they support. The proxy/gateway's response to that request MUST be in
+ the same major version as the request.
+
+ Note: Converting between versions of HTTP may involve modification
+ of header fields required or forbidden by the versions involved.
+
+3.2 Uniform Resource Identifiers
+
+ URIs have been known by many names: WWW addresses, Universal Document
+ Identifiers, Universal Resource Identifiers [3], and finally the
+ combination of Uniform Resource Locators (URL) [4] and Names (URN)
+ [20]. As far as HTTP is concerned, Uniform Resource Identifiers are
+ simply formatted strings which identify--via name, location, or any
+ other characteristic--a resource.
+
+3.2.1 General Syntax
+
+ URIs in HTTP can be represented in absolute form or relative to some
+ known base URI [11], depending upon the context of their use. The two
+ forms are differentiated by the fact that absolute URIs always begin
+ with a scheme name followed by a colon. For definitive information on
+ URL syntax and semantics, see "Uniform Resource Identifiers (URI):
+ Generic Syntax and Semantics," <a href="http://firefly.troll.no/rfcs/rfc2396.html">RFC 2396</a> [42] (which replaces RFCs
+ 1738 [4] and <a href="http://firefly.troll.no/rfcs/rfc1808.html">RFC 1808</a> [11]). This specification adopts the
+ definitions of "URI-reference", "absoluteURI", "relativeURI", "port",
+ "host","abs_path", "rel_path", and "authority" from that
+ specification.
+
+ The HTTP protocol does not place any a priori limit on the length of
+ a URI. Servers MUST be able to handle the URI of any resource they
+ serve, and SHOULD be able to handle URIs of unbounded length if they
+ provide GET-based forms that could generate such URIs. A server
+ SHOULD return 414 (Request-URI Too Long) status if a URI is longer
+ than the server can handle (see section 10.4.15).
+
+ Note: Servers ought to be cautious about depending on URI lengths
+ above 255 bytes, because some older client or proxy
+ implementations might not properly support these lengths.
+
+3.2.2 http URL
+
+ The "http" scheme is used to locate network resources via the HTTP
+ protocol. This section defines the scheme-specific syntax and
+ semantics for http URLs.
+
+ http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
+
+ If the port is empty or not given, port 80 is assumed. The semantics
+ are that the identified resource is located at the server listening
+ for TCP connections on that port of that host, and the Request-URI
+ for the resource is abs_path (section 5.1.2). The use of IP addresses
+ in URLs SHOULD be avoided whenever possible (see <a href="http://firefly.troll.no/rfcs/rfc1900.html">RFC 1900</a> [24]). If
+ the abs_path is not present in the URL, it MUST be given as "/" when
+ used as a Request-URI for a resource (section 5.1.2). If a proxy
+ receives a host name which is not a fully qualified domain name, it
+ MAY add its domain to the host name it received. If a proxy receives
+ a fully qualified domain name, the proxy MUST NOT change the host
+ name.
+
+3.2.3 URI Comparison
+
+ When comparing two URIs to decide if they match or not, a client
+ SHOULD use a case-sensitive octet-by-octet comparison of the entire
+ URIs, with these exceptions:
+
+ - A port that is empty or not given is equivalent to the default
+ port for that URI-reference;
+
+ - Comparisons of host names MUST be case-insensitive;
+
+ - Comparisons of scheme names MUST be case-insensitive;
+
+ - An empty abs_path is equivalent to an abs_path of "/".
+
+ Characters other than those in the "reserved" and "unsafe" sets (see
+ <a href="http://firefly.troll.no/rfcs/rfc2396.html">RFC 2396</a> [42]) are equivalent to their ""%" HEX HEX" encoding.
+
+ For example, the following three URIs are equivalent:
+
+ <a href="http://abc.com/%7Esmith/home.html">http://abc.com:80/~smith/home.html</a>
+ <a href="http://abc.com/%7Esmith/home.html">http://ABC.com/%7Esmith/home.html</a>
+ <a href="http://firefly.troll.no/%3CA%20HREF=" ftp:="" abc.com="" %7esmith="" home.html="">/ABC.com:/%7esmith/home.html</a>"&gt;http:/<a href="ftp://abc.com/%7esmith/home.html%3C/A%3E">/ABC.com:/%7esmith/home.html</a>
+
+3.3 Date/Time Formats
+
+3.3.1 Full Date
+
+ HTTP applications have historically allowed three different formats
+ for the representation of date/time stamps:
+
+ Sun, 06 Nov 1994 08:49:37 GMT ; <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a>, updated by <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a>
+ Sunday, 06-Nov-94 08:49:37 GMT ; <a href="http://firefly.troll.no/rfcs/rfc850.html">RFC 850</a>, obsoleted by <a href="http://firefly.troll.no/rfcs/rfc1036.html">RFC 1036</a>
+ Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+
+ The first format is preferred as an Internet standard and represents
+ a fixed-length subset of that defined by <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> [8] (an update to
+ <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]). The second format is in common use, but is based on the
+ obsolete <a href="http://firefly.troll.no/rfcs/rfc850.html">RFC 850</a> [12] date format and lacks a four-digit year.
+ HTTP/1.1 clients and servers that parse the date value MUST accept
+ all three formats (for compatibility with HTTP/1.0), though they MUST
+ only generate the <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> format for representing HTTP-date values
+ in header fields. See section 19.3 for further information.
+
+ Note: Recipients of date values are encouraged to be robust in
+ accepting date values that may have been sent by non-HTTP
+ applications, as is sometimes the case when retrieving or posting
+ messages via proxies/gateways to SMTP or NNTP.
+
+ All HTTP date/time stamps MUST be represented in Greenwich Mean Time
+ (GMT), without exception. For the purposes of HTTP, GMT is exactly
+ equal to UTC (Coordinated Universal Time). This is indicated in the
+ first two formats by the inclusion of "GMT" as the three-letter
+ abbreviation for time zone, and MUST be assumed when reading the
+ asctime format. HTTP-date is case sensitive and MUST NOT include
+ additional LWS beyond that specifically included as SP in the
+ grammar.
+
+ HTTP-date = <a href="http://firefly.troll.no/rfcs/rfc1123.html">rfc1123</a>-date | <a href="http://firefly.troll.no/rfcs/rfc850.html">rfc850</a>-date | asctime-date
+ <a href="http://firefly.troll.no/rfcs/rfc1123.html">rfc1123</a>-date = wkday "," SP date1 SP time SP "GMT"
+ <a href="http://firefly.troll.no/rfcs/rfc850.html">rfc850</a>-date = weekday "," SP date2 SP time SP "GMT"
+ asctime-date = wkday SP date3 SP time SP 4DIGIT
+ date1 = 2DIGIT SP month SP 4DIGIT
+ ; day month year (e.g., 02 Jun 1982)
+ date2 = 2DIGIT "-" month "-" 2DIGIT
+ ; day-month-year (e.g., 02-Jun-82)
+ date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+ ; month day (e.g., Jun 2)
+ time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ ; 00:00:00 - 23:59:59
+ wkday = "Mon" | "Tue" | "Wed"
+ | "Thu" | "Fri" | "Sat" | "Sun"
+ weekday = "Monday" | "Tuesday" | "Wednesday"
+ | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ month = "Jan" | "Feb" | "Mar" | "Apr"
+ | "May" | "Jun" | "Jul" | "Aug"
+ | "Sep" | "Oct" | "Nov" | "Dec"
+
+ Note: HTTP requirements for the date/time stamp format apply only
+ to their usage within the protocol stream. Clients and servers are
+ not required to use these formats for user presentation, request
+ logging, etc.
+
+3.3.2 Delta Seconds
+
+ Some HTTP header fields allow a time value to be specified as an
+ integer number of seconds, represented in decimal, after the time
+ that the message was received.
+
+ delta-seconds = 1*DIGIT
+
+3.4 Character Sets
+
+ HTTP uses the same definition of the term "character set" as that
+ described for MIME:
+
+ The term "character set" is used in this document to refer to a
+ method used with one or more tables to convert a sequence of octets
+ into a sequence of characters. Note that unconditional conversion in
+ the other direction is not required, in that not all characters may
+ be available in a given character set and a character set may provide
+ more than one sequence of octets to represent a particular character.
+ This definition is intended to allow various kinds of character
+ encoding, from simple single-table mappings such as US-ASCII to
+ complex table switching methods such as those that use ISO-2022's
+ techniques. However, the definition associated with a MIME character
+ set name MUST fully specify the mapping to be performed from octets
+ to characters. In particular, use of external profiling information
+ to determine the exact mapping is not permitted.
+
+ Note: This use of the term "character set" is more commonly
+ referred to as a "character encoding." However, since HTTP and
+ MIME share the same registry, it is important that the terminology
+ also be shared.
+
+ HTTP character sets are identified by case-insensitive tokens. The
+ complete set of tokens is defined by the IANA Character Set registry
+ [19].
+
+ charset = token
+
+ Although HTTP allows an arbitrary token to be used as a charset
+ value, any token that has a predefined value within the IANA
+ Character Set registry [19] MUST represent the character set defined
+ by that registry. Applications SHOULD limit their use of character
+ sets to those defined by the IANA registry.
+
+ Implementors should be aware of IETF character set requirements [38]
+ [41].
+
+3.4.1 Missing Charset
+
+ Some HTTP/1.0 software has interpreted a Content-Type header without
+ charset parameter incorrectly to mean "recipient should guess."
+ Senders wishing to defeat this behavior MAY include a charset
+ parameter even when the charset is ISO-8859-1 and SHOULD do so when
+ it is known that it will not confuse the recipient.
+
+ Unfortunately, some older HTTP/1.0 clients did not deal properly with
+ an explicit charset parameter. HTTP/1.1 recipients MUST respect the
+ charset label provided by the sender; and those user agents that have
+ a provision to "guess" a charset MUST use the charset from the
+
+ content-type field if they support that charset, rather than the
+ recipient's preference, when initially displaying a document. See
+ section 3.7.1.
+
+3.5 Content Codings
+
+ Content coding values indicate an encoding transformation that has
+ been or can be applied to an entity. Content codings are primarily
+ used to allow a document to be compressed or otherwise usefully
+ transformed without losing the identity of its underlying media type
+ and without loss of information. Frequently, the entity is stored in
+ coded form, transmitted directly, and only decoded by the recipient.
+
+ content-coding = token
+
+ All content-coding values are case-insensitive. HTTP/1.1 uses
+ content-coding values in the Accept-Encoding (section 14.3) and
+ Content-Encoding (section 14.11) header fields. Although the value
+ describes the content-coding, what is more important is that it
+ indicates what decoding mechanism will be required to remove the
+ encoding.
+
+ The Internet Assigned Numbers Authority (IANA) acts as a registry for
+ content-coding value tokens. Initially, the registry contains the
+ following tokens:
+
+ gzip An encoding format produced by the file compression program
+ "gzip" (GNU zip) as described in <a href="http://firefly.troll.no/rfcs/rfc1952.html">RFC 1952</a> [25]. This format is a
+ Lempel-Ziv coding (LZ77) with a 32 bit CRC.
+
+ compress
+ The encoding format produced by the common UNIX file compression
+ program "compress". This format is an adaptive Lempel-Ziv-Welch
+ coding (LZW).
+
+ Use of program names for the identification of encoding formats
+ is not desirable and is discouraged for future encodings. Their
+ use here is representative of historical practice, not good
+ design. For compatibility with previous implementations of HTTP,
+ applications SHOULD consider "x-gzip" and "x-compress" to be
+ equivalent to "gzip" and "compress" respectively.
+
+ deflate
+ The "zlib" format defined in <a href="http://firefly.troll.no/rfcs/rfc1950.html">RFC 1950</a> [31] in combination with
+ the "deflate" compression mechanism described in <a href="http://firefly.troll.no/rfcs/rfc1951.html">RFC 1951</a> [29].
+
+ identity
+ The default (identity) encoding; the use of no transformation
+ whatsoever. This content-coding is used only in the Accept-
+ Encoding header, and SHOULD NOT be used in the Content-Encoding
+ header.
+
+ New content-coding value tokens SHOULD be registered; to allow
+ interoperability between clients and servers, specifications of the
+ content coding algorithms needed to implement a new value SHOULD be
+ publicly available and adequate for independent implementation, and
+ conform to the purpose of content coding defined in this section.
+
+3.6 Transfer Codings
+
+ Transfer-coding values are used to indicate an encoding
+ transformation that has been, can be, or may need to be applied to an
+ entity-body in order to ensure "safe transport" through the network.
+ This differs from a content coding in that the transfer-coding is a
+ property of the message, not of the original entity.
+
+ transfer-coding = "chunked" | transfer-extension
+ transfer-extension = token *( ";" parameter )
+
+ Parameters are in the form of attribute/value pairs.
+
+ parameter = attribute "=" value
+ attribute = token
+ value = token | quoted-string
+
+ All transfer-coding values are case-insensitive. HTTP/1.1 uses
+ transfer-coding values in the TE header field (section 14.39) and in
+ the Transfer-Encoding header field (section 14.41).
+
+ Whenever a transfer-coding is applied to a message-body, the set of
+ transfer-codings MUST include "chunked", unless the message is
+ terminated by closing the connection. When the "chunked" transfer-
+ coding is used, it MUST be the last transfer-coding applied to the
+ message-body. The "chunked" transfer-coding MUST NOT be applied more
+ than once to a message-body. These rules allow the recipient to
+ determine the transfer-length of the message (section 4.4).
+
+ Transfer-codings are analogous to the Content-Transfer-Encoding
+ values of MIME [7], which were designed to enable safe transport of
+ binary data over a 7-bit transport service. However, safe transport
+ has a different focus for an 8bit-clean transfer protocol. In HTTP,
+ the only unsafe characteristic of message-bodies is the difficulty in
+ determining the exact body length (section 7.2.2), or the desire to
+ encrypt data over a shared transport.
+
+ The Internet Assigned Numbers Authority (IANA) acts as a registry for
+ transfer-coding value tokens. Initially, the registry contains the
+ following tokens: "chunked" (section 3.6.1), "identity" (section
+ 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate"
+ (section 3.5).
+
+ New transfer-coding value tokens SHOULD be registered in the same way
+ as new content-coding value tokens (section 3.5).
+
+ A server which receives an entity-body with a transfer-coding it does
+ not understand SHOULD return 501 (Unimplemented), and close the
+ connection. A server MUST NOT send transfer-codings to an HTTP/1.0
+ client.
+
+3.6.1 Chunked Transfer Coding
+
+ The chunked encoding modifies the body of a message in order to
+ transfer it as a series of chunks, each with its own size indicator,
+ followed by an OPTIONAL trailer containing entity-header fields. This
+ allows dynamically produced content to be transferred along with the
+ information necessary for the recipient to verify that it has
+ received the full message.
+
+ Chunked-Body = *chunk
+ last-chunk
+ trailer
+ CRLF
+
+ chunk = chunk-size [ chunk-extension ] CRLF
+ chunk-data CRLF
+ chunk-size = 1*HEX
+ last-chunk = 1*("0") [ chunk-extension ] CRLF
+
+ chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ chunk-ext-name = token
+ chunk-ext-val = token | quoted-string
+ chunk-data = chunk-size(OCTET)
+ trailer = *(entity-header CRLF)
+
+ The chunk-size field is a string of hex digits indicating the size of
+ the chunk. The chunked encoding is ended by any chunk whose size is
+ zero, followed by the trailer, which is terminated by an empty line.
+
+ The trailer allows the sender to include additional HTTP header
+ fields at the end of the message. The Trailer header field can be
+ used to indicate which header fields are included in a trailer (see
+ section 14.40).
+
+ A server using chunked transfer-coding in a response MUST NOT use the
+ trailer for any header fields unless at least one of the following is
+ true:
+
+ a)the request included a TE header field that indicates "trailers" is
+ acceptable in the transfer-coding of the response, as described in
+ section 14.39; or,
+
+ b)the server is the origin server for the response, the trailer
+ fields consist entirely of optional metadata, and the recipient
+ could use the message (in a manner acceptable to the origin server)
+ without receiving this metadata. In other words, the origin server
+ is willing to accept the possibility that the trailer fields might
+ be silently discarded along the path to the client.
+
+ This requirement prevents an interoperability failure when the
+ message is being received by an HTTP/1.1 (or later) proxy and
+ forwarded to an HTTP/1.0 recipient. It avoids a situation where
+ compliance with the protocol would have necessitated a possibly
+ infinite buffer on the proxy.
+
+ An example process for decoding a Chunked-Body is presented in
+ appendix 19.4.6.
+
+ All HTTP/1.1 applications MUST be able to receive and decode the
+ "chunked" transfer-coding, and MUST ignore chunk-extension extensions
+ they do not understand.
+
+3.7 Media Types
+
+ HTTP uses Internet Media Types [17] in the Content-Type (section
+ 14.17) and Accept (section 14.1) header fields in order to provide
+ open and extensible data typing and type negotiation.
+
+ media-type = type "/" subtype *( ";" parameter )
+ type = token
+ subtype = token
+
+ Parameters MAY follow the type/subtype in the form of attribute/value
+ pairs (as defined in section 3.6).
+
+ The type, subtype, and parameter attribute names are case-
+ insensitive. Parameter values might or might not be case-sensitive,
+ depending on the semantics of the parameter name. Linear white space
+ (LWS) MUST NOT be used between the type and subtype, nor between an
+ attribute and its value. The presence or absence of a parameter might
+ be significant to the processing of a media-type, depending on its
+ definition within the media type registry.
+
+ Note that some older HTTP applications do not recognize media type
+ parameters. When sending data to older HTTP applications,
+ implementations SHOULD only use media type parameters when they are
+ required by that type/subtype definition.
+
+ Media-type values are registered with the Internet Assigned Number
+ Authority (IANA [19]). The media type registration process is
+ outlined in <a href="http://firefly.troll.no/rfcs/rfc1590.html">RFC 1590</a> [17]. Use of non-registered media types is
+ discouraged.
+
+3.7.1 Canonicalization and Text Defaults
+
+ Internet media types are registered with a canonical form. An
+ entity-body transferred via HTTP messages MUST be represented in the
+ appropriate canonical form prior to its transmission except for
+ "text" types, as defined in the next paragraph.
+
+ When in canonical form, media subtypes of the "text" type use CRLF as
+ the text line break. HTTP relaxes this requirement and allows the
+ transport of text media with plain CR or LF alone representing a line
+ break when it is done consistently for an entire entity-body. HTTP
+ applications MUST accept CRLF, bare CR, and bare LF as being
+ representative of a line break in text media received via HTTP. In
+ addition, if the text is represented in a character set that does not
+ use octets 13 and 10 for CR and LF respectively, as is the case for
+ some multi-byte character sets, HTTP allows the use of whatever octet
+ sequences are defined by that character set to represent the
+ equivalent of CR and LF for line breaks. This flexibility regarding
+ line breaks applies only to text media in the entity-body; a bare CR
+ or LF MUST NOT be substituted for CRLF within any of the HTTP control
+ structures (such as header fields and multipart boundaries).
+
+ If an entity-body is encoded with a content-coding, the underlying
+ data MUST be in a form defined above prior to being encoded.
+
+ The "charset" parameter is used with some media types to define the
+ character set (section 3.4) of the data. When no explicit charset
+ parameter is provided by the sender, media subtypes of the "text"
+ type are defined to have a default charset value of "ISO-8859-1" when
+ received via HTTP. Data in character sets other than "ISO-8859-1" or
+ its subsets MUST be labeled with an appropriate charset value. See
+ section 3.4.1 for compatibility problems.
+
+3.7.2 Multipart Types
+
+ MIME provides for a number of "multipart" types -- encapsulations of
+ one or more entities within a single message-body. All multipart
+ types share a common syntax, as defined in section 5.1.1 of <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a>
+
+ [40], and MUST include a boundary parameter as part of the media type
+ value. The message body is itself a protocol element and MUST
+ therefore use only CRLF to represent line breaks between body-parts.
+ Unlike in <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a>, the epilogue of any multipart message MUST be
+ empty; HTTP applications MUST NOT transmit the epilogue (even if the
+ original multipart contains an epilogue). These restrictions exist in
+ order to preserve the self-delimiting nature of a multipart message-
+ body, wherein the "end" of the message-body is indicated by the
+ ending multipart boundary.
+
+ In general, HTTP treats a multipart message-body no differently than
+ any other media type: strictly as payload. The one exception is the
+ "multipart/byteranges" type (appendix 19.2) when it appears in a 206
+ (Partial Content) response, which will be interpreted by some HTTP
+ caching mechanisms as described in sections 13.5.4 and 14.16. In all
+ other cases, an HTTP user agent SHOULD follow the same or similar
+ behavior as a MIME user agent would upon receipt of a multipart type.
+ The MIME header fields within each body-part of a multipart message-
+ body do not have any significance to HTTP beyond that defined by
+ their MIME semantics.
+
+ In general, an HTTP user agent SHOULD follow the same or similar
+ behavior as a MIME user agent would upon receipt of a multipart type.
+ If an application receives an unrecognized multipart subtype, the
+ application MUST treat it as being equivalent to "multipart/mixed".
+
+ Note: The "multipart/form-data" type has been specifically defined
+ for carrying form data suitable for processing via the POST
+ request method, as described in <a href="http://firefly.troll.no/rfcs/rfc1867.html">RFC 1867</a> [15].
+
+3.8 Product Tokens
+
+ Product tokens are used to allow communicating applications to
+ identify themselves by software name and version. Most fields using
+ product tokens also allow sub-products which form a significant part
+ of the application to be listed, separated by white space. By
+ convention, the products are listed in order of their significance
+ for identifying the application.
+
+ product = token ["/" product-version]
+ product-version = token
+
+ Examples:
+
+ User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+ Server: Apache/0.8.4
+
+ Product tokens SHOULD be short and to the point. They MUST NOT be
+ used for advertising or other non-essential information. Although any
+ token character MAY appear in a product-version, this token SHOULD
+ only be used for a version identifier (i.e., successive versions of
+ the same product SHOULD only differ in the product-version portion of
+ the product value).
+
+3.9 Quality Values
+
+ HTTP content negotiation (section 12) uses short "floating point"
+ numbers to indicate the relative importance ("weight") of various
+ negotiable parameters. A weight is normalized to a real number in
+ the range 0 through 1, where 0 is the minimum and 1 the maximum
+ value. If a parameter has a quality value of 0, then content with
+ this parameter is `not acceptable' for the client. HTTP/1.1
+ applications MUST NOT generate more than three digits after the
+ decimal point. User configuration of these values SHOULD also be
+ limited in this fashion.
+
+ qvalue = ( "0" [ "." 0*3DIGIT ] )
+ | ( "1" [ "." 0*3("0") ] )
+
+ "Quality values" is a misnomer, since these values merely represent
+ relative degradation in desired quality.
+
+3.10 Language Tags
+
+ A language tag identifies a natural language spoken, written, or
+ otherwise conveyed by human beings for communication of information
+ to other human beings. Computer languages are explicitly excluded.
+ HTTP uses language tags within the Accept-Language and Content-
+ Language fields.
+
+ The syntax and registry of HTTP language tags is the same as that
+ defined by <a href="http://firefly.troll.no/rfcs/rfc1766.html">RFC 1766</a> [1]. In summary, a language tag is composed of 1
+ or more parts: A primary language tag and a possibly empty series of
+ subtags:
+
+ language-tag = primary-tag *( "-" subtag )
+ primary-tag = 1*8ALPHA
+ subtag = 1*8ALPHA
+
+ White space is not allowed within the tag and all tags are case-
+ insensitive. The name space of language tags is administered by the
+ IANA. Example tags include:
+
+ en, en-US, en-cockney, i-cherokee, x-pig-latin
+
+ where any two-letter primary-tag is an ISO-639 language abbreviation
+ and any two-letter initial subtag is an ISO-3166 country code. (The
+ last three tags above are not registered tags; all but the last are
+ examples of tags which could be registered in future.)
+
+3.11 Entity Tags
+
+ Entity tags are used for comparing two or more entities from the same
+ requested resource. HTTP/1.1 uses entity tags in the ETag (section
+ 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and
+ If-Range (section 14.27) header fields. The definition of how they
+ are used and compared as cache validators is in section 13.3.3. An
+ entity tag consists of an opaque quoted string, possibly prefixed by
+ a weakness indicator.
+
+ entity-tag = [ weak ] opaque-tag
+ weak = "W/"
+ opaque-tag = quoted-string
+
+ A "strong entity tag" MAY be shared by two entities of a resource
+ only if they are equivalent by octet equality.
+
+ A "weak entity tag," indicated by the "W/" prefix, MAY be shared by
+ two entities of a resource only if the entities are equivalent and
+ could be substituted for each other with no significant change in
+ semantics. A weak entity tag can only be used for weak comparison.
+
+ An entity tag MUST be unique across all versions of all entities
+ associated with a particular resource. A given entity tag value MAY
+ be used for entities obtained by requests on different URIs. The use
+ of the same entity tag value in conjunction with entities obtained by
+ requests on different URIs does not imply the equivalence of those
+ entities.
+
+3.12 Range Units
+
+ HTTP/1.1 allows a client to request that only part (a range of) the
+ response entity be included within the response. HTTP/1.1 uses range
+ units in the Range (section 14.35) and Content-Range (section 14.16)
+ header fields. An entity can be broken down into subranges according
+ to various structural units.
+
+ range-unit = bytes-unit | other-range-unit
+ bytes-unit = "bytes"
+ other-range-unit = token
+
+ The only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1
+ implementations MAY ignore ranges specified using other units.
+
+ HTTP/1.1 has been designed to allow implementations of applications
+ that do not depend on knowledge of ranges.
+
+4 HTTP Message
+
+4.1 Message Types
+
+ HTTP messages consist of requests from client to server and responses
+ from server to client.
+
+ HTTP-message = Request | Response ; HTTP/1.1 messages
+
+ Request (section 5) and Response (section 6) messages use the generic
+ message format of <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9] for transferring entities (the payload
+ of the message). Both types of message consist of a start-line, zero
+ or more header fields (also known as "headers"), an empty line (i.e.,
+ a line with nothing preceding the CRLF) indicating the end of the
+ header fields, and possibly a message-body.
+
+ generic-message = start-line
+ *(message-header CRLF)
+ CRLF
+ [ message-body ]
+ start-line = Request-Line | Status-Line
+
+ In the interest of robustness, servers SHOULD ignore any empty
+ line(s) received where a Request-Line is expected. In other words, if
+ the server is reading the protocol stream at the beginning of a
+ message and receives a CRLF first, it should ignore the CRLF.
+
+ Certain buggy HTTP/1.0 client implementations generate extra CRLF's
+ after a POST request. To restate what is explicitly forbidden by the
+ BNF, an HTTP/1.1 client MUST NOT preface or follow a request with an
+ extra CRLF.
+
+4.2 Message Headers
+
+ HTTP header fields, which include general-header (section 4.5),
+ request-header (section 5.3), response-header (section 6.2), and
+ entity-header (section 7.1) fields, follow the same generic format as
+ that given in Section 3.1 of <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]. Each header field consists
+ of a name followed by a colon (":") and the field value. Field names
+ are case-insensitive. The field value MAY be preceded by any amount
+ of LWS, though a single SP is preferred. Header fields can be
+ extended over multiple lines by preceding each extra line with at
+ least one SP or HT. Applications ought to follow "common form", where
+ one is known or indicated, when generating HTTP constructs, since
+ there might exist some implementations that fail to accept anything
+
+ beyond the common forms.
+
+ message-header = field-name ":" [ field-value ]
+ field-name = token
+ field-value = *( field-content | LWS )
+ field-content = &lt;the OCTETs making up the field-value
+ and consisting of either *TEXT or combinations
+ of token, separators, and quoted-string&gt;
+
+ The field-content does not include any leading or trailing LWS:
+ linear white space occurring before the first non-whitespace
+ character of the field-value or after the last non-whitespace
+ character of the field-value. Such leading or trailing LWS MAY be
+ removed without changing the semantics of the field value. Any LWS
+ that occurs between field-content MAY be replaced with a single SP
+ before interpreting the field value or forwarding the message
+ downstream.
+
+ The order in which header fields with differing field names are
+ received is not significant. However, it is "good practice" to send
+ general-header fields first, followed by request-header or response-
+ header fields, and ending with the entity-header fields.
+
+ Multiple message-header fields with the same field-name MAY be
+ present in a message if and only if the entire field-value for that
+ header field is defined as a comma-separated list [i.e., #(values)].
+ It MUST be possible to combine the multiple header fields into one
+ "field-name: field-value" pair, without changing the semantics of the
+ message, by appending each subsequent field-value to the first, each
+ separated by a comma. The order in which header fields with the same
+ field-name are received is therefore significant to the
+ interpretation of the combined field value, and thus a proxy MUST NOT
+ change the order of these field values when a message is forwarded.
+
+4.3 Message Body
+
+ The message-body (if any) of an HTTP message is used to carry the
+ entity-body associated with the request or response. The message-body
+ differs from the entity-body only when a transfer-coding has been
+ applied, as indicated by the Transfer-Encoding header field (section
+ 14.41).
+
+ message-body = entity-body
+ | &lt;entity-body encoded as per Transfer-Encoding&gt;
+
+ Transfer-Encoding MUST be used to indicate any transfer-codings
+ applied by an application to ensure safe and proper transfer of the
+ message. Transfer-Encoding is a property of the message, not of the
+
+ entity, and thus MAY be added or removed by any application along the
+ request/response chain. (However, section 3.6 places restrictions on
+ when certain transfer-codings may be used.)
+
+ The rules for when a message-body is allowed in a message differ for
+ requests and responses.
+
+ The presence of a message-body in a request is signaled by the
+ inclusion of a Content-Length or Transfer-Encoding header field in
+ the request's message-headers. A message-body MUST NOT be included in
+ a request if the specification of the request method (section 5.1.1)
+ does not allow sending an entity-body in requests. A server SHOULD
+ read and forward a message-body on any request; if the request method
+ does not include defined semantics for an entity-body, then the
+ message-body SHOULD be ignored when handling the request.
+
+ For response messages, whether or not a message-body is included with
+ a message is dependent on both the request method and the response
+ status code (section 6.1.1). All responses to the HEAD request method
+ MUST NOT include a message-body, even though the presence of entity-
+ header fields might lead one to believe they do. All 1xx
+ (informational), 204 (no content), and 304 (not modified) responses
+ MUST NOT include a message-body. All other responses do include a
+ message-body, although it MAY be of zero length.
+
+4.4 Message Length
+
+ The transfer-length of a message is the length of the message-body as
+ it appears in the message; that is, after any transfer-codings have
+ been applied. When a message-body is included with a message, the
+ transfer-length of that body is determined by one of the following
+ (in order of precedence):
+
+ 1.Any response message which "MUST NOT" include a message-body (such
+ as the 1xx, 204, and 304 responses and any response to a HEAD
+ request) is always terminated by the first empty line after the
+ header fields, regardless of the entity-header fields present in
+ the message.
+
+ 2.If a Transfer-Encoding header field (section 14.41) is present and
+ has any value other than "identity", then the transfer-length is
+ defined by use of the "chunked" transfer-coding (section 3.6),
+ unless the message is terminated by closing the connection.
+
+ 3.If a Content-Length header field (section 14.13) is present, its
+ decimal value in OCTETs represents both the entity-length and the
+ transfer-length. The Content-Length header field MUST NOT be sent
+ if these two lengths are different (i.e., if a Transfer-Encoding
+
+ header field is present). If a message is received with both a
+ Transfer-Encoding header field and a Content-Length header field,
+ the latter MUST be ignored.
+
+ 4.If the message uses the media type "multipart/byteranges", and the
+ ransfer-length is not otherwise specified, then this self-
+ elimiting media type defines the transfer-length. This media type
+ UST NOT be used unless the sender knows that the recipient can arse
+ it; the presence in a request of a Range header with ultiple byte-
+ range specifiers from a 1.1 client implies that the lient can parse
+ multipart/byteranges responses.
+
+ A range header might be forwarded by a 1.0 proxy that does not
+ understand multipart/byteranges; in this case the server MUST
+ delimit the message using methods defined in items 1,3 or 5 of
+ this section.
+
+ 5.By the server closing the connection. (Closing the connection
+ cannot be used to indicate the end of a request body, since that
+ would leave no possibility for the server to send back a response.)
+
+ For compatibility with HTTP/1.0 applications, HTTP/1.1 requests
+ containing a message-body MUST include a valid Content-Length header
+ field unless the server is known to be HTTP/1.1 compliant. If a
+ request contains a message-body and a Content-Length is not given,
+ the server SHOULD respond with 400 (bad request) if it cannot
+ determine the length of the message, or with 411 (length required) if
+ it wishes to insist on receiving a valid Content-Length.
+
+ All HTTP/1.1 applications that receive entities MUST accept the
+ "chunked" transfer-coding (section 3.6), thus allowing this mechanism
+ to be used for messages when the message length cannot be determined
+ in advance.
+
+ Messages MUST NOT include both a Content-Length header field and a
+ non-identity transfer-coding. If the message does include a non-
+ identity transfer-coding, the Content-Length MUST be ignored.
+
+ When a Content-Length is given in a message where a message-body is
+ allowed, its field value MUST exactly match the number of OCTETs in
+ the message-body. HTTP/1.1 user agents MUST notify the user when an
+ invalid length is received and detected.
+
+4.5 General Header Fields
+
+ There are a few header fields which have general applicability for
+ both request and response messages, but which do not apply to the
+ entity being transferred. These header fields apply only to the
+
+ message being transmitted.
+
+ general-header = Cache-Control ; Section 14.9
+ | Connection ; Section 14.10
+ | Date ; Section 14.18
+ | Pragma ; Section 14.32
+ | Trailer ; Section 14.40
+ | Transfer-Encoding ; Section 14.41
+ | Upgrade ; Section 14.42
+ | Via ; Section 14.45
+ | Warning ; Section 14.46
+
+ General-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields may be given the semantics of general
+ header fields if all parties in the communication recognize them to
+ be general-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+5 Request
+
+ A request message from a client to a server includes, within the
+ first line of that message, the method to be applied to the resource,
+ the identifier of the resource, and the protocol version in use.
+
+ Request = Request-Line ; Section 5.1
+ *(( general-header ; Section 4.5
+ | request-header ; Section 5.3
+ | entity-header ) CRLF) ; Section 7.1
+ CRLF
+ [ message-body ] ; Section 4.3
+
+5.1 Request-Line
+
+ The Request-Line begins with a method token, followed by the
+ Request-URI and the protocol version, and ending with CRLF. The
+ elements are separated by SP characters. No CR or LF is allowed
+ except in the final CRLF sequence.
+
+ Request-Line = Method SP Request-URI SP HTTP-Version CRLF
+
+5.1.1 Method
+
+ The Method token indicates the method to be performed on the
+ resource identified by the Request-URI. The method is case-sensitive.
+
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+
+ The list of methods allowed by a resource can be specified in an
+ Allow header field (section 14.7). The return code of the response
+ always notifies the client whether a method is currently allowed on a
+ resource, since the set of allowed methods can change dynamically. An
+ origin server SHOULD return the status code 405 (Method Not Allowed)
+ if the method is known by the origin server but not allowed for the
+ requested resource, and 501 (Not Implemented) if the method is
+ unrecognized or not implemented by the origin server. The methods GET
+ and HEAD MUST be supported by all general-purpose servers. All other
+ methods are OPTIONAL; however, if the above methods are implemented,
+ they MUST be implemented with the same semantics as those specified
+ in section 9.
+
+5.1.2 Request-URI
+
+ The Request-URI is a Uniform Resource Identifier (section 3.2) and
+ identifies the resource upon which to apply the request.
+
+ Request-URI = "*" | absoluteURI | abs_path | authority
+
+ The four options for Request-URI are dependent on the nature of the
+ request. The asterisk "*" means that the request does not apply to a
+ particular resource, but to the server itself, and is only allowed
+ when the method used does not necessarily apply to a resource. One
+ example would be
+
+ OPTIONS * HTTP/1.1
+
+ The absoluteURI form is REQUIRED when the request is being made to a
+ proxy. The proxy is requested to forward the request or service it
+ from a valid cache, and return the response. Note that the proxy MAY
+ forward the request on to another proxy or directly to the server
+
+ specified by the absoluteURI. In order to avoid request loops, a
+ proxy MUST be able to recognize all of its server names, including
+ any aliases, local variations, and the numeric IP address. An example
+ Request-Line would be:
+
+ GET <a href="http://www.w3.org/pub/WWW/TheProject.html">http://www.w3.org/pub/WWW/TheProject.html</a> HTTP/1.1
+
+ To allow for transition to absoluteURIs in all requests in future
+ versions of HTTP, all HTTP/1.1 servers MUST accept the absoluteURI
+ form in requests, even though HTTP/1.1 clients will only generate
+ them in requests to proxies.
+
+ The authority form is only used by the CONNECT method (section 9.9).
+
+ The most common form of Request-URI is that used to identify a
+ resource on an origin server or gateway. In this case the absolute
+ path of the URI MUST be transmitted (see section 3.2.1, abs_path) as
+ the Request-URI, and the network location of the URI (authority) MUST
+ be transmitted in a Host header field. For example, a client wishing
+ to retrieve the resource above directly from the origin server would
+ create a TCP connection to port 80 of the host "www.w3.org" and send
+ the lines:
+
+ GET /pub/WWW/TheProject.html HTTP/1.1
+ Host: www.w3.org
+
+ followed by the remainder of the Request. Note that the absolute path
+ cannot be empty; if none is present in the original URI, it MUST be
+ given as "/" (the server root).
+
+ The Request-URI is transmitted in the format specified in section
+ 3.2.1. If the Request-URI is encoded using the "% HEX HEX" encoding
+ [42], the origin server MUST decode the Request-URI in order to
+ properly interpret the request. Servers SHOULD respond to invalid
+ Request-URIs with an appropriate status code.
+
+ A transparent proxy MUST NOT rewrite the "abs_path" part of the
+ received Request-URI when forwarding it to the next inbound server,
+ except as noted above to replace a null abs_path with "/".
+
+ Note: The "no rewrite" rule prevents the proxy from changing the
+ meaning of the request when the origin server is improperly using
+ a non-reserved URI character for a reserved purpose. Implementors
+ should be aware that some pre-HTTP/1.1 proxies have been known to
+ rewrite the Request-URI.
+
+5.2 The Resource Identified by a Request
+
+ The exact resource identified by an Internet request is determined by
+ examining both the Request-URI and the Host header field.
+
+ An origin server that does not allow resources to differ by the
+ requested host MAY ignore the Host header field value when
+ determining the resource identified by an HTTP/1.1 request. (But see
+ section 19.6.1.1 for other requirements on Host support in HTTP/1.1.)
+
+ An origin server that does differentiate resources based on the host
+ requested (sometimes referred to as virtual hosts or vanity host
+ names) MUST use the following rules for determining the requested
+ resource on an HTTP/1.1 request:
+
+ 1. If Request-URI is an absoluteURI, the host is part of the
+ Request-URI. Any Host header field value in the request MUST be
+ ignored.
+
+ 2. If the Request-URI is not an absoluteURI, and the request includes
+ a Host header field, the host is determined by the Host header
+ field value.
+
+ 3. If the host as determined by rule 1 or 2 is not a valid host on
+ the server, the response MUST be a 400 (Bad Request) error message.
+
+ Recipients of an HTTP/1.0 request that lacks a Host header field MAY
+ attempt to use heuristics (e.g., examination of the URI path for
+ something unique to a particular host) in order to determine what
+ exact resource is being requested.
+
+5.3 Request Header Fields
+
+ The request-header fields allow the client to pass additional
+ information about the request, and about the client itself, to the
+ server. These fields act as request modifiers, with semantics
+ equivalent to the parameters on a programming language method
+ invocation.
+
+ request-header = Accept ; Section 14.1
+ | Accept-Charset ; Section 14.2
+ | Accept-Encoding ; Section 14.3
+ | Accept-Language ; Section 14.4
+ | Authorization ; Section 14.8
+ | Expect ; Section 14.20
+ | From ; Section 14.22
+ | Host ; Section 14.23
+ | If-Match ; Section 14.24
+
+ | If-Modified-Since ; Section 14.25
+ | If-None-Match ; Section 14.26
+ | If-Range ; Section 14.27
+ | If-Unmodified-Since ; Section 14.28
+ | Max-Forwards ; Section 14.31
+ | Proxy-Authorization ; Section 14.34
+ | Range ; Section 14.35
+ | Referer ; Section 14.36
+ | TE ; Section 14.39
+ | User-Agent ; Section 14.43
+
+ Request-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields MAY be given the semantics of request-
+ header fields if all parties in the communication recognize them to
+ be request-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+6 Response
+
+ After receiving and interpreting a request message, a server responds
+ with an HTTP response message.
+
+ Response = Status-Line ; Section 6.1
+ *(( general-header ; Section 4.5
+ | response-header ; Section 6.2
+ | entity-header ) CRLF) ; Section 7.1
+ CRLF
+ [ message-body ] ; Section 7.2
+
+6.1 Status-Line
+
+ The first line of a Response message is the Status-Line, consisting
+ of the protocol version followed by a numeric status code and its
+ associated textual phrase, with each element separated by SP
+ characters. No CR or LF is allowed except in the final CRLF sequence.
+
+ Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+
+6.1.1 Status Code and Reason Phrase
+
+ The Status-Code element is a 3-digit integer result code of the
+ attempt to understand and satisfy the request. These codes are fully
+ defined in section 10. The Reason-Phrase is intended to give a short
+ textual description of the Status-Code. The Status-Code is intended
+ for use by automata and the Reason-Phrase is intended for the human
+ user. The client is not required to examine or display the Reason-
+ Phrase.
+
+ The first digit of the Status-Code defines the class of response. The
+ last two digits do not have any categorization role. There are 5
+ values for the first digit:
+
+ - 1xx: Informational - Request received, continuing process
+
+ - 2xx: Success - The action was successfully received,
+ understood, and accepted
+
+ - 3xx: Redirection - Further action must be taken in order to
+ complete the request
+
+ - 4xx: Client Error - The request contains bad syntax or cannot
+ be fulfilled
+
+ - 5xx: Server Error - The server failed to fulfill an apparently
+ valid request
+
+ The individual values of the numeric status codes defined for
+ HTTP/1.1, and an example set of corresponding Reason-Phrase's, are
+ presented below. The reason phrases listed here are only
+ recommendations -- they MAY be replaced by local equivalents without
+ affecting the protocol.
+
+ Status-Code =
+ "100" ; Section 10.1.1: Continue
+ | "101" ; Section 10.1.2: Switching Protocols
+ | "200" ; Section 10.2.1: OK
+ | "201" ; Section 10.2.2: Created
+ | "202" ; Section 10.2.3: Accepted
+ | "203" ; Section 10.2.4: Non-Authoritative Information
+ | "204" ; Section 10.2.5: No Content
+ | "205" ; Section 10.2.6: Reset Content
+ | "206" ; Section 10.2.7: Partial Content
+ | "300" ; Section 10.3.1: Multiple Choices
+ | "301" ; Section 10.3.2: Moved Permanently
+ | "302" ; Section 10.3.3: Found
+ | "303" ; Section 10.3.4: See Other
+ | "304" ; Section 10.3.5: Not Modified
+ | "305" ; Section 10.3.6: Use Proxy
+ | "307" ; Section 10.3.8: Temporary Redirect
+ | "400" ; Section 10.4.1: Bad Request
+ | "401" ; Section 10.4.2: Unauthorized
+ | "402" ; Section 10.4.3: Payment Required
+ | "403" ; Section 10.4.4: Forbidden
+ | "404" ; Section 10.4.5: Not Found
+ | "405" ; Section 10.4.6: Method Not Allowed
+ | "406" ; Section 10.4.7: Not Acceptable
+
+ | "407" ; Section 10.4.8: Proxy Authentication Required
+ | "408" ; Section 10.4.9: Request Time-out
+ | "409" ; Section 10.4.10: Conflict
+ | "410" ; Section 10.4.11: Gone
+ | "411" ; Section 10.4.12: Length Required
+ | "412" ; Section 10.4.13: Precondition Failed
+ | "413" ; Section 10.4.14: Request Entity Too Large
+ | "414" ; Section 10.4.15: Request-URI Too Large
+ | "415" ; Section 10.4.16: Unsupported Media Type
+ | "416" ; Section 10.4.17: Requested range not satisfiable
+ | "417" ; Section 10.4.18: Expectation Failed
+ | "500" ; Section 10.5.1: Internal Server Error
+ | "501" ; Section 10.5.2: Not Implemented
+ | "502" ; Section 10.5.3: Bad Gateway
+ | "503" ; Section 10.5.4: Service Unavailable
+ | "504" ; Section 10.5.5: Gateway Time-out
+ | "505" ; Section 10.5.6: HTTP Version not supported
+ | extension-code
+
+ extension-code = 3DIGIT
+ Reason-Phrase = *&lt;TEXT, excluding CR, LF&gt;
+
+ HTTP status codes are extensible. HTTP applications are not required
+ to understand the meaning of all registered status codes, though such
+ understanding is obviously desirable. However, applications MUST
+ understand the class of any status code, as indicated by the first
+ digit, and treat any unrecognized response as being equivalent to the
+ x00 status code of that class, with the exception that an
+ unrecognized response MUST NOT be cached. For example, if an
+ unrecognized status code of 431 is received by the client, it can
+ safely assume that there was something wrong with its request and
+ treat the response as if it had received a 400 status code. In such
+ cases, user agents SHOULD present to the user the entity returned
+ with the response, since that entity is likely to include human-
+ readable information which will explain the unusual status.
+
+6.2 Response Header Fields
+
+ The response-header fields allow the server to pass additional
+ information about the response which cannot be placed in the Status-
+ Line. These header fields give information about the server and about
+ further access to the resource identified by the Request-URI.
+
+ response-header = Accept-Ranges ; Section 14.5
+ | Age ; Section 14.6
+ | ETag ; Section 14.19
+ | Location ; Section 14.30
+ | Proxy-Authenticate ; Section 14.33
+
+ | Retry-After ; Section 14.37
+ | Server ; Section 14.38
+ | Vary ; Section 14.44
+ | WWW-Authenticate ; Section 14.47
+
+ Response-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields MAY be given the semantics of response-
+ header fields if all parties in the communication recognize them to
+ be response-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+7 Entity
+
+ Request and Response messages MAY transfer an entity if not otherwise
+ restricted by the request method or response status code. An entity
+ consists of entity-header fields and an entity-body, although some
+ responses will only include the entity-headers.
+
+ In this section, both sender and recipient refer to either the client
+ or the server, depending on who sends and who receives the entity.
+
+7.1 Entity Header Fields
+
+ Entity-header fields define metainformation about the entity-body or,
+ if no body is present, about the resource identified by the request.
+ Some of this metainformation is OPTIONAL; some might be REQUIRED by
+ portions of this specification.
+
+ entity-header = Allow ; Section 14.7
+ | Content-Encoding ; Section 14.11
+ | Content-Language ; Section 14.12
+ | Content-Length ; Section 14.13
+ | Content-Location ; Section 14.14
+ | Content-MD5 ; Section 14.15
+ | Content-Range ; Section 14.16
+ | Content-Type ; Section 14.17
+ | Expires ; Section 14.21
+ | Last-Modified ; Section 14.29
+ | extension-header
+
+ extension-header = message-header
+
+ The extension-header mechanism allows additional entity-header fields
+ to be defined without changing the protocol, but these fields cannot
+ be assumed to be recognizable by the recipient. Unrecognized header
+ fields SHOULD be ignored by the recipient and MUST be forwarded by
+ transparent proxies.
+
+7.2 Entity Body
+
+ The entity-body (if any) sent with an HTTP request or response is in
+ a format and encoding defined by the entity-header fields.
+
+ entity-body = *OCTET
+
+ An entity-body is only present in a message when a message-body is
+ present, as described in section 4.3. The entity-body is obtained
+ from the message-body by decoding any Transfer-Encoding that might
+ have been applied to ensure safe and proper transfer of the message.
+
+7.2.1 Type
+
+ When an entity-body is included with a message, the data type of that
+ body is determined via the header fields Content-Type and Content-
+ Encoding. These define a two-layer, ordered encoding model:
+
+ entity-body := Content-Encoding( Content-Type( data ) )
+
+ Content-Type specifies the media type of the underlying data.
+ Content-Encoding may be used to indicate any additional content
+ codings applied to the data, usually for the purpose of data
+ compression, that are a property of the requested resource. There is
+ no default encoding.
+
+ Any HTTP/1.1 message containing an entity-body SHOULD include a
+ Content-Type header field defining the media type of that body. If
+ and only if the media type is not given by a Content-Type field, the
+ recipient MAY attempt to guess the media type via inspection of its
+ content and/or the name extension(s) of the URI used to identify the
+ resource. If the media type remains unknown, the recipient SHOULD
+ treat it as type "application/octet-stream".
+
+7.2.2 Entity Length
+
+ The entity-length of a message is the length of the message-body
+ before any transfer-codings have been applied. Section 4.4 defines
+ how the transfer-length of a message-body is determined.
+
+8 Connections
+
+8.1 Persistent Connections
+
+8.1.1 Purpose
+
+ Prior to persistent connections, a separate TCP connection was
+ established to fetch each URL, increasing the load on HTTP servers
+ and causing congestion on the Internet. The use of inline images and
+ other associated data often require a client to make multiple
+ requests of the same server in a short amount of time. Analysis of
+ these performance problems and results from a prototype
+ implementation are available [26] [30]. Implementation experience and
+ measurements of actual HTTP/1.1 (<a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>) implementations show good
+ results [39]. Alternatives have also been explored, for example,
+ T/TCP [27].
+
+ Persistent HTTP connections have a number of advantages:
+
+ - By opening and closing fewer TCP connections, CPU time is saved
+ in routers and hosts (clients, servers, proxies, gateways,
+ tunnels, or caches), and memory used for TCP protocol control
+ blocks can be saved in hosts.
+
+ - HTTP requests and responses can be pipelined on a connection.
+ Pipelining allows a client to make multiple requests without
+ waiting for each response, allowing a single TCP connection to
+ be used much more efficiently, with much lower elapsed time.
+
+ - Network congestion is reduced by reducing the number of packets
+ caused by TCP opens, and by allowing TCP sufficient time to
+ determine the congestion state of the network.
+
+ - Latency on subsequent requests is reduced since there is no time
+ spent in TCP's connection opening handshake.
+
+ - HTTP can evolve more gracefully, since errors can be reported
+ without the penalty of closing the TCP connection. Clients using
+ future versions of HTTP might optimistically try a new feature,
+ but if communicating with an older server, retry with old
+ semantics after an error is reported.
+
+ HTTP implementations SHOULD implement persistent connections.
+
+8.1.2 Overall Operation
+
+ A significant difference between HTTP/1.1 and earlier versions of
+ HTTP is that persistent connections are the default behavior of any
+ HTTP connection. That is, unless otherwise indicated, the client
+ SHOULD assume that the server will maintain a persistent connection,
+ even after error responses from the server.
+
+ Persistent connections provide a mechanism by which a client and a
+ server can signal the close of a TCP connection. This signaling takes
+ place using the Connection header field (section 14.10). Once a close
+ has been signaled, the client MUST NOT send any more requests on that
+ connection.
+
+8.1.2.1 Negotiation
+
+ An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to
+ maintain a persistent connection unless a Connection header including
+ the connection-token "close" was sent in the request. If the server
+ chooses to close the connection immediately after sending the
+ response, it SHOULD send a Connection header including the
+ connection-token close.
+
+ An HTTP/1.1 client MAY expect a connection to remain open, but would
+ decide to keep it open based on whether the response from a server
+ contains a Connection header with the connection-token close. In case
+ the client does not want to maintain a connection for more than that
+ request, it SHOULD send a Connection header including the
+ connection-token close.
+
+ If either the client or the server sends the close token in the
+ Connection header, that request becomes the last one for the
+ connection.
+
+ Clients and servers SHOULD NOT assume that a persistent connection is
+ maintained for HTTP versions less than 1.1 unless it is explicitly
+ signaled. See section 19.6.2 for more information on backward
+ compatibility with HTTP/1.0 clients.
+
+ In order to remain persistent, all messages on the connection MUST
+ have a self-defined message length (i.e., one not defined by closure
+ of the connection), as described in section 4.4.
+
+8.1.2.2 Pipelining
+
+ A client that supports persistent connections MAY "pipeline" its
+ requests (i.e., send multiple requests without waiting for each
+ response). A server MUST send its responses to those requests in the
+ same order that the requests were received.
+
+ Clients which assume persistent connections and pipeline immediately
+ after connection establishment SHOULD be prepared to retry their
+ connection if the first pipelined attempt fails. If a client does
+ such a retry, it MUST NOT pipeline before it knows the connection is
+ persistent. Clients MUST also be prepared to resend their requests if
+ the server closes the connection before sending all of the
+ corresponding responses.
+
+ Clients SHOULD NOT pipeline requests using non-idempotent methods or
+ non-idempotent sequences of methods (see section 9.1.2). Otherwise, a
+ premature termination of the transport connection could lead to
+ indeterminate results. A client wishing to send a non-idempotent
+ request SHOULD wait to send that request until it has received the
+ response status for the previous request.
+
+8.1.3 Proxy Servers
+
+ It is especially important that proxies correctly implement the
+ properties of the Connection header field as specified in section
+ 14.10.
+
+ The proxy server MUST signal persistent connections separately with
+ its clients and the origin servers (or other proxy servers) that it
+ connects to. Each persistent connection applies to only one transport
+ link.
+
+ A proxy server MUST NOT establish a HTTP/1.1 persistent connection
+ with an HTTP/1.0 client (but see <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> [33] for information and
+ discussion of the problems with the Keep-Alive header implemented by
+ many HTTP/1.0 clients).
+
+8.1.4 Practical Considerations
+
+ Servers will usually have some time-out value beyond which they will
+ no longer maintain an inactive connection. Proxy servers might make
+ this a higher value since it is likely that the client will be making
+ more connections through the same server. The use of persistent
+ connections places no requirements on the length (or existence) of
+ this time-out for either the client or the server.
+
+ When a client or server wishes to time-out it SHOULD issue a graceful
+ close on the transport connection. Clients and servers SHOULD both
+ constantly watch for the other side of the transport close, and
+ respond to it as appropriate. If a client or server does not detect
+ the other side's close promptly it could cause unnecessary resource
+ drain on the network.
+
+ A client, server, or proxy MAY close the transport connection at any
+ time. For example, a client might have started to send a new request
+ at the same time that the server has decided to close the "idle"
+ connection. From the server's point of view, the connection is being
+ closed while it was idle, but from the client's point of view, a
+ request is in progress.
+
+ This means that clients, servers, and proxies MUST be able to recover
+ from asynchronous close events. Client software SHOULD reopen the
+ transport connection and retransmit the aborted sequence of requests
+ without user interaction so long as the request sequence is
+ idempotent (see section 9.1.2). Non-idempotent methods or sequences
+ MUST NOT be automatically retried, although user agents MAY offer a
+ human operator the choice of retrying the request(s). Confirmation by
+ user-agent software with semantic understanding of the application
+ MAY substitute for user confirmation. The automatic retry SHOULD NOT
+ be repeated if the second sequence of requests fails.
+
+ Servers SHOULD always respond to at least one request per connection,
+ if at all possible. Servers SHOULD NOT close a connection in the
+ middle of transmitting a response, unless a network or client failure
+ is suspected.
+
+ Clients that use persistent connections SHOULD limit the number of
+ simultaneous connections that they maintain to a given server. A
+ single-user client SHOULD NOT maintain more than 2 connections with
+ any server or proxy. A proxy SHOULD use up to 2*N connections to
+ another server or proxy, where N is the number of simultaneously
+ active users. These guidelines are intended to improve HTTP response
+ times and avoid congestion.
+
+8.2 Message Transmission Requirements
+
+8.2.1 Persistent Connections and Flow Control
+
+ HTTP/1.1 servers SHOULD maintain persistent connections and use TCP's
+ flow control mechanisms to resolve temporary overloads, rather than
+ terminating connections with the expectation that clients will retry.
+ The latter technique can exacerbate network congestion.
+
+8.2.2 Monitoring Connections for Error Status Messages
+
+ An HTTP/1.1 (or later) client sending a message-body SHOULD monitor
+ the network connection for an error status while it is transmitting
+ the request. If the client sees an error status, it SHOULD
+ immediately cease transmitting the body. If the body is being sent
+ using a "chunked" encoding (section 3.6), a zero length chunk and
+ empty trailer MAY be used to prematurely mark the end of the message.
+ If the body was preceded by a Content-Length header, the client MUST
+ close the connection.
+
+8.2.3 Use of the 100 (Continue) Status
+
+ The purpose of the 100 (Continue) status (see section 10.1.1) is to
+ allow a client that is sending a request message with a request body
+ to determine if the origin server is willing to accept the request
+ (based on the request headers) before the client sends the request
+ body. In some cases, it might either be inappropriate or highly
+ inefficient for the client to send the body if the server will reject
+ the message without looking at the body.
+
+ Requirements for HTTP/1.1 clients:
+
+ - If a client will wait for a 100 (Continue) response before
+ sending the request body, it MUST send an Expect request-header
+ field (section 14.20) with the "100-continue" expectation.
+
+ - A client MUST NOT send an Expect request-header field (section
+ 14.20) with the "100-continue" expectation if it does not intend
+ to send a request body.
+
+ Because of the presence of older implementations, the protocol allows
+ ambiguous situations in which a client may send "Expect: 100-
+ continue" without receiving either a 417 (Expectation Failed) status
+ or a 100 (Continue) status. Therefore, when a client sends this
+ header field to an origin server (possibly via a proxy) from which it
+ has never seen a 100 (Continue) status, the client SHOULD NOT wait
+ for an indefinite period before sending the request body.
+
+ Requirements for HTTP/1.1 origin servers:
+
+ - Upon receiving a request which includes an Expect request-header
+ field with the "100-continue" expectation, an origin server MUST
+ either respond with 100 (Continue) status and continue to read
+ from the input stream, or respond with a final status code. The
+ origin server MUST NOT wait for the request body before sending
+ the 100 (Continue) response. If it responds with a final status
+ code, it MAY close the transport connection or it MAY continue
+
+ to read and discard the rest of the request. It MUST NOT
+ perform the requested method if it returns a final status code.
+
+ - An origin server SHOULD NOT send a 100 (Continue) response if
+ the request message does not include an Expect request-header
+ field with the "100-continue" expectation, and MUST NOT send a
+ 100 (Continue) response if such a request comes from an HTTP/1.0
+ (or earlier) client. There is an exception to this rule: for
+ compatibility with <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>, a server MAY send a 100 (Continue)
+ status in response to an HTTP/1.1 PUT or POST request that does
+ not include an Expect request-header field with the "100-
+ continue" expectation. This exception, the purpose of which is
+ to minimize any client processing delays associated with an
+ undeclared wait for 100 (Continue) status, applies only to
+ HTTP/1.1 requests, and not to requests with any other HTTP-
+ version value.
+
+ - An origin server MAY omit a 100 (Continue) response if it has
+ already received some or all of the request body for the
+ corresponding request.
+
+ - An origin server that sends a 100 (Continue) response MUST
+ ultimately send a final status code, once the request body is
+ received and processed, unless it terminates the transport
+ connection prematurely.
+
+ - If an origin server receives a request that does not include an
+ Expect request-header field with the "100-continue" expectation,
+ the request includes a request body, and the server responds
+ with a final status code before reading the entire request body
+ from the transport connection, then the server SHOULD NOT close
+ the transport connection until it has read the entire request,
+ or until the client closes the connection. Otherwise, the client
+ might not reliably receive the response message. However, this
+ requirement is not be construed as preventing a server from
+ defending itself against denial-of-service attacks, or from
+ badly broken client implementations.
+
+ Requirements for HTTP/1.1 proxies:
+
+ - If a proxy receives a request that includes an Expect request-
+ header field with the "100-continue" expectation, and the proxy
+ either knows that the next-hop server complies with HTTP/1.1 or
+ higher, or does not know the HTTP version of the next-hop
+ server, it MUST forward the request, including the Expect header
+ field.
+
+ - If the proxy knows that the version of the next-hop server is
+ HTTP/1.0 or lower, it MUST NOT forward the request, and it MUST
+ respond with a 417 (Expectation Failed) status.
+
+ - Proxies SHOULD maintain a cache recording the HTTP version
+ numbers received from recently-referenced next-hop servers.
+
+ - A proxy MUST NOT forward a 100 (Continue) response if the
+ request message was received from an HTTP/1.0 (or earlier)
+ client and did not include an Expect request-header field with
+ the "100-continue" expectation. This requirement overrides the
+ general rule for forwarding of 1xx responses (see section 10.1).
+
+8.2.4 Client Behavior if Server Prematurely Closes Connection
+
+ If an HTTP/1.1 client sends a request which includes a request body,
+ but which does not include an Expect request-header field with the
+ "100-continue" expectation, and if the client is not directly
+ connected to an HTTP/1.1 origin server, and if the client sees the
+ connection close before receiving any status from the server, the
+ client SHOULD retry the request. If the client does retry this
+ request, it MAY use the following "binary exponential backoff"
+ algorithm to be assured of obtaining a reliable response:
+
+ 1. Initiate a new connection to the server
+
+ 2. Transmit the request-headers
+
+ 3. Initialize a variable R to the estimated round-trip time to the
+ server (e.g., based on the time it took to establish the
+ connection), or to a constant value of 5 seconds if the round-
+ trip time is not available.
+
+ 4. Compute T = R * (2**N), where N is the number of previous
+ retries of this request.
+
+ 5. Wait either for an error response from the server, or for T
+ seconds (whichever comes first)
+
+ 6. If no error response is received, after T seconds transmit the
+ body of the request.
+
+ 7. If client sees that the connection is closed prematurely,
+ repeat from step 1 until the request is accepted, an error
+ response is received, or the user becomes impatient and
+ terminates the retry process.
+
+ If at any point an error status is received, the client
+
+ - SHOULD NOT continue and
+
+ - SHOULD close the connection if it has not completed sending the
+ request message.
+
+9 Method Definitions
+
+ The set of common methods for HTTP/1.1 is defined below. Although
+ this set can be expanded, additional methods cannot be assumed to
+ share the same semantics for separately extended clients and servers.
+
+ The Host request-header field (section 14.23) MUST accompany all
+ HTTP/1.1 requests.
+
+9.1 Safe and Idempotent Methods
+
+9.1.1 Safe Methods
+
+ Implementors should be aware that the software represents the user in
+ their interactions over the Internet, and should be careful to allow
+ the user to be aware of any actions they might take which may have an
+ unexpected significance to themselves or others.
+
+ In particular, the convention has been established that the GET and
+ HEAD methods SHOULD NOT have the significance of taking an action
+ other than retrieval. These methods ought to be considered "safe".
+ This allows user agents to represent other methods, such as POST, PUT
+ and DELETE, in a special way, so that the user is made aware of the
+ fact that a possibly unsafe action is being requested.
+
+ Naturally, it is not possible to ensure that the server does not
+ generate side-effects as a result of performing a GET request; in
+ fact, some dynamic resources consider that a feature. The important
+ distinction here is that the user did not request the side-effects,
+ so therefore cannot be held accountable for them.
+
+9.1.2 Idempotent Methods
+
+ Methods can also have the property of "idempotence" in that (aside
+ from error or expiration issues) the side-effects of N &gt; 0 identical
+ requests is the same as for a single request. The methods GET, HEAD,
+ PUT and DELETE share this property. Also, the methods OPTIONS and
+ TRACE SHOULD NOT have side effects, and so are inherently idempotent.
+
+ However, it is possible that a sequence of several requests is non-
+ idempotent, even if all of the methods executed in that sequence are
+ idempotent. (A sequence is idempotent if a single execution of the
+ entire sequence always yields a result that is not changed by a
+ reexecution of all, or part, of that sequence.) For example, a
+ sequence is non-idempotent if its result depends on a value that is
+ later modified in the same sequence.
+
+ A sequence that never has side effects is idempotent, by definition
+ (provided that no concurrent operations are being executed on the
+ same set of resources).
+
+9.2 OPTIONS
+
+ The OPTIONS method represents a request for information about the
+ communication options available on the request/response chain
+ identified by the Request-URI. This method allows the client to
+ determine the options and/or requirements associated with a resource,
+ or the capabilities of a server, without implying a resource action
+ or initiating a resource retrieval.
+
+ Responses to this method are not cacheable.
+
+ If the OPTIONS request includes an entity-body (as indicated by the
+ presence of Content-Length or Transfer-Encoding), then the media type
+ MUST be indicated by a Content-Type field. Although this
+ specification does not define any use for such a body, future
+ extensions to HTTP might use the OPTIONS body to make more detailed
+ queries on the server. A server that does not support such an
+ extension MAY discard the request body.
+
+ If the Request-URI is an asterisk ("*"), the OPTIONS request is
+ intended to apply to the server in general rather than to a specific
+ resource. Since a server's communication options typically depend on
+ the resource, the "*" request is only useful as a "ping" or "no-op"
+ type of method; it does nothing beyond allowing the client to test
+ the capabilities of the server. For example, this can be used to test
+ a proxy for HTTP/1.1 compliance (or lack thereof).
+
+ If the Request-URI is not an asterisk, the OPTIONS request applies
+ only to the options that are available when communicating with that
+ resource.
+
+ A 200 response SHOULD include any header fields that indicate
+ optional features implemented by the server and applicable to that
+ resource (e.g., Allow), possibly including extensions not defined by
+ this specification. The response body, if any, SHOULD also include
+ information about the communication options. The format for such a
+
+ body is not defined by this specification, but might be defined by
+ future extensions to HTTP. Content negotiation MAY be used to select
+ the appropriate response format. If no response body is included, the
+ response MUST include a Content-Length field with a field-value of
+ "0".
+
+ The Max-Forwards request-header field MAY be used to target a
+ specific proxy in the request chain. When a proxy receives an OPTIONS
+ request on an absoluteURI for which request forwarding is permitted,
+ the proxy MUST check for a Max-Forwards field. If the Max-Forwards
+ field-value is zero ("0"), the proxy MUST NOT forward the message;
+ instead, the proxy SHOULD respond with its own communication options.
+ If the Max-Forwards field-value is an integer greater than zero, the
+ proxy MUST decrement the field-value when it forwards the request. If
+ no Max-Forwards field is present in the request, then the forwarded
+ request MUST NOT include a Max-Forwards field.
+
+9.3 GET
+
+ The GET method means retrieve whatever information (in the form of an
+ entity) is identified by the Request-URI. If the Request-URI refers
+ to a data-producing process, it is the produced data which shall be
+ returned as the entity in the response and not the source text of the
+ process, unless that text happens to be the output of the process.
+
+ The semantics of the GET method change to a "conditional GET" if the
+ request message includes an If-Modified-Since, If-Unmodified-Since,
+ If-Match, If-None-Match, or If-Range header field. A conditional GET
+ method requests that the entity be transferred only under the
+ circumstances described by the conditional header field(s). The
+ conditional GET method is intended to reduce unnecessary network
+ usage by allowing cached entities to be refreshed without requiring
+ multiple requests or transferring data already held by the client.
+
+ The semantics of the GET method change to a "partial GET" if the
+ request message includes a Range header field. A partial GET requests
+ that only part of the entity be transferred, as described in section
+ 14.35. The partial GET method is intended to reduce unnecessary
+ network usage by allowing partially-retrieved entities to be
+ completed without transferring data already held by the client.
+
+ The response to a GET request is cacheable if and only if it meets
+ the requirements for HTTP caching described in section 13.
+
+ See section 15.1.3 for security considerations when used for forms.
+
+9.4 HEAD
+
+ The HEAD method is identical to GET except that the server MUST NOT
+ return a message-body in the response. The metainformation contained
+ in the HTTP headers in response to a HEAD request SHOULD be identical
+ to the information sent in response to a GET request. This method can
+ be used for obtaining metainformation about the entity implied by the
+ request without transferring the entity-body itself. This method is
+ often used for testing hypertext links for validity, accessibility,
+ and recent modification.
+
+ The response to a HEAD request MAY be cacheable in the sense that the
+ information contained in the response MAY be used to update a
+ previously cached entity from that resource. If the new field values
+ indicate that the cached entity differs from the current entity (as
+ would be indicated by a change in Content-Length, Content-MD5, ETag
+ or Last-Modified), then the cache MUST treat the cache entry as
+ stale.
+
+9.5 POST
+
+ The POST method is used to request that the origin server accept the
+ entity enclosed in the request as a new subordinate of the resource
+ identified by the Request-URI in the Request-Line. POST is designed
+ to allow a uniform method to cover the following functions:
+
+ - Annotation of existing resources;
+
+ - Posting a message to a bulletin board, newsgroup, mailing list,
+ or similar group of articles;
+
+ - Providing a block of data, such as the result of submitting a
+ form, to a data-handling process;
+
+ - Extending a database through an append operation.
+
+ The actual function performed by the POST method is determined by the
+ server and is usually dependent on the Request-URI. The posted entity
+ is subordinate to that URI in the same way that a file is subordinate
+ to a directory containing it, a news article is subordinate to a
+ newsgroup to which it is posted, or a record is subordinate to a
+ database.
+
+ The action performed by the POST method might not result in a
+ resource that can be identified by a URI. In this case, either 200
+ (OK) or 204 (No Content) is the appropriate response status,
+ depending on whether or not the response includes an entity that
+ describes the result.
+
+ If a resource has been created on the origin server, the response
+ SHOULD be 201 (Created) and contain an entity which describes the
+ status of the request and refers to the new resource, and a Location
+ header (see section 14.30).
+
+ Responses to this method are not cacheable, unless the response
+ includes appropriate Cache-Control or Expires header fields. However,
+ the 303 (See Other) response can be used to direct the user agent to
+ retrieve a cacheable resource.
+
+ POST requests MUST obey the message transmission requirements set out
+ in section 8.2.
+
+ See section 15.1.3 for security considerations.
+
+9.6 PUT
+
+ The PUT method requests that the enclosed entity be stored under the
+ supplied Request-URI. If the Request-URI refers to an already
+ existing resource, the enclosed entity SHOULD be considered as a
+ modified version of the one residing on the origin server. If the
+ Request-URI does not point to an existing resource, and that URI is
+ capable of being defined as a new resource by the requesting user
+ agent, the origin server can create the resource with that URI. If a
+ new resource is created, the origin server MUST inform the user agent
+ via the 201 (Created) response. If an existing resource is modified,
+ either the 200 (OK) or 204 (No Content) response codes SHOULD be sent
+ to indicate successful completion of the request. If the resource
+ could not be created or modified with the Request-URI, an appropriate
+ error response SHOULD be given that reflects the nature of the
+ problem. The recipient of the entity MUST NOT ignore any Content-*
+ (e.g. Content-Range) headers that it does not understand or implement
+ and MUST return a 501 (Not Implemented) response in such cases.
+
+ If the request passes through a cache and the Request-URI identifies
+ one or more currently cached entities, those entries SHOULD be
+ treated as stale. Responses to this method are not cacheable.
+
+ The fundamental difference between the POST and PUT requests is
+ reflected in the different meaning of the Request-URI. The URI in a
+ POST request identifies the resource that will handle the enclosed
+ entity. That resource might be a data-accepting process, a gateway to
+ some other protocol, or a separate entity that accepts annotations.
+ In contrast, the URI in a PUT request identifies the entity enclosed
+ with the request -- the user agent knows what URI is intended and the
+ server MUST NOT attempt to apply the request to some other resource.
+ If the server desires that the request be applied to a different URI,
+
+ it MUST send a 301 (Moved Permanently) response; the user agent MAY
+ then make its own decision regarding whether or not to redirect the
+ request.
+
+ A single resource MAY be identified by many different URIs. For
+ example, an article might have a URI for identifying "the current
+ version" which is separate from the URI identifying each particular
+ version. In this case, a PUT request on a general URI might result in
+ several other URIs being defined by the origin server.
+
+ HTTP/1.1 does not define how a PUT method affects the state of an
+ origin server.
+
+ PUT requests MUST obey the message transmission requirements set out
+ in section 8.2.
+
+ Unless otherwise specified for a particular entity-header, the
+ entity-headers in the PUT request SHOULD be applied to the resource
+ created or modified by the PUT.
+
+9.7 DELETE
+
+ The DELETE method requests that the origin server delete the resource
+ identified by the Request-URI. This method MAY be overridden by human
+ intervention (or other means) on the origin server. The client cannot
+ be guaranteed that the operation has been carried out, even if the
+ status code returned from the origin server indicates that the action
+ has been completed successfully. However, the server SHOULD NOT
+ indicate success unless, at the time the response is given, it
+ intends to delete the resource or move it to an inaccessible
+ location.
+
+ A successful response SHOULD be 200 (OK) if the response includes an
+ entity describing the status, 202 (Accepted) if the action has not
+ yet been enacted, or 204 (No Content) if the action has been enacted
+ but the response does not include an entity.
+
+ If the request passes through a cache and the Request-URI identifies
+ one or more currently cached entities, those entries SHOULD be
+ treated as stale. Responses to this method are not cacheable.
+
+9.8 TRACE
+
+ The TRACE method is used to invoke a remote, application-layer loop-
+ back of the request message. The final recipient of the request
+ SHOULD reflect the message received back to the client as the
+ entity-body of a 200 (OK) response. The final recipient is either the
+
+ origin server or the first proxy or gateway to receive a Max-Forwards
+ value of zero (0) in the request (see section 14.31). A TRACE request
+ MUST NOT include an entity.
+
+ TRACE allows the client to see what is being received at the other
+ end of the request chain and use that data for testing or diagnostic
+ information. The value of the Via header field (section 14.45) is of
+ particular interest, since it acts as a trace of the request chain.
+ Use of the Max-Forwards header field allows the client to limit the
+ length of the request chain, which is useful for testing a chain of
+ proxies forwarding messages in an infinite loop.
+
+ If the request is valid, the response SHOULD contain the entire
+ request message in the entity-body, with a Content-Type of
+ "message/http". Responses to this method MUST NOT be cached.
+
+9.9 CONNECT
+
+ This specification reserves the method name CONNECT for use with a
+ proxy that can dynamically switch to being a tunnel (e.g. SSL
+ tunneling [44]).
+
+10 Status Code Definitions
+
+ Each Status-Code is described below, including a description of which
+ method(s) it can follow and any metainformation required in the
+ response.
+
+10.1 Informational 1xx
+
+ This class of status code indicates a provisional response,
+ consisting only of the Status-Line and optional headers, and is
+ terminated by an empty line. There are no required headers for this
+ class of status code. Since HTTP/1.0 did not define any 1xx status
+ codes, servers MUST NOT send a 1xx response to an HTTP/1.0 client
+ except under experimental conditions.
+
+ A client MUST be prepared to accept one or more 1xx status responses
+ prior to a regular response, even if the client does not expect a 100
+ (Continue) status message. Unexpected 1xx status responses MAY be
+ ignored by a user agent.
+
+ Proxies MUST forward 1xx responses, unless the connection between the
+ proxy and its client has been closed, or unless the proxy itself
+ requested the generation of the 1xx response. (For example, if a
+
+ proxy adds a "Expect: 100-continue" field when it forwards a request,
+ then it need not forward the corresponding 100 (Continue)
+ response(s).)
+
+10.1.1 100 Continue
+
+ The client SHOULD continue with its request. This interim response is
+ used to inform the client that the initial part of the request has
+ been received and has not yet been rejected by the server. The client
+ SHOULD continue by sending the remainder of the request or, if the
+ request has already been completed, ignore this response. The server
+ MUST send a final response after the request has been completed. See
+ section 8.2.3 for detailed discussion of the use and handling of this
+ status code.
+
+10.1.2 101 Switching Protocols
+
+ The server understands and is willing to comply with the client's
+ request, via the Upgrade message header field (section 14.42), for a
+ change in the application protocol being used on this connection. The
+ server will switch protocols to those defined by the response's
+ Upgrade header field immediately after the empty line which
+ terminates the 101 response.
+
+ The protocol SHOULD be switched only when it is advantageous to do
+ so. For example, switching to a newer version of HTTP is advantageous
+ over older versions, and switching to a real-time, synchronous
+ protocol might be advantageous when delivering resources that use
+ such features.
+
+10.2 Successful 2xx
+
+ This class of status code indicates that the client's request was
+ successfully received, understood, and accepted.
+
+10.2.1 200 OK
+
+ The request has succeeded. The information returned with the response
+ is dependent on the method used in the request, for example:
+
+ GET an entity corresponding to the requested resource is sent in
+ the response;
+
+ HEAD the entity-header fields corresponding to the requested
+ resource are sent in the response without any message-body;
+
+ POST an entity describing or containing the result of the action;
+
+ TRACE an entity containing the request message as received by the
+ end server.
+
+10.2.2 201 Created
+
+ The request has been fulfilled and resulted in a new resource being
+ created. The newly created resource can be referenced by the URI(s)
+ returned in the entity of the response, with the most specific URI
+ for the resource given by a Location header field. The response
+ SHOULD include an entity containing a list of resource
+ characteristics and location(s) from which the user or user agent can
+ choose the one most appropriate. The entity format is specified by
+ the media type given in the Content-Type header field. The origin
+ server MUST create the resource before returning the 201 status code.
+ If the action cannot be carried out immediately, the server SHOULD
+ respond with 202 (Accepted) response instead.
+
+ A 201 response MAY contain an ETag response header field indicating
+ the current value of the entity tag for the requested variant just
+ created, see section 14.19.
+
+10.2.3 202 Accepted
+
+ The request has been accepted for processing, but the processing has
+ not been completed. The request might or might not eventually be
+ acted upon, as it might be disallowed when processing actually takes
+ place. There is no facility for re-sending a status code from an
+ asynchronous operation such as this.
+
+ The 202 response is intentionally non-committal. Its purpose is to
+ allow a server to accept a request for some other process (perhaps a
+ batch-oriented process that is only run once per day) without
+ requiring that the user agent's connection to the server persist
+ until the process is completed. The entity returned with this
+ response SHOULD include an indication of the request's current status
+ and either a pointer to a status monitor or some estimate of when the
+ user can expect the request to be fulfilled.
+
+10.2.4 203 Non-Authoritative Information
+
+ The returned metainformation in the entity-header is not the
+ definitive set as available from the origin server, but is gathered
+ from a local or a third-party copy. The set presented MAY be a subset
+ or superset of the original version. For example, including local
+ annotation information about the resource might result in a superset
+ of the metainformation known by the origin server. Use of this
+ response code is not required and is only appropriate when the
+ response would otherwise be 200 (OK).
+
+10.2.5 204 No Content
+
+ The server has fulfilled the request but does not need to return an
+ entity-body, and might want to return updated metainformation. The
+ response MAY include new or updated metainformation in the form of
+ entity-headers, which if present SHOULD be associated with the
+ requested variant.
+
+ If the client is a user agent, it SHOULD NOT change its document view
+ from that which caused the request to be sent. This response is
+ primarily intended to allow input for actions to take place without
+ causing a change to the user agent's active document view, although
+ any new or updated metainformation SHOULD be applied to the document
+ currently in the user agent's active view.
+
+ The 204 response MUST NOT include a message-body, and thus is always
+ terminated by the first empty line after the header fields.
+
+10.2.6 205 Reset Content
+
+ The server has fulfilled the request and the user agent SHOULD reset
+ the document view which caused the request to be sent. This response
+ is primarily intended to allow input for actions to take place via
+ user input, followed by a clearing of the form in which the input is
+ given so that the user can easily initiate another input action. The
+ response MUST NOT include an entity.
+
+10.2.7 206 Partial Content
+
+ The server has fulfilled the partial GET request for the resource.
+ The request MUST have included a Range header field (section 14.35)
+ indicating the desired range, and MAY have included an If-Range
+ header field (section 14.27) to make the request conditional.
+
+ The response MUST include the following header fields:
+
+ - Either a Content-Range header field (section 14.16) indicating
+ the range included with this response, or a multipart/byteranges
+ Content-Type including Content-Range fields for each part. If a
+ Content-Length header field is present in the response, its
+ value MUST match the actual number of OCTETs transmitted in the
+ message-body.
+
+ - Date
+
+ - ETag and/or Content-Location, if the header would have been sent
+ in a 200 response to the same request
+
+ - Expires, Cache-Control, and/or Vary, if the field-value might
+ differ from that sent in any previous response for the same
+ variant
+
+ If the 206 response is the result of an If-Range request that used a
+ strong cache validator (see section 13.3.3), the response SHOULD NOT
+ include other entity-headers. If the response is the result of an
+ If-Range request that used a weak validator, the response MUST NOT
+ include other entity-headers; this prevents inconsistencies between
+ cached entity-bodies and updated headers. Otherwise, the response
+ MUST include all of the entity-headers that would have been returned
+ with a 200 (OK) response to the same request.
+
+ A cache MUST NOT combine a 206 response with other previously cached
+ content if the ETag or Last-Modified headers do not match exactly,
+ see 13.5.4.
+
+ A cache that does not support the Range and Content-Range headers
+ MUST NOT cache 206 (Partial) responses.
+
+10.3 Redirection 3xx
+
+ This class of status code indicates that further action needs to be
+ taken by the user agent in order to fulfill the request. The action
+ required MAY be carried out by the user agent without interaction
+ with the user if and only if the method used in the second request is
+ GET or HEAD. A client SHOULD detect infinite redirection loops, since
+ such loops generate network traffic for each redirection.
+
+ Note: previous versions of this specification recommended a
+ maximum of five redirections. Content developers should be aware
+ that there might be clients that implement such a fixed
+ limitation.
+
+10.3.1 300 Multiple Choices
+
+ The requested resource corresponds to any one of a set of
+ representations, each with its own specific location, and agent-
+ driven negotiation information (section 12) is being provided so that
+ the user (or user agent) can select a preferred representation and
+ redirect its request to that location.
+
+ Unless it was a HEAD request, the response SHOULD include an entity
+ containing a list of resource characteristics and location(s) from
+ which the user or user agent can choose the one most appropriate. The
+ entity format is specified by the media type given in the Content-
+ Type header field. Depending upon the format and the capabilities of
+
+ the user agent, selection of the most appropriate choice MAY be
+ performed automatically. However, this specification does not define
+ any standard for such automatic selection.
+
+ If the server has a preferred choice of representation, it SHOULD
+ include the specific URI for that representation in the Location
+ field; user agents MAY use the Location field value for automatic
+ redirection. This response is cacheable unless indicated otherwise.
+
+10.3.2 301 Moved Permanently
+
+ The requested resource has been assigned a new permanent URI and any
+ future references to this resource SHOULD use one of the returned
+ URIs. Clients with link editing capabilities ought to automatically
+ re-link references to the Request-URI to one or more of the new
+ references returned by the server, where possible. This response is
+ cacheable unless indicated otherwise.
+
+ The new permanent URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ If the 301 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+ Note: When automatically redirecting a POST request after
+ receiving a 301 status code, some existing HTTP/1.0 user agents
+ will erroneously change it into a GET request.
+
+10.3.3 302 Found
+
+ The requested resource resides temporarily under a different URI.
+ Since the redirection might be altered on occasion, the client SHOULD
+ continue to use the Request-URI for future requests. This response
+ is only cacheable if indicated by a Cache-Control or Expires header
+ field.
+
+ The temporary URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ If the 302 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+ Note: <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a> and <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> specify that the client is not allowed
+ to change the method on the redirected request. However, most
+ existing user agent implementations treat 302 as if it were a 303
+ response, performing a GET on the Location field-value regardless
+ of the original request method. The status codes 303 and 307 have
+ been added for servers that wish to make unambiguously clear which
+ kind of reaction is expected of the client.
+
+10.3.4 303 See Other
+
+ The response to the request can be found under a different URI and
+ SHOULD be retrieved using a GET method on that resource. This method
+ exists primarily to allow the output of a POST-activated script to
+ redirect the user agent to a selected resource. The new URI is not a
+ substitute reference for the originally requested resource. The 303
+ response MUST NOT be cached, but the response to the second
+ (redirected) request might be cacheable.
+
+ The different URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ Note: Many pre-HTTP/1.1 user agents do not understand the 303
+ status. When interoperability with such clients is a concern, the
+ 302 status code may be used instead, since most user agents react
+ to a 302 response as described here for 303.
+
+10.3.5 304 Not Modified
+
+ If the client has performed a conditional GET request and access is
+ allowed, but the document has not been modified, the server SHOULD
+ respond with this status code. The 304 response MUST NOT contain a
+ message-body, and thus is always terminated by the first empty line
+ after the header fields.
+
+ The response MUST include the following header fields:
+
+ - Date, unless its omission is required by section 14.18.1
+
+ If a clockless origin server obeys these rules, and proxies and
+ clients add their own Date to any response received without one (as
+ already specified by [<a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>], section 14.19), caches will operate
+ correctly.
+
+ - ETag and/or Content-Location, if the header would have been sent
+ in a 200 response to the same request
+
+ - Expires, Cache-Control, and/or Vary, if the field-value might
+ differ from that sent in any previous response for the same
+ variant
+
+ If the conditional GET used a strong cache validator (see section
+ 13.3.3), the response SHOULD NOT include other entity-headers.
+ Otherwise (i.e., the conditional GET used a weak validator), the
+ response MUST NOT include other entity-headers; this prevents
+ inconsistencies between cached entity-bodies and updated headers.
+
+ If a 304 response indicates an entity not currently cached, then the
+ cache MUST disregard the response and repeat the request without the
+ conditional.
+
+ If a cache uses a received 304 response to update a cache entry, the
+ cache MUST update the entry to reflect any new field values given in
+ the response.
+
+10.3.6 305 Use Proxy
+
+ The requested resource MUST be accessed through the proxy given by
+ the Location field. The Location field gives the URI of the proxy.
+ The recipient is expected to repeat this single request via the
+ proxy. 305 responses MUST only be generated by origin servers.
+
+ Note: <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> was not clear that 305 was intended to redirect a
+ single request, and to be generated by origin servers only. Not
+ observing these limitations has significant security consequences.
+
+10.3.7 306 (Unused)
+
+ The 306 status code was used in a previous version of the
+ specification, is no longer used, and the code is reserved.
+
+10.3.8 307 Temporary Redirect
+
+ The requested resource resides temporarily under a different URI.
+ Since the redirection MAY be altered on occasion, the client SHOULD
+ continue to use the Request-URI for future requests. This response
+ is only cacheable if indicated by a Cache-Control or Expires header
+ field.
+
+ The temporary URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s) , since many pre-HTTP/1.1 user agents do not
+ understand the 307 status. Therefore, the note SHOULD contain the
+ information necessary for a user to repeat the original request on
+ the new URI.
+
+ If the 307 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+10.4 Client Error 4xx
+
+ The 4xx class of status code is intended for cases in which the
+ client seems to have erred. Except when responding to a HEAD request,
+ the server SHOULD include an entity containing an explanation of the
+ error situation, and whether it is a temporary or permanent
+ condition. These status codes are applicable to any request method.
+ User agents SHOULD display any included entity to the user.
+
+ If the client is sending data, a server implementation using TCP
+ SHOULD be careful to ensure that the client acknowledges receipt of
+ the packet(s) containing the response, before the server closes the
+ input connection. If the client continues sending data to the server
+ after the close, the server's TCP stack will send a reset packet to
+ the client, which may erase the client's unacknowledged input buffers
+ before they can be read and interpreted by the HTTP application.
+
+10.4.1 400 Bad Request
+
+ The request could not be understood by the server due to malformed
+ syntax. The client SHOULD NOT repeat the request without
+ modifications.
+
+10.4.2 401 Unauthorized
+
+ The request requires user authentication. The response MUST include a
+ WWW-Authenticate header field (section 14.47) containing a challenge
+ applicable to the requested resource. The client MAY repeat the
+ request with a suitable Authorization header field (section 14.8). If
+ the request already included Authorization credentials, then the 401
+ response indicates that authorization has been refused for those
+ credentials. If the 401 response contains the same challenge as the
+ prior response, and the user agent has already attempted
+ authentication at least once, then the user SHOULD be presented the
+ entity that was given in the response, since that entity might
+ include relevant diagnostic information. HTTP access authentication
+ is explained in "HTTP Authentication: Basic and Digest Access
+ Authentication" [43].
+
+10.4.3 402 Payment Required
+
+ This code is reserved for future use.
+
+10.4.4 403 Forbidden
+
+ The server understood the request, but is refusing to fulfill it.
+ Authorization will not help and the request SHOULD NOT be repeated.
+ If the request method was not HEAD and the server wishes to make
+ public why the request has not been fulfilled, it SHOULD describe the
+ reason for the refusal in the entity. If the server does not wish to
+ make this information available to the client, the status code 404
+ (Not Found) can be used instead.
+
+10.4.5 404 Not Found
+
+ The server has not found anything matching the Request-URI. No
+ indication is given of whether the condition is temporary or
+ permanent. The 410 (Gone) status code SHOULD be used if the server
+ knows, through some internally configurable mechanism, that an old
+ resource is permanently unavailable and has no forwarding address.
+ This status code is commonly used when the server does not wish to
+ reveal exactly why the request has been refused, or when no other
+ response is applicable.
+
+10.4.6 405 Method Not Allowed
+
+ The method specified in the Request-Line is not allowed for the
+ resource identified by the Request-URI. The response MUST include an
+ Allow header containing a list of valid methods for the requested
+ resource.
+
+10.4.7 406 Not Acceptable
+
+ The resource identified by the request is only capable of generating
+ response entities which have content characteristics not acceptable
+ according to the accept headers sent in the request.
+
+ Unless it was a HEAD request, the response SHOULD include an entity
+ containing a list of available entity characteristics and location(s)
+ from which the user or user agent can choose the one most
+ appropriate. The entity format is specified by the media type given
+ in the Content-Type header field. Depending upon the format and the
+ capabilities of the user agent, selection of the most appropriate
+ choice MAY be performed automatically. However, this specification
+ does not define any standard for such automatic selection.
+
+ Note: HTTP/1.1 servers are allowed to return responses which are
+ not acceptable according to the accept headers sent in the
+ request. In some cases, this may even be preferable to sending a
+ 406 response. User agents are encouraged to inspect the headers of
+ an incoming response to determine if it is acceptable.
+
+ If the response could be unacceptable, a user agent SHOULD
+ temporarily stop receipt of more data and query the user for a
+ decision on further actions.
+
+10.4.8 407 Proxy Authentication Required
+
+ This code is similar to 401 (Unauthorized), but indicates that the
+ client must first authenticate itself with the proxy. The proxy MUST
+ return a Proxy-Authenticate header field (section 14.33) containing a
+ challenge applicable to the proxy for the requested resource. The
+ client MAY repeat the request with a suitable Proxy-Authorization
+ header field (section 14.34). HTTP access authentication is explained
+ in "HTTP Authentication: Basic and Digest Access Authentication"
+ [43].
+
+10.4.9 408 Request Timeout
+
+ The client did not produce a request within the time that the server
+ was prepared to wait. The client MAY repeat the request without
+ modifications at any later time.
+
+10.4.10 409 Conflict
+
+ The request could not be completed due to a conflict with the current
+ state of the resource. This code is only allowed in situations where
+ it is expected that the user might be able to resolve the conflict
+ and resubmit the request. The response body SHOULD include enough
+
+ information for the user to recognize the source of the conflict.
+ Ideally, the response entity would include enough information for the
+ user or user agent to fix the problem; however, that might not be
+ possible and is not required.
+
+ Conflicts are most likely to occur in response to a PUT request. For
+ example, if versioning were being used and the entity being PUT
+ included changes to a resource which conflict with those made by an
+ earlier (third-party) request, the server might use the 409 response
+ to indicate that it can't complete the request. In this case, the
+ response entity would likely contain a list of the differences
+ between the two versions in a format defined by the response
+ Content-Type.
+
+10.4.11 410 Gone
+
+ The requested resource is no longer available at the server and no
+ forwarding address is known. This condition is expected to be
+ considered permanent. Clients with link editing capabilities SHOULD
+ delete references to the Request-URI after user approval. If the
+ server does not know, or has no facility to determine, whether or not
+ the condition is permanent, the status code 404 (Not Found) SHOULD be
+ used instead. This response is cacheable unless indicated otherwise.
+
+ The 410 response is primarily intended to assist the task of web
+ maintenance by notifying the recipient that the resource is
+ intentionally unavailable and that the server owners desire that
+ remote links to that resource be removed. Such an event is common for
+ limited-time, promotional services and for resources belonging to
+ individuals no longer working at the server's site. It is not
+ necessary to mark all permanently unavailable resources as "gone" or
+ to keep the mark for any length of time -- that is left to the
+ discretion of the server owner.
+
+10.4.12 411 Length Required
+
+ The server refuses to accept the request without a defined Content-
+ Length. The client MAY repeat the request if it adds a valid
+ Content-Length header field containing the length of the message-body
+ in the request message.
+
+10.4.13 412 Precondition Failed
+
+ The precondition given in one or more of the request-header fields
+ evaluated to false when it was tested on the server. This response
+ code allows the client to place preconditions on the current resource
+ metainformation (header field data) and thus prevent the requested
+ method from being applied to a resource other than the one intended.
+
+10.4.14 413 Request Entity Too Large
+
+ The server is refusing to process a request because the request
+ entity is larger than the server is willing or able to process. The
+ server MAY close the connection to prevent the client from continuing
+ the request.
+
+ If the condition is temporary, the server SHOULD include a Retry-
+ After header field to indicate that it is temporary and after what
+ time the client MAY try again.
+
+10.4.15 414 Request-URI Too Long
+
+ The server is refusing to service the request because the Request-URI
+ is longer than the server is willing to interpret. This rare
+ condition is only likely to occur when a client has improperly
+ converted a POST request to a GET request with long query
+ information, when the client has descended into a URI "black hole" of
+ redirection (e.g., a redirected URI prefix that points to a suffix of
+ itself), or when the server is under attack by a client attempting to
+ exploit security holes present in some servers using fixed-length
+ buffers for reading or manipulating the Request-URI.
+
+10.4.16 415 Unsupported Media Type
+
+ The server is refusing to service the request because the entity of
+ the request is in a format not supported by the requested resource
+ for the requested method.
+
+10.4.17 416 Requested Range Not Satisfiable
+
+ A server SHOULD return a response with this status code if a request
+ included a Range request-header field (section 14.35), and none of
+ the range-specifier values in this field overlap the current extent
+ of the selected resource, and the request did not include an If-Range
+ request-header field. (For byte-ranges, this means that the first-
+ byte-pos of all of the byte-range-spec values were greater than the
+ current length of the selected resource.)
+
+ When this status code is returned for a byte-range request, the
+ response SHOULD include a Content-Range entity-header field
+ specifying the current length of the selected resource (see section
+ 14.16). This response MUST NOT use the multipart/byteranges content-
+ type.
+
+10.4.18 417 Expectation Failed
+
+ The expectation given in an Expect request-header field (see section
+ 14.20) could not be met by this server, or, if the server is a proxy,
+ the server has unambiguous evidence that the request could not be met
+ by the next-hop server.
+
+10.5 Server Error 5xx
+
+ Response status codes beginning with the digit "5" indicate cases in
+ which the server is aware that it has erred or is incapable of
+ performing the request. Except when responding to a HEAD request, the
+ server SHOULD include an entity containing an explanation of the
+ error situation, and whether it is a temporary or permanent
+ condition. User agents SHOULD display any included entity to the
+ user. These response codes are applicable to any request method.
+
+10.5.1 500 Internal Server Error
+
+ The server encountered an unexpected condition which prevented it
+ from fulfilling the request.
+
+10.5.2 501 Not Implemented
+
+ The server does not support the functionality required to fulfill the
+ request. This is the appropriate response when the server does not
+ recognize the request method and is not capable of supporting it for
+ any resource.
+
+10.5.3 502 Bad Gateway
+
+ The server, while acting as a gateway or proxy, received an invalid
+ response from the upstream server it accessed in attempting to
+ fulfill the request.
+
+10.5.4 503 Service Unavailable
+
+ The server is currently unable to handle the request due to a
+ temporary overloading or maintenance of the server. The implication
+ is that this is a temporary condition which will be alleviated after
+ some delay. If known, the length of the delay MAY be indicated in a
+ Retry-After header. If no Retry-After is given, the client SHOULD
+ handle the response as it would for a 500 response.
+
+ Note: The existence of the 503 status code does not imply that a
+ server must use it when becoming overloaded. Some servers may wish
+ to simply refuse the connection.
+
+10.5.5 504 Gateway Timeout
+
+ The server, while acting as a gateway or proxy, did not receive a
+ timely response from the upstream server specified by the URI (e.g.
+ HTTP, FTP, LDAP) or some other auxiliary server (e.g. DNS) it needed
+ to access in attempting to complete the request.
+
+ Note: Note to implementors: some deployed proxies are known to
+ return 400 or 500 when DNS lookups time out.
+
+10.5.6 505 HTTP Version Not Supported
+
+ The server does not support, or refuses to support, the HTTP protocol
+ version that was used in the request message. The server is
+ indicating that it is unable or unwilling to complete the request
+ using the same major version as the client, as described in section
+ 3.1, other than with this error message. The response SHOULD contain
+ an entity describing why that version is not supported and what other
+ protocols are supported by that server.
+
+11 Access Authentication
+
+ HTTP provides several OPTIONAL challenge-response authentication
+ mechanisms which can be used by a server to challenge a client
+ request and by a client to provide authentication information. The
+ general framework for access authentication, and the specification of
+ "basic" and "digest" authentication, are specified in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. This
+ specification adopts the definitions of "challenge" and "credentials"
+ from that specification.
+
+12 Content Negotiation
+
+ Most HTTP responses include an entity which contains information for
+ interpretation by a human user. Naturally, it is desirable to supply
+ the user with the "best available" entity corresponding to the
+ request. Unfortunately for servers and caches, not all users have the
+ same preferences for what is "best," and not all user agents are
+ equally capable of rendering all entity types. For that reason, HTTP
+ has provisions for several mechanisms for "content negotiation" --
+ the process of selecting the best representation for a given response
+ when there are multiple representations available.
+
+ Note: This is not called "format negotiation" because the
+ alternate representations may be of the same media type, but use
+ different capabilities of that type, be in different languages,
+ etc.
+
+ Any response containing an entity-body MAY be subject to negotiation,
+ including error responses.
+
+ There are two kinds of content negotiation which are possible in
+ HTTP: server-driven and agent-driven negotiation. These two kinds of
+ negotiation are orthogonal and thus may be used separately or in
+ combination. One method of combination, referred to as transparent
+ negotiation, occurs when a cache uses the agent-driven negotiation
+ information provided by the origin server in order to provide
+ server-driven negotiation for subsequent requests.
+
+12.1 Server-driven Negotiation
+
+ If the selection of the best representation for a response is made by
+ an algorithm located at the server, it is called server-driven
+ negotiation. Selection is based on the available representations of
+ the response (the dimensions over which it can vary; e.g. language,
+ content-coding, etc.) and the contents of particular header fields in
+ the request message or on other information pertaining to the request
+ (such as the network address of the client).
+
+ Server-driven negotiation is advantageous when the algorithm for
+ selecting from among the available representations is difficult to
+ describe to the user agent, or when the server desires to send its
+ "best guess" to the client along with the first response (hoping to
+ avoid the round-trip delay of a subsequent request if the "best
+ guess" is good enough for the user). In order to improve the server's
+ guess, the user agent MAY include request header fields (Accept,
+ Accept-Language, Accept-Encoding, etc.) which describe its
+ preferences for such a response.
+
+ Server-driven negotiation has disadvantages:
+
+ 1. It is impossible for the server to accurately determine what
+ might be "best" for any given user, since that would require
+ complete knowledge of both the capabilities of the user agent
+ and the intended use for the response (e.g., does the user want
+ to view it on screen or print it on paper?).
+
+ 2. Having the user agent describe its capabilities in every
+ request can be both very inefficient (given that only a small
+ percentage of responses have multiple representations) and a
+ potential violation of the user's privacy.
+
+ 3. It complicates the implementation of an origin server and the
+ algorithms for generating responses to a request.
+
+ 4. It may limit a public cache's ability to use the same response
+ for multiple user's requests.
+
+ HTTP/1.1 includes the following request-header fields for enabling
+ server-driven negotiation through description of user agent
+ capabilities and user preferences: Accept (section 14.1), Accept-
+ Charset (section 14.2), Accept-Encoding (section 14.3), Accept-
+ Language (section 14.4), and User-Agent (section 14.43). However, an
+ origin server is not limited to these dimensions and MAY vary the
+ response based on any aspect of the request, including information
+ outside the request-header fields or within extension header fields
+ not defined by this specification.
+
+ The Vary header field can be used to express the parameters the
+ server uses to select a representation that is subject to server-
+ driven negotiation. See section 13.6 for use of the Vary header field
+ by caches and section 14.44 for use of the Vary header field by
+ servers.
+
+12.2 Agent-driven Negotiation
+
+ With agent-driven negotiation, selection of the best representation
+ for a response is performed by the user agent after receiving an
+ initial response from the origin server. Selection is based on a list
+ of the available representations of the response included within the
+ header fields or entity-body of the initial response, with each
+ representation identified by its own URI. Selection from among the
+ representations may be performed automatically (if the user agent is
+ capable of doing so) or manually by the user selecting from a
+ generated (possibly hypertext) menu.
+
+ Agent-driven negotiation is advantageous when the response would vary
+ over commonly-used dimensions (such as type, language, or encoding),
+ when the origin server is unable to determine a user agent's
+ capabilities from examining the request, and generally when public
+ caches are used to distribute server load and reduce network usage.
+
+ Agent-driven negotiation suffers from the disadvantage of needing a
+ second request to obtain the best alternate representation. This
+ second request is only efficient when caching is used. In addition,
+ this specification does not define any mechanism for supporting
+ automatic selection, though it also does not prevent any such
+ mechanism from being developed as an extension and used within
+ HTTP/1.1.
+
+ HTTP/1.1 defines the 300 (Multiple Choices) and 406 (Not Acceptable)
+ status codes for enabling agent-driven negotiation when the server is
+ unwilling or unable to provide a varying response using server-driven
+ negotiation.
+
+12.3 Transparent Negotiation
+
+ Transparent negotiation is a combination of both server-driven and
+ agent-driven negotiation. When a cache is supplied with a form of the
+ list of available representations of the response (as in agent-driven
+ negotiation) and the dimensions of variance are completely understood
+ by the cache, then the cache becomes capable of performing server-
+ driven negotiation on behalf of the origin server for subsequent
+ requests on that resource.
+
+ Transparent negotiation has the advantage of distributing the
+ negotiation work that would otherwise be required of the origin
+ server and also removing the second request delay of agent-driven
+ negotiation when the cache is able to correctly guess the right
+ response.
+
+ This specification does not define any mechanism for transparent
+ negotiation, though it also does not prevent any such mechanism from
+ being developed as an extension that could be used within HTTP/1.1.
+
+13 Caching in HTTP
+
+ HTTP is typically used for distributed information systems, where
+ performance can be improved by the use of response caches. The
+ HTTP/1.1 protocol includes a number of elements intended to make
+ caching work as well as possible. Because these elements are
+ inextricable from other aspects of the protocol, and because they
+ interact with each other, it is useful to describe the basic caching
+ design of HTTP separately from the detailed descriptions of methods,
+ headers, response codes, etc.
+
+ Caching would be useless if it did not significantly improve
+ performance. The goal of caching in HTTP/1.1 is to eliminate the need
+ to send requests in many cases, and to eliminate the need to send
+ full responses in many other cases. The former reduces the number of
+ network round-trips required for many operations; we use an
+ "expiration" mechanism for this purpose (see section 13.2). The
+ latter reduces network bandwidth requirements; we use a "validation"
+ mechanism for this purpose (see section 13.3).
+
+ Requirements for performance, availability, and disconnected
+ operation require us to be able to relax the goal of semantic
+ transparency. The HTTP/1.1 protocol allows origin servers, caches,
+
+ and clients to explicitly reduce transparency when necessary.
+ However, because non-transparent operation may confuse non-expert
+ users, and might be incompatible with certain server applications
+ (such as those for ordering merchandise), the protocol requires that
+ transparency be relaxed
+
+ - only by an explicit protocol-level request when relaxed by
+ client or origin server
+
+ - only with an explicit warning to the end user when relaxed by
+ cache or client
+
+ Therefore, the HTTP/1.1 protocol provides these important elements:
+
+ 1. Protocol features that provide full semantic transparency when
+ this is required by all parties.
+
+ 2. Protocol features that allow an origin server or user agent to
+ explicitly request and control non-transparent operation.
+
+ 3. Protocol features that allow a cache to attach warnings to
+ responses that do not preserve the requested approximation of
+ semantic transparency.
+
+ A basic principle is that it must be possible for the clients to
+ detect any potential relaxation of semantic transparency.
+
+ Note: The server, cache, or client implementor might be faced with
+ design decisions not explicitly discussed in this specification.
+ If a decision might affect semantic transparency, the implementor
+ ought to err on the side of maintaining transparency unless a
+ careful and complete analysis shows significant benefits in
+ breaking transparency.
+
+13.1.1 Cache Correctness
+
+ A correct cache MUST respond to a request with the most up-to-date
+ response held by the cache that is appropriate to the request (see
+ sections 13.2.5, 13.2.6, and 13.12) which meets one of the following
+ conditions:
+
+ 1. It has been checked for equivalence with what the origin server
+ would have returned by revalidating the response with the
+ origin server (section 13.3);
+
+ 2. It is "fresh enough" (see section 13.2). In the default case,
+ this means it meets the least restrictive freshness requirement
+ of the client, origin server, and cache (see section 14.9); if
+ the origin server so specifies, it is the freshness requirement
+ of the origin server alone.
+
+ If a stored response is not "fresh enough" by the most
+ restrictive freshness requirement of both the client and the
+ origin server, in carefully considered circumstances the cache
+ MAY still return the response with the appropriate Warning
+ header (see section 13.1.5 and 14.46), unless such a response
+ is prohibited (e.g., by a "no-store" cache-directive, or by a
+ "no-cache" cache-request-directive; see section 14.9).
+
+ 3. It is an appropriate 304 (Not Modified), 305 (Proxy Redirect),
+ or error (4xx or 5xx) response message.
+
+ If the cache can not communicate with the origin server, then a
+ correct cache SHOULD respond as above if the response can be
+ correctly served from the cache; if not it MUST return an error or
+ warning indicating that there was a communication failure.
+
+ If a cache receives a response (either an entire response, or a 304
+ (Not Modified) response) that it would normally forward to the
+ requesting client, and the received response is no longer fresh, the
+ cache SHOULD forward it to the requesting client without adding a new
+ Warning (but without removing any existing Warning headers). A cache
+ SHOULD NOT attempt to revalidate a response simply because that
+ response became stale in transit; this might lead to an infinite
+ loop. A user agent that receives a stale response without a Warning
+ MAY display a warning indication to the user.
+
+13.1.2 Warnings
+
+ Whenever a cache returns a response that is neither first-hand nor
+ "fresh enough" (in the sense of condition 2 in section 13.1.1), it
+ MUST attach a warning to that effect, using a Warning general-header.
+ The Warning header and the currently defined warnings are described
+ in section 14.46. The warning allows clients to take appropriate
+ action.
+
+ Warnings MAY be used for other purposes, both cache-related and
+ otherwise. The use of a warning, rather than an error status code,
+ distinguish these responses from true failures.
+
+ Warnings are assigned three digit warn-codes. The first digit
+ indicates whether the Warning MUST or MUST NOT be deleted from a
+ stored cache entry after a successful revalidation:
+
+ 1xx Warnings that describe the freshness or revalidation status of
+ the response, and so MUST be deleted after a successful
+ revalidation. 1XX warn-codes MAY be generated by a cache only when
+ validating a cached entry. It MUST NOT be generated by clients.
+
+ 2xx Warnings that describe some aspect of the entity body or entity
+ headers that is not rectified by a revalidation (for example, a
+ lossy compression of the entity bodies) and which MUST NOT be
+ deleted after a successful revalidation.
+
+ See section 14.46 for the definitions of the codes themselves.
+
+ HTTP/1.0 caches will cache all Warnings in responses, without
+ deleting the ones in the first category. Warnings in responses that
+ are passed to HTTP/1.0 caches carry an extra warning-date field,
+ which prevents a future HTTP/1.1 recipient from believing an
+ erroneously cached Warning.
+
+ Warnings also carry a warning text. The text MAY be in any
+ appropriate natural language (perhaps based on the client's Accept
+ headers), and include an OPTIONAL indication of what character set is
+ used.
+
+ Multiple warnings MAY be attached to a response (either by the origin
+ server or by a cache), including multiple warnings with the same code
+ number. For example, a server might provide the same warning with
+ texts in both English and Basque.
+
+ When multiple warnings are attached to a response, it might not be
+ practical or reasonable to display all of them to the user. This
+ version of HTTP does not specify strict priority rules for deciding
+ which warnings to display and in what order, but does suggest some
+ heuristics.
+
+13.1.3 Cache-control Mechanisms
+
+ The basic cache mechanisms in HTTP/1.1 (server-specified expiration
+ times and validators) are implicit directives to caches. In some
+ cases, a server or client might need to provide explicit directives
+ to the HTTP caches. We use the Cache-Control header for this purpose.
+
+ The Cache-Control header allows a client or server to transmit a
+ variety of directives in either requests or responses. These
+ directives typically override the default caching algorithms. As a
+ general rule, if there is any apparent conflict between header
+ values, the most restrictive interpretation is applied (that is, the
+ one that is most likely to preserve semantic transparency). However,
+
+ in some cases, cache-control directives are explicitly specified as
+ weakening the approximation of semantic transparency (for example,
+ "max-stale" or "public").
+
+ The cache-control directives are described in detail in section 14.9.
+
+13.1.4 Explicit User Agent Warnings
+
+ Many user agents make it possible for users to override the basic
+ caching mechanisms. For example, the user agent might allow the user
+ to specify that cached entities (even explicitly stale ones) are
+ never validated. Or the user agent might habitually add "Cache-
+ Control: max-stale=3600" to every request. The user agent SHOULD NOT
+ default to either non-transparent behavior, or behavior that results
+ in abnormally ineffective caching, but MAY be explicitly configured
+ to do so by an explicit action of the user.
+
+ If the user has overridden the basic caching mechanisms, the user
+ agent SHOULD explicitly indicate to the user whenever this results in
+ the display of information that might not meet the server's
+ transparency requirements (in particular, if the displayed entity is
+ known to be stale). Since the protocol normally allows the user agent
+ to determine if responses are stale or not, this indication need only
+ be displayed when this actually happens. The indication need not be a
+ dialog box; it could be an icon (for example, a picture of a rotting
+ fish) or some other indicator.
+
+ If the user has overridden the caching mechanisms in a way that would
+ abnormally reduce the effectiveness of caches, the user agent SHOULD
+ continually indicate this state to the user (for example, by a
+ display of a picture of currency in flames) so that the user does not
+ inadvertently consume excess resources or suffer from excessive
+ latency.
+
+13.1.5 Exceptions to the Rules and Warnings
+
+ In some cases, the operator of a cache MAY choose to configure it to
+ return stale responses even when not requested by clients. This
+ decision ought not be made lightly, but may be necessary for reasons
+ of availability or performance, especially when the cache is poorly
+ connected to the origin server. Whenever a cache returns a stale
+ response, it MUST mark it as such (using a Warning header) enabling
+ the client software to alert the user that there might be a potential
+ problem.
+
+ It also allows the user agent to take steps to obtain a first-hand or
+ fresh response. For this reason, a cache SHOULD NOT return a stale
+ response if the client explicitly requests a first-hand or fresh one,
+ unless it is impossible to comply for technical or policy reasons.
+
+13.1.6 Client-controlled Behavior
+
+ While the origin server (and to a lesser extent, intermediate caches,
+ by their contribution to the age of a response) are the primary
+ source of expiration information, in some cases the client might need
+ to control a cache's decision about whether to return a cached
+ response without validating it. Clients do this using several
+ directives of the Cache-Control header.
+
+ A client's request MAY specify the maximum age it is willing to
+ accept of an unvalidated response; specifying a value of zero forces
+ the cache(s) to revalidate all responses. A client MAY also specify
+ the minimum time remaining before a response expires. Both of these
+ options increase constraints on the behavior of caches, and so cannot
+ further relax the cache's approximation of semantic transparency.
+
+ A client MAY also specify that it will accept stale responses, up to
+ some maximum amount of staleness. This loosens the constraints on the
+ caches, and so might violate the origin server's specified
+ constraints on semantic transparency, but might be necessary to
+ support disconnected operation, or high availability in the face of
+ poor connectivity.
+
+13.2 Expiration Model
+
+13.2.1 Server-Specified Expiration
+
+ HTTP caching works best when caches can entirely avoid making
+ requests to the origin server. The primary mechanism for avoiding
+ requests is for an origin server to provide an explicit expiration
+ time in the future, indicating that a response MAY be used to satisfy
+ subsequent requests. In other words, a cache can return a fresh
+ response without first contacting the server.
+
+ Our expectation is that servers will assign future explicit
+ expiration times to responses in the belief that the entity is not
+ likely to change, in a semantically significant way, before the
+ expiration time is reached. This normally preserves semantic
+ transparency, as long as the server's expiration times are carefully
+ chosen.
+
+ The expiration mechanism applies only to responses taken from a cache
+ and not to first-hand responses forwarded immediately to the
+ requesting client.
+
+ If an origin server wishes to force a semantically transparent cache
+ to validate every request, it MAY assign an explicit expiration time
+ in the past. This means that the response is always stale, and so the
+ cache SHOULD validate it before using it for subsequent requests. See
+ section 14.9.4 for a more restrictive way to force revalidation.
+
+ If an origin server wishes to force any HTTP/1.1 cache, no matter how
+ it is configured, to validate every request, it SHOULD use the "must-
+ revalidate" cache-control directive (see section 14.9).
+
+ Servers specify explicit expiration times using either the Expires
+ header, or the max-age directive of the Cache-Control header.
+
+ An expiration time cannot be used to force a user agent to refresh
+ its display or reload a resource; its semantics apply only to caching
+ mechanisms, and such mechanisms need only check a resource's
+ expiration status when a new request for that resource is initiated.
+ See section 13.13 for an explanation of the difference between caches
+ and history mechanisms.
+
+13.2.2 Heuristic Expiration
+
+ Since origin servers do not always provide explicit expiration times,
+ HTTP caches typically assign heuristic expiration times, employing
+ algorithms that use other header values (such as the Last-Modified
+ time) to estimate a plausible expiration time. The HTTP/1.1
+ specification does not provide specific algorithms, but does impose
+ worst-case constraints on their results. Since heuristic expiration
+ times might compromise semantic transparency, they ought to used
+ cautiously, and we encourage origin servers to provide explicit
+ expiration times as much as possible.
+
+13.2.3 Age Calculations
+
+ In order to know if a cached entry is fresh, a cache needs to know if
+ its age exceeds its freshness lifetime. We discuss how to calculate
+ the latter in section 13.2.4; this section describes how to calculate
+ the age of a response or cache entry.
+
+ In this discussion, we use the term "now" to mean "the current value
+ of the clock at the host performing the calculation." Hosts that use
+ HTTP, but especially hosts running origin servers and caches, SHOULD
+ use NTP [28] or some similar protocol to synchronize their clocks to
+ a globally accurate time standard.
+
+ HTTP/1.1 requires origin servers to send a Date header, if possible,
+ with every response, giving the time at which the response was
+ generated (see section 14.18). We use the term "date_value" to denote
+ the value of the Date header, in a form appropriate for arithmetic
+ operations.
+
+ HTTP/1.1 uses the Age response-header to convey the estimated age of
+ the response message when obtained from a cache. The Age field value
+ is the cache's estimate of the amount of time since the response was
+ generated or revalidated by the origin server.
+
+ In essence, the Age value is the sum of the time that the response
+ has been resident in each of the caches along the path from the
+ origin server, plus the amount of time it has been in transit along
+ network paths.
+
+ We use the term "age_value" to denote the value of the Age header, in
+ a form appropriate for arithmetic operations.
+
+ A response's age can be calculated in two entirely independent ways:
+
+ 1. now minus date_value, if the local clock is reasonably well
+ synchronized to the origin server's clock. If the result is
+ negative, the result is replaced by zero.
+
+ 2. age_value, if all of the caches along the response path
+ implement HTTP/1.1.
+
+ Given that we have two independent ways to compute the age of a
+ response when it is received, we can combine these as
+
+ corrected_received_age = max(now - date_value, age_value)
+
+ and as long as we have either nearly synchronized clocks or all-
+ HTTP/1.1 paths, one gets a reliable (conservative) result.
+
+ Because of network-imposed delays, some significant interval might
+ pass between the time that a server generates a response and the time
+ it is received at the next outbound cache or client. If uncorrected,
+ this delay could result in improperly low ages.
+
+ Because the request that resulted in the returned Age value must have
+ been initiated prior to that Age value's generation, we can correct
+ for delays imposed by the network by recording the time at which the
+ request was initiated. Then, when an Age value is received, it MUST
+ be interpreted relative to the time the request was initiated, not
+
+ the time that the response was received. This algorithm results in
+ conservative behavior no matter how much delay is experienced. So, we
+ compute:
+
+ corrected_initial_age = corrected_received_age
+ + (now - request_time)
+
+ where "request_time" is the time (according to the local clock) when
+ the request that elicited this response was sent.
+
+ Summary of age calculation algorithm, when a cache receives a
+ response:
+
+ /*
+ * age_value
+ * is the value of Age: header received by the cache with
+ * this response.
+ * date_value
+ * is the value of the origin server's Date: header
+ * request_time
+ * is the (local) time when the cache made the request
+ * that resulted in this cached response
+ * response_time
+ * is the (local) time when the cache received the
+ * response
+ * now
+ * is the current (local) time
+ */
+
+ apparent_age = max(0, response_time - date_value);
+ corrected_received_age = max(apparent_age, age_value);
+ response_delay = response_time - request_time;
+ corrected_initial_age = corrected_received_age + response_delay;
+ resident_time = now - response_time;
+ current_age = corrected_initial_age + resident_time;
+
+ The current_age of a cache entry is calculated by adding the amount
+ of time (in seconds) since the cache entry was last validated by the
+ origin server to the corrected_initial_age. When a response is
+ generated from a cache entry, the cache MUST include a single Age
+ header field in the response with a value equal to the cache entry's
+ current_age.
+
+ The presence of an Age header field in a response implies that a
+ response is not first-hand. However, the converse is not true, since
+ the lack of an Age header field in a response does not imply that the
+
+ response is first-hand unless all caches along the request path are
+ compliant with HTTP/1.1 (i.e., older HTTP caches did not implement
+ the Age header field).
+
+13.2.4 Expiration Calculations
+
+ In order to decide whether a response is fresh or stale, we need to
+ compare its freshness lifetime to its age. The age is calculated as
+ described in section 13.2.3; this section describes how to calculate
+ the freshness lifetime, and to determine if a response has expired.
+ In the discussion below, the values can be represented in any form
+ appropriate for arithmetic operations.
+
+ We use the term "expires_value" to denote the value of the Expires
+ header. We use the term "max_age_value" to denote an appropriate
+ value of the number of seconds carried by the "max-age" directive of
+ the Cache-Control header in a response (see section 14.9.3).
+
+ The max-age directive takes priority over Expires, so if max-age is
+ present in a response, the calculation is simply:
+
+ freshness_lifetime = max_age_value
+
+ Otherwise, if Expires is present in the response, the calculation is:
+
+ freshness_lifetime = expires_value - date_value
+
+ Note that neither of these calculations is vulnerable to clock skew,
+ since all of the information comes from the origin server.
+
+ If none of Expires, Cache-Control: max-age, or Cache-Control: s-
+ maxage (see section 14.9.3) appears in the response, and the response
+ does not include other restrictions on caching, the cache MAY compute
+ a freshness lifetime using a heuristic. The cache MUST attach Warning
+ 113 to any response whose age is more than 24 hours if such warning
+ has not already been added.
+
+ Also, if the response does have a Last-Modified time, the heuristic
+ expiration value SHOULD be no more than some fraction of the interval
+ since that time. A typical setting of this fraction might be 10%.
+
+ The calculation to determine if a response has expired is quite
+ simple:
+
+ response_is_fresh = (freshness_lifetime &gt; current_age)
+
+13.2.5 Disambiguating Expiration Values
+
+ Because expiration values are assigned optimistically, it is possible
+ for two caches to contain fresh values for the same resource that are
+ different.
+
+ If a client performing a retrieval receives a non-first-hand response
+ for a request that was already fresh in its own cache, and the Date
+ header in its existing cache entry is newer than the Date on the new
+ response, then the client MAY ignore the response. If so, it MAY
+ retry the request with a "Cache-Control: max-age=0" directive (see
+ section 14.9), to force a check with the origin server.
+
+ If a cache has two fresh responses for the same representation with
+ different validators, it MUST use the one with the more recent Date
+ header. This situation might arise because the cache is pooling
+ responses from other caches, or because a client has asked for a
+ reload or a revalidation of an apparently fresh cache entry.
+
+13.2.6 Disambiguating Multiple Responses
+
+ Because a client might be receiving responses via multiple paths, so
+ that some responses flow through one set of caches and other
+ responses flow through a different set of caches, a client might
+ receive responses in an order different from that in which the origin
+ server sent them. We would like the client to use the most recently
+ generated response, even if older responses are still apparently
+ fresh.
+
+ Neither the entity tag nor the expiration value can impose an
+ ordering on responses, since it is possible that a later response
+ intentionally carries an earlier expiration time. The Date values are
+ ordered to a granularity of one second.
+
+ When a client tries to revalidate a cache entry, and the response it
+ receives contains a Date header that appears to be older than the one
+ for the existing entry, then the client SHOULD repeat the request
+ unconditionally, and include
+
+ Cache-Control: max-age=0
+
+ to force any intermediate caches to validate their copies directly
+ with the origin server, or
+
+ Cache-Control: no-cache
+
+ to force any intermediate caches to obtain a new copy from the origin
+ server.
+
+ If the Date values are equal, then the client MAY use either response
+ (or MAY, if it is being extremely prudent, request a new response).
+ Servers MUST NOT depend on clients being able to choose
+ deterministically between responses generated during the same second,
+ if their expiration times overlap.
+
+13.3 Validation Model
+
+ When a cache has a stale entry that it would like to use as a
+ response to a client's request, it first has to check with the origin
+ server (or possibly an intermediate cache with a fresh response) to
+ see if its cached entry is still usable. We call this "validating"
+ the cache entry. Since we do not want to have to pay the overhead of
+ retransmitting the full response if the cached entry is good, and we
+ do not want to pay the overhead of an extra round trip if the cached
+ entry is invalid, the HTTP/1.1 protocol supports the use of
+ conditional methods.
+
+ The key protocol features for supporting conditional methods are
+ those concerned with "cache validators." When an origin server
+ generates a full response, it attaches some sort of validator to it,
+ which is kept with the cache entry. When a client (user agent or
+ proxy cache) makes a conditional request for a resource for which it
+ has a cache entry, it includes the associated validator in the
+ request.
+
+ The server then checks that validator against the current validator
+ for the entity, and, if they match (see section 13.3.3), it responds
+ with a special status code (usually, 304 (Not Modified)) and no
+ entity-body. Otherwise, it returns a full response (including
+ entity-body). Thus, we avoid transmitting the full response if the
+ validator matches, and we avoid an extra round trip if it does not
+ match.
+
+ In HTTP/1.1, a conditional request looks exactly the same as a normal
+ request for the same resource, except that it carries a special
+ header (which includes the validator) that implicitly turns the
+ method (usually, GET) into a conditional.
+
+ The protocol includes both positive and negative senses of cache-
+ validating conditions. That is, it is possible to request either that
+ a method be performed if and only if a validator matches or if and
+ only if no validators match.
+
+ Note: a response that lacks a validator may still be cached, and
+ served from cache until it expires, unless this is explicitly
+ prohibited by a cache-control directive. However, a cache cannot
+ do a conditional retrieval if it does not have a validator for the
+ entity, which means it will not be refreshable after it expires.
+
+13.3.1 Last-Modified Dates
+
+ The Last-Modified entity-header field value is often used as a cache
+ validator. In simple terms, a cache entry is considered to be valid
+ if the entity has not been modified since the Last-Modified value.
+
+13.3.2 Entity Tag Cache Validators
+
+ The ETag response-header field value, an entity tag, provides for an
+ "opaque" cache validator. This might allow more reliable validation
+ in situations where it is inconvenient to store modification dates,
+ where the one-second resolution of HTTP date values is not
+ sufficient, or where the origin server wishes to avoid certain
+ paradoxes that might arise from the use of modification dates.
+
+ Entity Tags are described in section 3.11. The headers used with
+ entity tags are described in sections 14.19, 14.24, 14.26 and 14.44.
+
+13.3.3 Weak and Strong Validators
+
+ Since both origin servers and caches will compare two validators to
+ decide if they represent the same or different entities, one normally
+ would expect that if the entity (the entity-body or any entity-
+ headers) changes in any way, then the associated validator would
+ change as well. If this is true, then we call this validator a
+ "strong validator."
+
+ However, there might be cases when a server prefers to change the
+ validator only on semantically significant changes, and not when
+ insignificant aspects of the entity change. A validator that does not
+ always change when the resource changes is a "weak validator."
+
+ Entity tags are normally "strong validators," but the protocol
+ provides a mechanism to tag an entity tag as "weak." One can think of
+ a strong validator as one that changes whenever the bits of an entity
+ changes, while a weak value changes whenever the meaning of an entity
+ changes. Alternatively, one can think of a strong validator as part
+ of an identifier for a specific entity, while a weak validator is
+ part of an identifier for a set of semantically equivalent entities.
+
+ Note: One example of a strong validator is an integer that is
+ incremented in stable storage every time an entity is changed.
+
+ An entity's modification time, if represented with one-second
+ resolution, could be a weak validator, since it is possible that
+ the resource might be modified twice during a single second.
+
+ Support for weak validators is optional. However, weak validators
+ allow for more efficient caching of equivalent objects; for
+ example, a hit counter on a site is probably good enough if it is
+ updated every few days or weeks, and any value during that period
+ is likely "good enough" to be equivalent.
+
+ A "use" of a validator is either when a client generates a request
+ and includes the validator in a validating header field, or when a
+ server compares two validators.
+
+ Strong validators are usable in any context. Weak validators are only
+ usable in contexts that do not depend on exact equality of an entity.
+ For example, either kind is usable for a conditional GET of a full
+ entity. However, only a strong validator is usable for a sub-range
+ retrieval, since otherwise the client might end up with an internally
+ inconsistent entity.
+
+ Clients MAY issue simple (non-subrange) GET requests with either weak
+ validators or strong validators. Clients MUST NOT use weak validators
+ in other forms of request.
+
+ The only function that the HTTP/1.1 protocol defines on validators is
+ comparison. There are two validator comparison functions, depending
+ on whether the comparison context allows the use of weak validators
+ or not:
+
+ - The strong comparison function: in order to be considered equal,
+ both validators MUST be identical in every way, and both MUST
+ NOT be weak.
+
+ - The weak comparison function: in order to be considered equal,
+ both validators MUST be identical in every way, but either or
+ both of them MAY be tagged as "weak" without affecting the
+ result.
+
+ An entity tag is strong unless it is explicitly tagged as weak.
+ Section 3.11 gives the syntax for entity tags.
+
+ A Last-Modified time, when used as a validator in a request, is
+ implicitly weak unless it is possible to deduce that it is strong,
+ using the following rules:
+
+ - The validator is being compared by an origin server to the
+ actual current validator for the entity and,
+
+ - That origin server reliably knows that the associated entity did
+ not change twice during the second covered by the presented
+ validator.
+
+ or
+
+ - The validator is about to be used by a client in an If-
+ Modified-Since or If-Unmodified-Since header, because the client
+ has a cache entry for the associated entity, and
+
+ - That cache entry includes a Date value, which gives the time
+ when the origin server sent the original response, and
+
+ - The presented Last-Modified time is at least 60 seconds before
+ the Date value.
+
+ or
+
+ - The validator is being compared by an intermediate cache to the
+ validator stored in its cache entry for the entity, and
+
+ - That cache entry includes a Date value, which gives the time
+ when the origin server sent the original response, and
+
+ - The presented Last-Modified time is at least 60 seconds before
+ the Date value.
+
+ This method relies on the fact that if two different responses were
+ sent by the origin server during the same second, but both had the
+ same Last-Modified time, then at least one of those responses would
+ have a Date value equal to its Last-Modified time. The arbitrary 60-
+ second limit guards against the possibility that the Date and Last-
+ Modified values are generated from different clocks, or at somewhat
+ different times during the preparation of the response. An
+ implementation MAY use a value larger than 60 seconds, if it is
+ believed that 60 seconds is too short.
+
+ If a client wishes to perform a sub-range retrieval on a value for
+ which it has only a Last-Modified time and no opaque validator, it
+ MAY do this only if the Last-Modified time is strong in the sense
+ described here.
+
+ A cache or origin server receiving a conditional request, other than
+ a full-body GET request, MUST use the strong comparison function to
+ evaluate the condition.
+
+ These rules allow HTTP/1.1 caches and clients to safely perform sub-
+ range retrievals on values that have been obtained from HTTP/1.0
+
+ servers.
+
+13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates
+
+ We adopt a set of rules and recommendations for origin servers,
+ clients, and caches regarding when various validator types ought to
+ be used, and for what purposes.
+
+ HTTP/1.1 origin servers:
+
+ - SHOULD send an entity tag validator unless it is not feasible to
+ generate one.
+
+ - MAY send a weak entity tag instead of a strong entity tag, if
+ performance considerations support the use of weak entity tags,
+ or if it is unfeasible to send a strong entity tag.
+
+ - SHOULD send a Last-Modified value if it is feasible to send one,
+ unless the risk of a breakdown in semantic transparency that
+ could result from using this date in an If-Modified-Since header
+ would lead to serious problems.
+
+ In other words, the preferred behavior for an HTTP/1.1 origin server
+ is to send both a strong entity tag and a Last-Modified value.
+
+ In order to be legal, a strong entity tag MUST change whenever the
+ associated entity value changes in any way. A weak entity tag SHOULD
+ change whenever the associated entity changes in a semantically
+ significant way.
+
+ Note: in order to provide semantically transparent caching, an
+ origin server must avoid reusing a specific strong entity tag
+ value for two different entities, or reusing a specific weak
+ entity tag value for two semantically different entities. Cache
+ entries might persist for arbitrarily long periods, regardless of
+ expiration times, so it might be inappropriate to expect that a
+ cache will never again attempt to validate an entry using a
+ validator that it obtained at some point in the past.
+
+ HTTP/1.1 clients:
+
+ - If an entity tag has been provided by the origin server, MUST
+ use that entity tag in any cache-conditional request (using If-
+ Match or If-None-Match).
+
+ - If only a Last-Modified value has been provided by the origin
+ server, SHOULD use that value in non-subrange cache-conditional
+ requests (using If-Modified-Since).
+
+ - If only a Last-Modified value has been provided by an HTTP/1.0
+ origin server, MAY use that value in subrange cache-conditional
+ requests (using If-Unmodified-Since:). The user agent SHOULD
+ provide a way to disable this, in case of difficulty.
+
+ - If both an entity tag and a Last-Modified value have been
+ provided by the origin server, SHOULD use both validators in
+ cache-conditional requests. This allows both HTTP/1.0 and
+ HTTP/1.1 caches to respond appropriately.
+
+ An HTTP/1.1 origin server, upon receiving a conditional request that
+ includes both a Last-Modified date (e.g., in an If-Modified-Since or
+ If-Unmodified-Since header field) and one or more entity tags (e.g.,
+ in an If-Match, If-None-Match, or If-Range header field) as cache
+ validators, MUST NOT return a response status of 304 (Not Modified)
+ unless doing so is consistent with all of the conditional header
+ fields in the request.
+
+ An HTTP/1.1 caching proxy, upon receiving a conditional request that
+ includes both a Last-Modified date and one or more entity tags as
+ cache validators, MUST NOT return a locally cached response to the
+ client unless that cached response is consistent with all of the
+ conditional header fields in the request.
+
+ Note: The general principle behind these rules is that HTTP/1.1
+ servers and clients should transmit as much non-redundant
+ information as is available in their responses and requests.
+ HTTP/1.1 systems receiving this information will make the most
+ conservative assumptions about the validators they receive.
+
+ HTTP/1.0 clients and caches will ignore entity tags. Generally,
+ last-modified values received or used by these systems will
+ support transparent and efficient caching, and so HTTP/1.1 origin
+ servers should provide Last-Modified values. In those rare cases
+ where the use of a Last-Modified value as a validator by an
+ HTTP/1.0 system could result in a serious problem, then HTTP/1.1
+ origin servers should not provide one.
+
+13.3.5 Non-validating Conditionals
+
+ The principle behind entity tags is that only the service author
+ knows the semantics of a resource well enough to select an
+ appropriate cache validation mechanism, and the specification of any
+ validator comparison function more complex than byte-equality would
+ open up a can of worms. Thus, comparisons of any other headers
+ (except Last-Modified, for compatibility with HTTP/1.0) are never
+ used for purposes of validating a cache entry.
+
+13.4 Response Cacheability
+
+ Unless specifically constrained by a cache-control (section 14.9)
+ directive, a caching system MAY always store a successful response
+ (see section 13.8) as a cache entry, MAY return it without validation
+ if it is fresh, and MAY return it after successful validation. If
+ there is neither a cache validator nor an explicit expiration time
+ associated with a response, we do not expect it to be cached, but
+ certain caches MAY violate this expectation (for example, when little
+ or no network connectivity is available). A client can usually detect
+ that such a response was taken from a cache by comparing the Date
+ header to the current time.
+
+ Note: some HTTP/1.0 caches are known to violate this expectation
+ without providing any Warning.
+
+ However, in some cases it might be inappropriate for a cache to
+ retain an entity, or to return it in response to a subsequent
+ request. This might be because absolute semantic transparency is
+ deemed necessary by the service author, or because of security or
+ privacy considerations. Certain cache-control directives are
+ therefore provided so that the server can indicate that certain
+ resource entities, or portions thereof, are not to be cached
+ regardless of other considerations.
+
+ Note that section 14.8 normally prevents a shared cache from saving
+ and returning a response to a previous request if that request
+ included an Authorization header.
+
+ A response received with a status code of 200, 203, 206, 300, 301 or
+ 410 MAY be stored by a cache and used in reply to a subsequent
+ request, subject to the expiration mechanism, unless a cache-control
+ directive prohibits caching. However, a cache that does not support
+ the Range and Content-Range headers MUST NOT cache 206 (Partial
+ Content) responses.
+
+ A response received with any other status code (e.g. status codes 302
+ and 307) MUST NOT be returned in a reply to a subsequent request
+ unless there are cache-control directives or another header(s) that
+ explicitly allow it. For example, these include the following: an
+ Expires header (section 14.21); a "max-age", "s-maxage", "must-
+ revalidate", "proxy-revalidate", "public" or "private" cache-control
+ directive (section 14.9).
+
+13.5 Constructing Responses From Caches
+
+ The purpose of an HTTP cache is to store information received in
+ response to requests for use in responding to future requests. In
+ many cases, a cache simply returns the appropriate parts of a
+ response to the requester. However, if the cache holds a cache entry
+ based on a previous response, it might have to combine parts of a new
+ response with what is held in the cache entry.
+
+13.5.1 End-to-end and Hop-by-hop Headers
+
+ For the purpose of defining the behavior of caches and non-caching
+ proxies, we divide HTTP headers into two categories:
+
+ - End-to-end headers, which are transmitted to the ultimate
+ recipient of a request or response. End-to-end headers in
+ responses MUST be stored as part of a cache entry and MUST be
+ transmitted in any response formed from a cache entry.
+
+ - Hop-by-hop headers, which are meaningful only for a single
+ transport-level connection, and are not stored by caches or
+ forwarded by proxies.
+
+ The following HTTP/1.1 headers are hop-by-hop headers:
+
+ - Connection
+ - Keep-Alive
+ - Proxy-Authenticate
+ - Proxy-Authorization
+ - TE
+ - Trailers
+ - Transfer-Encoding
+ - Upgrade
+
+ All other headers defined by HTTP/1.1 are end-to-end headers.
+
+ Other hop-by-hop headers MUST be listed in a Connection header,
+ (section 14.10) to be introduced into HTTP/1.1 (or later).
+
+13.5.2 Non-modifiable Headers
+
+ Some features of the HTTP/1.1 protocol, such as Digest
+ Authentication, depend on the value of certain end-to-end headers. A
+ transparent proxy SHOULD NOT modify an end-to-end header unless the
+ definition of that header requires or specifically allows that.
+
+ A transparent proxy MUST NOT modify any of the following fields in a
+ request or response, and it MUST NOT add any of these fields if not
+ already present:
+
+ - Content-Location
+
+ - Content-MD5
+
+ - ETag
+
+ - Last-Modified
+
+ A transparent proxy MUST NOT modify any of the following fields in a
+ response:
+
+ - Expires
+
+ but it MAY add any of these fields if not already present. If an
+ Expires header is added, it MUST be given a field-value identical to
+ that of the Date header in that response.
+
+ A proxy MUST NOT modify or add any of the following fields in a
+ message that contains the no-transform cache-control directive, or in
+ any request:
+
+ - Content-Encoding
+
+ - Content-Range
+
+ - Content-Type
+
+ A non-transparent proxy MAY modify or add these fields to a message
+ that does not include no-transform, but if it does so, it MUST add a
+ Warning 214 (Transformation applied) if one does not already appear
+ in the message (see section 14.46).
+
+ Warning: unnecessary modification of end-to-end headers might
+ cause authentication failures if stronger authentication
+ mechanisms are introduced in later versions of HTTP. Such
+ authentication mechanisms MAY rely on the values of header fields
+ not listed here.
+
+ The Content-Length field of a request or response is added or deleted
+ according to the rules in section 4.4. A transparent proxy MUST
+ preserve the entity-length (section 7.2.2) of the entity-body,
+ although it MAY change the transfer-length (section 4.4).
+
+13.5.3 Combining Headers
+
+ When a cache makes a validating request to a server, and the server
+ provides a 304 (Not Modified) response or a 206 (Partial Content)
+ response, the cache then constructs a response to send to the
+ requesting client.
+
+ If the status code is 304 (Not Modified), the cache uses the entity-
+ body stored in the cache entry as the entity-body of this outgoing
+ response. If the status code is 206 (Partial Content) and the ETag or
+ Last-Modified headers match exactly, the cache MAY combine the
+ contents stored in the cache entry with the new contents received in
+ the response and use the result as the entity-body of this outgoing
+ response, (see 13.5.4).
+
+ The end-to-end headers stored in the cache entry are used for the
+ constructed response, except that
+
+ - any stored Warning headers with warn-code 1xx (see section
+ 14.46) MUST be deleted from the cache entry and the forwarded
+ response.
+
+ - any stored Warning headers with warn-code 2xx MUST be retained
+ in the cache entry and the forwarded response.
+
+ - any end-to-end headers provided in the 304 or 206 response MUST
+ replace the corresponding headers from the cache entry.
+
+ Unless the cache decides to remove the cache entry, it MUST also
+ replace the end-to-end headers stored with the cache entry with
+ corresponding headers received in the incoming response, except for
+ Warning headers as described immediately above. If a header field-
+ name in the incoming response matches more than one header in the
+ cache entry, all such old headers MUST be replaced.
+
+ In other words, the set of end-to-end headers received in the
+ incoming response overrides all corresponding end-to-end headers
+ stored with the cache entry (except for stored Warning headers with
+ warn-code 1xx, which are deleted even if not overridden).
+
+ Note: this rule allows an origin server to use a 304 (Not
+ Modified) or a 206 (Partial Content) response to update any header
+ associated with a previous response for the same entity or sub-
+ ranges thereof, although it might not always be meaningful or
+ correct to do so. This rule does not allow an origin server to use
+ a 304 (Not Modified) or a 206 (Partial Content) response to
+ entirely delete a header that it had provided with a previous
+ response.
+
+13.5.4 Combining Byte Ranges
+
+ A response might transfer only a subrange of the bytes of an entity-
+ body, either because the request included one or more Range
+ specifications, or because a connection was broken prematurely. After
+ several such transfers, a cache might have received several ranges of
+ the same entity-body.
+
+ If a cache has a stored non-empty set of subranges for an entity, and
+ an incoming response transfers another subrange, the cache MAY
+ combine the new subrange with the existing set if both the following
+ conditions are met:
+
+ - Both the incoming response and the cache entry have a cache
+ validator.
+
+ - The two cache validators match using the strong comparison
+ function (see section 13.3.3).
+
+ If either requirement is not met, the cache MUST use only the most
+ recent partial response (based on the Date values transmitted with
+ every response, and using the incoming response if these values are
+ equal or missing), and MUST discard the other partial information.
+
+13.6 Caching Negotiated Responses
+
+ Use of server-driven content negotiation (section 12.1), as indicated
+ by the presence of a Vary header field in a response, alters the
+ conditions and procedure by which a cache can use the response for
+ subsequent requests. See section 14.44 for use of the Vary header
+ field by servers.
+
+ A server SHOULD use the Vary header field to inform a cache of what
+ request-header fields were used to select among multiple
+ representations of a cacheable response subject to server-driven
+ negotiation. The set of header fields named by the Vary field value
+ is known as the "selecting" request-headers.
+
+ When the cache receives a subsequent request whose Request-URI
+ specifies one or more cache entries including a Vary header field,
+ the cache MUST NOT use such a cache entry to construct a response to
+ the new request unless all of the selecting request-headers present
+ in the new request match the corresponding stored request-headers in
+ the original request.
+
+ The selecting request-headers from two requests are defined to match
+ if and only if the selecting request-headers in the first request can
+ be transformed to the selecting request-headers in the second request
+
+ by adding or removing linear white space (LWS) at places where this
+ is allowed by the corresponding BNF, and/or combining multiple
+ message-header fields with the same field name following the rules
+ about message headers in section 4.2.
+
+ A Vary header field-value of "*" always fails to match and subsequent
+ requests on that resource can only be properly interpreted by the
+ origin server.
+
+ If the selecting request header fields for the cached entry do not
+ match the selecting request header fields of the new request, then
+ the cache MUST NOT use a cached entry to satisfy the request unless
+ it first relays the new request to the origin server in a conditional
+ request and the server responds with 304 (Not Modified), including an
+ entity tag or Content-Location that indicates the entity to be used.
+
+ If an entity tag was assigned to a cached representation, the
+ forwarded request SHOULD be conditional and include the entity tags
+ in an If-None-Match header field from all its cache entries for the
+ resource. This conveys to the server the set of entities currently
+ held by the cache, so that if any one of these entities matches the
+ requested entity, the server can use the ETag header field in its 304
+ (Not Modified) response to tell the cache which entry is appropriate.
+ If the entity-tag of the new response matches that of an existing
+ entry, the new response SHOULD be used to update the header fields of
+ the existing entry, and the result MUST be returned to the client.
+
+ If any of the existing cache entries contains only partial content
+ for the associated entity, its entity-tag SHOULD NOT be included in
+ the If-None-Match header field unless the request is for a range that
+ would be fully satisfied by that entry.
+
+ If a cache receives a successful response whose Content-Location
+ field matches that of an existing cache entry for the same Request-
+ ]URI, whose entity-tag differs from that of the existing entry, and
+ whose Date is more recent than that of the existing entry, the
+ existing entry SHOULD NOT be returned in response to future requests
+ and SHOULD be deleted from the cache.
+
+13.7 Shared and Non-Shared Caches
+
+ For reasons of security and privacy, it is necessary to make a
+ distinction between "shared" and "non-shared" caches. A non-shared
+ cache is one that is accessible only to a single user. Accessibility
+ in this case SHOULD be enforced by appropriate security mechanisms.
+ All other caches are considered to be "shared." Other sections of
+
+ this specification place certain constraints on the operation of
+ shared caches in order to prevent loss of privacy or failure of
+ access controls.
+
+13.8 Errors or Incomplete Response Cache Behavior
+
+ A cache that receives an incomplete response (for example, with fewer
+ bytes of data than specified in a Content-Length header) MAY store
+ the response. However, the cache MUST treat this as a partial
+ response. Partial responses MAY be combined as described in section
+ 13.5.4; the result might be a full response or might still be
+ partial. A cache MUST NOT return a partial response to a client
+ without explicitly marking it as such, using the 206 (Partial
+ Content) status code. A cache MUST NOT return a partial response
+ using a status code of 200 (OK).
+
+ If a cache receives a 5xx response while attempting to revalidate an
+ entry, it MAY either forward this response to the requesting client,
+ or act as if the server failed to respond. In the latter case, it MAY
+ return a previously received response unless the cached entry
+ includes the "must-revalidate" cache-control directive (see section
+ 14.9).
+
+13.9 Side Effects of GET and HEAD
+
+ Unless the origin server explicitly prohibits the caching of their
+ responses, the application of GET and HEAD methods to any resources
+ SHOULD NOT have side effects that would lead to erroneous behavior if
+ these responses are taken from a cache. They MAY still have side
+ effects, but a cache is not required to consider such side effects in
+ its caching decisions. Caches are always expected to observe an
+ origin server's explicit restrictions on caching.
+
+ We note one exception to this rule: since some applications have
+ traditionally used GETs and HEADs with query URLs (those containing a
+ "?" in the rel_path part) to perform operations with significant side
+ effects, caches MUST NOT treat responses to such URIs as fresh unless
+ the server provides an explicit expiration time. This specifically
+ means that responses from HTTP/1.0 servers for such URIs SHOULD NOT
+ be taken from a cache. See section 9.1.1 for related information.
+
+13.10 Invalidation After Updates or Deletions
+
+ The effect of certain methods performed on a resource at the origin
+ server might cause one or more existing cache entries to become non-
+ transparently invalid. That is, although they might continue to be
+ "fresh," they do not accurately reflect what the origin server would
+ return for a new request on that resource.
+
+ There is no way for the HTTP protocol to guarantee that all such
+ cache entries are marked invalid. For example, the request that
+ caused the change at the origin server might not have gone through
+ the proxy where a cache entry is stored. However, several rules help
+ reduce the likelihood of erroneous behavior.
+
+ In this section, the phrase "invalidate an entity" means that the
+ cache will either remove all instances of that entity from its
+ storage, or will mark these as "invalid" and in need of a mandatory
+ revalidation before they can be returned in response to a subsequent
+ request.
+
+ Some HTTP methods MUST cause a cache to invalidate an entity. This is
+ either the entity referred to by the Request-URI, or by the Location
+ or Content-Location headers (if present). These methods are:
+
+ - PUT
+
+ - DELETE
+
+ - POST
+
+ In order to prevent denial of service attacks, an invalidation based
+ on the URI in a Location or Content-Location header MUST only be
+ performed if the host part is the same as in the Request-URI.
+
+ A cache that passes through requests for methods it does not
+ understand SHOULD invalidate any entities referred to by the
+ Request-URI.
+
+13.11 Write-Through Mandatory
+
+ All methods that might be expected to cause modifications to the
+ origin server's resources MUST be written through to the origin
+ server. This currently includes all methods except for GET and HEAD.
+ A cache MUST NOT reply to such a request from a client before having
+ transmitted the request to the inbound server, and having received a
+ corresponding response from the inbound server. This does not prevent
+ a proxy cache from sending a 100 (Continue) response before the
+ inbound server has sent its final reply.
+
+ The alternative (known as "write-back" or "copy-back" caching) is not
+ allowed in HTTP/1.1, due to the difficulty of providing consistent
+ updates and the problems arising from server, cache, or network
+ failure prior to write-back.
+
+13.12 Cache Replacement
+
+ If a new cacheable (see sections 14.9.2, 13.2.5, 13.2.6 and 13.8)
+ response is received from a resource while any existing responses for
+ the same resource are cached, the cache SHOULD use the new response
+ to reply to the current request. It MAY insert it into cache storage
+ and MAY, if it meets all other requirements, use it to respond to any
+ future requests that would previously have caused the old response to
+ be returned. If it inserts the new response into cache storage the
+ rules in section 13.5.3 apply.
+
+ Note: a new response that has an older Date header value than
+ existing cached responses is not cacheable.
+
+13.13 History Lists
+
+ User agents often have history mechanisms, such as "Back" buttons and
+ history lists, which can be used to redisplay an entity retrieved
+ earlier in a session.
+
+ History mechanisms and caches are different. In particular history
+ mechanisms SHOULD NOT try to show a semantically transparent view of
+ the current state of a resource. Rather, a history mechanism is meant
+ to show exactly what the user saw at the time when the resource was
+ retrieved.
+
+ By default, an expiration time does not apply to history mechanisms.
+ If the entity is still in storage, a history mechanism SHOULD display
+ it even if the entity has expired, unless the user has specifically
+ configured the agent to refresh expired history documents.
+
+ This is not to be construed to prohibit the history mechanism from
+ telling the user that a view might be stale.
+
+ Note: if history list mechanisms unnecessarily prevent users from
+ viewing stale resources, this will tend to force service authors
+ to avoid using HTTP expiration controls and cache controls when
+ they would otherwise like to. Service authors may consider it
+ important that users not be presented with error messages or
+ warning messages when they use navigation controls (such as BACK)
+ to view previously fetched resources. Even though sometimes such
+ resources ought not to cached, or ought to expire quickly, user
+ interface considerations may force service authors to resort to
+ other means of preventing caching (e.g. "once-only" URLs) in order
+ not to suffer the effects of improperly functioning history
+ mechanisms.
+
+14 Header Field Definitions
+
+ This section defines the syntax and semantics of all standard
+ HTTP/1.1 header fields. For entity-header fields, both sender and
+ recipient refer to either the client or the server, depending on who
+ sends and who receives the entity.
+
+14.1 Accept
+
+ The Accept request-header field can be used to specify certain media
+ types which are acceptable for the response. Accept headers can be
+ used to indicate that the request is specifically limited to a small
+ set of desired types, as in the case of a request for an in-line
+ image.
+
+ Accept = "Accept" ":"
+ #( media-range [ accept-params ] )
+
+ media-range = ( "*/*"
+ | ( type "/" "*" )
+ | ( type "/" subtype )
+ ) *( ";" parameter )
+ accept-params = ";" "q" "=" qvalue *( accept-extension )
+ accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+
+ The asterisk "*" character is used to group media types into ranges,
+ with "*/*" indicating all media types and "type/*" indicating all
+ subtypes of that type. The media-range MAY include media type
+ parameters that are applicable to that range.
+
+ Each media-range MAY be followed by one or more accept-params,
+ beginning with the "q" parameter for indicating a relative quality
+ factor. The first "q" parameter (if any) separates the media-range
+ parameter(s) from the accept-params. Quality factors allow the user
+ or user agent to indicate the relative degree of preference for that
+ media-range, using the qvalue scale from 0 to 1 (section 3.9). The
+ default value is q=1.
+
+ Note: Use of the "q" parameter name to separate media type
+ parameters from Accept extension parameters is due to historical
+ practice. Although this prevents any media type parameter named
+ "q" from being used with a media range, such an event is believed
+ to be unlikely given the lack of any "q" parameters in the IANA
+ media type registry and the rare usage of any media type
+ parameters in Accept. Future media types are discouraged from
+ registering any parameter named "q".
+
+ The example
+
+ Accept: audio/*; q=0.2, audio/basic
+
+ SHOULD be interpreted as "I prefer audio/basic, but send me any audio
+ type if it is the best available after an 80% mark-down in quality."
+
+ If no Accept header field is present, then it is assumed that the
+ client accepts all media types. If an Accept header field is present,
+ and if the server cannot send a response which is acceptable
+ according to the combined Accept field value, then the server SHOULD
+ send a 406 (not acceptable) response.
+
+ A more elaborate example is
+
+ Accept: text/plain; q=0.5, text/html,
+ text/x-dvi; q=0.8, text/x-c
+
+ Verbally, this would be interpreted as "text/html and text/x-c are
+ the preferred media types, but if they do not exist, then send the
+ text/x-dvi entity, and if that does not exist, send the text/plain
+ entity."
+
+ Media ranges can be overridden by more specific media ranges or
+ specific media types. If more than one media range applies to a given
+ type, the most specific reference has precedence. For example,
+
+ Accept: text/*, text/html, text/html;level=1, */*
+
+ have the following precedence:
+
+ 1) text/html;level=1
+ 2) text/html
+ 3) text/*
+ 4) */*
+
+ The media type quality factor associated with a given type is
+ determined by finding the media range with the highest precedence
+ which matches that type. For example,
+
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ text/html;level=2;q=0.4, */*;q=0.5
+
+ would cause the following values to be associated:
+
+ text/html;level=1 = 1
+ text/html = 0.7
+ text/plain = 0.3
+
+ image/jpeg = 0.5
+ text/html;level=2 = 0.4
+ text/html;level=3 = 0.7
+
+ Note: A user agent might be provided with a default set of quality
+ values for certain media ranges. However, unless the user agent is
+ a closed system which cannot interact with other rendering agents,
+ this default set ought to be configurable by the user.
+
+14.2 Accept-Charset
+
+ The Accept-Charset request-header field can be used to indicate what
+ character sets are acceptable for the response. This field allows
+ clients capable of understanding more comprehensive or special-
+ purpose character sets to signal that capability to a server which is
+ capable of representing documents in those character sets.
+
+ Accept-Charset = "Accept-Charset" ":"
+ 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
+
+ Character set values are described in section 3.4. Each charset MAY
+ be given an associated quality value which represents the user's
+ preference for that charset. The default value is q=1. An example is
+
+ Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
+
+ The special value "*", if present in the Accept-Charset field,
+ matches every character set (including ISO-8859-1) which is not
+ mentioned elsewhere in the Accept-Charset field. If no "*" is present
+ in an Accept-Charset field, then all character sets not explicitly
+ mentioned get a quality value of 0, except for ISO-8859-1, which gets
+ a quality value of 1 if not explicitly mentioned.
+
+ If no Accept-Charset header is present, the default is that any
+ character set is acceptable. If an Accept-Charset header is present,
+ and if the server cannot send a response which is acceptable
+ according to the Accept-Charset header, then the server SHOULD send
+ an error response with the 406 (not acceptable) status code, though
+ the sending of an unacceptable response is also allowed.
+
+14.3 Accept-Encoding
+
+ The Accept-Encoding request-header field is similar to Accept, but
+ restricts the content-codings (section 3.5) that are acceptable in
+ the response.
+
+ Accept-Encoding = "Accept-Encoding" ":"
+
+ 1#( codings [ ";" "q" "=" qvalue ] )
+ codings = ( content-coding | "*" )
+
+ Examples of its use are:
+
+ Accept-Encoding: compress, gzip
+ Accept-Encoding:
+ Accept-Encoding: *
+ Accept-Encoding: compress;q=0.5, gzip;q=1.0
+ Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
+
+ A server tests whether a content-coding is acceptable, according to
+ an Accept-Encoding field, using these rules:
+
+ 1. If the content-coding is one of the content-codings listed in
+ the Accept-Encoding field, then it is acceptable, unless it is
+ accompanied by a qvalue of 0. (As defined in section 3.9, a
+ qvalue of 0 means "not acceptable.")
+
+ 2. The special "*" symbol in an Accept-Encoding field matches any
+ available content-coding not explicitly listed in the header
+ field.
+
+ 3. If multiple content-codings are acceptable, then the acceptable
+ content-coding with the highest non-zero qvalue is preferred.
+
+ 4. The "identity" content-coding is always acceptable, unless
+ specifically refused because the Accept-Encoding field includes
+ "identity;q=0", or because the field includes "*;q=0" and does
+ not explicitly include the "identity" content-coding. If the
+ Accept-Encoding field-value is empty, then only the "identity"
+ encoding is acceptable.
+
+ If an Accept-Encoding field is present in a request, and if the
+ server cannot send a response which is acceptable according to the
+ Accept-Encoding header, then the server SHOULD send an error response
+ with the 406 (Not Acceptable) status code.
+
+ If no Accept-Encoding field is present in a request, the server MAY
+ assume that the client will accept any content coding. In this case,
+ if "identity" is one of the available content-codings, then the
+ server SHOULD use the "identity" content-coding, unless it has
+ additional information that a different content-coding is meaningful
+ to the client.
+
+ Note: If the request does not include an Accept-Encoding field,
+ and if the "identity" content-coding is unavailable, then
+ content-codings commonly understood by HTTP/1.0 clients (i.e.,
+
+ "gzip" and "compress") are preferred; some older clients
+ improperly display messages sent with other content-codings. The
+ server might also make this decision based on information about
+ the particular user-agent or client.
+
+ Note: Most HTTP/1.0 applications do not recognize or obey qvalues
+ associated with content-codings. This means that qvalues will not
+ work and are not permitted with x-gzip or x-compress.
+
+14.4 Accept-Language
+
+ The Accept-Language request-header field is similar to Accept, but
+ restricts the set of natural languages that are preferred as a
+ response to the request. Language tags are defined in section 3.10.
+
+ Accept-Language = "Accept-Language" ":"
+ 1#( language-range [ ";" "q" "=" qvalue ] )
+ language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+
+ Each language-range MAY be given an associated quality value which
+ represents an estimate of the user's preference for the languages
+ specified by that range. The quality value defaults to "q=1". For
+ example,
+
+ Accept-Language: da, en-gb;q=0.8, en;q=0.7
+
+ would mean: "I prefer Danish, but will accept British English and
+ other types of English." A language-range matches a language-tag if
+ it exactly equals the tag, or if it exactly equals a prefix of the
+ tag such that the first tag character following the prefix is "-".
+ The special range "*", if present in the Accept-Language field,
+ matches every tag not matched by any other range present in the
+ Accept-Language field.
+
+ Note: This use of a prefix matching rule does not imply that
+ language tags are assigned to languages in such a way that it is
+ always true that if a user understands a language with a certain
+ tag, then this user will also understand all languages with tags
+ for which this tag is a prefix. The prefix rule simply allows the
+ use of prefix tags if this is the case.
+
+ The language quality factor assigned to a language-tag by the
+ Accept-Language field is the quality value of the longest language-
+ range in the field that matches the language-tag. If no language-
+ range in the field matches the tag, the language quality factor
+ assigned is 0. If no Accept-Language header is present in the
+ request, the server
+
+ SHOULD assume that all languages are equally acceptable. If an
+ Accept-Language header is present, then all languages which are
+ assigned a quality factor greater than 0 are acceptable.
+
+ It might be contrary to the privacy expectations of the user to send
+ an Accept-Language header with the complete linguistic preferences of
+ the user in every request. For a discussion of this issue, see
+ section 15.1.4.
+
+ As intelligibility is highly dependent on the individual user, it is
+ recommended that client applications make the choice of linguistic
+ preference available to the user. If the choice is not made
+ available, then the Accept-Language header field MUST NOT be given in
+ the request.
+
+ Note: When making the choice of linguistic preference available to
+ the user, we remind implementors of the fact that users are not
+ familiar with the details of language matching as described above,
+ and should provide appropriate guidance. As an example, users
+ might assume that on selecting "en-gb", they will be served any
+ kind of English document if British English is not available. A
+ user agent might suggest in such a case to add "en" to get the
+ best matching behavior.
+
+14.5 Accept-Ranges
+
+ The Accept-Ranges response-header field allows the server to
+ indicate its acceptance of range requests for a resource:
+
+ Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges
+ acceptable-ranges = 1#range-unit | "none"
+
+ Origin servers that accept byte-range requests MAY send
+
+ Accept-Ranges: bytes
+
+ but are not required to do so. Clients MAY generate byte-range
+ requests without having received this header for the resource
+ involved. Range units are defined in section 3.12.
+
+ Servers that do not accept any kind of range request for a
+ resource MAY send
+
+ Accept-Ranges: none
+
+ to advise the client not to attempt a range request.
+
+14.6 Age
+
+ The Age response-header field conveys the sender's estimate of the
+ amount of time since the response (or its revalidation) was
+ generated at the origin server. A cached response is "fresh" if
+ its age does not exceed its freshness lifetime. Age values are
+ calculated as specified in section 13.2.3.
+
+ Age = "Age" ":" age-value
+ age-value = delta-seconds
+
+ Age values are non-negative decimal integers, representing time in
+ seconds.
+
+ If a cache receives a value larger than the largest positive
+ integer it can represent, or if any of its age calculations
+ overflows, it MUST transmit an Age header with a value of
+ 2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST
+ include an Age header field in every response generated from its
+ own cache. Caches SHOULD use an arithmetic type of at least 31
+ bits of range.
+
+14.7 Allow
+
+ The Allow entity-header field lists the set of methods supported
+ by the resource identified by the Request-URI. The purpose of this
+ field is strictly to inform the recipient of valid methods
+ associated with the resource. An Allow header field MUST be
+ present in a 405 (Method Not Allowed) response.
+
+ Allow = "Allow" ":" #Method
+
+ Example of use:
+
+ Allow: GET, HEAD, PUT
+
+ This field cannot prevent a client from trying other methods.
+ However, the indications given by the Allow header field value
+ SHOULD be followed. The actual set of allowed methods is defined
+ by the origin server at the time of each request.
+
+ The Allow header field MAY be provided with a PUT request to
+ recommend the methods to be supported by the new or modified
+ resource. The server is not required to support these methods and
+ SHOULD include an Allow header in the response giving the actual
+ supported methods.
+
+ A proxy MUST NOT modify the Allow header field even if it does not
+ understand all the methods specified, since the user agent might
+ have other means of communicating with the origin server.
+
+14.8 Authorization
+
+ A user agent that wishes to authenticate itself with a server--
+ usually, but not necessarily, after receiving a 401 response--does
+ so by including an Authorization request-header field with the
+ request. The Authorization field value consists of credentials
+ containing the authentication information of the user agent for
+ the realm of the resource being requested.
+
+ Authorization = "Authorization" ":" credentials
+
+ HTTP access authentication is described in "HTTP Authentication:
+ Basic and Digest Access Authentication" [43]. If a request is
+ authenticated and a realm specified, the same credentials SHOULD
+ be valid for all other requests within this realm (assuming that
+ the authentication scheme itself does not require otherwise, such
+ as credentials that vary according to a challenge value or using
+ synchronized clocks).
+
+ When a shared cache (see section 13.7) receives a request
+ containing an Authorization field, it MUST NOT return the
+ corresponding response as a reply to any other request, unless one
+ of the following specific exceptions holds:
+
+ 1. If the response includes the "s-maxage" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But (if the specified maximum age has
+ passed) a proxy cache MUST first revalidate it with the origin
+ server, using the request-headers from the new request to allow
+ the origin server to authenticate the new request. (This is the
+ defined behavior for s-maxage.) If the response includes "s-
+ maxage=0", the proxy MUST always revalidate it before re-using
+ it.
+
+ 2. If the response includes the "must-revalidate" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But if the response is stale, all caches
+ MUST first revalidate it with the origin server, using the
+ request-headers from the new request to allow the origin server
+ to authenticate the new request.
+
+ 3. If the response includes the "public" cache-control directive,
+ it MAY be returned in reply to any subsequent request.
+
+14.9 Cache-Control
+
+ The Cache-Control general-header field is used to specify directives
+ that MUST be obeyed by all caching mechanisms along the
+ request/response chain. The directives specify behavior intended to
+ prevent caches from adversely interfering with the request or
+ response. These directives typically override the default caching
+ algorithms. Cache directives are unidirectional in that the presence
+ of a directive in a request does not imply that the same directive is
+ to be given in the response.
+
+ Note that HTTP/1.0 caches might not implement Cache-Control and
+ might only implement Pragma: no-cache (see section 14.32).
+
+ Cache directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application,
+ since the directives might be applicable to all recipients along the
+ request/response chain. It is not possible to specify a cache-
+ directive for a specific cache.
+
+ Cache-Control = "Cache-Control" ":" 1#cache-directive
+
+ cache-directive = cache-request-directive
+ | cache-response-directive
+
+ cache-request-directive =
+ "no-cache" ; Section 14.9.1
+ | "no-store" ; Section 14.9.2
+ | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
+ | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
+ | "min-fresh" "=" delta-seconds ; Section 14.9.3
+ | "no-transform" ; Section 14.9.5
+ | "only-if-cached" ; Section 14.9.4
+ | cache-extension ; Section 14.9.6
+
+ cache-response-directive =
+ "public" ; Section 14.9.1
+ | "private" [ "=" &lt;"&gt; 1#field-name &lt;"&gt; ] ; Section 14.9.1
+ | "no-cache" [ "=" &lt;"&gt; 1#field-name &lt;"&gt; ]; Section 14.9.1
+ | "no-store" ; Section 14.9.2
+ | "no-transform" ; Section 14.9.5
+ | "must-revalidate" ; Section 14.9.4
+ | "proxy-revalidate" ; Section 14.9.4
+ | "max-age" "=" delta-seconds ; Section 14.9.3
+ | "s-maxage" "=" delta-seconds ; Section 14.9.3
+ | cache-extension ; Section 14.9.6
+
+ cache-extension = token [ "=" ( token | quoted-string ) ]
+
+ When a directive appears without any 1#field-name parameter, the
+ directive applies to the entire request or response. When such a
+ directive appears with a 1#field-name parameter, it applies only to
+ the named field or fields, and not to the rest of the request or
+ response. This mechanism supports extensibility; implementations of
+ future versions of the HTTP protocol might apply these directives to
+ header fields not defined in HTTP/1.1.
+
+ The cache-control directives can be broken down into these general
+ categories:
+
+ - Restrictions on what are cacheable; these may only be imposed by
+ the origin server.
+
+ - Restrictions on what may be stored by a cache; these may be
+ imposed by either the origin server or the user agent.
+
+ - Modifications of the basic expiration mechanism; these may be
+ imposed by either the origin server or the user agent.
+
+ - Controls over cache revalidation and reload; these may only be
+ imposed by a user agent.
+
+ - Control over transformation of entities.
+
+ - Extensions to the caching system.
+
+14.9.1 What is Cacheable
+
+ By default, a response is cacheable if the requirements of the
+ request method, request header fields, and the response status
+ indicate that it is cacheable. Section 13.4 summarizes these defaults
+ for cacheability. The following Cache-Control response directives
+ allow an origin server to override the default cacheability of a
+ response:
+
+ public
+ Indicates that the response MAY be cached by any cache, even if it
+ would normally be non-cacheable or cacheable only within a non-
+ shared cache. (See also Authorization, section 14.8, for
+ additional details.)
+
+ private
+ Indicates that all or part of the response message is intended for
+ a single user and MUST NOT be cached by a shared cache. This
+ allows an origin server to state that the specified parts of the
+
+ response are intended for only one user and are not a valid
+ response for requests by other users. A private (non-shared) cache
+ MAY cache the response.
+
+ Note: This usage of the word private only controls where the
+ response may be cached, and cannot ensure the privacy of the
+ message content.
+
+ no-cache
+ If the no-cache directive does not specify a field-name, then a
+ cache MUST NOT use the response to satisfy a subsequent request
+ without successful revalidation with the origin server. This
+ allows an origin server to prevent caching even by caches that
+ have been configured to return stale responses to client requests.
+
+ If the no-cache directive does specify one or more field-names,
+ then a cache MAY use the response to satisfy a subsequent request,
+ subject to any other restrictions on caching. However, the
+ specified field-name(s) MUST NOT be sent in the response to a
+ subsequent request without successful revalidation with the origin
+ server. This allows an origin server to prevent the re-use of
+ certain header fields in a response, while still allowing caching
+ of the rest of the response.
+
+ Note: Most HTTP/1.0 caches will not recognize or obey this
+ directive.
+
+14.9.2 What May be Stored by Caches
+
+ no-store
+ The purpose of the no-store directive is to prevent the
+ inadvertent release or retention of sensitive information (for
+ example, on backup tapes). The no-store directive applies to the
+ entire message, and MAY be sent either in a response or in a
+ request. If sent in a request, a cache MUST NOT store any part of
+ either this request or any response to it. If sent in a response,
+ a cache MUST NOT store any part of either this response or the
+ request that elicited it. This directive applies to both non-
+ shared and shared caches. "MUST NOT store" in this context means
+ that the cache MUST NOT intentionally store the information in
+ non-volatile storage, and MUST make a best-effort attempt to
+ remove the information from volatile storage as promptly as
+ possible after forwarding it.
+
+ Even when this directive is associated with a response, users
+ might explicitly store such a response outside of the caching
+ system (e.g., with a "Save As" dialog). History buffers MAY store
+ such responses as part of their normal operation.
+
+ The purpose of this directive is to meet the stated requirements
+ of certain users and service authors who are concerned about
+ accidental releases of information via unanticipated accesses to
+ cache data structures. While the use of this directive might
+ improve privacy in some cases, we caution that it is NOT in any
+ way a reliable or sufficient mechanism for ensuring privacy. In
+ particular, malicious or compromised caches might not recognize or
+ obey this directive, and communications networks might be
+ vulnerable to eavesdropping.
+
+14.9.3 Modifications of the Basic Expiration Mechanism
+
+ The expiration time of an entity MAY be specified by the origin
+ server using the Expires header (see section 14.21). Alternatively,
+ it MAY be specified using the max-age directive in a response. When
+ the max-age cache-control directive is present in a cached response,
+ the response is stale if its current age is greater than the age
+ value given (in seconds) at the time of a new request for that
+ resource. The max-age directive on a response implies that the
+ response is cacheable (i.e., "public") unless some other, more
+ restrictive cache directive is also present.
+
+ If a response includes both an Expires header and a max-age
+ directive, the max-age directive overrides the Expires header, even
+ if the Expires header is more restrictive. This rule allows an origin
+ server to provide, for a given response, a longer expiration time to
+ an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
+ useful if certain HTTP/1.0 caches improperly calculate ages or
+ expiration times, perhaps due to desynchronized clocks.
+
+ Many HTTP/1.0 cache implementations will treat an Expires value that
+ is less than or equal to the response Date value as being equivalent
+ to the Cache-Control response directive "no-cache". If an HTTP/1.1
+ cache receives such a response, and the response does not include a
+ Cache-Control header field, it SHOULD consider the response to be
+ non-cacheable in order to retain compatibility with HTTP/1.0 servers.
+
+ Note: An origin server might wish to use a relatively new HTTP
+ cache control feature, such as the "private" directive, on a
+ network including older caches that do not understand that
+ feature. The origin server will need to combine the new feature
+ with an Expires field whose value is less than or equal to the
+ Date value. This will prevent older caches from improperly
+ caching the response.
+
+ s-maxage
+ If a response includes an s-maxage directive, then for a shared
+ cache (but not for a private cache), the maximum age specified by
+ this directive overrides the maximum age specified by either the
+ max-age directive or the Expires header. The s-maxage directive
+ also implies the semantics of the proxy-revalidate directive (see
+ section 14.9.4), i.e., that the shared cache must not use the
+ entry after it becomes stale to respond to a subsequent request
+ without first revalidating it with the origin server. The s-
+ maxage directive is always ignored by a private cache.
+
+ Note that most older caches, not compliant with this specification,
+ do not implement any cache-control directives. An origin server
+ wishing to use a cache-control directive that restricts, but does not
+ prevent, caching by an HTTP/1.1-compliant cache MAY exploit the
+ requirement that the max-age directive overrides the Expires header,
+ and the fact that pre-HTTP/1.1-compliant caches do not observe the
+ max-age directive.
+
+ Other directives allow a user agent to modify the basic expiration
+ mechanism. These directives MAY be specified on a request:
+
+ max-age
+ Indicates that the client is willing to accept a response whose
+ age is no greater than the specified time in seconds. Unless max-
+ stale directive is also included, the client is not willing to
+ accept a stale response.
+
+ min-fresh
+ Indicates that the client is willing to accept a response whose
+ freshness lifetime is no less than its current age plus the
+ specified time in seconds. That is, the client wants a response
+ that will still be fresh for at least the specified number of
+ seconds.
+
+ max-stale
+ Indicates that the client is willing to accept a response that has
+ exceeded its expiration time. If max-stale is assigned a value,
+ then the client is willing to accept a response that has exceeded
+ its expiration time by no more than the specified number of
+ seconds. If no value is assigned to max-stale, then the client is
+ willing to accept a stale response of any age.
+
+ If a cache returns a stale response, either because of a max-stale
+ directive on a request, or because the cache is configured to
+ override the expiration time of a response, the cache MUST attach a
+ Warning header to the stale response, using Warning 110 (Response is
+ stale).
+
+ A cache MAY be configured to return stale responses without
+ validation, but only if this does not conflict with any "MUST"-level
+ requirements concerning cache validation (e.g., a "must-revalidate"
+ cache-control directive).
+
+ If both the new request and the cached entry include "max-age"
+ directives, then the lesser of the two values is used for determining
+ the freshness of the cached entry for that request.
+
+14.9.4 Cache Revalidation and Reload Controls
+
+ Sometimes a user agent might want or need to insist that a cache
+ revalidate its cache entry with the origin server (and not just with
+ the next cache along the path to the origin server), or to reload its
+ cache entry from the origin server. End-to-end revalidation might be
+ necessary if either the cache or the origin server has overestimated
+ the expiration time of the cached response. End-to-end reload may be
+ necessary if the cache entry has become corrupted for some reason.
+
+ End-to-end revalidation may be requested either when the client does
+ not have its own local cached copy, in which case we call it
+ "unspecified end-to-end revalidation", or when the client does have a
+ local cached copy, in which case we call it "specific end-to-end
+ revalidation."
+
+ The client can specify these three kinds of action using Cache-
+ Control request directives:
+
+ End-to-end reload
+ The request includes a "no-cache" cache-control directive or, for
+ compatibility with HTTP/1.0 clients, "Pragma: no-cache". Field
+ names MUST NOT be included with the no-cache directive in a
+ request. The server MUST NOT use a cached copy when responding to
+ such a request.
+
+ Specific end-to-end revalidation
+ The request includes a "max-age=0" cache-control directive, which
+ forces each cache along the path to the origin server to
+ revalidate its own entry, if any, with the next cache or server.
+ The initial request includes a cache-validating conditional with
+ the client's current validator.
+
+ Unspecified end-to-end revalidation
+ The request includes "max-age=0" cache-control directive, which
+ forces each cache along the path to the origin server to
+ revalidate its own entry, if any, with the next cache or server.
+ The initial request does not include a cache-validating
+
+ conditional; the first cache along the path (if any) that holds a
+ cache entry for this resource includes a cache-validating
+ conditional with its current validator.
+
+ max-age
+ When an intermediate cache is forced, by means of a max-age=0
+ directive, to revalidate its own cache entry, and the client has
+ supplied its own validator in the request, the supplied validator
+ might differ from the validator currently stored with the cache
+ entry. In this case, the cache MAY use either validator in making
+ its own request without affecting semantic transparency.
+
+ However, the choice of validator might affect performance. The
+ best approach is for the intermediate cache to use its own
+ validator when making its request. If the server replies with 304
+ (Not Modified), then the cache can return its now validated copy
+ to the client with a 200 (OK) response. If the server replies with
+ a new entity and cache validator, however, the intermediate cache
+ can compare the returned validator with the one provided in the
+ client's request, using the strong comparison function. If the
+ client's validator is equal to the origin server's, then the
+ intermediate cache simply returns 304 (Not Modified). Otherwise,
+ it returns the new entity with a 200 (OK) response.
+
+ If a request includes the no-cache directive, it SHOULD NOT
+ include min-fresh, max-stale, or max-age.
+
+ only-if-cached
+ In some cases, such as times of extremely poor network
+ connectivity, a client may want a cache to return only those
+ responses that it currently has stored, and not to reload or
+ revalidate with the origin server. To do this, the client may
+ include the only-if-cached directive in a request. If it receives
+ this directive, a cache SHOULD either respond using a cached entry
+ that is consistent with the other constraints of the request, or
+ respond with a 504 (Gateway Timeout) status. However, if a group
+ of caches is being operated as a unified system with good internal
+ connectivity, such a request MAY be forwarded within that group of
+ caches.
+
+ must-revalidate
+ Because a cache MAY be configured to ignore a server's specified
+ expiration time, and because a client request MAY include a max-
+ stale directive (which has a similar effect), the protocol also
+ includes a mechanism for the origin server to require revalidation
+ of a cache entry on any subsequent use. When the must-revalidate
+ directive is present in a response received by a cache, that cache
+ MUST NOT use the entry after it becomes stale to respond to a
+
+ subsequent request without first revalidating it with the origin
+ server. (I.e., the cache MUST do an end-to-end revalidation every
+ time, if, based solely on the origin server's Expires or max-age
+ value, the cached response is stale.)
+
+ The must-revalidate directive is necessary to support reliable
+ operation for certain protocol features. In all circumstances an
+ HTTP/1.1 cache MUST obey the must-revalidate directive; in
+ particular, if the cache cannot reach the origin server for any
+ reason, it MUST generate a 504 (Gateway Timeout) response.
+
+ Servers SHOULD send the must-revalidate directive if and only if
+ failure to revalidate a request on the entity could result in
+ incorrect operation, such as a silently unexecuted financial
+ transaction. Recipients MUST NOT take any automated action that
+ violates this directive, and MUST NOT automatically provide an
+ unvalidated copy of the entity if revalidation fails.
+
+ Although this is not recommended, user agents operating under
+ severe connectivity constraints MAY violate this directive but, if
+ so, MUST explicitly warn the user that an unvalidated response has
+ been provided. The warning MUST be provided on each unvalidated
+ access, and SHOULD require explicit user confirmation.
+
+ proxy-revalidate
+ The proxy-revalidate directive has the same meaning as the must-
+ revalidate directive, except that it does not apply to non-shared
+ user agent caches. It can be used on a response to an
+ authenticated request to permit the user's cache to store and
+ later return the response without needing to revalidate it (since
+ it has already been authenticated once by that user), while still
+ requiring proxies that service many users to revalidate each time
+ (in order to make sure that each user has been authenticated).
+ Note that such authenticated responses also need the public cache
+ control directive in order to allow them to be cached at all.
+
+14.9.5 No-Transform Directive
+
+ no-transform
+ Implementors of intermediate caches (proxies) have found it useful
+ to convert the media type of certain entity bodies. A non-
+ transparent proxy might, for example, convert between image
+ formats in order to save cache space or to reduce the amount of
+ traffic on a slow link.
+
+ Serious operational problems occur, however, when these
+ transformations are applied to entity bodies intended for certain
+ kinds of applications. For example, applications for medical
+
+ imaging, scientific data analysis and those using end-to-end
+ authentication, all depend on receiving an entity body that is bit
+ for bit identical to the original entity-body.
+
+ Therefore, if a message includes the no-transform directive, an
+ intermediate cache or proxy MUST NOT change those headers that are
+ listed in section 13.5.2 as being subject to the no-transform
+ directive. This implies that the cache or proxy MUST NOT change
+ any aspect of the entity-body that is specified by these headers,
+ including the value of the entity-body itself.
+
+14.9.6 Cache Control Extensions
+
+ The Cache-Control header field can be extended through the use of one
+ or more cache-extension tokens, each with an optional assigned value.
+ Informational extensions (those which do not require a change in
+ cache behavior) MAY be added without changing the semantics of other
+ directives. Behavioral extensions are designed to work by acting as
+ modifiers to the existing base of cache directives. Both the new
+ directive and the standard directive are supplied, such that
+ applications which do not understand the new directive will default
+ to the behavior specified by the standard directive, and those that
+ understand the new directive will recognize it as modifying the
+ requirements associated with the standard directive. In this way,
+ extensions to the cache-control directives can be made without
+ requiring changes to the base protocol.
+
+ This extension mechanism depends on an HTTP cache obeying all of the
+ cache-control directives defined for its native HTTP-version, obeying
+ certain extensions, and ignoring all directives that it does not
+ understand.
+
+ For example, consider a hypothetical new response directive called
+ community which acts as a modifier to the private directive. We
+ define this new directive to mean that, in addition to any non-shared
+ cache, any cache which is shared only by members of the community
+ named within its value may cache the response. An origin server
+ wishing to allow the UCI community to use an otherwise private
+ response in their shared cache(s) could do so by including
+
+ Cache-Control: private, community="UCI"
+
+ A cache seeing this header field will act correctly even if the cache
+ does not understand the community cache-extension, since it will also
+ see and understand the private directive and thus default to the safe
+ behavior.
+
+ Unrecognized cache-directives MUST be ignored; it is assumed that any
+ cache-directive likely to be unrecognized by an HTTP/1.1 cache will
+ be combined with standard directives (or the response's default
+ cacheability) such that the cache behavior will remain minimally
+ correct even if the cache does not understand the extension(s).
+
+14.10 Connection
+
+ The Connection general-header field allows the sender to specify
+ options that are desired for that particular connection and MUST NOT
+ be communicated by proxies over further connections.
+
+ The Connection header has the following grammar:
+
+ Connection = "Connection" ":" 1#(connection-token)
+ connection-token = token
+
+ HTTP/1.1 proxies MUST parse the Connection header field before a
+ message is forwarded and, for each connection-token in this field,
+ remove any header field(s) from the message with the same name as the
+ connection-token. Connection options are signaled by the presence of
+ a connection-token in the Connection header field, not by any
+ corresponding additional header field(s), since the additional header
+ field may not be sent if there are no parameters associated with that
+ connection option.
+
+ Message headers listed in the Connection header MUST NOT include
+ end-to-end headers, such as Cache-Control.
+
+ HTTP/1.1 defines the "close" connection option for the sender to
+ signal that the connection will be closed after completion of the
+ response. For example,
+
+ Connection: close
+
+ in either the request or the response header fields indicates that
+ the connection SHOULD NOT be considered `persistent' (section 8.1)
+ after the current request/response is complete.
+
+ HTTP/1.1 applications that do not support persistent connections MUST
+ include the "close" connection option in every message.
+
+ A system receiving an HTTP/1.0 (or lower-version) message that
+ includes a Connection header MUST, for each connection-token in this
+ field, remove and ignore any header field(s) from the message with
+ the same name as the connection-token. This protects against mistaken
+ forwarding of such header fields by pre-HTTP/1.1 proxies. See section
+ 19.6.2.
+
+14.11 Content-Encoding
+
+ The Content-Encoding entity-header field is used as a modifier to the
+ media-type. When present, its value indicates what additional content
+ codings have been applied to the entity-body, and thus what decoding
+ mechanisms must be applied in order to obtain the media-type
+ referenced by the Content-Type header field. Content-Encoding is
+ primarily used to allow a document to be compressed without losing
+ the identity of its underlying media type.
+
+ Content-Encoding = "Content-Encoding" ":" 1#content-coding
+
+ Content codings are defined in section 3.5. An example of its use is
+
+ Content-Encoding: gzip
+
+ The content-coding is a characteristic of the entity identified by
+ the Request-URI. Typically, the entity-body is stored with this
+ encoding and is only decoded before rendering or analogous usage.
+ However, a non-transparent proxy MAY modify the content-coding if the
+ new coding is known to be acceptable to the recipient, unless the
+ "no-transform" cache-control directive is present in the message.
+
+ If the content-coding of an entity is not "identity", then the
+ response MUST include a Content-Encoding entity-header (section
+ 14.11) that lists the non-identity content-coding(s) used.
+
+ If the content-coding of an entity in a request message is not
+ acceptable to the origin server, the server SHOULD respond with a
+ status code of 415 (Unsupported Media Type).
+
+ If multiple encodings have been applied to an entity, the content
+ codings MUST be listed in the order in which they were applied.
+ Additional information about the encoding parameters MAY be provided
+ by other entity-header fields not defined by this specification.
+
+14.12 Content-Language
+
+ The Content-Language entity-header field describes the natural
+ language(s) of the intended audience for the enclosed entity. Note
+ that this might not be equivalent to all the languages used within
+ the entity-body.
+
+ Content-Language = "Content-Language" ":" 1#language-tag
+
+ Language tags are defined in section 3.10. The primary purpose of
+ Content-Language is to allow a user to identify and differentiate
+ entities according to the user's own preferred language. Thus, if the
+ body content is intended only for a Danish-literate audience, the
+ appropriate field is
+
+ Content-Language: da
+
+ If no Content-Language is specified, the default is that the content
+ is intended for all language audiences. This might mean that the
+ sender does not consider it to be specific to any natural language,
+ or that the sender does not know for which language it is intended.
+
+ Multiple languages MAY be listed for content that is intended for
+ multiple audiences. For example, a rendition of the "Treaty of
+ Waitangi," presented simultaneously in the original Maori and English
+ versions, would call for
+
+ Content-Language: mi, en
+
+ However, just because multiple languages are present within an entity
+ does not mean that it is intended for multiple linguistic audiences.
+ An example would be a beginner's language primer, such as "A First
+ Lesson in Latin," which is clearly intended to be used by an
+ English-literate audience. In this case, the Content-Language would
+ properly only include "en".
+
+ Content-Language MAY be applied to any media type -- it is not
+ limited to textual documents.
+
+14.13 Content-Length
+
+ The Content-Length entity-header field indicates the size of the
+ entity-body, in decimal number of OCTETs, sent to the recipient or,
+ in the case of the HEAD method, the size of the entity-body that
+ would have been sent had the request been a GET.
+
+ Content-Length = "Content-Length" ":" 1*DIGIT
+
+ An example is
+
+ Content-Length: 3495
+
+ Applications SHOULD use this field to indicate the transfer-length of
+ the message-body, unless this is prohibited by the rules in section
+ 4.4.
+
+ Any Content-Length greater than or equal to zero is a valid value.
+ Section 4.4 describes how to determine the length of a message-body
+ if a Content-Length is not given.
+
+ Note that the meaning of this field is significantly different from
+ the corresponding definition in MIME, where it is an optional field
+ used within the "message/external-body" content-type. In HTTP, it
+ SHOULD be sent whenever the message's length can be determined prior
+ to being transferred, unless this is prohibited by the rules in
+ section 4.4.
+
+14.14 Content-Location
+
+ The Content-Location entity-header field MAY be used to supply the
+ resource location for the entity enclosed in the message when that
+ entity is accessible from a location separate from the requested
+ resource's URI. A server SHOULD provide a Content-Location for the
+ variant corresponding to the response entity; especially in the case
+ where a resource has multiple entities associated with it, and those
+ entities actually have separate locations by which they might be
+ individually accessed, the server SHOULD provide a Content-Location
+ for the particular variant which is returned.
+
+ Content-Location = "Content-Location" ":"
+ ( absoluteURI | relativeURI )
+
+ The value of Content-Location also defines the base URI for the
+ entity.
+
+ The Content-Location value is not a replacement for the original
+ requested URI; it is only a statement of the location of the resource
+ corresponding to this particular entity at the time of the request.
+ Future requests MAY specify the Content-Location URI as the request-
+ URI if the desire is to identify the source of that particular
+ entity.
+
+ A cache cannot assume that an entity with a Content-Location
+ different from the URI used to retrieve it can be used to respond to
+ later requests on that Content-Location URI. However, the Content-
+ Location can be used to differentiate between multiple entities
+ retrieved from a single requested resource, as described in section
+ 13.6.
+
+ If the Content-Location is a relative URI, the relative URI is
+ interpreted relative to the Request-URI.
+
+ The meaning of the Content-Location header in PUT or POST requests is
+ undefined; servers are free to ignore it in those cases.
+
+14.15 Content-MD5
+
+ The Content-MD5 entity-header field, as defined in <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a> [23], is
+ an MD5 digest of the entity-body for the purpose of providing an
+ end-to-end message integrity check (MIC) of the entity-body. (Note: a
+ MIC is good for detecting accidental modification of the entity-body
+ in transit, but is not proof against malicious attacks.)
+
+ Content-MD5 = "Content-MD5" ":" md5-digest
+ md5-digest = &lt;base64 of 128 bit MD5 digest as per <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a>&gt;
+
+ The Content-MD5 header field MAY be generated by an origin server or
+ client to function as an integrity check of the entity-body. Only
+ origin servers or clients MAY generate the Content-MD5 header field;
+ proxies and gateways MUST NOT generate it, as this would defeat its
+ value as an end-to-end integrity check. Any recipient of the entity-
+ body, including gateways and proxies, MAY check that the digest value
+ in this header field matches that of the entity-body as received.
+
+ The MD5 digest is computed based on the content of the entity-body,
+ including any content-coding that has been applied, but not including
+ any transfer-encoding applied to the message-body. If the message is
+ received with a transfer-encoding, that encoding MUST be removed
+ prior to checking the Content-MD5 value against the received entity.
+
+ This has the result that the digest is computed on the octets of the
+ entity-body exactly as, and in the order that, they would be sent if
+ no transfer-encoding were being applied.
+
+ HTTP extends <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a> to permit the digest to be computed for MIME
+ composite media-types (e.g., multipart/* and message/rfc822), but
+ this does not change how the digest is computed as defined in the
+ preceding paragraph.
+
+ There are several consequences of this. The entity-body for composite
+ types MAY contain many body-parts, each with its own MIME and HTTP
+ headers (including Content-MD5, Content-Transfer-Encoding, and
+ Content-Encoding headers). If a body-part has a Content-Transfer-
+ Encoding or Content-Encoding header, it is assumed that the content
+ of the body-part has had the encoding applied, and the body-part is
+ included in the Content-MD5 digest as is -- i.e., after the
+ application. The Transfer-Encoding header field is not allowed within
+ body-parts.
+
+ Conversion of all line breaks to CRLF MUST NOT be done before
+ computing or checking the digest: the line break convention used in
+ the text actually transmitted MUST be left unaltered when computing
+ the digest.
+
+ Note: while the definition of Content-MD5 is exactly the same for
+ HTTP as in <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a> for MIME entity-bodies, there are several ways
+ in which the application of Content-MD5 to HTTP entity-bodies
+ differs from its application to MIME entity-bodies. One is that
+ HTTP, unlike MIME, does not use Content-Transfer-Encoding, and
+ does use Transfer-Encoding and Content-Encoding. Another is that
+ HTTP more frequently uses binary content types than MIME, so it is
+ worth noting that, in such cases, the byte order used to compute
+ the digest is the transmission byte order defined for the type.
+ Lastly, HTTP allows transmission of text types with any of several
+ line break conventions and not just the canonical form using CRLF.
+
+14.16 Content-Range
+
+ The Content-Range entity-header is sent with a partial entity-body to
+ specify where in the full entity-body the partial body should be
+ applied. Range units are defined in section 3.12.
+
+ Content-Range = "Content-Range" ":" content-range-spec
+
+ content-range-spec = byte-content-range-spec
+ byte-content-range-spec = bytes-unit SP
+ byte-range-resp-spec "/"
+ ( instance-length | "*" )
+
+ byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
+ | "*"
+ instance-length = 1*DIGIT
+
+ The header SHOULD indicate the total length of the full entity-body,
+ unless this length is unknown or difficult to determine. The asterisk
+ "*" character means that the instance-length is unknown at the time
+ when the response was generated.
+
+ Unlike byte-ranges-specifier values (see section 14.35.1), a byte-
+ range-resp-spec MUST only specify one range, and MUST contain
+ absolute byte positions for both the first and last byte of the
+ range.
+
+ A byte-content-range-spec with a byte-range-resp-spec whose last-
+ byte-pos value is less than its first-byte-pos value, or whose
+ instance-length value is less than or equal to its last-byte-pos
+ value, is invalid. The recipient of an invalid byte-content-range-
+ spec MUST ignore it and any content transferred along with it.
+
+ A server sending a response with status code 416 (Requested range not
+ satisfiable) SHOULD include a Content-Range field with a byte-range-
+ resp-spec of "*". The instance-length specifies the current length of
+
+ the selected resource. A response with status code 206 (Partial
+ Content) MUST NOT include a Content-Range field with a byte-range-
+ resp-spec of "*".
+
+ Examples of byte-content-range-spec values, assuming that the entity
+ contains a total of 1234 bytes:
+
+ . The first 500 bytes:
+ bytes 0-499/1234
+
+ . The second 500 bytes:
+ bytes 500-999/1234
+
+ . All except for the first 500 bytes:
+ bytes 500-1233/1234
+
+ . The last 500 bytes:
+ bytes 734-1233/1234
+
+ When an HTTP message includes the content of a single range (for
+ example, a response to a request for a single range, or to a request
+ for a set of ranges that overlap without any holes), this content is
+ transmitted with a Content-Range header, and a Content-Length header
+ showing the number of bytes actually transferred. For example,
+
+ HTTP/1.1 206 Partial content
+ Date: Wed, 15 Nov 1995 06:25:24 GMT
+ Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ Content-Range: bytes 21010-47021/47022
+ Content-Length: 26012
+ Content-Type: image/gif
+
+ When an HTTP message includes the content of multiple ranges (for
+ example, a response to a request for multiple non-overlapping
+ ranges), these are transmitted as a multipart message. The multipart
+ media type used for this purpose is "multipart/byteranges" as defined
+ in appendix 19.2. See appendix 19.6.3 for a compatibility issue.
+
+ A response to a request for a single range MUST NOT be sent using the
+ multipart/byteranges media type. A response to a request for
+ multiple ranges, whose result is a single range, MAY be sent as a
+ multipart/byteranges media type with one part. A client that cannot
+ decode a multipart/byteranges message MUST NOT ask for multiple
+ byte-ranges in a single request.
+
+ When a client requests multiple byte-ranges in one request, the
+ server SHOULD return them in the order that they appeared in the
+ request.
+
+ If the server ignores a byte-range-spec because it is syntactically
+ invalid, the server SHOULD treat the request as if the invalid Range
+ header field did not exist. (Normally, this means return a 200
+ response containing the full entity).
+
+ If the server receives a request (other than one including an If-
+ Range request-header field) with an unsatisfiable Range request-
+ header field (that is, all of whose byte-range-spec values have a
+ first-byte-pos value greater than the current length of the selected
+ resource), it SHOULD return a response code of 416 (Requested range
+ not satisfiable) (section 10.4.17).
+
+ Note: clients cannot depend on servers to send a 416 (Requested
+ range not satisfiable) response instead of a 200 (OK) response for
+ an unsatisfiable Range request-header, since not all servers
+ implement this request-header.
+
+14.17 Content-Type
+
+ The Content-Type entity-header field indicates the media type of the
+ entity-body sent to the recipient or, in the case of the HEAD method,
+ the media type that would have been sent had the request been a GET.
+
+ Content-Type = "Content-Type" ":" media-type
+
+ Media types are defined in section 3.7. An example of the field is
+
+ Content-Type: text/html; charset=ISO-8859-4
+
+ Further discussion of methods for identifying the media type of an
+ entity is provided in section 7.2.1.
+
+14.18 Date
+
+ The Date general-header field represents the date and time at which
+ the message was originated, having the same semantics as orig-date in
+ <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a>. The field value is an HTTP-date, as described in section
+ 3.3.1; it MUST be sent in <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> [8]-date format.
+
+ Date = "Date" ":" HTTP-date
+
+ An example is
+
+ Date: Tue, 15 Nov 1994 08:12:31 GMT
+
+ Origin servers MUST include a Date header field in all responses,
+ except in these cases:
+
+ 1. If the response status code is 100 (Continue) or 101 (Switching
+ Protocols), the response MAY include a Date header field, at
+ the server's option.
+
+ 2. If the response status code conveys a server error, e.g. 500
+ (Internal Server Error) or 503 (Service Unavailable), and it is
+ inconvenient or impossible to generate a valid Date.
+
+ 3. If the server does not have a clock that can provide a
+ reasonable approximation of the current time, its responses
+ MUST NOT include a Date header field. In this case, the rules
+ in section 14.18.1 MUST be followed.
+
+ A received message that does not have a Date header field MUST be
+ assigned one by the recipient if the message will be cached by that
+ recipient or gatewayed via a protocol which requires a Date. An HTTP
+ implementation without a clock MUST NOT cache responses without
+ revalidating them on every use. An HTTP cache, especially a shared
+ cache, SHOULD use a mechanism, such as NTP [28], to synchronize its
+ clock with a reliable external standard.
+
+ Clients SHOULD only send a Date header field in messages that include
+ an entity-body, as in the case of the PUT and POST requests, and even
+ then it is optional. A client without a clock MUST NOT send a Date
+ header field in a request.
+
+ The HTTP-date sent in a Date header SHOULD NOT represent a date and
+ time subsequent to the generation of the message. It SHOULD represent
+ the best available approximation of the date and time of message
+ generation, unless the implementation has no means of generating a
+ reasonably accurate date and time. In theory, the date ought to
+ represent the moment just before the entity is generated. In
+ practice, the date can be generated at any time during the message
+ origination without affecting its semantic value.
+
+14.18.1 Clockless Origin Server Operation
+
+ Some origin server implementations might not have a clock available.
+ An origin server without a clock MUST NOT assign Expires or Last-
+ Modified values to a response, unless these values were associated
+ with the resource by a system or user with a reliable clock. It MAY
+ assign an Expires value that is known, at or before server
+ configuration time, to be in the past (this allows "pre-expiration"
+ of responses without storing separate Expires values for each
+ resource).
+
+14.19 ETag
+
+ The ETag response-header field provides the current value of the
+ entity tag for the requested variant. The headers used with entity
+ tags are described in sections 14.24, 14.26 and 14.44. The entity tag
+ MAY be used for comparison with other entities from the same resource
+ (see section 13.3.3).
+
+ ETag = "ETag" ":" entity-tag
+
+ Examples:
+
+ ETag: "xyzzy"
+ ETag: W/"xyzzy"
+ ETag: ""
+
+14.20 Expect
+
+ The Expect request-header field is used to indicate that particular
+ server behaviors are required by the client.
+
+ Expect = "Expect" ":" 1#expectation
+
+ expectation = "100-continue" | expectation-extension
+ expectation-extension = token [ "=" ( token | quoted-string )
+ *expect-params ]
+ expect-params = ";" token [ "=" ( token | quoted-string ) ]
+
+ A server that does not understand or is unable to comply with any of
+ the expectation values in the Expect field of a request MUST respond
+ with appropriate error status. The server MUST respond with a 417
+ (Expectation Failed) status if any of the expectations cannot be met
+ or, if there are other problems with the request, some other 4xx
+ status.
+
+ This header field is defined with extensible syntax to allow for
+ future extensions. If a server receives a request containing an
+ Expect field that includes an expectation-extension that it does not
+ support, it MUST respond with a 417 (Expectation Failed) status.
+
+ Comparison of expectation values is case-insensitive for unquoted
+ tokens (including the 100-continue token), and is case-sensitive for
+ quoted-string expectation-extensions.
+
+ The Expect mechanism is hop-by-hop: that is, an HTTP/1.1 proxy MUST
+ return a 417 (Expectation Failed) status if it receives a request
+ with an expectation that it cannot meet. However, the Expect
+ request-header itself is end-to-end; it MUST be forwarded if the
+ request is forwarded.
+
+ Many older HTTP/1.0 and HTTP/1.1 applications do not understand the
+ Expect header.
+
+ See section 8.2.3 for the use of the 100 (continue) status.
+
+14.21 Expires
+
+ The Expires entity-header field gives the date/time after which the
+ response is considered stale. A stale cache entry may not normally be
+ returned by a cache (either a proxy cache or a user agent cache)
+ unless it is first validated with the origin server (or with an
+ intermediate cache that has a fresh copy of the entity). See section
+ 13.2 for further discussion of the expiration model.
+
+ The presence of an Expires field does not imply that the original
+ resource will change or cease to exist at, before, or after that
+ time.
+
+ The format is an absolute date and time as defined by HTTP-date in
+ section 3.3.1; it MUST be in <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> date format:
+
+ Expires = "Expires" ":" HTTP-date
+
+ An example of its use is
+
+ Expires: Thu, 01 Dec 1994 16:00:00 GMT
+
+ Note: if a response includes a Cache-Control field with the max-
+ age directive (see section 14.9.3), that directive overrides the
+ Expires field.
+
+ HTTP/1.1 clients and caches MUST treat other invalid date formats,
+ especially including the value "0", as in the past (i.e., "already
+ expired").
+
+ To mark a response as "already expired," an origin server sends an
+ Expires date that is equal to the Date header value. (See the rules
+ for expiration calculations in section 13.2.4.)
+
+ To mark a response as "never expires," an origin server sends an
+ Expires date approximately one year from the time the response is
+ sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one
+ year in the future.
+
+ The presence of an Expires header field with a date value of some
+ time in the future on a response that otherwise would by default be
+ non-cacheable indicates that the response is cacheable, unless
+ indicated otherwise by a Cache-Control header field (section 14.9).
+
+14.22 From
+
+ The From request-header field, if given, SHOULD contain an Internet
+ e-mail address for the human user who controls the requesting user
+ agent. The address SHOULD be machine-usable, as defined by "mailbox"
+ in <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9] as updated by <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> [8]:
+
+ From = "From" ":" mailbox
+
+ An example is:
+
+ From: <a href="mailto:webmaster@w3.org">webmaster@w3.org</a>
+
+ This header field MAY be used for logging purposes and as a means for
+ identifying the source of invalid or unwanted requests. It SHOULD NOT
+ be used as an insecure form of access protection. The interpretation
+ of this field is that the request is being performed on behalf of the
+ person given, who accepts responsibility for the method performed. In
+ particular, robot agents SHOULD include this header so that the
+ person responsible for running the robot can be contacted if problems
+ occur on the receiving end.
+
+ The Internet e-mail address in this field MAY be separate from the
+ Internet host which issued the request. For example, when a request
+ is passed through a proxy the original issuer's address SHOULD be
+ used.
+
+ The client SHOULD NOT send the From header field without the user's
+ approval, as it might conflict with the user's privacy interests or
+ their site's security policy. It is strongly recommended that the
+ user be able to disable, enable, and modify the value of this field
+ at any time prior to a request.
+
+14.23 Host
+
+ The Host request-header field specifies the Internet host and port
+ number of the resource being requested, as obtained from the original
+ URI given by the user or referring resource (generally an HTTP URL,
+
+ as described in section 3.2.2). The Host field value MUST represent
+ the naming authority of the origin server or gateway given by the
+ original URL. This allows the origin server or gateway to
+ differentiate between internally-ambiguous URLs, such as the root "/"
+ URL of a server for multiple host names on a single IP address.
+
+ Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
+
+ A "host" without any trailing port information implies the default
+ port for the service requested (e.g., "80" for an HTTP URL). For
+ example, a request on the origin server for
+ &lt;<a href="http://www.w3.org/pub/WWW/">http://www.w3.org/pub/WWW/</a>&gt; would properly include:
+
+ GET /pub/WWW/ HTTP/1.1
+ Host: www.w3.org
+
+ A client MUST include a Host header field in all HTTP/1.1 request
+ messages . If the requested URI does not include an Internet host
+ name for the service being requested, then the Host header field MUST
+ be given with an empty value. An HTTP/1.1 proxy MUST ensure that any
+ request message it forwards does contain an appropriate Host header
+ field that identifies the service being requested by the proxy. All
+ Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request)
+ status code to any HTTP/1.1 request message which lacks a Host header
+ field.
+
+ See sections 5.2 and 19.6.1.1 for other requirements relating to
+ Host.
+
+14.24 If-Match
+
+ The If-Match request-header field is used with a method to make it
+ conditional. A client that has one or more entities previously
+ obtained from the resource can verify that one of those entities is
+ current by including a list of their associated entity tags in the
+ If-Match header field. Entity tags are defined in section 3.11. The
+ purpose of this feature is to allow efficient updates of cached
+ information with a minimum amount of transaction overhead. It is also
+ used, on updating requests, to prevent inadvertent modification of
+ the wrong version of a resource. As a special case, the value "*"
+ matches any current entity of the resource.
+
+ If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
+
+ If any of the entity tags match the entity tag of the entity that
+ would have been returned in the response to a similar GET request
+ (without the If-Match header) on that resource, or if "*" is given
+
+ and any current entity exists for that resource, then the server MAY
+ perform the requested method as if the If-Match header field did not
+ exist.
+
+ A server MUST use the strong comparison function (see section 13.3.3)
+ to compare the entity tags in If-Match.
+
+ If none of the entity tags match, or if "*" is given and no current
+ entity exists, the server MUST NOT perform the requested method, and
+ MUST return a 412 (Precondition Failed) response. This behavior is
+ most useful when the client wants to prevent an updating method, such
+ as PUT, from modifying a resource that has changed since the client
+ last retrieved it.
+
+ If the request would, without the If-Match header field, result in
+ anything other than a 2xx or 412 status, then the If-Match header
+ MUST be ignored.
+
+ The meaning of "If-Match: *" is that the method SHOULD be performed
+ if the representation selected by the origin server (or by a cache,
+ possibly using the Vary mechanism, see section 14.44) exists, and
+ MUST NOT be performed if the representation does not exist.
+
+ A request intended to update a resource (e.g., a PUT) MAY include an
+ If-Match header field to signal that the request method MUST NOT be
+ applied if the entity corresponding to the If-Match value (a single
+ entity tag) is no longer a representation of that resource. This
+ allows the user to indicate that they do not wish the request to be
+ successful if the resource has been changed without their knowledge.
+ Examples:
+
+ If-Match: "xyzzy"
+ If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ If-Match: *
+
+ The result of a request having both an If-Match header field and
+ either an If-None-Match or an If-Modified-Since header fields is
+ undefined by this specification.
+
+14.25 If-Modified-Since
+
+ The If-Modified-Since request-header field is used with a method to
+ make it conditional: if the requested variant has not been modified
+ since the time specified in this field, an entity will not be
+ returned from the server; instead, a 304 (not modified) response will
+ be returned without any message-body.
+
+ If-Modified-Since = "If-Modified-Since" ":" HTTP-date
+
+ An example of the field is:
+
+ If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+
+ A GET method with an If-Modified-Since header and no Range header
+ requests that the identified entity be transferred only if it has
+ been modified since the date given by the If-Modified-Since header.
+ The algorithm for determining this includes the following cases:
+
+ a) If the request would normally result in anything other than a
+ 200 (OK) status, or if the passed If-Modified-Since date is
+ invalid, the response is exactly the same as for a normal GET.
+ A date which is later than the server's current time is
+ invalid.
+
+ b) If the variant has been modified since the If-Modified-Since
+ date, the response is exactly the same as for a normal GET.
+
+ c) If the variant has not been modified since a valid If-
+ Modified-Since date, the server SHOULD return a 304 (Not
+ Modified) response.
+
+ The purpose of this feature is to allow efficient updates of cached
+ information with a minimum amount of transaction overhead.
+
+ Note: The Range request-header field modifies the meaning of If-
+ Modified-Since; see section 14.35 for full details.
+
+ Note: If-Modified-Since times are interpreted by the server, whose
+ clock might not be synchronized with the client.
+
+ Note: When handling an If-Modified-Since header field, some
+ servers will use an exact date comparison function, rather than a
+ less-than function, for deciding whether to send a 304 (Not
+ Modified) response. To get best results when sending an If-
+ Modified-Since header field for cache validation, clients are
+ advised to use the exact date string received in a previous Last-
+ Modified header field whenever possible.
+
+ Note: If a client uses an arbitrary date in the If-Modified-Since
+ header instead of a date taken from the Last-Modified header for
+ the same request, the client should be aware of the fact that this
+ date is interpreted in the server's understanding of time. The
+ client should consider unsynchronized clocks and rounding problems
+ due to the different encodings of time between the client and
+ server. This includes the possibility of race conditions if the
+ document has changed between the time it was first requested and
+ the If-Modified-Since date of a subsequent request, and the
+
+ possibility of clock-skew-related problems if the If-Modified-
+ Since date is derived from the client's clock without correction
+ to the server's clock. Corrections for different time bases
+ between client and server are at best approximate due to network
+ latency.
+
+ The result of a request having both an If-Modified-Since header field
+ and either an If-Match or an If-Unmodified-Since header fields is
+ undefined by this specification.
+
+14.26 If-None-Match
+
+ The If-None-Match request-header field is used with a method to make
+ it conditional. A client that has one or more entities previously
+ obtained from the resource can verify that none of those entities is
+ current by including a list of their associated entity tags in the
+ If-None-Match header field. The purpose of this feature is to allow
+ efficient updates of cached information with a minimum amount of
+ transaction overhead. It is also used to prevent a method (e.g. PUT)
+ from inadvertently modifying an existing resource when the client
+ believes that the resource does not exist.
+
+ As a special case, the value "*" matches any current entity of the
+ resource.
+
+ If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
+
+ If any of the entity tags match the entity tag of the entity that
+ would have been returned in the response to a similar GET request
+ (without the If-None-Match header) on that resource, or if "*" is
+ given and any current entity exists for that resource, then the
+ server MUST NOT perform the requested method, unless required to do
+ so because the resource's modification date fails to match that
+ supplied in an If-Modified-Since header field in the request.
+ Instead, if the request method was GET or HEAD, the server SHOULD
+ respond with a 304 (Not Modified) response, including the cache-
+ related header fields (particularly ETag) of one of the entities that
+ matched. For all other request methods, the server MUST respond with
+ a status of 412 (Precondition Failed).
+
+ See section 13.3.3 for rules on how to determine if two entities tags
+ match. The weak comparison function can only be used with GET or HEAD
+ requests.
+
+ If none of the entity tags match, then the server MAY perform the
+ requested method as if the If-None-Match header field did not exist,
+ but MUST also ignore any If-Modified-Since header field(s) in the
+ request. That is, if no entity tags match, then the server MUST NOT
+ return a 304 (Not Modified) response.
+
+ If the request would, without the If-None-Match header field, result
+ in anything other than a 2xx or 304 status, then the If-None-Match
+ header MUST be ignored. (See section 13.3.4 for a discussion of
+ server behavior when both If-Modified-Since and If-None-Match appear
+ in the same request.)
+
+ The meaning of "If-None-Match: *" is that the method MUST NOT be
+ performed if the representation selected by the origin server (or by
+ a cache, possibly using the Vary mechanism, see section 14.44)
+ exists, and SHOULD be performed if the representation does not exist.
+ This feature is intended to be useful in preventing races between PUT
+ operations.
+
+ Examples:
+
+ If-None-Match: "xyzzy"
+ If-None-Match: W/"xyzzy"
+ If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
+ If-None-Match: *
+
+ The result of a request having both an If-None-Match header field and
+ either an If-Match or an If-Unmodified-Since header fields is
+ undefined by this specification.
+
+14.27 If-Range
+
+ If a client has a partial copy of an entity in its cache, and wishes
+ to have an up-to-date copy of the entire entity in its cache, it
+ could use the Range request-header with a conditional GET (using
+ either or both of If-Unmodified-Since and If-Match.) However, if the
+ condition fails because the entity has been modified, the client
+ would then have to make a second request to obtain the entire current
+ entity-body.
+
+ The If-Range header allows a client to "short-circuit" the second
+ request. Informally, its meaning is `if the entity is unchanged, send
+ me the part(s) that I am missing; otherwise, send me the entire new
+ entity'.
+
+ If-Range = "If-Range" ":" ( entity-tag | HTTP-date )
+
+ If the client has no entity tag for an entity, but does have a Last-
+ Modified date, it MAY use that date in an If-Range header. (The
+ server can distinguish between a valid HTTP-date and any form of
+ entity-tag by examining no more than two characters.) The If-Range
+ header SHOULD only be used together with a Range header, and MUST be
+ ignored if the request does not include a Range header, or if the
+ server does not support the sub-range operation.
+
+ If the entity tag given in the If-Range header matches the current
+ entity tag for the entity, then the server SHOULD provide the
+ specified sub-range of the entity using a 206 (Partial content)
+ response. If the entity tag does not match, then the server SHOULD
+ return the entire entity using a 200 (OK) response.
+
+14.28 If-Unmodified-Since
+
+ The If-Unmodified-Since request-header field is used with a method to
+ make it conditional. If the requested resource has not been modified
+ since the time specified in this field, the server SHOULD perform the
+ requested operation as if the If-Unmodified-Since header were not
+ present.
+
+ If the requested variant has been modified since the specified time,
+ the server MUST NOT perform the requested operation, and MUST return
+ a 412 (Precondition Failed).
+
+ If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date
+
+ An example of the field is:
+
+ If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+
+ If the request normally (i.e., without the If-Unmodified-Since
+ header) would result in anything other than a 2xx or 412 status, the
+ If-Unmodified-Since header SHOULD be ignored.
+
+ If the specified date is invalid, the header is ignored.
+
+ The result of a request having both an If-Unmodified-Since header
+ field and either an If-None-Match or an If-Modified-Since header
+ fields is undefined by this specification.
+
+14.29 Last-Modified
+
+ The Last-Modified entity-header field indicates the date and time at
+ which the origin server believes the variant was last modified.
+
+ Last-Modified = "Last-Modified" ":" HTTP-date
+
+ An example of its use is
+
+ Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
+
+ The exact meaning of this header field depends on the implementation
+ of the origin server and the nature of the original resource. For
+ files, it may be just the file system last-modified time. For
+ entities with dynamically included parts, it may be the most recent
+ of the set of last-modify times for its component parts. For database
+ gateways, it may be the last-update time stamp of the record. For
+ virtual objects, it may be the last time the internal state changed.
+
+ An origin server MUST NOT send a Last-Modified date which is later
+ than the server's time of message origination. In such cases, where
+ the resource's last modification would indicate some time in the
+ future, the server MUST replace that date with the message
+ origination date.
+
+ An origin server SHOULD obtain the Last-Modified value of the entity
+ as close as possible to the time that it generates the Date value of
+ its response. This allows a recipient to make an accurate assessment
+ of the entity's modification time, especially if the entity changes
+ near the time that the response is generated.
+
+ HTTP/1.1 servers SHOULD send Last-Modified whenever feasible.
+
+14.30 Location
+
+ The Location response-header field is used to redirect the recipient
+ to a location other than the Request-URI for completion of the
+ request or identification of a new resource. For 201 (Created)
+ responses, the Location is that of the new resource which was created
+ by the request. For 3xx responses, the location SHOULD indicate the
+ server's preferred URI for automatic redirection to the resource. The
+ field value consists of a single absolute URI.
+
+ Location = "Location" ":" absoluteURI
+
+ An example is:
+
+ Location: <a href="http://www.w3.org/pub/WWW/People.html">http://www.w3.org/pub/WWW/People.html</a>
+
+ Note: The Content-Location header field (section 14.14) differs
+ from Location in that the Content-Location identifies the original
+ location of the entity enclosed in the request. It is therefore
+ possible for a response to contain header fields for both Location
+ and Content-Location. Also see section 13.10 for cache
+ requirements of some methods.
+
+14.31 Max-Forwards
+
+ The Max-Forwards request-header field provides a mechanism with the
+ TRACE (section 9.8) and OPTIONS (section 9.2) methods to limit the
+ number of proxies or gateways that can forward the request to the
+ next inbound server. This can be useful when the client is attempting
+ to trace a request chain which appears to be failing or looping in
+ mid-chain.
+
+ Max-Forwards = "Max-Forwards" ":" 1*DIGIT
+
+ The Max-Forwards value is a decimal integer indicating the remaining
+ number of times this request message may be forwarded.
+
+ Each proxy or gateway recipient of a TRACE or OPTIONS request
+ containing a Max-Forwards header field MUST check and update its
+ value prior to forwarding the request. If the received value is zero
+ (0), the recipient MUST NOT forward the request; instead, it MUST
+ respond as the final recipient. If the received Max-Forwards value is
+ greater than zero, then the forwarded message MUST contain an updated
+ Max-Forwards field with a value decremented by one (1).
+
+ The Max-Forwards header field MAY be ignored for all other methods
+ defined by this specification and for any extension methods for which
+ it is not explicitly referred to as part of that method definition.
+
+14.32 Pragma
+
+ The Pragma general-header field is used to include implementation-
+ specific directives that might apply to any recipient along the
+ request/response chain. All pragma directives specify optional
+ behavior from the viewpoint of the protocol; however, some systems
+ MAY require that behavior be consistent with the directives.
+
+ Pragma = "Pragma" ":" 1#pragma-directive
+ pragma-directive = "no-cache" | extension-pragma
+ extension-pragma = token [ "=" ( token | quoted-string ) ]
+
+ When the no-cache directive is present in a request message, an
+ application SHOULD forward the request toward the origin server even
+ if it has a cached copy of what is being requested. This pragma
+ directive has the same semantics as the no-cache cache-directive (see
+ section 14.9) and is defined here for backward compatibility with
+ HTTP/1.0. Clients SHOULD include both header fields when a no-cache
+ request is sent to a server not known to be HTTP/1.1 compliant.
+
+ Pragma directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application,
+ since the directives might be applicable to all recipients along the
+ request/response chain. It is not possible to specify a pragma for a
+ specific recipient; however, any pragma directive not relevant to a
+ recipient SHOULD be ignored by that recipient.
+
+ HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client had
+ sent "Cache-Control: no-cache". No new Pragma directives will be
+ defined in HTTP.
+
+ Note: because the meaning of "Pragma: no-cache as a response
+ header field is not actually specified, it does not provide a
+ reliable replacement for "Cache-Control: no-cache" in a response
+
+14.33 Proxy-Authenticate
+
+ The Proxy-Authenticate response-header field MUST be included as part
+ of a 407 (Proxy Authentication Required) response. The field value
+ consists of a challenge that indicates the authentication scheme and
+ parameters applicable to the proxy for this Request-URI.
+
+ Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. Unlike
+ WWW-Authenticate, the Proxy-Authenticate header field applies only to
+ the current connection and SHOULD NOT be passed on to downstream
+ clients. However, an intermediate proxy might need to obtain its own
+ credentials by requesting them from the downstream client, which in
+ some circumstances will appear as if the proxy is forwarding the
+ Proxy-Authenticate header field.
+
+14.34 Proxy-Authorization
+
+ The Proxy-Authorization request-header field allows the client to
+ identify itself (or its user) to a proxy which requires
+ authentication. The Proxy-Authorization field value consists of
+ credentials containing the authentication information of the user
+ agent for the proxy and/or realm of the resource being requested.
+
+ Proxy-Authorization = "Proxy-Authorization" ":" credentials
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43] . Unlike
+ Authorization, the Proxy-Authorization header field applies only to
+ the next outbound proxy that demanded authentication using the Proxy-
+ Authenticate field. When multiple proxies are used in a chain, the
+
+ Proxy-Authorization header field is consumed by the first outbound
+ proxy that was expecting to receive credentials. A proxy MAY relay
+ the credentials from the client request to the next proxy if that is
+ the mechanism by which the proxies cooperatively authenticate a given
+ request.
+
+14.35 Range
+
+14.35.1 Byte Ranges
+
+ Since all HTTP entities are represented in HTTP messages as sequences
+ of bytes, the concept of a byte range is meaningful for any HTTP
+ entity. (However, not all clients and servers need to support byte-
+ range operations.)
+
+ Byte range specifications in HTTP apply to the sequence of bytes in
+ the entity-body (not necessarily the same as the message-body).
+
+ A byte range operation MAY specify a single range of bytes, or a set
+ of ranges within a single entity.
+
+ ranges-specifier = byte-ranges-specifier
+ byte-ranges-specifier = bytes-unit "=" byte-range-set
+ byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
+ byte-range-spec = first-byte-pos "-" [last-byte-pos]
+ first-byte-pos = 1*DIGIT
+ last-byte-pos = 1*DIGIT
+
+ The first-byte-pos value in a byte-range-spec gives the byte-offset
+ of the first byte in a range. The last-byte-pos value gives the
+ byte-offset of the last byte in the range; that is, the byte
+ positions specified are inclusive. Byte offsets start at zero.
+
+ If the last-byte-pos value is present, it MUST be greater than or
+ equal to the first-byte-pos in that byte-range-spec, or the byte-
+ range-spec is syntactically invalid. The recipient of a byte-range-
+ set that includes one or more syntactically invalid byte-range-spec
+ values MUST ignore the header field that includes that byte-range-
+ set.
+
+ If the last-byte-pos value is absent, or if the value is greater than
+ or equal to the current length of the entity-body, last-byte-pos is
+ taken to be equal to one less than the current length of the entity-
+ body in bytes.
+
+ By its choice of last-byte-pos, a client can limit the number of
+ bytes retrieved without knowing the size of the entity.
+
+ suffix-byte-range-spec = "-" suffix-length
+ suffix-length = 1*DIGIT
+
+ A suffix-byte-range-spec is used to specify the suffix of the
+ entity-body, of a length given by the suffix-length value. (That is,
+ this form specifies the last N bytes of an entity-body.) If the
+ entity is shorter than the specified suffix-length, the entire
+ entity-body is used.
+
+ If a syntactically valid byte-range-set includes at least one byte-
+ range-spec whose first-byte-pos is less than the current length of
+ the entity-body, or at least one suffix-byte-range-spec with a non-
+ zero suffix-length, then the byte-range-set is satisfiable.
+ Otherwise, the byte-range-set is unsatisfiable. If the byte-range-set
+ is unsatisfiable, the server SHOULD return a response with a status
+ of 416 (Requested range not satisfiable). Otherwise, the server
+ SHOULD return a response with a status of 206 (Partial Content)
+ containing the satisfiable ranges of the entity-body.
+
+ Examples of byte-ranges-specifier values (assuming an entity-body of
+ length 10000):
+
+ - The first 500 bytes (byte offsets 0-499, inclusive): bytes=0-
+ 499
+
+ - The second 500 bytes (byte offsets 500-999, inclusive):
+ bytes=500-999
+
+ - The final 500 bytes (byte offsets 9500-9999, inclusive):
+ bytes=-500
+
+ - Or bytes=9500-
+
+ - The first and last bytes only (bytes 0 and 9999): bytes=0-0,-1
+
+ - Several legal but not canonical specifications of the second 500
+ bytes (byte offsets 500-999, inclusive):
+ bytes=500-600,601-999
+ bytes=500-700,601-999
+
+14.35.2 Range Retrieval Requests
+
+ HTTP retrieval requests using conditional or unconditional GET
+ methods MAY request one or more sub-ranges of the entity, instead of
+ the entire entity, using the Range request header, which applies to
+ the entity returned as the result of the request:
+
+ Range = "Range" ":" ranges-specifier
+
+ A server MAY ignore the Range header. However, HTTP/1.1 origin
+ servers and intermediate caches ought to support byte ranges when
+ possible, since Range supports efficient recovery from partially
+ failed transfers, and supports efficient partial retrieval of large
+ entities.
+
+ If the server supports the Range header and the specified range or
+ ranges are appropriate for the entity:
+
+ - The presence of a Range header in an unconditional GET modifies
+ what is returned if the GET is otherwise successful. In other
+ words, the response carries a status code of 206 (Partial
+ Content) instead of 200 (OK).
+
+ - The presence of a Range header in a conditional GET (a request
+ using one or both of If-Modified-Since and If-None-Match, or
+ one or both of If-Unmodified-Since and If-Match) modifies what
+ is returned if the GET is otherwise successful and the
+ condition is true. It does not affect the 304 (Not Modified)
+ response returned if the conditional is false.
+
+ In some cases, it might be more appropriate to use the If-Range
+ header (see section 14.27) in addition to the Range header.
+
+ If a proxy that supports ranges receives a Range request, forwards
+ the request to an inbound server, and receives an entire entity in
+ reply, it SHOULD only return the requested range to its client. It
+ SHOULD store the entire received response in its cache if that is
+ consistent with its cache allocation policies.
+
+14.36 Referer
+
+ The Referer[sic] request-header field allows the client to specify,
+ for the server's benefit, the address (URI) of the resource from
+ which the Request-URI was obtained (the "referrer", although the
+ header field is misspelled.) The Referer request-header allows a
+ server to generate lists of back-links to resources for interest,
+ logging, optimized caching, etc. It also allows obsolete or mistyped
+ links to be traced for maintenance. The Referer field MUST NOT be
+ sent if the Request-URI was obtained from a source that does not have
+ its own URI, such as input from the user keyboard.
+
+ Referer = "Referer" ":" ( absoluteURI | relativeURI )
+
+ Example:
+
+ Referer: <a href="http://www.w3.org/hypertext/DataSources/Overview.html">http://www.w3.org/hypertext/DataSources/Overview.html</a>
+
+ If the field value is a relative URI, it SHOULD be interpreted
+ relative to the Request-URI. The URI MUST NOT include a fragment. See
+ section 15.1.3 for security considerations.
+
+14.37 Retry-After
+
+ The Retry-After response-header field can be used with a 503 (Service
+ Unavailable) response to indicate how long the service is expected to
+ be unavailable to the requesting client. This field MAY also be used
+ with any 3xx (Redirection) response to indicate the minimum time the
+ user-agent is asked wait before issuing the redirected request. The
+ value of this field can be either an HTTP-date or an integer number
+ of seconds (in decimal) after the time of the response.
+
+ Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
+
+ Two examples of its use are
+
+ Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+ Retry-After: 120
+
+ In the latter example, the delay is 2 minutes.
+
+14.38 Server
+
+ The Server response-header field contains information about the
+ software used by the origin server to handle the request. The field
+ can contain multiple product tokens (section 3.8) and comments
+ identifying the server and any significant subproducts. The product
+ tokens are listed in order of their significance for identifying the
+ application.
+
+ Server = "Server" ":" 1*( product | comment )
+
+ Example:
+
+ Server: CERN/3.0 libwww/2.17
+
+ If the response is being forwarded through a proxy, the proxy
+ application MUST NOT modify the Server response-header. Instead, it
+ SHOULD include a Via field (as described in section 14.45).
+
+ Note: Revealing the specific software version of the server might
+ allow the server machine to become more vulnerable to attacks
+ against software that is known to contain security holes. Server
+ implementors are encouraged to make this field a configurable
+ option.
+
+14.39 TE
+
+ The TE request-header field indicates what extension transfer-codings
+ it is willing to accept in the response and whether or not it is
+ willing to accept trailer fields in a chunked transfer-coding. Its
+ value may consist of the keyword "trailers" and/or a comma-separated
+ list of extension transfer-coding names with optional accept
+ parameters (as described in section 3.6).
+
+ TE = "TE" ":" #( t-codings )
+ t-codings = "trailers" | ( transfer-extension [ accept-params ] )
+
+ The presence of the keyword "trailers" indicates that the client is
+ willing to accept trailer fields in a chunked transfer-coding, as
+ defined in section 3.6.1. This keyword is reserved for use with
+ transfer-coding values even though it does not itself represent a
+ transfer-coding.
+
+ Examples of its use are:
+
+ TE: deflate
+ TE:
+ TE: trailers, deflate;q=0.5
+
+ The TE header field only applies to the immediate connection.
+ Therefore, the keyword MUST be supplied within a Connection header
+ field (section 14.10) whenever TE is present in an HTTP/1.1 message.
+
+ A server tests whether a transfer-coding is acceptable, according to
+ a TE field, using these rules:
+
+ 1. The "chunked" transfer-coding is always acceptable. If the
+ keyword "trailers" is listed, the client indicates that it is
+ willing to accept trailer fields in the chunked response on
+ behalf of itself and any downstream clients. The implication is
+ that, if given, the client is stating that either all
+ downstream clients are willing to accept trailer fields in the
+ forwarded response, or that it will attempt to buffer the
+ response on behalf of downstream recipients.
+
+ Note: HTTP/1.1 does not define any means to limit the size of a
+ chunked response such that a client can be assured of buffering
+ the entire response.
+
+ 2. If the transfer-coding being tested is one of the transfer-
+ codings listed in the TE field, then it is acceptable unless it
+ is accompanied by a qvalue of 0. (As defined in section 3.9, a
+ qvalue of 0 means "not acceptable.")
+
+ 3. If multiple transfer-codings are acceptable, then the
+ acceptable transfer-coding with the highest non-zero qvalue is
+ preferred. The "chunked" transfer-coding always has a qvalue
+ of 1.
+
+ If the TE field-value is empty or if no TE field is present, the only
+ transfer-coding is "chunked". A message with no transfer-coding is
+ always acceptable.
+
+14.40 Trailer
+
+ The Trailer general field value indicates that the given set of
+ header fields is present in the trailer of a message encoded with
+ chunked transfer-coding.
+
+ Trailer = "Trailer" ":" 1#field-name
+
+ An HTTP/1.1 message SHOULD include a Trailer header field in a
+ message using chunked transfer-coding with a non-empty trailer. Doing
+ so allows the recipient to know which header fields to expect in the
+ trailer.
+
+ If no Trailer header field is present, the trailer SHOULD NOT include
+ any header fields. See section 3.6.1 for restrictions on the use of
+ trailer fields in a "chunked" transfer-coding.
+
+ Message header fields listed in the Trailer header field MUST NOT
+ include the following header fields:
+
+ . Transfer-Encoding
+
+ . Content-Length
+
+ . Trailer
+
+14.41 Transfer-Encoding
+
+ The Transfer-Encoding general-header field indicates what (if any)
+ type of transformation has been applied to the message body in order
+ to safely transfer it between the sender and the recipient. This
+ differs from the content-coding in that the transfer-coding is a
+ property of the message, not of the entity.
+
+ Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
+
+ Transfer-codings are defined in section 3.6. An example is:
+
+ Transfer-Encoding: chunked
+
+ If multiple encodings have been applied to an entity, the transfer-
+ codings MUST be listed in the order in which they were applied.
+ Additional information about the encoding parameters MAY be provided
+ by other entity-header fields not defined by this specification.
+
+ Many older HTTP/1.0 applications do not understand the Transfer-
+ Encoding header.
+
+14.42 Upgrade
+
+ The Upgrade general-header allows the client to specify what
+ additional communication protocols it supports and would like to use
+ if the server finds it appropriate to switch protocols. The server
+ MUST use the Upgrade header field within a 101 (Switching Protocols)
+ response to indicate which protocol(s) are being switched.
+
+ Upgrade = "Upgrade" ":" 1#product
+
+ For example,
+
+ Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
+
+ The Upgrade header field is intended to provide a simple mechanism
+ for transition from HTTP/1.1 to some other, incompatible protocol. It
+ does so by allowing the client to advertise its desire to use another
+ protocol, such as a later version of HTTP with a higher major version
+ number, even though the current request has been made using HTTP/1.1.
+ This eases the difficult transition between incompatible protocols by
+ allowing the client to initiate a request in the more commonly
+ supported protocol while indicating to the server that it would like
+ to use a "better" protocol if available (where "better" is determined
+ by the server, possibly according to the nature of the method and/or
+ resource being requested).
+
+ The Upgrade header field only applies to switching application-layer
+ protocols upon the existing transport-layer connection. Upgrade
+ cannot be used to insist on a protocol change; its acceptance and use
+ by the server is optional. The capabilities and nature of the
+ application-layer communication after the protocol change is entirely
+ dependent upon the new protocol chosen, although the first action
+ after changing the protocol MUST be a response to the initial HTTP
+ request containing the Upgrade header field.
+
+ The Upgrade header field only applies to the immediate connection.
+ Therefore, the upgrade keyword MUST be supplied within a Connection
+ header field (section 14.10) whenever Upgrade is present in an
+ HTTP/1.1 message.
+
+ The Upgrade header field cannot be used to indicate a switch to a
+ protocol on a different connection. For that purpose, it is more
+ appropriate to use a 301, 302, 303, or 305 redirection response.
+
+ This specification only defines the protocol name "HTTP" for use by
+ the family of Hypertext Transfer Protocols, as defined by the HTTP
+ version rules of section 3.1 and future updates to this
+ specification. Any token can be used as a protocol name; however, it
+ will only be useful if both the client and server associate the name
+ with the same protocol.
+
+14.43 User-Agent
+
+ The User-Agent request-header field contains information about the
+ user agent originating the request. This is for statistical purposes,
+ the tracing of protocol violations, and automated recognition of user
+ agents for the sake of tailoring responses to avoid particular user
+ agent limitations. User agents SHOULD include this field with
+ requests. The field can contain multiple product tokens (section 3.8)
+ and comments identifying the agent and any subproducts which form a
+ significant part of the user agent. By convention, the product tokens
+ are listed in order of their significance for identifying the
+ application.
+
+ User-Agent = "User-Agent" ":" 1*( product | comment )
+
+ Example:
+
+ User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+
+14.44 Vary
+
+ The Vary field value indicates the set of request-header fields that
+ fully determines, while the response is fresh, whether a cache is
+ permitted to use the response to reply to a subsequent request
+ without revalidation. For uncacheable or stale responses, the Vary
+ field value advises the user agent about the criteria that were used
+ to select the representation. A Vary field value of "*" implies that
+ a cache cannot determine from the request headers of a subsequent
+ request whether this response is the appropriate representation. See
+ section 13.6 for use of the Vary header field by caches.
+
+ Vary = "Vary" ":" ( "*" | 1#field-name )
+
+ An HTTP/1.1 server SHOULD include a Vary header field with any
+ cacheable response that is subject to server-driven negotiation.
+ Doing so allows a cache to properly interpret future requests on that
+ resource and informs the user agent about the presence of negotiation
+
+ on that resource. A server MAY include a Vary header field with a
+ non-cacheable response that is subject to server-driven negotiation,
+ since this might provide the user agent with useful information about
+ the dimensions over which the response varies at the time of the
+ response.
+
+ A Vary field value consisting of a list of field-names signals that
+ the representation selected for the response is based on a selection
+ algorithm which considers ONLY the listed request-header field values
+ in selecting the most appropriate representation. A cache MAY assume
+ that the same selection will be made for future requests with the
+ same values for the listed field names, for the duration of time for
+ which the response is fresh.
+
+ The field-names given are not limited to the set of standard
+ request-header fields defined by this specification. Field names are
+ case-insensitive.
+
+ A Vary field value of "*" signals that unspecified parameters not
+ limited to the request-headers (e.g., the network address of the
+ client), play a role in the selection of the response representation.
+ The "*" value MUST NOT be generated by a proxy server; it may only be
+ generated by an origin server.
+
+14.45 Via
+
+ The Via general-header field MUST be used by gateways and proxies to
+ indicate the intermediate protocols and recipients between the user
+ agent and the server on requests, and between the origin server and
+ the client on responses. It is analogous to the "Received" field of
+ <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9] and is intended to be used for tracking message forwards,
+ avoiding request loops, and identifying the protocol capabilities of
+ all senders along the request/response chain.
+
+ Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
+ received-protocol = [ protocol-name "/" ] protocol-version
+ protocol-name = token
+ protocol-version = token
+ received-by = ( host [ ":" port ] ) | pseudonym
+ pseudonym = token
+
+ The received-protocol indicates the protocol version of the message
+ received by the server or client along each segment of the
+ request/response chain. The received-protocol version is appended to
+ the Via field value when the message is forwarded so that information
+ about the protocol capabilities of upstream applications remains
+ visible to all recipients.
+
+ The protocol-name is optional if and only if it would be "HTTP". The
+ received-by field is normally the host and optional port number of a
+ recipient server or client that subsequently forwarded the message.
+ However, if the real host is considered to be sensitive information,
+ it MAY be replaced by a pseudonym. If the port is not given, it MAY
+ be assumed to be the default port of the received-protocol.
+
+ Multiple Via field values represents each proxy or gateway that has
+ forwarded the message. Each recipient MUST append its information
+ such that the end result is ordered according to the sequence of
+ forwarding applications.
+
+ Comments MAY be used in the Via header field to identify the software
+ of the recipient proxy or gateway, analogous to the User-Agent and
+ Server header fields. However, all comments in the Via field are
+ optional and MAY be removed by any recipient prior to forwarding the
+ message.
+
+ For example, a request message could be sent from an HTTP/1.0 user
+ agent to an internal proxy code-named "fred", which uses HTTP/1.1 to
+ forward the request to a public proxy at nowhere.com, which completes
+ the request by forwarding it to the origin server at www.ics.uci.edu.
+ The request received by www.ics.uci.edu would then have the following
+ Via header field:
+
+ Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
+
+ Proxies and gateways used as a portal through a network firewall
+ SHOULD NOT, by default, forward the names and ports of hosts within
+ the firewall region. This information SHOULD only be propagated if
+ explicitly enabled. If not enabled, the received-by host of any host
+ behind the firewall SHOULD be replaced by an appropriate pseudonym
+ for that host.
+
+ For organizations that have strong privacy requirements for hiding
+ internal structures, a proxy MAY combine an ordered subsequence of
+ Via header field entries with identical received-protocol values into
+ a single such entry. For example,
+
+ Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
+
+ could be collapsed to
+
+ Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
+
+ Applications SHOULD NOT combine multiple entries unless they are all
+ under the same organizational control and the hosts have already been
+ replaced by pseudonyms. Applications MUST NOT combine entries which
+ have different received-protocol values.
+
+14.46 Warning
+
+ The Warning general-header field is used to carry additional
+ information about the status or transformation of a message which
+ might not be reflected in the message. This information is typically
+ used to warn about a possible lack of semantic transparency from
+ caching operations or transformations applied to the entity body of
+ the message.
+
+ Warning headers are sent with responses using:
+
+ Warning = "Warning" ":" 1#warning-value
+
+ warning-value = warn-code SP warn-agent SP warn-text
+ [SP warn-date]
+
+ warn-code = 3DIGIT
+ warn-agent = ( host [ ":" port ] ) | pseudonym
+ ; the name or pseudonym of the server adding
+ ; the Warning header, for use in debugging
+ warn-text = quoted-string
+ warn-date = &lt;"&gt; HTTP-date &lt;"&gt;
+
+ A response MAY carry more than one Warning header.
+
+ The warn-text SHOULD be in a natural language and character set that
+ is most likely to be intelligible to the human user receiving the
+ response. This decision MAY be based on any available knowledge, such
+ as the location of the cache or user, the Accept-Language field in a
+ request, the Content-Language field in a response, etc. The default
+ language is English and the default character set is ISO-8859-1.
+
+ If a character set other than ISO-8859-1 is used, it MUST be encoded
+ in the warn-text using the method described in <a href="http://firefly.troll.no/rfcs/rfc2047.html">RFC 2047</a> [14].
+
+ Warning headers can in general be applied to any message, however
+ some specific warn-codes are specific to caches and can only be
+ applied to response messages. New Warning headers SHOULD be added
+ after any existing Warning headers. A cache MUST NOT delete any
+ Warning header that it received with a message. However, if a cache
+ successfully validates a cache entry, it SHOULD remove any Warning
+ headers previously attached to that entry except as specified for
+
+ specific Warning codes. It MUST then add any Warning headers received
+ in the validating response. In other words, Warning headers are those
+ that would be attached to the most recent relevant response.
+
+ When multiple Warning headers are attached to a response, the user
+ agent ought to inform the user of as many of them as possible, in the
+ order that they appear in the response. If it is not possible to
+ inform the user of all of the warnings, the user agent SHOULD follow
+ these heuristics:
+
+ - Warnings that appear early in the response take priority over
+ those appearing later in the response.
+
+ - Warnings in the user's preferred character set take priority
+ over warnings in other character sets but with identical warn-
+ codes and warn-agents.
+
+ Systems that generate multiple Warning headers SHOULD order them with
+ this user agent behavior in mind.
+
+ Requirements for the behavior of caches with respect to Warnings are
+ stated in section 13.1.2.
+
+ This is a list of the currently-defined warn-codes, each with a
+ recommended warn-text in English, and a description of its meaning.
+
+ 110 Response is stale
+ MUST be included whenever the returned response is stale.
+
+ 111 Revalidation failed
+ MUST be included if a cache returns a stale response because an
+ attempt to revalidate the response failed, due to an inability to
+ reach the server.
+
+ 112 Disconnected operation
+ SHOULD be included if the cache is intentionally disconnected from
+ the rest of the network for a period of time.
+
+ 113 Heuristic expiration
+ MUST be included if the cache heuristically chose a freshness
+ lifetime greater than 24 hours and the response's age is greater
+ than 24 hours.
+
+ 199 Miscellaneous warning
+ The warning text MAY include arbitrary information to be presented
+ to a human user, or logged. A system receiving this warning MUST
+ NOT take any automated action, besides presenting the warning to
+ the user.
+
+ 214 Transformation applied
+ MUST be added by an intermediate cache or proxy if it applies any
+ transformation changing the content-coding (as specified in the
+ Content-Encoding header) or media-type (as specified in the
+ Content-Type header) of the response, or the entity-body of the
+ response, unless this Warning code already appears in the response.
+
+ 299 Miscellaneous persistent warning
+ The warning text MAY include arbitrary information to be presented
+ to a human user, or logged. A system receiving this warning MUST
+ NOT take any automated action.
+
+ If an implementation sends a message with one or more Warning headers
+ whose version is HTTP/1.0 or lower, then the sender MUST include in
+ each warning-value a warn-date that matches the date in the response.
+
+ If an implementation receives a message with a warning-value that
+ includes a warn-date, and that warn-date is different from the Date
+ value in the response, then that warning-value MUST be deleted from
+ the message before storing, forwarding, or using it. (This prevents
+ bad consequences of naive caching of Warning header fields.) If all
+ of the warning-values are deleted for this reason, the Warning header
+ MUST be deleted as well.
+
+14.47 WWW-Authenticate
+
+ The WWW-Authenticate response-header field MUST be included in 401
+ (Unauthorized) response messages. The field value consists of at
+ least one challenge that indicates the authentication scheme(s) and
+ parameters applicable to the Request-URI.
+
+ WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. User
+ agents are advised to take special care in parsing the WWW-
+ Authenticate field value as it might contain more than one challenge,
+ or if more than one WWW-Authenticate header field is provided, the
+ contents of a challenge itself can contain a comma-separated list of
+ authentication parameters.
+
+15 Security Considerations
+
+ This section is meant to inform application developers, information
+ providers, and users of the security limitations in HTTP/1.1 as
+ described by this document. The discussion does not include
+ definitive solutions to the problems revealed, though it does make
+ some suggestions for reducing security risks.
+
+15.1 Personal Information
+
+ HTTP clients are often privy to large amounts of personal information
+ (e.g. the user's name, location, mail address, passwords, encryption
+ keys, etc.), and SHOULD be very careful to prevent unintentional
+ leakage of this information via the HTTP protocol to other sources.
+ We very strongly recommend that a convenient interface be provided
+ for the user to control dissemination of such information, and that
+ designers and implementors be particularly careful in this area.
+ History shows that errors in this area often create serious security
+ and/or privacy problems and generate highly adverse publicity for the
+ implementor's company.
+
+15.1.1 Abuse of Server Log Information
+
+ A server is in the position to save personal data about a user's
+ requests which might identify their reading patterns or subjects of
+ interest. This information is clearly confidential in nature and its
+ handling can be constrained by law in certain countries. People using
+ the HTTP protocol to provide data are responsible for ensuring that
+ such material is not distributed without the permission of any
+ individuals that are identifiable by the published results.
+
+15.1.2 Transfer of Sensitive Information
+
+ Like any generic data transfer protocol, HTTP cannot regulate the
+ content of the data that is transferred, nor is there any a priori
+ method of determining the sensitivity of any particular piece of
+ information within the context of any given request. Therefore,
+ applications SHOULD supply as much control over this information as
+ possible to the provider of that information. Four header fields are
+ worth special mention in this context: Server, Via, Referer and From.
+
+ Revealing the specific software version of the server might allow the
+ server machine to become more vulnerable to attacks against software
+ that is known to contain security holes. Implementors SHOULD make the
+ Server header field a configurable option.
+
+ Proxies which serve as a portal through a network firewall SHOULD
+ take special precautions regarding the transfer of header information
+ that identifies the hosts behind the firewall. In particular, they
+ SHOULD remove, or replace with sanitized versions, any Via fields
+ generated behind the firewall.
+
+ The Referer header allows reading patterns to be studied and reverse
+ links drawn. Although it can be very useful, its power can be abused
+ if user details are not separated from the information contained in
+
+ the Referer. Even when the personal information has been removed, the
+ Referer header might indicate a private document's URI whose
+ publication would be inappropriate.
+
+ The information sent in the From field might conflict with the user's
+ privacy interests or their site's security policy, and hence it
+ SHOULD NOT be transmitted without the user being able to disable,
+ enable, and modify the contents of the field. The user MUST be able
+ to set the contents of this field within a user preference or
+ application defaults configuration.
+
+ We suggest, though do not require, that a convenient toggle interface
+ be provided for the user to enable or disable the sending of From and
+ Referer information.
+
+ The User-Agent (section 14.43) or Server (section 14.38) header
+ fields can sometimes be used to determine that a specific client or
+ server have a particular security hole which might be exploited.
+ Unfortunately, this same information is often used for other valuable
+ purposes for which HTTP currently has no better mechanism.
+
+15.1.3 Encoding Sensitive Information in URI's
+
+ Because the source of a link might be private information or might
+ reveal an otherwise private information source, it is strongly
+ recommended that the user be able to select whether or not the
+ Referer field is sent. For example, a browser client could have a
+ toggle switch for browsing openly/anonymously, which would
+ respectively enable/disable the sending of Referer and From
+ information.
+
+ Clients SHOULD NOT include a Referer header field in a (non-secure)
+ HTTP request if the referring page was transferred with a secure
+ protocol.
+
+ Authors of services which use the HTTP protocol SHOULD NOT use GET
+ based forms for the submission of sensitive data, because this will
+ cause this data to be encoded in the Request-URI. Many existing
+ servers, proxies, and user agents will log the request URI in some
+ place where it might be visible to third parties. Servers can use
+ POST-based form submission instead
+
+15.1.4 Privacy Issues Connected to Accept Headers
+
+ Accept request-headers can reveal information about the user to all
+ servers which are accessed. The Accept-Language header in particular
+ can reveal information the user would consider to be of a private
+ nature, because the understanding of particular languages is often
+
+ strongly correlated to the membership of a particular ethnic group.
+ User agents which offer the option to configure the contents of an
+ Accept-Language header to be sent in every request are strongly
+ encouraged to let the configuration process include a message which
+ makes the user aware of the loss of privacy involved.
+
+ An approach that limits the loss of privacy would be for a user agent
+ to omit the sending of Accept-Language headers by default, and to ask
+ the user whether or not to start sending Accept-Language headers to a
+ server if it detects, by looking for any Vary response-header fields
+ generated by the server, that such sending could improve the quality
+ of service.
+
+ Elaborate user-customized accept header fields sent in every request,
+ in particular if these include quality values, can be used by servers
+ as relatively reliable and long-lived user identifiers. Such user
+ identifiers would allow content providers to do click-trail tracking,
+ and would allow collaborating content providers to match cross-server
+ click-trails or form submissions of individual users. Note that for
+ many users not behind a proxy, the network address of the host
+ running the user agent will also serve as a long-lived user
+ identifier. In environments where proxies are used to enhance
+ privacy, user agents ought to be conservative in offering accept
+ header configuration options to end users. As an extreme privacy
+ measure, proxies could filter the accept headers in relayed requests.
+ General purpose user agents which provide a high degree of header
+ configurability SHOULD warn users about the loss of privacy which can
+ be involved.
+
+15.2 Attacks Based On File and Path Names
+
+ Implementations of HTTP origin servers SHOULD be careful to restrict
+ the documents returned by HTTP requests to be only those that were
+ intended by the server administrators. If an HTTP server translates
+ HTTP URIs directly into file system calls, the server MUST take
+ special care not to serve files that were not intended to be
+ delivered to HTTP clients. For example, UNIX, Microsoft Windows, and
+ other operating systems use ".." as a path component to indicate a
+ directory level above the current one. On such a system, an HTTP
+ server MUST disallow any such construct in the Request-URI if it
+ would otherwise allow access to a resource outside those intended to
+ be accessible via the HTTP server. Similarly, files intended for
+ reference only internally to the server (such as access control
+ files, configuration files, and script code) MUST be protected from
+ inappropriate retrieval, since they might contain sensitive
+ information. Experience has shown that minor bugs in such HTTP server
+ implementations have turned into security risks.
+
+15.3 DNS Spoofing
+
+ Clients using HTTP rely heavily on the Domain Name Service, and are
+ thus generally prone to security attacks based on the deliberate
+ mis-association of IP addresses and DNS names. Clients need to be
+ cautious in assuming the continuing validity of an IP number/DNS name
+ association.
+
+ In particular, HTTP clients SHOULD rely on their name resolver for
+ confirmation of an IP number/DNS name association, rather than
+ caching the result of previous host name lookups. Many platforms
+ already can cache host name lookups locally when appropriate, and
+ they SHOULD be configured to do so. It is proper for these lookups to
+ be cached, however, only when the TTL (Time To Live) information
+ reported by the name server makes it likely that the cached
+ information will remain useful.
+
+ If HTTP clients cache the results of host name lookups in order to
+ achieve a performance improvement, they MUST observe the TTL
+ information reported by DNS.
+
+ If HTTP clients do not observe this rule, they could be spoofed when
+ a previously-accessed server's IP address changes. As network
+ renumbering is expected to become increasingly common [24], the
+ possibility of this form of attack will grow. Observing this
+ requirement thus reduces this potential security vulnerability.
+
+ This requirement also improves the load-balancing behavior of clients
+ for replicated servers using the same DNS name and reduces the
+ likelihood of a user's experiencing failure in accessing sites which
+ use that strategy.
+
+15.4 Location Headers and Spoofing
+
+ If a single server supports multiple organizations that do not trust
+ one another, then it MUST check the values of Location and Content-
+ Location headers in responses that are generated under control of
+ said organizations to make sure that they do not attempt to
+ invalidate resources over which they have no authority.
+
+15.5 Content-Disposition Issues
+
+ <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a> [35], from which the often implemented Content-Disposition
+ (see section 19.5.1) header in HTTP is derived, has a number of very
+ serious security considerations. Content-Disposition is not part of
+ the HTTP standard, but since it is widely implemented, we are
+ documenting its use and risks for implementors. See <a href="http://firefly.troll.no/rfcs/rfc2183.html">RFC 2183</a> [49]
+ (which updates <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a>) for details.
+
+15.6 Authentication Credentials and Idle Clients
+
+ Existing HTTP clients and user agents typically retain authentication
+ information indefinitely. HTTP/1.1. does not provide a method for a
+ server to direct clients to discard these cached credentials. This is
+ a significant defect that requires further extensions to HTTP.
+ Circumstances under which credential caching can interfere with the
+ application's security model include but are not limited to:
+
+ - Clients which have been idle for an extended period following
+ which the server might wish to cause the client to reprompt the
+ user for credentials.
+
+ - Applications which include a session termination indication
+ (such as a `logout' or `commit' button on a page) after which
+ the server side of the application `knows' that there is no
+ further reason for the client to retain the credentials.
+
+ This is currently under separate study. There are a number of work-
+ arounds to parts of this problem, and we encourage the use of
+ password protection in screen savers, idle time-outs, and other
+ methods which mitigate the security problems inherent in this
+ problem. In particular, user agents which cache credentials are
+ encouraged to provide a readily accessible mechanism for discarding
+ cached credentials under user control.
+
+15.7 Proxies and Caching
+
+ By their very nature, HTTP proxies are men-in-the-middle, and
+ represent an opportunity for man-in-the-middle attacks. Compromise of
+ the systems on which the proxies run can result in serious security
+ and privacy problems. Proxies have access to security-related
+ information, personal information about individual users and
+ organizations, and proprietary information belonging to users and
+ content providers. A compromised proxy, or a proxy implemented or
+ configured without regard to security and privacy considerations,
+ might be used in the commission of a wide range of potential attacks.
+
+ Proxy operators should protect the systems on which proxies run as
+ they would protect any system that contains or transports sensitive
+ information. In particular, log information gathered at proxies often
+ contains highly sensitive personal information, and/or information
+ about organizations. Log information should be carefully guarded, and
+ appropriate guidelines for use developed and followed. (Section
+ 15.1.1).
+
+ Caching proxies provide additional potential vulnerabilities, since
+ the contents of the cache represent an attractive target for
+ malicious exploitation. Because cache contents persist after an HTTP
+ request is complete, an attack on the cache can reveal information
+ long after a user believes that the information has been removed from
+ the network. Therefore, cache contents should be protected as
+ sensitive information.
+
+ Proxy implementors should consider the privacy and security
+ implications of their design and coding decisions, and of the
+ configuration options they provide to proxy operators (especially the
+ default configuration).
+
+ Users of a proxy need to be aware that they are no trustworthier than
+ the people who run the proxy; HTTP itself cannot solve this problem.
+
+ The judicious use of cryptography, when appropriate, may suffice to
+ protect against a broad range of security and privacy attacks. Such
+ cryptography is beyond the scope of the HTTP/1.1 specification.
+
+15.7.1 Denial of Service Attacks on Proxies
+
+ They exist. They are hard to defend against. Research continues.
+ Beware.
+
+16 Acknowledgments
+
+ This specification makes heavy use of the augmented BNF and generic
+ constructs defined by David H. Crocker for <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]. Similarly, it
+ reuses many of the definitions provided by Nathaniel Borenstein and
+ Ned Freed for MIME [7]. We hope that their inclusion in this
+ specification will help reduce past confusion over the relationship
+ between HTTP and Internet mail message formats.
+
+ The HTTP protocol has evolved considerably over the years. It has
+ benefited from a large and active developer community--the many
+ people who have participated on the www-talk mailing list--and it is
+ that community which has been most responsible for the success of
+ HTTP and of the World-Wide Web in general. Marc Andreessen, Robert
+ Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois
+ Groff, Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob
+ McCool, Lou Montulli, Dave Raggett, Tony Sanders, and Marc
+ VanHeyningen deserve special recognition for their efforts in
+ defining early aspects of the protocol.
+
+ This document has benefited greatly from the comments of all those
+ participating in the HTTP-WG. In addition to those already mentioned,
+ the following individuals have contributed to this specification:
+
+ Gary Adams Ross Patterson
+ Harald Tveit Alvestrand Albert Lunde
+ Keith Ball John C. Mallery
+ Brian Behlendorf Jean-Philippe Martin-Flatin
+ Paul Burchard Mitra
+ Maurizio Codogno David Morris
+ Mike Cowlishaw Gavin Nicol
+ Roman Czyborra Bill Perry
+ Michael A. Dolan Jeffrey Perry
+ David J. Fiander Scott Powers
+ Alan Freier Owen Rees
+ Marc Hedlund Luigi Rizzo
+ Greg Herlihy David Robinson
+ Koen Holtman Marc Salomon
+ Alex Hopmann Rich Salz
+ Bob Jernigan Allan M. Schiffman
+ Shel Kaphan Jim Seidman
+ Rohit Khare Chuck Shotton
+ John Klensin Eric W. Sink
+ Martijn Koster Simon E. Spero
+ Alexei Kosut Richard N. Taylor
+ David M. Kristol Robert S. Thau
+ Daniel LaLiberte Bill (BearHeart) Weinman
+ Ben Laurie Francois Yergeau
+ Paul J. Leach Mary Ellen Zurko
+ Daniel DuBois Josh Cohen
+
+ Much of the content and presentation of the caching design is due to
+ suggestions and comments from individuals including: Shel Kaphan,
+ Paul Leach, Koen Holtman, David Morris, and Larry Masinter.
+
+ Most of the specification of ranges is based on work originally done
+ by Ari Luotonen and John Franks, with additional input from Steve
+ Zilles.
+
+ Thanks to the "cave men" of Palo Alto. You know who you are.
+
+ Jim Gettys (the current editor of this document) wishes particularly
+ to thank Roy Fielding, the previous editor of this document, along
+ with John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen
+ Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, and
+ Larry Masinter for their help. And thanks go particularly to Jeff
+ Mogul and Scott Lawrence for performing the "MUST/MAY/SHOULD" audit.
+
+ The Apache Group, Anselm Baird-Smith, author of Jigsaw, and Henrik
+ Frystyk implemented <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> early, and we wish to thank them for the
+ discovery of many of the problems that this document attempts to
+ rectify.
+
+17 References
+
+ [1] Alvestrand, H., "Tags for the Identification of Languages", RFC
+ 1766, March 1995.
+
+ [2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey,
+ D. and B. Alberti, "The Internet Gopher Protocol (a distributed
+ document search and retrieval protocol)", <a href="http://firefly.troll.no/rfcs/rfc1436.html">RFC 1436</a>, March 1993.
+
+ [3] Berners-Lee, T., "Universal Resource Identifiers in WWW", RFC
+ 1630, June 1994.
+
+ [4] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource
+ Locators (URL)", <a href="http://firefly.troll.no/rfcs/rfc1738.html">RFC 1738</a>, December 1994.
+
+ [5] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language -
+ 2.0", <a href="http://firefly.troll.no/rfcs/rfc1866.html">RFC 1866</a>, November 1995.
+
+ [6] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer
+ Protocol -- HTTP/1.0", <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a>, May 1996.
+
+ [7] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>, November 1996.
+
+ [8] Braden, R., "Requirements for Internet Hosts -- Communication
+ Layers", STD 3, <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a>, October 1989.
+
+ [9] Crocker, D., "Standard for The Format of ARPA Internet Text
+ Messages", STD 11, <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a>, August 1982.
+
+ [10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R.,
+ Sui, J., and M. Grinbaum, "WAIS Interface Protocol Prototype
+ Functional Specification," (v1.5), Thinking Machines
+ Corporation, April 1990.
+
+ [11] Fielding, R., "Relative Uniform Resource Locators", <a href="http://firefly.troll.no/rfcs/rfc1808.html">RFC 1808</a>,
+ June 1995.
+
+ [12] Horton, M. and R. Adams, "Standard for Interchange of USENET
+ Messages", <a href="http://firefly.troll.no/rfcs/rfc1036.html">RFC 1036</a>, December 1987.
+
+ [13] Kantor, B. and P. Lapsley, "Network News Transfer Protocol", RFC
+ 977, February 1986.
+
+ [14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
+ Three: Message Header Extensions for Non-ASCII Text", <a href="http://firefly.troll.no/rfcs/rfc2047.html">RFC 2047</a>,
+ November 1996.
+
+ [15] Nebel, E. and L. Masinter, "Form-based File Upload in HTML", RFC
+ 1867, November 1995.
+
+ [16] Postel, J., "Simple Mail Transfer Protocol", STD 10, <a href="http://firefly.troll.no/rfcs/rfc821.html">RFC 821</a>,
+ August 1982.
+
+ [17] Postel, J., "Media Type Registration Procedure", <a href="http://firefly.troll.no/rfcs/rfc1590.html">RFC 1590</a>,
+ November 1996.
+
+ [18] Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC
+ 959, October 1985.
+
+ [19] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, <a href="http://firefly.troll.no/rfcs/rfc1700.html">RFC 1700</a>,
+ October 1994.
+
+ [20] Sollins, K. and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", <a href="http://firefly.troll.no/rfcs/rfc1737.html">RFC 1737</a>, December 1994.
+
+ [21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for
+ Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.
+
+ [22] ISO-8859. International Standard -- Information Processing --
+ 8-bit Single-Byte Coded Graphic Character Sets --
+ Part 1: Latin alphabet No. 1, ISO-8859-1:1987.
+ Part 2: Latin alphabet No. 2, ISO-8859-2, 1987.
+ Part 3: Latin alphabet No. 3, ISO-8859-3, 1988.
+ Part 4: Latin alphabet No. 4, ISO-8859-4, 1988.
+ Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988.
+ Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987.
+ Part 7: Latin/Greek alphabet, ISO-8859-7, 1987.
+ Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988.
+ Part 9: Latin alphabet No. 5, ISO-8859-9, 1990.
+
+ [23] Meyers, J. and M. Rose, "The Content-MD5 Header Field", RFC
+ 1864, October 1995.
+
+ [24] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC
+ 1900, February 1996.
+
+ [25] Deutsch, P., "GZIP file format specification version 4.3", RFC
+ 1952, May 1996.
+
+ [26] Venkata N. Padmanabhan, and Jeffrey C. Mogul. "Improving HTTP
+ Latency", Computer Networks and ISDN Systems, v. 28, pp. 25-35,
+ Dec. 1995. Slightly revised version of paper in Proc. 2nd
+ International WWW Conference '94: Mosaic and the Web, Oct. 1994,
+ which is available at
+ <a href="http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat">http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat</a>
+ ency.html.
+
+ [27] Joe Touch, John Heidemann, and Katia Obraczka. "Analysis of HTTP
+ Performance", &lt;URL: <a href="http://www.isi.edu/touch/pubs/http-perf96/">http://www.isi.edu/touch/pubs/http-perf96/</a>&gt;,
+ ISI Research Report ISI/RR-98-463, (original report dated Aug.
+ 1996), USC/Information Sciences Institute, August 1998.
+
+ [28] Mills, D., "Network Time Protocol (Version 3) Specification,
+ Implementation and Analysis", <a href="http://firefly.troll.no/rfcs/rfc1305.html">RFC 1305</a>, March 1992.
+
+ [29] Deutsch, P., "DEFLATE Compressed Data Format Specification
+ version 1.3", <a href="http://firefly.troll.no/rfcs/rfc1951.html">RFC 1951</a>, May 1996.
+
+ [30] S. Spero, "Analysis of HTTP Performance Problems,"
+ <a href="http://sunsite.unc.edu/mdma-release/http-prob.html">http://sunsite.unc.edu/mdma-release/http-prob.html</a>.
+
+ [31] Deutsch, P. and J. Gailly, "ZLIB Compressed Data Format
+ Specification version 3.3", <a href="http://firefly.troll.no/rfcs/rfc1950.html">RFC 1950</a>, May 1996.
+
+ [32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+ Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP:
+ Digest Access Authentication", <a href="http://firefly.troll.no/rfcs/rfc2069.html">RFC 2069</a>, January 1997.
+
+ [33] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
+ Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC
+ 2068, January 1997.
+
+ [34] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, <a href="http://firefly.troll.no/rfcs/rfc2119.html">RFC 2119</a>, March 1997.
+
+ [35] Troost, R. and Dorner, S., "Communicating Presentation
+ Information in Internet Messages: The Content-Disposition
+ Header", <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a>, June 1995.
+
+ [36] Mogul, J., Fielding, R., Gettys, J. and H. Frystyk, "Use and
+ Interpretation of HTTP Version Numbers", <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a>, May 1997.
+ [jg639]
+
+ [37] Palme, J., "Common Internet Message Headers", <a href="http://firefly.troll.no/rfcs/rfc2076.html">RFC 2076</a>, February
+ 1997. [jg640]
+
+ [38] Yergeau, F., "UTF-8, a transformation format of Unicode and
+ ISO-10646", <a href="http://firefly.troll.no/rfcs/rfc2279.html">RFC 2279</a>, January 1998. [jg641]
+
+ [39] Nielsen, H.F., Gettys, J., Baird-Smith, A., Prud'hommeaux, E.,
+ Lie, H., and C. Lilley. "Network Performance Effects of
+ HTTP/1.1, CSS1, and PNG," Proceedings of ACM SIGCOMM '97, Cannes
+ France, September 1997.[jg642]
+
+ [40] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a>, November
+ 1996. [jg643]
+
+ [41] Alvestrand, H., "IETF Policy on Character Sets and Languages",
+ BCP 18, <a href="http://firefly.troll.no/rfcs/rfc2277.html">RFC 2277</a>, January 1998. [jg644]
+
+ [42] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource
+ Identifiers (URI): Generic Syntax and Semantics", <a href="http://firefly.troll.no/rfcs/rfc2396.html">RFC 2396</a>,
+ August 1998. [jg645]
+
+ [43] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
+ Leach, P., Luotonen, A., Sink, E. and L. Stewart, "HTTP
+ Authentication: Basic and Digest Access Authentication", RFC
+ 2617, June 1999. [jg646]
+
+ [44] Luotonen, A., "Tunneling TCP based protocols through Web proxy
+ servers," Work in Progress. [jg647]
+
+ [45] Palme, J. and A. Hopmann, "MIME E-mail Encapsulation of
+ Aggregate Documents, such as HTML (MHTML)", <a href="http://firefly.troll.no/rfcs/rfc2110.html">RFC 2110</a>, March
+ 1997.
+
+ [46] Bradner, S., "The Internet Standards Process -- Revision 3", BCP
+ 9, <a href="http://firefly.troll.no/rfcs/rfc2026.html">RFC 2026</a>, October 1996.
+
+ [47] Masinter, L., "Hyper Text Coffee Pot Control Protocol
+ (HTCPCP/1.0)", <a href="http://firefly.troll.no/rfcs/rfc2324.html">RFC 2324</a>, 1 April 1998.
+
+ [48] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Five: Conformance Criteria and Examples",
+ <a href="http://firefly.troll.no/rfcs/rfc2049.html">RFC 2049</a>, November 1996.
+
+ [49] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation
+ Information in Internet Messages: The Content-Disposition Header
+ Field", <a href="http://firefly.troll.no/rfcs/rfc2183.html">RFC 2183</a>, August 1997.
+
+18 Authors' Addresses
+
+ Roy T. Fielding
+ Information and Computer Science
+ University of California, Irvine
+ Irvine, CA 92697-3425, USA
+
+ Fax: +1 (949) 824-1715
+ EMail: <a href="mailto:fielding@ics.uci.edu">fielding@ics.uci.edu</a>
+
+ James Gettys
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: <a href="mailto:jg@w3.org">jg@w3.org</a>
+
+ Jeffrey C. Mogul
+ Western Research Laboratory
+ Compaq Computer Corporation
+ 250 University Avenue
+ Palo Alto, California, 94305, USA
+
+ EMail: <a href="mailto:mogul@wrl.dec.com">mogul@wrl.dec.com</a>
+
+ Henrik Frystyk Nielsen
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: <a href="mailto:frystyk@w3.org">frystyk@w3.org</a>
+
+ Larry Masinter
+ Xerox Corporation
+ 3333 Coyote Hill Road
+ Palo Alto, CA 94034, USA
+
+ EMail: <a href="mailto:masinter@parc.xerox.com">masinter@parc.xerox.com</a>
+
+ Paul J. Leach
+ Microsoft Corporation
+ 1 Microsoft Way
+ Redmond, WA 98052, USA
+
+ EMail: <a href="mailto:paulle@microsoft.com">paulle@microsoft.com</a>
+
+ Tim Berners-Lee
+ Director, World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: <a href="mailto:timbl@w3.org">timbl@w3.org</a>
+
+19 Appendices
+
+19.1 Internet Media Type message/http and application/http
+
+ In addition to defining the HTTP/1.1 protocol, this document serves
+ as the specification for the Internet media type "message/http" and
+ "application/http". The message/http type can be used to enclose a
+ single HTTP request or response message, provided that it obeys the
+ MIME restrictions for all "message" types regarding line length and
+ encodings. The application/http type can be used to enclose a
+ pipeline of one or more HTTP request or response messages (not
+ intermixed). The following is to be registered with IANA [17].
+
+ Media Type name: message
+ Media subtype name: http
+ Required parameters: none
+ Optional parameters: version, msgtype
+ version: The HTTP-Version number of the enclosed message
+ (e.g., "1.1"). If not present, the version can be
+ determined from the first line of the body.
+ msgtype: The message type -- "request" or "response". If not
+ present, the type can be determined from the first
+ line of the body.
+ Encoding considerations: only "7bit", "8bit", or "binary" are
+ permitted
+ Security considerations: none
+
+ Media Type name: application
+ Media subtype name: http
+ Required parameters: none
+ Optional parameters: version, msgtype
+ version: The HTTP-Version number of the enclosed messages
+ (e.g., "1.1"). If not present, the version can be
+ determined from the first line of the body.
+ msgtype: The message type -- "request" or "response". If not
+ present, the type can be determined from the first
+ line of the body.
+ Encoding considerations: HTTP messages enclosed by this type
+ are in "binary" format; use of an appropriate
+ Content-Transfer-Encoding is required when
+ transmitted via E-mail.
+ Security considerations: none
+
+19.2 Internet Media Type multipart/byteranges
+
+ When an HTTP 206 (Partial Content) response message includes the
+ content of multiple ranges (a response to a request for multiple
+ non-overlapping ranges), these are transmitted as a multipart
+ message-body. The media type for this purpose is called
+ "multipart/byteranges".
+
+ The multipart/byteranges media type includes two or more parts, each
+ with its own Content-Type and Content-Range fields. The required
+ boundary parameter specifies the boundary string used to separate
+ each body-part.
+
+ Media Type name: multipart
+ Media subtype name: byteranges
+ Required parameters: boundary
+ Optional parameters: none
+ Encoding considerations: only "7bit", "8bit", or "binary" are
+ permitted
+ Security considerations: none
+
+ For example:
+
+ HTTP/1.1 206 Partial Content
+ Date: Wed, 15 Nov 1995 06:25:24 GMT
+ Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
+
+ --THIS_STRING_SEPARATES
+ Content-type: application/pdf
+ Content-range: bytes 500-999/8000
+
+ ...the first range...
+ --THIS_STRING_SEPARATES
+ Content-type: application/pdf
+ Content-range: bytes 7000-7999/8000
+
+ ...the second range
+ --THIS_STRING_SEPARATES--
+
+ Notes:
+
+ 1) Additional CRLFs may precede the first boundary string in the
+ entity.
+
+ 2) Although <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a> [40] permits the boundary string to be
+ quoted, some existing implementations handle a quoted boundary
+ string incorrectly.
+
+ 3) A number of browsers and servers were coded to an early draft
+ of the byteranges specification to use a media type of
+ multipart/x-byteranges, which is almost, but not quite
+ compatible with the version documented in HTTP/1.1.
+
+19.3 Tolerant Applications
+
+ Although this document specifies the requirements for the generation
+ of HTTP/1.1 messages, not all applications will be correct in their
+ implementation. We therefore recommend that operational applications
+ be tolerant of deviations whenever those deviations can be
+ interpreted unambiguously.
+
+ Clients SHOULD be tolerant in parsing the Status-Line and servers
+ tolerant when parsing the Request-Line. In particular, they SHOULD
+ accept any amount of SP or HT characters between fields, even though
+ only a single SP is required.
+
+ The line terminator for message-header fields is the sequence CRLF.
+ However, we recommend that applications, when parsing such headers,
+ recognize a single LF as a line terminator and ignore the leading CR.
+
+ The character set of an entity-body SHOULD be labeled as the lowest
+ common denominator of the character codes used within that body, with
+ the exception that not labeling the entity is preferred over labeling
+ the entity with the labels US-ASCII or ISO-8859-1. See section 3.7.1
+ and 3.4.1.
+
+ Additional rules for requirements on parsing and encoding of dates
+ and other potential problems with date encodings include:
+
+ - HTTP/1.1 clients and caches SHOULD assume that an <a href="http://firefly.troll.no/rfcs/rfc850.html">RFC-850</a> date
+ which appears to be more than 50 years in the future is in fact
+ in the past (this helps solve the "year 2000" problem).
+
+ - An HTTP/1.1 implementation MAY internally represent a parsed
+ Expires date as earlier than the proper value, but MUST NOT
+ internally represent a parsed Expires date as later than the
+ proper value.
+
+ - All expiration-related calculations MUST be done in GMT. The
+ local time zone MUST NOT influence the calculation or comparison
+ of an age or expiration time.
+
+ - If an HTTP header incorrectly carries a date value with a time
+ zone other than GMT, it MUST be converted into GMT using the
+ most conservative possible conversion.
+
+19.4 Differences Between HTTP Entities and <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> Entities
+
+ HTTP/1.1 uses many of the constructs defined for Internet Mail (RFC
+ 822 [9]) and the Multipurpose Internet Mail Extensions (MIME [7]) to
+ allow entities to be transmitted in an open variety of
+ representations and with extensible mechanisms. However, <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>
+ discusses mail, and HTTP has a few features that are different from
+ those described in <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>. These differences were carefully chosen
+ to optimize performance over binary connections, to allow greater
+ freedom in the use of new media types, to make date comparisons
+ easier, and to acknowledge the practice of some early HTTP servers
+ and clients.
+
+ This appendix describes specific areas where HTTP differs from RFC
+ 2045. Proxies and gateways to strict MIME environments SHOULD be
+ aware of these differences and provide the appropriate conversions
+ where necessary. Proxies and gateways from MIME environments to HTTP
+ also need to be aware of the differences because some conversions
+ might be required.
+
+19.4.1 MIME-Version
+
+ HTTP is not a MIME-compliant protocol. However, HTTP/1.1 messages MAY
+ include a single MIME-Version general-header field to indicate what
+ version of the MIME protocol was used to construct the message. Use
+ of the MIME-Version header field indicates that the message is in
+ full compliance with the MIME protocol (as defined in <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>[7]).
+ Proxies/gateways are responsible for ensuring full compliance (where
+ possible) when exporting HTTP messages to strict MIME environments.
+
+ MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
+
+ MIME version "1.0" is the default for use in HTTP/1.1. However,
+ HTTP/1.1 message parsing and semantics are defined by this document
+ and not the MIME specification.
+
+19.4.2 Conversion to Canonical Form
+
+ <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> [7] requires that an Internet mail entity be converted to
+ canonical form prior to being transferred, as described in section 4
+ of <a href="http://firefly.troll.no/rfcs/rfc2049.html">RFC 2049</a> [48]. Section 3.7.1 of this document describes the forms
+ allowed for subtypes of the "text" media type when transmitted over
+ HTTP. <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a> requires that content with a type of "text" represent
+ line breaks as CRLF and forbids the use of CR or LF outside of line
+
+ break sequences. HTTP allows CRLF, bare CR, and bare LF to indicate a
+ line break within text content when a message is transmitted over
+ HTTP.
+
+ Where it is possible, a proxy or gateway from HTTP to a strict MIME
+ environment SHOULD translate all line breaks within the text media
+ types described in section 3.7.1 of this document to the <a href="http://firefly.troll.no/rfcs/rfc2049.html">RFC 2049</a>
+ canonical form of CRLF. Note, however, that this might be complicated
+ by the presence of a Content-Encoding and by the fact that HTTP
+ allows the use of some character sets which do not use octets 13 and
+ 10 to represent CR and LF, as is the case for some multi-byte
+ character sets.
+
+ Implementors should note that conversion will break any cryptographic
+ checksums applied to the original content unless the original content
+ is already in canonical form. Therefore, the canonical form is
+ recommended for any content that uses such checksums in HTTP.
+
+19.4.3 Conversion of Date Formats
+
+ HTTP/1.1 uses a restricted set of date formats (section 3.3.1) to
+ simplify the process of date comparison. Proxies and gateways from
+ other protocols SHOULD ensure that any Date header field present in a
+ message conforms to one of the HTTP/1.1 formats and rewrite the date
+ if necessary.
+
+19.4.4 Introduction of Content-Encoding
+
+ <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> does not include any concept equivalent to HTTP/1.1's
+ Content-Encoding header field. Since this acts as a modifier on the
+ media type, proxies and gateways from HTTP to MIME-compliant
+ protocols MUST either change the value of the Content-Type header
+ field or decode the entity-body before forwarding the message. (Some
+ experimental applications of Content-Type for Internet mail have used
+ a media-type parameter of ";conversions=&lt;content-coding&gt;" to perform
+ a function equivalent to Content-Encoding. However, this parameter is
+ not part of <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>.)
+
+19.4.5 No Content-Transfer-Encoding
+
+ HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC
+ 2045. Proxies and gateways from MIME-compliant protocols to HTTP MUST
+ remove any non-identity CTE ("quoted-printable" or "base64") encoding
+ prior to delivering the response message to an HTTP client.
+
+ Proxies and gateways from HTTP to MIME-compliant protocols are
+ responsible for ensuring that the message is in the correct format
+ and encoding for safe transport on that protocol, where "safe
+
+ transport" is defined by the limitations of the protocol being used.
+ Such a proxy or gateway SHOULD label the data with an appropriate
+ Content-Transfer-Encoding if doing so will improve the likelihood of
+ safe transport over the destination protocol.
+
+19.4.6 Introduction of Transfer-Encoding
+
+ HTTP/1.1 introduces the Transfer-Encoding header field (section
+ 14.41). Proxies/gateways MUST remove any transfer-coding prior to
+ forwarding a message via a MIME-compliant protocol.
+
+ A process for decoding the "chunked" transfer-coding (section 3.6)
+ can be represented in pseudo-code as:
+
+ length := 0
+ read chunk-size, chunk-extension (if any) and CRLF
+ while (chunk-size &gt; 0) {
+ read chunk-data and CRLF
+ append chunk-data to entity-body
+ length := length + chunk-size
+ read chunk-size and CRLF
+ }
+ read entity-header
+ while (entity-header not empty) {
+ append entity-header to existing header fields
+ read entity-header
+ }
+ Content-Length := length
+ Remove "chunked" from Transfer-Encoding
+
+19.4.7 MHTML and Line Length Limitations
+
+ HTTP implementations which share code with MHTML [45] implementations
+ need to be aware of MIME line length limitations. Since HTTP does not
+ have this limitation, HTTP does not fold long lines. MHTML messages
+ being transported by HTTP follow all conventions of MHTML, including
+ line length limitations and folding, canonicalization, etc., since
+ HTTP transports all message-bodies as payload (see section 3.7.2) and
+ does not interpret the content or any MIME header lines that might be
+ contained therein.
+
+19.5 Additional Features
+
+ <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a> and <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> document protocol elements used by some
+ existing HTTP implementations, but not consistently and correctly
+ across most HTTP/1.1 applications. Implementors are advised to be
+ aware of these features, but cannot rely upon their presence in, or
+ interoperability with, other HTTP/1.1 applications. Some of these
+
+ describe proposed experimental features, and some describe features
+ that experimental deployment found lacking that are now addressed in
+ the base HTTP/1.1 specification.
+
+ A number of other headers, such as Content-Disposition and Title,
+ from SMTP and MIME are also often implemented (see <a href="http://firefly.troll.no/rfcs/rfc2076.html">RFC 2076</a> [37]).
+
+19.5.1 Content-Disposition
+
+ The Content-Disposition response-header field has been proposed as a
+ means for the origin server to suggest a default filename if the user
+ requests that the content is saved to a file. This usage is derived
+ from the definition of Content-Disposition in <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a> [35].
+
+ content-disposition = "Content-Disposition" ":"
+ disposition-type *( ";" disposition-parm )
+ disposition-type = "attachment" | disp-extension-token
+ disposition-parm = filename-parm | disp-extension-parm
+ filename-parm = "filename" "=" quoted-string
+ disp-extension-token = token
+ disp-extension-parm = token "=" ( token | quoted-string )
+
+ An example is
+
+ Content-Disposition: attachment; filename="fname.ext"
+
+ The receiving user agent SHOULD NOT respect any directory path
+ information present in the filename-parm parameter, which is the only
+ parameter believed to apply to HTTP implementations at this time. The
+ filename SHOULD be treated as a terminal component only.
+
+ If this header is used in a response with the application/octet-
+ stream content-type, the implied suggestion is that the user agent
+ should not display the response, but directly enter a `save response
+ as...' dialog.
+
+ See section 15.5 for Content-Disposition security issues.
+
+19.6 Compatibility with Previous Versions
+
+ It is beyond the scope of a protocol specification to mandate
+ compliance with previous versions. HTTP/1.1 was deliberately
+ designed, however, to make supporting previous versions easy. It is
+ worth noting that, at the time of composing this specification
+ (1996), we would expect commercial HTTP/1.1 servers to:
+
+ - recognize the format of the Request-Line for HTTP/0.9, 1.0, and
+ 1.1 requests;
+
+ - understand any valid request in the format of HTTP/0.9, 1.0, or
+ 1.1;
+
+ - respond appropriately with a message in the same major version
+ used by the client.
+
+ And we would expect HTTP/1.1 clients to:
+
+ - recognize the format of the Status-Line for HTTP/1.0 and 1.1
+ responses;
+
+ - understand any valid response in the format of HTTP/0.9, 1.0, or
+ 1.1.
+
+ For most implementations of HTTP/1.0, each connection is established
+ by the client prior to the request and closed by the server after
+ sending the response. Some implementations implement the Keep-Alive
+ version of persistent connections described in section 19.7.1 of RFC
+ 2068 [33].
+
+19.6.1 Changes from HTTP/1.0
+
+ This section summarizes major differences between versions HTTP/1.0
+ and HTTP/1.1.
+
+19.6.1.1 Changes to Simplify Multi-homed Web Servers and Conserve IP
+ Addresses
+
+ The requirements that clients and servers support the Host request-
+ header, report an error if the Host request-header (section 14.23) is
+ missing from an HTTP/1.1 request, and accept absolute URIs (section
+ 5.1.2) are among the most important changes defined by this
+ specification.
+
+ Older HTTP/1.0 clients assumed a one-to-one relationship of IP
+ addresses and servers; there was no other established mechanism for
+ distinguishing the intended server of a request than the IP address
+ to which that request was directed. The changes outlined above will
+ allow the Internet, once older HTTP clients are no longer common, to
+ support multiple Web sites from a single IP address, greatly
+ simplifying large operational Web servers, where allocation of many
+ IP addresses to a single host has created serious problems. The
+ Internet will also be able to recover the IP addresses that have been
+ allocated for the sole purpose of allowing special-purpose domain
+ names to be used in root-level HTTP URLs. Given the rate of growth of
+ the Web, and the number of servers already deployed, it is extremely
+
+ important that all implementations of HTTP (including updates to
+ existing HTTP/1.0 applications) correctly implement these
+ requirements:
+
+ - Both clients and servers MUST support the Host request-header.
+
+ - A client that sends an HTTP/1.1 request MUST send a Host header.
+
+ - Servers MUST report a 400 (Bad Request) error if an HTTP/1.1
+ request does not include a Host request-header.
+
+ - Servers MUST accept absolute URIs.
+
+19.6.2 Compatibility with HTTP/1.0 Persistent Connections
+
+ Some clients and servers might wish to be compatible with some
+ previous implementations of persistent connections in HTTP/1.0
+ clients and servers. Persistent connections in HTTP/1.0 are
+ explicitly negotiated as they are not the default behavior. HTTP/1.0
+ experimental implementations of persistent connections are faulty,
+ and the new facilities in HTTP/1.1 are designed to rectify these
+ problems. The problem was that some existing 1.0 clients may be
+ sending Keep-Alive to a proxy server that doesn't understand
+ Connection, which would then erroneously forward it to the next
+ inbound server, which would establish the Keep-Alive connection and
+ result in a hung HTTP/1.0 proxy waiting for the close on the
+ response. The result is that HTTP/1.0 clients must be prevented from
+ using Keep-Alive when talking to proxies.
+
+ However, talking to proxies is the most important use of persistent
+ connections, so that prohibition is clearly unacceptable. Therefore,
+ we need some other mechanism for indicating a persistent connection
+ is desired, which is safe to use even when talking to an old proxy
+ that ignores Connection. Persistent connections are the default for
+ HTTP/1.1 messages; we introduce a new keyword (Connection: close) for
+ declaring non-persistence. See section 14.10.
+
+ The original HTTP/1.0 form of persistent connections (the Connection:
+ Keep-Alive and Keep-Alive header) is documented in <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>. [33]
+
+19.6.3 Changes from <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>
+
+ This specification has been carefully audited to correct and
+ disambiguate key word usage; <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> had many problems in respect to
+ the conventions laid out in <a href="http://firefly.troll.no/rfcs/rfc2119.html">RFC 2119</a> [34].
+
+ Clarified which error code should be used for inbound server failures
+ (e.g. DNS failures). (Section 10.5.5).
+
+ CREATE had a race that required an Etag be sent when a resource is
+ first created. (Section 10.2.2).
+
+ Content-Base was deleted from the specification: it was not
+ implemented widely, and there is no simple, safe way to introduce it
+ without a robust extension mechanism. In addition, it is used in a
+ similar, but not identical fashion in MHTML [45].
+
+ Transfer-coding and message lengths all interact in ways that
+ required fixing exactly when chunked encoding is used (to allow for
+ transfer encoding that may not be self delimiting); it was important
+ to straighten out exactly how message lengths are computed. (Sections
+ 3.6, 4.4, 7.2.2, 13.5.2, 14.13, 14.16)
+
+ A content-coding of "identity" was introduced, to solve problems
+ discovered in caching. (section 3.5)
+
+ Quality Values of zero should indicate that "I don't want something"
+ to allow clients to refuse a representation. (Section 3.9)
+
+ The use and interpretation of HTTP version numbers has been clarified
+ by <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a>. Require proxies to upgrade requests to highest protocol
+ version they support to deal with problems discovered in HTTP/1.0
+ implementations (Section 3.1)
+
+ Charset wildcarding is introduced to avoid explosion of character set
+ names in accept headers. (Section 14.2)
+
+ A case was missed in the Cache-Control model of HTTP/1.1; s-maxage
+ was introduced to add this missing case. (Sections 13.4, 14.8, 14.9,
+ 14.9.3)
+
+ The Cache-Control: max-age directive was not properly defined for
+ responses. (Section 14.9.3)
+
+ There are situations where a server (especially a proxy) does not
+ know the full length of a response but is capable of serving a
+ byterange request. We therefore need a mechanism to allow byteranges
+ with a content-range not indicating the full length of the message.
+ (Section 14.16)
+
+ Range request responses would become very verbose if all meta-data
+ were always returned; by allowing the server to only send needed
+ headers in a 206 response, this problem can be avoided. (Section
+ 10.2.7, 13.5.3, and 14.27)
+
+ Fix problem with unsatisfiable range requests; there are two cases:
+ syntactic problems, and range doesn't exist in the document. The 416
+ status code was needed to resolve this ambiguity needed to indicate
+ an error for a byte range request that falls outside of the actual
+ contents of a document. (Section 10.4.17, 14.16)
+
+ Rewrite of message transmission requirements to make it much harder
+ for implementors to get it wrong, as the consequences of errors here
+ can have significant impact on the Internet, and to deal with the
+ following problems:
+
+ 1. Changing "HTTP/1.1 or later" to "HTTP/1.1", in contexts where
+ this was incorrectly placing a requirement on the behavior of
+ an implementation of a future version of HTTP/1.x
+
+ 2. Made it clear that user-agents should retry requests, not
+ "clients" in general.
+
+ 3. Converted requirements for clients to ignore unexpected 100
+ (Continue) responses, and for proxies to forward 100 responses,
+ into a general requirement for 1xx responses.
+
+ 4. Modified some TCP-specific language, to make it clearer that
+ non-TCP transports are possible for HTTP.
+
+ 5. Require that the origin server MUST NOT wait for the request
+ body before it sends a required 100 (Continue) response.
+
+ 6. Allow, rather than require, a server to omit 100 (Continue) if
+ it has already seen some of the request body.
+
+ 7. Allow servers to defend against denial-of-service attacks and
+ broken clients.
+
+ This change adds the Expect header and 417 status code. The message
+ transmission requirements fixes are in sections 8.2, 10.4.18,
+ 8.1.2.2, 13.11, and 14.20.
+
+ Proxies should be able to add Content-Length when appropriate.
+ (Section 13.5.2)
+
+ Clean up confusion between 403 and 404 responses. (Section 10.4.4,
+ 10.4.5, and 10.4.11)
+
+ Warnings could be cached incorrectly, or not updated appropriately.
+ (Section 13.1.2, 13.2.4, 13.5.2, 13.5.3, 14.9.3, and 14.46) Warning
+ also needed to be a general header, as PUT or other methods may have
+ need for it in requests.
+
+ Transfer-coding had significant problems, particularly with
+ interactions with chunked encoding. The solution is that transfer-
+ codings become as full fledged as content-codings. This involves
+ adding an IANA registry for transfer-codings (separate from content
+ codings), a new header field (TE) and enabling trailer headers in the
+ future. Transfer encoding is a major performance benefit, so it was
+ worth fixing [39]. TE also solves another, obscure, downward
+ interoperability problem that could have occurred due to interactions
+ between authentication trailers, chunked encoding and HTTP/1.0
+ clients.(Section 3.6, 3.6.1, and 14.39)
+
+ The PATCH, LINK, UNLINK methods were defined but not commonly
+ implemented in previous versions of this specification. See <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>
+ [33].
+
+ The Alternates, Content-Version, Derived-From, Link, URI, Public and
+ Content-Base header fields were defined in previous versions of this
+ specification, but not commonly implemented. See <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> [33].
+
+20 Index
+
+ Please see the PostScript version of this RFC for the INDEX.
+
+21. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+</pre>
+<p align="center"><script language="JavaScript"><!--
+erfc("2616");
+// --></script><a href="http://firefly.troll.no/rfccomment.php?rfcnum=2616" target="_blank" onclick="window.open('/rfccomment.php?rfcnum=2616','Popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=680,height=530,left=30,top=43'); return false;" )="">Comment on RFC 2616</a>
+</p>
+&nbsp;<br>
+<div align="center">
+<center>
+<table border="0" cellpadding="4" cellspacing="4" width="100%">
+<tbody><tr><td bgcolor="#d6d6c0" width="100%">
+<p><font face="Arial">Comments about this RFC:</font></p>
+<ul>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-869.html">RFC 2616: Very basic HTTP Server written in Emacs Lisp: http://www.chez.com/emarsden/downl...</a> by Alex Schröder (5/12/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-539.html">RFC 2616: If someone has got sample code for a basic HTTP/1.1 Server please let me know......</a> by Mike (2/4/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-486.html">RFC 2616: I am seeking ladies for nothing but sex that is all i want from the lady sorry...</a> by treblav (1/16/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2360.html">RFC 2616: Hello.
+
+ I have realized that point 8.1.4 of the RFC 2616 is a big threat to...</a> by Doolyo (8/20/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1522.html">RFC 2616: êêêöïïäììóì::::::@::@"""@:&gt;c
+ :::@"$$%^^*^^*((((99(
+ &lt;&lt;&gt;:"? </a> by óäöóöóöóö (12/16/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2147.html">RFC 2616: Man Such a big and boring doc.. thats why ppl shy away from RFC stuff. Make it...</a> by AnurgaM (6/15/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2277.html">RFC 2616: igeve uo 100 dolars
+
+ iwant password
+
+ farh51@hotmail.com </a> by farh (7/24/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2349.html">RFC 2616: I have realized that point 8.1.4 of this RFC is a big threat to the load speed...</a> by Doolyo (8/15/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1230.html">RFC 2616: Would it possible to extend the
+ protocol to allow another GET,
+ HEAD, POST,...</a> by CCaldwell (9/15/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-692.html">RFC 2616: Wonder if he got his lady? </a> by SinJax (3/26/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2056.html">RFC 2616: it's for shareaza that the program go fasther </a> by sylle (5/24/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2526.html">RFC 2616: Only 2 simultaneous connections is a big threat to the load speed of HTML...</a> by Doolyo (9/30/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-736.html">RFC 2616: yo to the southampton uni coursework massive </a> by anon (4/6/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1574.html">RFC 2616: If you know everything about HTTP this rfc will be helpful to you (as a recap...</a> by just a developer (1/5/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1111.html">RFC 2616: Please note that section 3.6.2, referenced in section 3.5 (page 25)
+ may most...</a> by Patrick Powell (8/12/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1354.html">RFC 2616: gtu87t 86t8o;koip]0-n df bhvfjkhfgfter6ecvgjlhhjuhjioy uftyei vn bk.jljpoi
+ =- ...</a> by jkl (10/20/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1973.html">RFC 2616: I HOPE KNOW MANY OF SOME RFC </a> by MARRY (5/5/2005)</font></li>
+</ul>
+</td></tr></tbody></table> <br></center></div>
+<div align="center">
+<table border="0" cellpadding="3" cellspacing="3" width="100%">
+<tbody><tr><td width="45%">
+<p align="left">Previous: <a href="http://firefly.troll.no/rfcs/rfc2615.html">RFC 2615 - PPP over SONET/SDH</a>
+</p></td><td width="10%">&nbsp;</td><td width="45%">
+<p align="right">Next: <a href="http://firefly.troll.no/rfcs/rfc2617.html">RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication</a>
+</p></td></tr></tbody></table></div><p align="right">&nbsp;</p>
+<hr noshade="noshade" size="2">
+<div align="center">[ <a href="http://firefly.troll.no/rfcs/">RFC Index</a> | <a href="http://firefly.troll.no/rfcs/rfcsearch.html">RFC Search</a> | <a href="http://firefly.troll.no/faqs/">Usenet FAQs</a> | <a href="http://firefly.troll.no/contrib/">Web FAQs</a> | <a href="http://firefly.troll.no/docs/">Documents</a> | <a href="http://www.city-data.com/">Cities</a> ]
+<p>
+</p></div>
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.pdf">rfc2616.pdf</a>
+<small>
+<address>
+<p align="center">
+
+</p>
+</address>
+</small>
+</body></html> \ No newline at end of file
diff --git a/tests/testserver/common/startup.sh b/tests/testserver/common/startup.sh
index 74990a47f6..1386314e38 100755
--- a/tests/testserver/common/startup.sh
+++ b/tests/testserver/common/startup.sh
@@ -34,7 +34,7 @@ set -ex
# export variables
export USER=qt-test-server
export PASS=password
-export CONFIG=common/testdata
+export CONFIG=service/testdata
export TESTDATA=service/testdata
# add users
@@ -43,17 +43,4 @@ useradd -m -s /bin/bash $USER; echo "$USER:$PASS" | chpasswd
# install configurations and test data
su $USER -c "cp $CONFIG/system/passwords ~/"
-# modules initialization (apache2.sh, ftp-proxy.sh ...)
-for RUN_CMD
-do $RUN_CMD
-done
-
-# start multicast DNS service discovery (mDNS)
-sed -i -e "s,#domain-name=local,domain-name=${test_domain:-test-net.qt.local}," \
- -e "s,#publish-aaaa-on-ipv4=yes,publish-aaaa-on-ipv4=no," \
- /etc/avahi/avahi-daemon.conf
-service dbus restart
-service avahi-daemon restart
-
-# keep-alive in docker detach mode
-sleep infinity
+./startup.sh "$@"
diff --git a/tests/testserver/cyrus/cyrus.sh b/tests/testserver/cyrus/cyrus.sh
new file mode 100755
index 0000000000..92c3bfa703
--- /dev/null
+++ b/tests/testserver/cyrus/cyrus.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2019 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$
+## 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 or (at your option) 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.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-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+echo "tls_cert_file: /home/qt-test-server/ssl-certs/qt-test-server-cert.pem" >> /etc/imapd.conf
+echo "tls_key_file: /home/qt-test-server/ssl-certs/private/qt-test-server-key.pem" >> /etc/imapd.conf
+chmod +3 /home/qt-test-server/ssl-certs/private/
+mkdir -m 007 -p /run/cyrus/proc
+sed -i 's/#imaps\t\tcmd="imapd/imaps\t\tcmd="imapd/' /etc/cyrus.conf
+
+service cyrus-imapd restart
diff --git a/tests/testserver/docker-compose-bridge-network.yml b/tests/testserver/docker-compose-bridge-network.yml
new file mode 100644
index 0000000000..2cabeee1dc
--- /dev/null
+++ b/tests/testserver/docker-compose-bridge-network.yml
@@ -0,0 +1,157 @@
+version: '2.1'
+
+# The tag of images is used by docker compose file to launch the corresponding
+# docker containers. The value of tag comes from the provisioning script
+# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
+# of each server context as the tag of docker images. If one of the server
+# contexts gets changes, please make sure to update this compose file as well.
+# You can run command 'docker images' to list all the tags of test server images.
+# For example:
+# REPOSITORY TAG
+# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
+
+services:
+ apache2:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-apache2
+ hostname: ${HOST_NAME:-apache2}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ shareDir: ./common
+ serviceDir: ./apache2
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/apache2.sh]
+
+ squid:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-squid
+ hostname: ${HOST_NAME:-squid}
+ depends_on:
+ - apache2
+ external_links:
+ - apache2:apache2.${TEST_DOMAIN}
+ - cyrus:cyrus.${TEST_DOMAIN}
+ - iptables:iptables.${TEST_DOMAIN}
+ - vsftpd:vsftpd.${TEST_DOMAIN}
+ - echo:echo.${TEST_DOMAIN}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ shareDir: ./common
+ serviceDir: ./squid
+ entrypoint: service/startup.sh
+ command: service/squid.sh
+
+ vsftpd:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-vsftpd
+ hostname: ${HOST_NAME:-vsftpd}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ shareDir: ./common
+ serviceDir: ./vsftpd
+ entrypoint: service/startup.sh
+ command: service/vsftpd.sh
+
+ ftp-proxy:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-ftp-proxy
+ hostname: ${HOST_NAME:-ftp-proxy}
+ depends_on:
+ - vsftpd
+ external_links:
+ - vsftpd:vsftpd.${TEST_DOMAIN}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ shareDir: ./common
+ serviceDir: ./ftp-proxy
+ entrypoint: service/startup.sh
+ command: service/ftp-proxy.sh
+
+ danted:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-danted
+ hostname: ${HOST_NAME:-danted}
+ depends_on:
+ - apache2
+ - vsftpd
+ - ftp-proxy
+ external_links:
+ - apache2:apache2.${TEST_DOMAIN}
+ - vsftpd:vsftpd.${TEST_DOMAIN}
+ - ftp-proxy:ftp-proxy.${TEST_DOMAIN}
+ - cyrus:cyrus.${TEST_DOMAIN}
+ - echo:echo.${TEST_DOMAIN}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ shareDir: ./common
+ serviceDir: ./danted
+ entrypoint: service/startup.sh
+ command: service/danted.sh
+
+ cyrus:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-cyrus
+ hostname: ${HOST_NAME:-cyrus}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-cyrus:c8d72754abc0e501afd624ce838e4df35505abc9
+ shareDir: ./common
+ serviceDir: ./cyrus
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/cyrus.sh]
+
+ iptables:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-iptables
+ hostname: ${HOST_NAME:-iptables}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-iptables:cb7a8bd6d28602085a88c8ced7d67e28e75781e2
+ shareDir: ./common
+ serviceDir: ./iptables
+ entrypoint: service/startup.sh
+ command: service/iptables.sh
+ cap_add:
+ - NET_ADMIN
+ - NET_RAW
+
+ echo:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-echo
+ hostname: ${HOST_NAME:-echo}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-echo:b29ad409e746a834c1055fd0f7a55fd5056da6ea
+ shareDir: ./common
+ serviceDir: ./echo
+ entrypoint: service/startup.sh
+ command: service/echo.sh
diff --git a/tests/testserver/docker-compose-for-macOS.yml b/tests/testserver/docker-compose-for-macOS.yml
deleted file mode 100644
index aa610dfb88..0000000000
--- a/tests/testserver/docker-compose-for-macOS.yml
+++ /dev/null
@@ -1,100 +0,0 @@
-version: '3.4'
-
-# The tag of images is used by docker compose file to launch the corresponding
-# docker containers. The value of tag comes from the provisioning script
-# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
-# of each server context as the tag of docker images. If one of the server
-# contexts gets changes, please make sure to update this compose file as well.
-# You can run command 'docker images' to list all the tags of test server images.
-# For example:
-# REPOSITORY TAG
-# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
-
-services:
- apache2:
- image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
- container_name: qt-test-server-apache2
- domainname: ${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./apache2:/service:ro
- entrypoint: common/startup.sh
- command: [common/ssl.sh, service/apache2.sh]
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
- - test_cert="qt-test-server-host-network-cacert.pem"
-
- squid:
- image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
- container_name: qt-test-server-squid
- domainname: ${TEST_DOMAIN}
- depends_on:
- - apache2
- volumes:
- - ./common:/common:ro
- - ./squid:/service:ro
- entrypoint: common/startup.sh
- command: service/squid.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
-
- vsftpd:
- image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
- container_name: qt-test-server-vsftpd
- domainname: ${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./vsftpd:/service:ro
- entrypoint: common/startup.sh
- command: service/vsftpd.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
-
- ftp-proxy:
- image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
- container_name: qt-test-server-ftp-proxy
- domainname: ${TEST_DOMAIN}
- depends_on:
- - vsftpd
- volumes:
- - ./common:/common:ro
- - ./ftp-proxy:/service:ro
- entrypoint: common/startup.sh
- command: service/ftp-proxy.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
-
- danted:
- image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
- container_name: qt-test-server-danted
- domainname: ${TEST_DOMAIN}
- depends_on:
- - apache2
- - vsftpd
- - ftp-proxy
- volumes:
- - ./common:/common:ro
- - ./danted:/service:ro
- entrypoint: common/startup.sh
- command: service/danted.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - danted_internal=${MACHINE_IP}
- - danted_external=${MACHINE_IP}
- - danted_auth_internal=${MACHINE_IP}
- - danted_auth_external=${MACHINE_IP}
- - test_domain=${TEST_DOMAIN}
diff --git a/tests/testserver/docker-compose-for-windows.yml b/tests/testserver/docker-compose-for-windows.yml
deleted file mode 100644
index aa610dfb88..0000000000
--- a/tests/testserver/docker-compose-for-windows.yml
+++ /dev/null
@@ -1,100 +0,0 @@
-version: '3.4'
-
-# The tag of images is used by docker compose file to launch the corresponding
-# docker containers. The value of tag comes from the provisioning script
-# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
-# of each server context as the tag of docker images. If one of the server
-# contexts gets changes, please make sure to update this compose file as well.
-# You can run command 'docker images' to list all the tags of test server images.
-# For example:
-# REPOSITORY TAG
-# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
-
-services:
- apache2:
- image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
- container_name: qt-test-server-apache2
- domainname: ${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./apache2:/service:ro
- entrypoint: common/startup.sh
- command: [common/ssl.sh, service/apache2.sh]
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
- - test_cert="qt-test-server-host-network-cacert.pem"
-
- squid:
- image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
- container_name: qt-test-server-squid
- domainname: ${TEST_DOMAIN}
- depends_on:
- - apache2
- volumes:
- - ./common:/common:ro
- - ./squid:/service:ro
- entrypoint: common/startup.sh
- command: service/squid.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
-
- vsftpd:
- image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
- container_name: qt-test-server-vsftpd
- domainname: ${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./vsftpd:/service:ro
- entrypoint: common/startup.sh
- command: service/vsftpd.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
-
- ftp-proxy:
- image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
- container_name: qt-test-server-ftp-proxy
- domainname: ${TEST_DOMAIN}
- depends_on:
- - vsftpd
- volumes:
- - ./common:/common:ro
- - ./ftp-proxy:/service:ro
- entrypoint: common/startup.sh
- command: service/ftp-proxy.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - test_domain=${TEST_DOMAIN}
-
- danted:
- image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
- container_name: qt-test-server-danted
- domainname: ${TEST_DOMAIN}
- depends_on:
- - apache2
- - vsftpd
- - ftp-proxy
- volumes:
- - ./common:/common:ro
- - ./danted:/service:ro
- entrypoint: common/startup.sh
- command: service/danted.sh
- network_mode: "host"
- extra_hosts:
- - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
- environment:
- - danted_internal=${MACHINE_IP}
- - danted_external=${MACHINE_IP}
- - danted_auth_internal=${MACHINE_IP}
- - danted_auth_external=${MACHINE_IP}
- - test_domain=${TEST_DOMAIN}
diff --git a/tests/testserver/docker-compose-host-network.yml b/tests/testserver/docker-compose-host-network.yml
new file mode 100644
index 0000000000..4b2e1ebdab
--- /dev/null
+++ b/tests/testserver/docker-compose-host-network.yml
@@ -0,0 +1,102 @@
+version: '2.1'
+
+# The tag of images is used by docker compose file to launch the corresponding
+# docker containers. The value of tag comes from the provisioning script
+# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
+# of each server context as the tag of docker images. If one of the server
+# contexts gets changes, please make sure to update this compose file as well.
+# You can run command 'docker images' to list all the tags of test server images.
+# For example:
+# REPOSITORY TAG
+# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
+
+services:
+ apache2:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-apache2
+ hostname: ${HOST_NAME:-apache2}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ shareDir: ./common
+ serviceDir: ./apache2
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/apache2.sh]
+ environment:
+ - test_cert="qt-test-server-host-network-cacert.pem"
+
+ squid:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-squid
+ hostname: ${HOST_NAME:-squid}
+ depends_on:
+ - apache2
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ shareDir: ./common
+ serviceDir: ./squid
+ entrypoint: service/startup.sh
+ command: service/squid.sh
+
+ vsftpd:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-vsftpd
+ hostname: ${HOST_NAME:-vsftpd}
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ shareDir: ./common
+ serviceDir: ./vsftpd
+ entrypoint: service/startup.sh
+ command: service/vsftpd.sh
+
+ ftp-proxy:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-ftp-proxy
+ hostname: ${HOST_NAME:-ftp-proxy}
+ depends_on:
+ - vsftpd
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ shareDir: ./common
+ serviceDir: ./ftp-proxy
+ entrypoint: service/startup.sh
+ command: service/ftp-proxy.sh
+
+ danted:
+ extends:
+ file: ${SHARED_DATA}/docker-compose-common.yml
+ service: ${SHARED_SERVICE}
+ container_name: qt-test-server-danted
+ hostname: ${HOST_NAME:-danted}
+ depends_on:
+ - apache2
+ - vsftpd
+ - ftp-proxy
+ build:
+ context: .
+ args:
+ provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ shareDir: ./common
+ serviceDir: ./danted
+ entrypoint: service/startup.sh
+ command: service/danted.sh
+ environment:
+ - danted_internal=${MACHINE_IP}
+ - danted_external=${MACHINE_IP}
+ - danted_auth_internal=${MACHINE_IP}
+ - danted_auth_external=${MACHINE_IP}
diff --git a/tests/testserver/docker-compose.yml b/tests/testserver/docker-compose.yml
deleted file mode 100644
index be65e5a26a..0000000000
--- a/tests/testserver/docker-compose.yml
+++ /dev/null
@@ -1,83 +0,0 @@
-version: '3.4'
-
-# The tag of images is used by docker compose file to launch the corresponding
-# docker containers. The value of tag comes from the provisioning script
-# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
-# of each server context as the tag of docker images. If one of the server
-# contexts gets changes, please make sure to update this compose file as well.
-# You can run command 'docker images' to list all the tag of test server images.
-# For example:
-# REPOSITORY TAG
-# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
-
-services:
- apache2:
- image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
- container_name: qt-test-server-apache2
- domainname: ${TEST_DOMAIN}
- hostname: apache2
- volumes:
- - ./common:/common:ro
- - ./apache2:/service:ro
- entrypoint: common/startup.sh
- command: [common/ssl.sh, service/apache2.sh]
-
- squid:
- image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
- container_name: qt-test-server-squid
- domainname: ${TEST_DOMAIN}
- hostname: squid
- depends_on:
- - apache2
- external_links:
- - apache2:apache2.${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./squid:/service:ro
- entrypoint: common/startup.sh
- command: service/squid.sh
-
- vsftpd:
- image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
- container_name: qt-test-server-vsftpd
- domainname: ${TEST_DOMAIN}
- hostname: vsftpd
- volumes:
- - ./common:/common:ro
- - ./vsftpd:/service:ro
- entrypoint: common/startup.sh
- command: service/vsftpd.sh
-
- ftp-proxy:
- image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
- container_name: qt-test-server-ftp-proxy
- domainname: ${TEST_DOMAIN}
- hostname: ftp-proxy
- depends_on:
- - vsftpd
- external_links:
- - vsftpd:vsftpd.${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./ftp-proxy:/service:ro
- entrypoint: common/startup.sh
- command: service/ftp-proxy.sh
-
- danted:
- image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
- container_name: qt-test-server-danted
- domainname: ${TEST_DOMAIN}
- hostname: danted
- depends_on:
- - apache2
- - vsftpd
- - ftp-proxy
- external_links:
- - apache2:apache2.${TEST_DOMAIN}
- - vsftpd:vsftpd.${TEST_DOMAIN}
- - ftp-proxy:ftp-proxy.${TEST_DOMAIN}
- volumes:
- - ./common:/common:ro
- - ./danted:/service:ro
- entrypoint: common/startup.sh
- command: service/danted.sh
diff --git a/tests/testserver/echo/echo.sh b/tests/testserver/echo/echo.sh
new file mode 100755
index 0000000000..f0da9627d5
--- /dev/null
+++ b/tests/testserver/echo/echo.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+# Disabled by default, enable it.
+sed -i 's/disable\t\t= yes/disable = no/' /etc/xinetd.d/echo
+sed -i 's/disable\t\t= yes/disable = no/' /etc/xinetd.d/daytime
+
+service xinetd restart
diff --git a/tests/testserver/ftp-proxy/ftp-proxy.sh b/tests/testserver/ftp-proxy/ftp-proxy.sh
index 087a7b7bcc..e5b9631bbb 100755
--- a/tests/testserver/ftp-proxy/ftp-proxy.sh
+++ b/tests/testserver/ftp-proxy/ftp-proxy.sh
@@ -34,7 +34,9 @@ set -ex
# package ftp-proxy
# install configurations and test data
-sed -i 's/# AllowMagicUser\tno/AllowMagicUser\tyes/' /etc/proxy-suite/ftp-proxy.conf
+sed -i -e 's/# AllowMagicUser\tno/AllowMagicUser\tyes/' \
+ -e 's/# ForkLimit\t\t40/ForkLimit\t\t2000/' \
+ /etc/proxy-suite/ftp-proxy.conf
# enable service with installed configurations
ftp-proxy -d
diff --git a/tests/testserver/iptables/iptables.sh b/tests/testserver/iptables/iptables.sh
new file mode 100755
index 0000000000..9a48686d8b
--- /dev/null
+++ b/tests/testserver/iptables/iptables.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2019 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$
+## 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 or (at your option) 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.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-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+iptables -A INPUT -p tcp --destination-port 1357 -j DROP
diff --git a/tests/testserver/vsftpd/testdata/vsftpd.conf b/tests/testserver/vsftpd/testdata/vsftpd.conf
index 6bdb186c9f..e67cccefcc 100644
--- a/tests/testserver/vsftpd/testdata/vsftpd.conf
+++ b/tests/testserver/vsftpd/testdata/vsftpd.conf
@@ -101,6 +101,10 @@ userlist_enable=YES
listen=YES
tcp_wrappers=YES
+# An internal setting used for testing the relative benefit of using the
+# sendfile() system call on your platform.
+use_sendfile=NO
+
# Enabling SFTP
#ssl_enable=YES
#allow_anon_ssl=YES
diff --git a/tests/testserver/vsftpd/vsftpd.sh b/tests/testserver/vsftpd/vsftpd.sh
index 14364f94c2..bd09ad3902 100755
--- a/tests/testserver/vsftpd/vsftpd.sh
+++ b/tests/testserver/vsftpd/vsftpd.sh
@@ -54,6 +54,10 @@ ln -s /home/$USER/ftp /var/ftp
su $USER -c "mkdir -p ~/ftp/qtest/"
su $USER -c "cp rfc3252.txt ~/ftp/qtest/"; rm rfc3252.txt
+# tst_QNetworkReply::proxy_data()
+su $USER -c "ln ~/ftp/qtest/rfc3252.txt ~/ftp/qtest/rfc3252"
+su $USER -c "mkdir -p ~/ftp/qtest/nonASCII/"
+
# Duplicate rfc3252.txt 20 times for bigfile tests:
su $USER -c "seq 20 | xargs -i cat ~/ftp/qtest/rfc3252.txt >> ~/ftp/qtest/bigfile"