diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-09-05 11:08:59 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-09-05 11:08:59 +0200 |
commit | 2746518c76e02c642ff29faf568de4de90216e58 (patch) | |
tree | 822a6d979c13b6450c221b2a45ccfb6674bcb8e4 /tests | |
parent | 9e32b23a1514f367921b4a9ee25bc864a008463c (diff) | |
parent | bdf0a46c289298f7378796d62ae5fb283e08657d (diff) |
Merge remote-tracking branch 'origin/dev' into wip/qt6
Conflicts:
.qmake.conf
src/qml/qml/qqmlengine.cpp
src/qmlmodels/qqmlmodelsmodule.cpp
Change-Id: Id60420f8250a9c97fcfe56d4eea19b62c6870404
Diffstat (limited to 'tests')
94 files changed, 1547 insertions, 107 deletions
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index f304a99705..bda5d626a9 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -27,3 +27,15 @@ add_test(qtquickcompiler ${CMAKE_CTEST_COMMAND} --build-options "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" ${BUILD_OPTIONS_LIST} --test-command qqc_test ) + +add_test(qmlimportscanner ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMAKE_CURRENT_SOURCE_DIR}/qmlimportscanner/" + "${CMAKE_CURRENT_BINARY_DIR}/qmlimportscanner" + --build-config "${CMAKE_BUILD_TYPE}" + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-project qis_test + --build-options "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" ${BUILD_OPTIONS_LIST} + --test-command qis_test +) diff --git a/tests/auto/cmake/qmlimportscanner/CMakeLists.txt b/tests/auto/cmake/qmlimportscanner/CMakeLists.txt new file mode 100644 index 0000000000..354b0f8dfc --- /dev/null +++ b/tests/auto/cmake/qmlimportscanner/CMakeLists.txt @@ -0,0 +1,18 @@ + +cmake_minimum_required(VERSION 3.1) +project(qis_test) + +find_package(Qt5Qml 5.0.0 REQUIRED) +find_package(Qt5Gui 5.0.0 REQUIRED) +find_package(Qt5Test 5.0.0 REQUIRED) +find_package(Qt5QmlImportScanner REQUIRED) + +set(CMAKE_CXXFLAGS "${CMAKE_CXXFLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +add_executable(qis_test "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/qis_test.qrc") +target_link_libraries(qis_test PRIVATE Qt5::Gui Qt5::Qml Qt5::Test) +qt5_import_qml_plugins(qis_test) diff --git a/tests/auto/cmake/qmlimportscanner/main.cpp b/tests/auto/cmake/qmlimportscanner/main.cpp new file mode 100644 index 0000000000..370b10e113 --- /dev/null +++ b/tests/auto/cmake/qmlimportscanner/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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> +#include <QtQml> +#include <QtTest> + +class tst_QQC : public QObject +{ + Q_OBJECT +private slots: + void staticBuildTest(); +}; + +void tst_QQC::staticBuildTest() +{ +#ifdef QT_STATIC + QQmlEngine engine; + QQmlComponent component(&engine, QUrl("qrc:/main.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("success").toInt(), 42); +#endif +} + +QTEST_MAIN(tst_QQC) + +#include "main.moc" diff --git a/tests/auto/cmake/qmlimportscanner/main.qml b/tests/auto/cmake/qmlimportscanner/main.qml new file mode 100644 index 0000000000..e0101958ea --- /dev/null +++ b/tests/auto/cmake/qmlimportscanner/main.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 +import QtQuick 2.0 +QtObject { + property int success: 42 +} diff --git a/tests/auto/cmake/qmlimportscanner/qis_test.qrc b/tests/auto/cmake/qmlimportscanner/qis_test.qrc new file mode 100644 index 0000000000..1f88fc4e71 --- /dev/null +++ b/tests/auto/cmake/qmlimportscanner/qis_test.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> +<file>./main.qml</file> +<file alias="main.cpp">./main.cpp</file> +</qresource> +</RCC> diff --git a/tests/auto/qml/bindingdependencyapi/dummy_imports.qml b/tests/auto/qml/bindingdependencyapi/dummy_imports.qml new file mode 100644 index 0000000000..b9a196e188 --- /dev/null +++ b/tests/auto/qml/bindingdependencyapi/dummy_imports.qml @@ -0,0 +1,8 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in C++ +// code in tst_parserstress.cpp + +import QtQuick 2.0 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qjsengine/dummy_imports.qml b/tests/auto/qml/qjsengine/dummy_imports.qml new file mode 100644 index 0000000000..8d86f3583b --- /dev/null +++ b/tests/auto/qml/qjsengine/dummy_imports.qml @@ -0,0 +1,8 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in C++ +// code in tst_parserstress.cpp + +import QtQml 2.0 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 0ccb8210bc..1c895eb793 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -201,7 +201,9 @@ private slots: void engineForObject(); void intConversion_QTBUG43309(); +#ifdef QT_DEPRECATED void toFixed(); +#endif void argumentEvaluationOrder(); @@ -4323,7 +4325,10 @@ void tst_QJSEngine::engineForObject() QVERIFY(!qjsEngine(&object)); QJSValue wrapper = engine.newQObject(&object); QQmlEngine::setObjectOwnership(&object, QQmlEngine::CppOwnership); + QVERIFY(qjsEngine(&object)); +#ifdef QT_DEPRECATED QCOMPARE(qjsEngine(&object), wrapper.engine()); +#endif } QVERIFY(!qjsEngine(&object)); } @@ -4338,6 +4343,7 @@ void tst_QJSEngine::intConversion_QTBUG43309() QCOMPARE(result.toNumber(), 25.0); } +#ifdef QT_DEPRECATED // QTBUG-44039 and QTBUG-43885: void tst_QJSEngine::toFixed() { @@ -4349,6 +4355,7 @@ void tst_QJSEngine::toFixed() QVERIFY(result.isString()); QCOMPARE(result.toString(), QStringLiteral("12.1")); } +#endif void tst_QJSEngine::argumentEvaluationOrder() { diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index 4de72ae7a1..37d0ea4dea 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -52,7 +52,9 @@ void tst_QJSValue::ctor_invalid() { QJSValue v; QVERIFY(v.isUndefined()); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } } @@ -63,7 +65,9 @@ void tst_QJSValue::ctor_undefinedWithEngine() QJSValue v = eng.toScriptValue(QVariant()); QVERIFY(v.isUndefined()); QCOMPARE(v.isObject(), false); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -75,7 +79,9 @@ void tst_QJSValue::ctor_nullWithEngine() QVERIFY(!v.isUndefined()); QCOMPARE(v.isNull(), true); QCOMPARE(v.isObject(), false); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -88,7 +94,9 @@ void tst_QJSValue::ctor_boolWithEngine() QCOMPARE(v.isBool(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toBool(), false); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -101,7 +109,9 @@ void tst_QJSValue::ctor_intWithEngine() QCOMPARE(v.isNumber(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toNumber(), 1.0); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -118,7 +128,9 @@ void tst_QJSValue::ctor_int() QCOMPARE(v.isNumber(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toNumber(), 1.0); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } } @@ -131,7 +143,9 @@ void tst_QJSValue::ctor_uintWithEngine() QCOMPARE(v.isNumber(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toNumber(), 1.0); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -148,7 +162,9 @@ void tst_QJSValue::ctor_uint() QCOMPARE(v.isNumber(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toNumber(), 1.0); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } } @@ -161,7 +177,9 @@ void tst_QJSValue::ctor_floatWithEngine() QCOMPARE(v.isNumber(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toNumber(), 1.0); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -178,7 +196,9 @@ void tst_QJSValue::ctor_float() QCOMPARE(v.isNumber(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toNumber(), 1.0); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } } @@ -191,7 +211,9 @@ void tst_QJSValue::ctor_stringWithEngine() QCOMPARE(v.isString(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toString(), QLatin1String("ciao")); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), &eng); +#endif } } @@ -203,7 +225,9 @@ void tst_QJSValue::ctor_string() QCOMPARE(v.isString(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toString(), QLatin1String("ciao")); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } { QJSValue v("ciao"); @@ -211,7 +235,9 @@ void tst_QJSValue::ctor_string() QCOMPARE(v.isString(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toString(), QLatin1String("ciao")); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } } @@ -223,12 +249,16 @@ void tst_QJSValue::ctor_copyAndAssignWithEngine() QJSValue v = eng.toScriptValue(1.0); QJSValue v2(v); QCOMPARE(v2.strictlyEquals(v), true); +#ifdef QT_DEPRECATED QCOMPARE(v2.engine(), &eng); +#endif QJSValue v3(v); QCOMPARE(v3.strictlyEquals(v), true); QCOMPARE(v3.strictlyEquals(v2), true); +#ifdef QT_DEPRECATED QCOMPARE(v3.engine(), &eng); +#endif QJSValue v4 = eng.toScriptValue(2.0); QCOMPARE(v4.strictlyEquals(v), false); @@ -253,7 +283,9 @@ void tst_QJSValue::ctor_undefined() QJSValue v(QJSValue::UndefinedValue); QVERIFY(v.isUndefined()); QCOMPARE(v.isObject(), false); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } void tst_QJSValue::ctor_null() @@ -262,7 +294,9 @@ void tst_QJSValue::ctor_null() QVERIFY(!v.isUndefined()); QCOMPARE(v.isNull(), true); QCOMPARE(v.isObject(), false); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } void tst_QJSValue::ctor_bool() @@ -273,7 +307,9 @@ void tst_QJSValue::ctor_bool() QCOMPARE(v.isBool(), true); QCOMPARE(v.isObject(), false); QCOMPARE(v.toBool(), false); +#ifdef QT_DEPRECATED QCOMPARE(v.engine(), (QJSEngine *)nullptr); +#endif } void tst_QJSValue::ctor_copyAndAssign() @@ -281,12 +317,16 @@ void tst_QJSValue::ctor_copyAndAssign() QJSValue v(1.0); QJSValue v2(v); QCOMPARE(v2.strictlyEquals(v), true); +#ifdef QT_DEPRECATED QCOMPARE(v2.engine(), (QJSEngine *)nullptr); +#endif QJSValue v3(v); QCOMPARE(v3.strictlyEquals(v), true); QCOMPARE(v3.strictlyEquals(v2), true); +#ifdef QT_DEPRECATED QCOMPARE(v3.engine(), (QJSEngine *)nullptr); +#endif QJSValue v4(2.0); QCOMPARE(v4.strictlyEquals(v), false); @@ -423,7 +463,9 @@ void tst_QJSValue::toString() QCOMPARE(o.toString(), QStringLiteral("[object Object]")); o = createUnboundValue(o); +#ifdef QT_DEPRECATED QVERIFY(!o.engine()); +#endif QCOMPARE(o.toString(), QStringLiteral("[object Object]")); } @@ -435,7 +477,9 @@ void tst_QJSValue::toString() QCOMPARE(o.toString(), QStringLiteral("1,2,3")); o = createUnboundValue(o); +#ifdef QT_DEPRECATED QVERIFY(!o.engine()); +#endif QCOMPARE(o.toString(), QStringLiteral("1,2,3")); } @@ -1641,10 +1685,14 @@ void tst_QJSValue::getSetProperty() QCOMPARE(object.property("baz").toNumber(), num.toNumber()); QJSValue strstr = QJSValue("bar"); +#ifdef QT_DEPRECATED QCOMPARE(strstr.engine(), (QJSEngine *)nullptr); +#endif object.setProperty("foo", strstr); QCOMPARE(object.property("foo").toString(), strstr.toString()); +#ifdef QT_DEPRECATED QCOMPARE(strstr.engine(), &eng); // the value has been bound to the engine +#endif QJSValue numnum = QJSValue(123.0); object.setProperty("baz", numnum); @@ -2536,15 +2584,18 @@ void tst_QJSValue::engineDeleted() delete eng; QVERIFY(v1.isUndefined()); - QVERIFY(!v1.engine()); QVERIFY(v2.isUndefined()); - QVERIFY(!v2.engine()); QVERIFY(v3.isUndefined()); - QVERIFY(!v3.engine()); QVERIFY(v4.isUndefined()); - QVERIFY(!v4.engine()); QVERIFY(v5.isString()); // was not bound to engine + +#ifdef QT_DEPRECATED + QVERIFY(!v1.engine()); + QVERIFY(!v2.engine()); + QVERIFY(!v3.engine()); + QVERIFY(!v4.engine()); QVERIFY(!v5.engine()); +#endif QVERIFY(v3.property("foo").isUndefined()); } diff --git a/tests/auto/qml/qmldiskcache/dummy_imports.qml b/tests/auto/qml/qmldiskcache/dummy_imports.qml new file mode 100644 index 0000000000..b9a196e188 --- /dev/null +++ b/tests/auto/qml/qmldiskcache/dummy_imports.qml @@ -0,0 +1,8 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in C++ +// code in tst_parserstress.cpp + +import QtQuick 2.0 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qmllint/data/CatchStatement.qml b/tests/auto/qml/qmllint/data/CatchStatement.qml new file mode 100644 index 0000000000..e0f70fce7e --- /dev/null +++ b/tests/auto/qml/qmllint/data/CatchStatement.qml @@ -0,0 +1,8 @@ +import QtQml 2.12 + +QtObject { + function f() { + try {} catch(err) {} + console.log(err); + } +} diff --git a/tests/auto/qml/qmllint/data/catchIdentifierNoWarning.qml b/tests/auto/qml/qmllint/data/catchIdentifierNoWarning.qml new file mode 100644 index 0000000000..097baa6fcf --- /dev/null +++ b/tests/auto/qml/qmllint/data/catchIdentifierNoWarning.qml @@ -0,0 +1,7 @@ +import QtQml 2.12 + +QtObject { + function f() { + try {} catch(err) {console.log(err);} + } +} diff --git a/tests/auto/qml/qmllint/qmllint.pro b/tests/auto/qml/qmllint/qmllint.pro index b53a6f6877..95470b4085 100644 --- a/tests/auto/qml/qmllint/qmllint.pro +++ b/tests/auto/qml/qmllint/qmllint.pro @@ -1,6 +1,11 @@ -TEMPLATE = app -TARGET = testqmllint -INCLUDEPATH += . +CONFIG += testcase +TARGET = tst_qmllint +macos:CONFIG -= app_bundle + +SOURCES += tst_qmllint.cpp + +include (../../shared/util.pri) + +TESTDATA = data/* -SOURCES += main.cpp QT += testlib diff --git a/tests/auto/qml/qmllint/main.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 928575bc82..582f146dca 100644 --- a/tests/auto/qml/qmllint/main.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -30,23 +30,27 @@ #include <QProcess> #include <QString> -class TestQmllint: public QObject +#include <util.h> + +class TestQmllint: public QQmlDataTest { Q_OBJECT private Q_SLOTS: - void initTestCase(); + void initTestCase() override; void test(); void test_data(); void testUnqualified(); void testUnqualified_data(); void testUnqualifiedNoSpuriousParentWarning(); + void catchIdentifierNoFalsePositive(); private: QString m_qmllintPath; }; void TestQmllint::initTestCase() { + QQmlDataTest::initTestCase(); m_qmllintPath = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/qmllint"); #ifdef Q_OS_WIN m_qmllintPath += QLatin1String(".exe"); @@ -79,9 +83,8 @@ void TestQmllint::testUnqualified() QFETCH(QString, warningMessage); QFETCH(int, warningLine); QFETCH(int, warningColumn); - filename.prepend(QStringLiteral("data/")); QStringList args; - args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir; + args << QStringLiteral("-U") << testFile(filename) << QStringLiteral("-I") << qmlImportDir; QProcess process; process.start(m_qmllintPath, args); @@ -113,15 +116,15 @@ void TestQmllint::testUnqualified_data() QTest::newRow("SignalHandler2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPositionChanged: function(mouse) {...") << 10 << 21; QTest::newRow("SignalHandlerShort1") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onClicked: (mouse) => {...") << 8 << 29; QTest::newRow("SignalHandlerShort2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPressAndHold: (mouse) => {...") << 12 << 34; - + // access catch identifier outside catch block + QTest::newRow("CatchStatement") << QStringLiteral("CatchStatement.qml") << QStringLiteral("err") << 6 << 21; } void TestQmllint::testUnqualifiedNoSpuriousParentWarning() { auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); { - QString filename = QLatin1String("spuriousParentWarning.qml"); - filename.prepend(QStringLiteral("data/")); + QString filename = testFile("spuriousParentWarning.qml"); QStringList args; args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir; QProcess process; @@ -131,8 +134,7 @@ void TestQmllint::testUnqualifiedNoSpuriousParentWarning() QVERIFY(process.exitCode() == 0); } { - QString filename = QLatin1String("nonSpuriousParentWarning.qml"); - filename.prepend(QStringLiteral("data/")); + QString filename = testFile("nonSpuriousParentWarning.qml"); QStringList args; args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir; QProcess process; @@ -143,17 +145,30 @@ void TestQmllint::testUnqualifiedNoSpuriousParentWarning() } } +void TestQmllint::catchIdentifierNoFalsePositive() +{ + auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); + QString filename = QLatin1String("catchIdentifierNoWarning.qml"); + filename.prepend(QStringLiteral("data/")); + QStringList args; + args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir; + QProcess process; + process.start(m_qmllintPath, args); + QVERIFY(process.waitForFinished()); + QVERIFY(process.exitStatus() == QProcess::NormalExit); + QVERIFY(process.exitCode() == 0); +} + void TestQmllint::test() { QFETCH(QString, filename); QFETCH(bool, isValid); - filename = QStringLiteral("data/") + filename; QStringList args; - args << QStringLiteral("--silent") << filename; + args << QStringLiteral("--silent") << testFile(filename); bool success = QProcess::execute(m_qmllintPath, args) == 0; QCOMPARE(success, isValid); } QTEST_MAIN(TestQmllint) -#include "main.moc" +#include "tst_qmllint.moc" diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp index 8787a43884..0f5eea8b95 100644 --- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp +++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp @@ -52,6 +52,7 @@ private slots: void removeObjectsWhenDestroyed(); void loadTranslation_data(); void loadTranslation(); + void setInitialProperties(); private: QString buildDir; @@ -275,6 +276,23 @@ void tst_qqmlapplicationengine::loadTranslation() QCOMPARE(rootObject->property("translation").toString(), translation); } +void tst_qqmlapplicationengine::setInitialProperties() +{ + QQmlApplicationEngine test {}; + { + test.setInitialProperties(QVariantMap{{"success", false}}); + test.load(testFileUrl("basicTest.qml")); + QVERIFY(!test.rootObjects().empty()); + QCOMPARE(test.rootObjects().first()->property("success").toBool(), false); + } + { + test.setInitialProperties({{"success", true}}); + test.load(testFileUrl("basicTest.qml")); + QCOMPARE(test.rootObjects().size(), 2); + QCOMPARE(test.rootObjects().at(1)->property("success").toBool(), true); + } +} + QTEST_MAIN(tst_qqmlapplicationengine) #include "tst_qqmlapplicationengine.moc" diff --git a/tests/auto/qml/qqmlcomponent/data/allJSONTypes.qml b/tests/auto/qml/qqmlcomponent/data/allJSONTypes.qml new file mode 100644 index 0000000000..0541c9b104 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/allJSONTypes.qml @@ -0,0 +1,9 @@ +import QtQuick 2.14 + +Item { + property int i + property bool b + property double d + property string s + property var nothing +} diff --git a/tests/auto/qml/qqmlcomponent/data/variantBasedInitialization.qml b/tests/auto/qml/qqmlcomponent/data/variantBasedInitialization.qml new file mode 100644 index 0000000000..acf08e94d2 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/variantBasedInitialization.qml @@ -0,0 +1,21 @@ +import QtQuick 2.14 + +Item { + property int i + property bool b + property double d + property string s + property var nothing + property url myurl + property color c + property font myfont + property date mydate + property point mypoint + property size mysize + property rect myrect + property matrix4x4 matrix + property quaternion quat + property vector2d vec2 + property vector3d vec3 + property vector4d vec4 +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 71d3e8fe5f..79ec507388 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -121,6 +121,7 @@ private slots: void relativeUrl_data(); void relativeUrl(); void setDataNoEngineNoSegfault(); + void testSetInitialProperties(); private: QQmlEngine engine; @@ -667,6 +668,101 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault() QVERIFY(!c); } +void tst_qqmlcomponent::testSetInitialProperties() +{ + QQmlEngine eng; + { + // JSON based initialization + QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("allJSONTypes.qml")); + QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) }; + QVERIFY(obj); + comp.setInitialProperties(obj.get(), QVariantMap { + {QLatin1String("i"), 42}, + {QLatin1String("b"), true}, + {QLatin1String("d"), 3.1416}, + {QLatin1String("s"), QLatin1String("hello world")}, + {QLatin1String("nothing"), QVariant::fromValue(nullptr)} + }); + comp.completeCreate(); + if (!comp.errors().empty()) + qDebug() << comp.errorString() << comp.errors(); + QVERIFY(comp.errors().empty()); + QCOMPARE(obj->property("i"), 42); + QCOMPARE(obj->property("b"), true); + QCOMPARE(obj->property("d"), 3.1416); + QCOMPARE(obj->property("s"), QLatin1String("hello world")); + QCOMPARE(obj->property("nothing"), QVariant::fromValue(nullptr)); + } + { + // QVariant + QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("variantBasedInitialization.qml")); + QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) }; + QVERIFY(obj); + QUrl myurl = comp.url(); + QFont myfont; + QDateTime mydate = QDateTime::currentDateTime(); + QPoint mypoint {1,2}; + QSizeF mysize {0.5, 0.3}; + QMatrix4x4 matrix {}; + QQuaternion quat {5.0f, 0.3f, 0.2f, 0.1f}; + QVector2D vec2 {2.0f, 3.1f}; + QVector3D vec3 {1.0f, 2.0, 3.0f}; + QVector4D vec4 {1.0f, 2.0f, 3.0f, 4.0f}; +#define ASJSON(NAME) {QLatin1String(#NAME), NAME} + comp.setInitialProperties(obj.get(), QVariantMap { + {QLatin1String("i"), 42}, + {QLatin1String("b"), true}, + {QLatin1String("d"), 3.1416}, + {QLatin1String("s"), QLatin1String("hello world")}, + {QLatin1String("nothing"), QVariant::fromValue( nullptr)}, + ASJSON(myurl), + ASJSON(myfont), + ASJSON(mydate), + ASJSON(mypoint), + ASJSON(mysize), + ASJSON(matrix), + ASJSON(quat), + ASJSON(vec2), ASJSON(vec3), ASJSON(vec4) + }); +#undef ASJSON + comp.completeCreate(); + if (!comp.errors().empty()) + qDebug() << comp.errorString() << comp.errors(); + QVERIFY(comp.errors().empty()); + QCOMPARE(obj->property("i"), 42); + QCOMPARE(obj->property("b"), true); + QCOMPARE(obj->property("d"), 3.1416); + QCOMPARE(obj->property("s"), QLatin1String("hello world")); + QCOMPARE(obj->property("nothing"), QVariant::fromValue(nullptr)); +#define COMPARE(NAME) QCOMPARE(obj->property(#NAME), NAME) + COMPARE(myurl); + COMPARE(myfont); + COMPARE(mydate); + COMPARE(mypoint); + COMPARE(mysize); + COMPARE(matrix); + COMPARE(quat); + COMPARE(vec2); + COMPARE(vec3); + COMPARE(vec4); +#undef COMPARE + + } + { + // createWithInitialProperties: setting a nonexistent property + QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("allJSONTypes.qml")); + QScopedPointer<QObject> obj { + comp.createWithInitialProperties(QVariantMap { {"notThePropertiesYoureLookingFor", 42} }) + }; + qDebug() << comp.errorString(); + QVERIFY(obj); + QVERIFY(comp.errorString().contains("Could not set property notThePropertiesYoureLookingFor")); + } +} + QTEST_MAIN(tst_qqmlcomponent) #include "tst_qqmlcomponent.moc" diff --git a/tests/auto/qml/qqmlconnections/data/connection-no-signal-name.qml b/tests/auto/qml/qqmlconnections/data/bindings/connection-no-signal-name.qml index 462a9577ff..462a9577ff 100644 --- a/tests/auto/qml/qqmlconnections/data/connection-no-signal-name.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/connection-no-signal-name.qml diff --git a/tests/auto/qml/qqmlconnections/data/connection-targetchange.qml b/tests/auto/qml/qqmlconnections/data/bindings/connection-targetchange.qml index 154c309c9c..154c309c9c 100644 --- a/tests/auto/qml/qqmlconnections/data/connection-targetchange.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/connection-targetchange.qml diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-ignored.qml b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals-ignored.qml index 0780dd1509..0780dd1509 100644 --- a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-ignored.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals-ignored.qml diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-notarget.qml b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals-notarget.qml index 3da3e0f5d1..3da3e0f5d1 100644 --- a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-notarget.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals-notarget.qml diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-parent.qml b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals-parent.qml index 2c55215579..2c55215579 100644 --- a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-parent.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals-parent.qml diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals.qml b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals.qml index a351016b4a..a351016b4a 100644 --- a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/connection-unknownsignals.qml diff --git a/tests/auto/qml/qqmlconnections/data/disabled-at-start.qml b/tests/auto/qml/qqmlconnections/data/bindings/disabled-at-start.qml index 1a823f87f6..1a823f87f6 100644 --- a/tests/auto/qml/qqmlconnections/data/disabled-at-start.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/disabled-at-start.qml diff --git a/tests/auto/qml/qqmlconnections/data/override-proxy-type.qml b/tests/auto/qml/qqmlconnections/data/bindings/override-proxy-type.qml index 80e459966b..80e459966b 100644 --- a/tests/auto/qml/qqmlconnections/data/override-proxy-type.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/override-proxy-type.qml diff --git a/tests/auto/qml/qqmlconnections/data/rewriteError-global.qml b/tests/auto/qml/qqmlconnections/data/bindings/rewriteError-global.qml index 1d0b557069..1d0b557069 100644 --- a/tests/auto/qml/qqmlconnections/data/rewriteError-global.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/rewriteError-global.qml diff --git a/tests/auto/qml/qqmlconnections/data/rewriteError-unnamed.qml b/tests/auto/qml/qqmlconnections/data/bindings/rewriteError-unnamed.qml index a4849e994b..a4849e994b 100644 --- a/tests/auto/qml/qqmlconnections/data/rewriteError-unnamed.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/rewriteError-unnamed.qml diff --git a/tests/auto/qml/qqmlconnections/data/singletontype-target.qml b/tests/auto/qml/qqmlconnections/data/bindings/singletontype-target.qml index 7de488c2dd..7de488c2dd 100644 --- a/tests/auto/qml/qqmlconnections/data/singletontype-target.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/singletontype-target.qml diff --git a/tests/auto/qml/qqmlconnections/data/test-connection-implicit.qml b/tests/auto/qml/qqmlconnections/data/bindings/test-connection-implicit.qml index d5aa0f102a..d5aa0f102a 100644 --- a/tests/auto/qml/qqmlconnections/data/test-connection-implicit.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/test-connection-implicit.qml diff --git a/tests/auto/qml/qqmlconnections/data/test-connection.qml b/tests/auto/qml/qqmlconnections/data/bindings/test-connection.qml index f44cbc047f..f44cbc047f 100644 --- a/tests/auto/qml/qqmlconnections/data/test-connection.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/test-connection.qml diff --git a/tests/auto/qml/qqmlconnections/data/trimming.qml b/tests/auto/qml/qqmlconnections/data/bindings/trimming.qml index 4c37eb22af..4c37eb22af 100644 --- a/tests/auto/qml/qqmlconnections/data/trimming.qml +++ b/tests/auto/qml/qqmlconnections/data/bindings/trimming.qml diff --git a/tests/auto/qml/qqmlconnections/data/functions/connection-no-signal-name.qml b/tests/auto/qml/qqmlconnections/data/functions/connection-no-signal-name.qml new file mode 100644 index 0000000000..04cc36b3c5 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/connection-no-signal-name.qml @@ -0,0 +1,15 @@ +import QtQuick 2.4 + +Item { + id: blaBlaBla + function hint() { + } + + Connections { + //target: blaBlaBla + // function onHint() { hint() }; + on: true + } +} + + diff --git a/tests/auto/qml/qqmlconnections/data/functions/connection-targetchange.qml b/tests/auto/qml/qqmlconnections/data/functions/connection-targetchange.qml new file mode 100644 index 0000000000..692194e837 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/connection-targetchange.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Item { + Component { + id: item1 + Item { + objectName: "item1" + } + } + Component { + id: item2 + Item { + objectName: "item2" + } + } + Loader { + id: loader + sourceComponent: item1 + } + Connections { + objectName: "connections" + target: loader.item + function onWidthChanged() { loader.sourceComponent = item2 } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-ignored.qml b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-ignored.qml new file mode 100644 index 0000000000..f70d8cdb15 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-ignored.qml @@ -0,0 +1,17 @@ +import QtQml 2.0 + +QtObject { + id: root + + property Connections c1: Connections { + target: root; + function onNotFooBar1() {} + ignoreUnknownSignals: true + } + + property Connections c2: Connections { + objectName: "connections" + function onNotFooBar2() {} + ignoreUnknownSignals: true + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-notarget.qml b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-notarget.qml new file mode 100644 index 0000000000..7658728dd9 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-notarget.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 + +QtObject { + property Connections c1: Connections { + objectName: "connections" + target: null + function onNotFooBar() {} + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-parent.qml b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-parent.qml new file mode 100644 index 0000000000..ece76b0cf7 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals-parent.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 + +QtObject { + property Connections c1: Connections { + objectName: "connections" + function onFooBar() {} + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals.qml b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals.qml new file mode 100644 index 0000000000..a198a724d0 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/connection-unknownsignals.qml @@ -0,0 +1,11 @@ +import QtQml 2.0 + +QtObject { + id: screen + + property Connections c1: Connections { + objectName: "connections" + target: screen + function onFooBar() {} + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/disabled-at-start.qml b/tests/auto/qml/qqmlconnections/data/functions/disabled-at-start.qml new file mode 100644 index 0000000000..981437fe8c --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/disabled-at-start.qml @@ -0,0 +1,14 @@ +import QtQuick 2.9 + +Item { + id: root + + property bool tested: false + signal testMe() + + Connections { + target: root + enabled: false + function onTestMe() { root.tested = true; } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/override-proxy-type.qml b/tests/auto/qml/qqmlconnections/data/functions/override-proxy-type.qml new file mode 100644 index 0000000000..b83f0baa11 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/override-proxy-type.qml @@ -0,0 +1,13 @@ +import QtQml 2.12 +import test.proxy 1.0 + +Proxy { + property int testEnum: 0; + id: proxy + property Connections connections: Connections { + target: proxy + function onSomeSignal() { testEnum = Proxy.EnumValue } + } + + Component.onCompleted: someSignal() +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/rewriteError-global.qml b/tests/auto/qml/qqmlconnections/data/functions/rewriteError-global.qml new file mode 100644 index 0000000000..de3154c431 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/rewriteError-global.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 +import Test 1.0 + +TestObject { + property QtObject connection: Connections { + function onSignalWithGlobalName() { ran = true } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/rewriteError-unnamed.qml b/tests/auto/qml/qqmlconnections/data/functions/rewriteError-unnamed.qml new file mode 100644 index 0000000000..fa1d1b17d7 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/rewriteError-unnamed.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import Test 1.0 + +TestObject { + property QtObject connection: Connections { + function onUnnamedArgumentSignal() { ran = true } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/singletontype-target.qml b/tests/auto/qml/qqmlconnections/data/functions/singletontype-target.qml new file mode 100644 index 0000000000..935b610351 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/singletontype-target.qml @@ -0,0 +1,22 @@ +import QtQml 2.0 +import MyTestSingletonType 1.0 as MyTestSingletonType + +QtObject { + id: rootObject + objectName: "rootObject" + property int newIntPropValue: 12 + + property int moduleIntPropChangedCount: 0 + property int moduleOtherSignalCount: 0 + + function setModuleIntProp() { + MyTestSingletonType.Api.intProp = newIntPropValue; + newIntPropValue = newIntPropValue + 1; + } + + property Connections c: Connections { + target: MyTestSingletonType.Api + function onIntPropChanged() { moduleIntPropChangedCount = moduleIntPropChangedCount + 1 } + function onOtherSignal() { moduleOtherSignalCount = moduleOtherSignalCount + 1 } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/test-connection-implicit.qml b/tests/auto/qml/qqmlconnections/data/functions/test-connection-implicit.qml new file mode 100644 index 0000000000..2ed5278636 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/test-connection-implicit.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 + +Item { + width: 50 + + property bool tested: false + + Connections { function onWidthChanged() { tested = true } } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/test-connection.qml b/tests/auto/qml/qqmlconnections/data/functions/test-connection.qml new file mode 100644 index 0000000000..c706797ea4 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/test-connection.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + id: screen; width: 50 + + property bool tested: false + signal testMe + + Connections { + objectName: "connections" + target: screen; + function onWidthChanged() { screen.tested = true } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/functions/trimming.qml b/tests/auto/qml/qqmlconnections/data/functions/trimming.qml new file mode 100644 index 0000000000..7dfd673539 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/functions/trimming.qml @@ -0,0 +1,13 @@ +import QtQml 2.0 + +QtObject { + id: root + + property string tested + signal testMe(int param1, string param2) + + property Connections c: Connections { + target: root + function onTestMe(param1, param2) { root.tested = param2 + param1 } + } +} diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index 7e6a0f79f9..cf0f3c7bb3 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -42,29 +42,57 @@ public: private slots: void defaultValues(); void properties(); + + void connection_data() { prefixes(); } void connection(); + + void trimming_data() { prefixes(); } void trimming(); + + void targetChanged_data() { prefixes(); }; void targetChanged(); + void unknownSignals_data(); void unknownSignals(); + void errors_data(); void errors(); + + void rewriteErrors_data() { prefixes(); } void rewriteErrors(); + + void singletonTypeTarget_data() { prefixes(); } void singletonTypeTarget(); + + void enableDisable_QTBUG_36350_data() { prefixes(); } void enableDisable_QTBUG_36350(); + + void disabledAtStart_data() { prefixes(); } void disabledAtStart(); + + void clearImplicitTarget_data() { prefixes(); } void clearImplicitTarget(); void onWithoutASignal(); + + void noAcceleratedGlobalLookup_data() { prefixes(); } void noAcceleratedGlobalLookup(); private: QQmlEngine engine; + void prefixes(); }; tst_qqmlconnections::tst_qqmlconnections() { } +void tst_qqmlconnections::prefixes() +{ + QTest::addColumn<QString>("prefix"); + QTest::newRow("functions") << QString("functions"); + QTest::newRow("bindings") << QString("bindings"); +} + void tst_qqmlconnections::defaultValues() { QQmlEngine engine; @@ -93,8 +121,9 @@ void tst_qqmlconnections::properties() void tst_qqmlconnections::connection() { + QFETCH(QString, prefix); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-connection.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection.qml")); QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); QVERIFY(item != nullptr); @@ -110,8 +139,9 @@ void tst_qqmlconnections::connection() void tst_qqmlconnections::trimming() { + QFETCH(QString, prefix); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("trimming.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/trimming.qml")); QObject *object = c.create(); QVERIFY(object != nullptr); @@ -131,8 +161,9 @@ void tst_qqmlconnections::trimming() // Confirm that target can be changed by one of our signal handlers void tst_qqmlconnections::targetChanged() { + QFETCH(QString, prefix); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("connection-targetchange.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/connection-targetchange.qml")); QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); QVERIFY(item != nullptr); @@ -158,10 +189,15 @@ void tst_qqmlconnections::unknownSignals_data() QTest::addColumn<QString>("file"); QTest::addColumn<QString>("error"); - QTest::newRow("basic") << "connection-unknownsignals.qml" << ":6:30: QML Connections: Cannot assign to non-existent property \"onFooBar\""; - QTest::newRow("parent") << "connection-unknownsignals-parent.qml" << ":4:30: QML Connections: Cannot assign to non-existent property \"onFooBar\""; - QTest::newRow("ignored") << "connection-unknownsignals-ignored.qml" << ""; // should be NO error - QTest::newRow("notarget") << "connection-unknownsignals-notarget.qml" << ""; // should be NO error + QTest::newRow("functions/basic") << "functions/connection-unknownsignals.qml" << ":6:30: QML Connections: Detected function \"onFooBar\" in Connections element. This is probably intended to be a signal handler but no signal of the target matches the name."; + QTest::newRow("functions/parent") << "functions/connection-unknownsignals-parent.qml" << ":4:30: QML Connections: Detected function \"onFooBar\" in Connections element. This is probably intended to be a signal handler but no signal of the target matches the name."; + QTest::newRow("functions/ignored") << "functions/connection-unknownsignals-ignored.qml" << ""; // should be NO error + QTest::newRow("functions/notarget") << "functions/connection-unknownsignals-notarget.qml" << ""; // should be NO error + + QTest::newRow("bindings/basic") << "bindings/connection-unknownsignals.qml" << ":6:30: QML Connections: Cannot assign to non-existent property \"onFooBar\""; + QTest::newRow("bindings/parent") << "bindings/connection-unknownsignals-parent.qml" << ":4:30: QML Connections: Cannot assign to non-existent property \"onFooBar\""; + QTest::newRow("bindings/ignored") << "bindings/connection-unknownsignals-ignored.qml" << ""; // should be NO error + QTest::newRow("bindings/notarget") << "bindings/connection-unknownsignals-notarget.qml" << ""; // should be NO error } void tst_qqmlconnections::unknownSignals() @@ -239,10 +275,11 @@ private: void tst_qqmlconnections::rewriteErrors() { + QFETCH(QString, prefix); qmlRegisterType<TestObject>("Test", 1, 0, "TestObject"); { QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("rewriteError-unnamed.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/rewriteError-unnamed.qml")); QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1()); TestObject *obj = qobject_cast<TestObject*>(c.create()); QVERIFY(obj != nullptr); @@ -254,7 +291,7 @@ void tst_qqmlconnections::rewriteErrors() { QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("rewriteError-global.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/rewriteError-global.qml")); QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1()); TestObject *obj = qobject_cast<TestObject*>(c.create()); QVERIFY(obj != nullptr); @@ -305,8 +342,9 @@ static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine) // QTBUG-20937 void tst_qqmlconnections::singletonTypeTarget() { + QFETCH(QString, prefix); qmlRegisterSingletonType<MyTestSingletonType>("MyTestSingletonType", 1, 0, "Api", module_api_factory); - QQmlComponent component(&engine, testFileUrl("singletontype-target.qml")); + QQmlComponent component(&engine, testFileUrl(prefix + "/singletontype-target.qml")); QObject *object = component.create(); QVERIFY(object != nullptr); @@ -331,8 +369,9 @@ void tst_qqmlconnections::singletonTypeTarget() void tst_qqmlconnections::enableDisable_QTBUG_36350() { + QFETCH(QString, prefix); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-connection.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection.qml")); QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); QVERIFY(item != nullptr); @@ -358,8 +397,9 @@ void tst_qqmlconnections::enableDisable_QTBUG_36350() void tst_qqmlconnections::disabledAtStart() { + QFETCH(QString, prefix); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("disabled-at-start.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/disabled-at-start.qml")); QObject * const object = c.create(); QVERIFY(object != nullptr); @@ -376,8 +416,9 @@ void tst_qqmlconnections::disabledAtStart() //QTBUG-56499 void tst_qqmlconnections::clearImplicitTarget() { + QFETCH(QString, prefix); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-connection-implicit.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection-implicit.qml")); QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); QVERIFY(item != nullptr); @@ -421,10 +462,11 @@ signals: void tst_qqmlconnections::noAcceleratedGlobalLookup() { + QFETCH(QString, prefix); qRegisterMetaType<Proxy::MyEnum>(); qmlRegisterType<Proxy>("test.proxy", 1, 0, "Proxy"); QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("override-proxy-type.qml")); + QQmlComponent c(&engine, testFileUrl(prefix + "/override-proxy-type.qml")); QVERIFY(c.isReady()); QScopedPointer<QObject> object(c.create()); const QVariant val = object->property("testEnum"); diff --git a/tests/auto/qml/qqmlecmascript/data/semicolonAfterProperty.qml b/tests/auto/qml/qqmlecmascript/data/semicolonAfterProperty.qml new file mode 100644 index 0000000000..0a75ea6f36 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/semicolonAfterProperty.qml @@ -0,0 +1,10 @@ +import QtQml 2.0 + +QtObject { + property var field: { "key": "value"}; + property list<QtObject> mylist: [ + QtObject {id: a}, + QtObject {id: b} + ]; + property var object: QtObject {}; +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index b44fe9766c..269d90c891 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -374,6 +374,7 @@ private slots: void hugeRegexpQuantifiers(); void singletonTypeWrapperLookup(); void getThisObject(); + void semicolonAfterProperty(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -9106,6 +9107,16 @@ void tst_qqmlecmascript::getThisObject() QTRY_COMPARE(qvariant_cast<QObject *>(test->property("self")), test.data()); } +// QTBUG-77954 +void tst_qqmlecmascript::semicolonAfterProperty() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("semicolonAfterProperty.qml")); + QVERIFY(component.isReady()); + QScopedPointer<QObject> test(component.create()); + QVERIFY(!test.isNull()); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmllanguage/data/propertyUnknownType.errors.txt b/tests/auto/qml/qqmllanguage/data/propertyUnknownType.errors.txt new file mode 100644 index 0000000000..1655f9264a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/propertyUnknownType.errors.txt @@ -0,0 +1 @@ +3:23:Cannot assign to property of unknown type "SomethingUnknown*". diff --git a/tests/auto/qml/qqmllanguage/data/propertyUnknownType.qml b/tests/auto/qml/qqmllanguage/data/propertyUnknownType.qml new file mode 100644 index 0000000000..c22fd65350 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/propertyUnknownType.qml @@ -0,0 +1,4 @@ +import Test 1.0 +MyQmlObject { + somethingUnknown: SomethingKnown {} +} diff --git a/tests/auto/qml/qqmllanguage/qqmllanguage.pro b/tests/auto/qml/qqmllanguage/qqmllanguage.pro index 3e88f3f0db..724a27320c 100644 --- a/tests/auto/qml/qqmllanguage/qqmllanguage.pro +++ b/tests/auto/qml/qqmllanguage/qqmllanguage.pro @@ -17,3 +17,5 @@ include (../../shared/util.pri) OTHER_FILES += \ data/readonlyObjectProperty.qml + +android: RESOURCES += qqmllanguage.qrc diff --git a/tests/auto/qml/qqmllanguage/qqmllanguage.qrc b/tests/auto/qml/qqmllanguage/qqmllanguage.qrc new file mode 100644 index 0000000000..f5212ac75c --- /dev/null +++ b/tests/auto/qml/qqmllanguage/qqmllanguage.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> +<file alias="data/I18nTypeÁâãäå.qml">data/I18nType30.qml</file> +</qresource> +</RCC> diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index ffb1d51971..6956533196 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -62,6 +62,7 @@ void registerTypes() qmlRegisterType<MyRevisionedClass,1>("Test",1,1,"MyRevisionedClass"); qmlRegisterType<MyRevisionedIllegalOverload>("Test",1,0,"MyRevisionedIllegalOverload"); qmlRegisterType<MyRevisionedLegalOverload>("Test",1,0,"MyRevisionedLegalOverload"); + qmlRegisterType<SomethingKnown>("Test",1,0,"SomethingKnown"); // Register the uncreatable base class qmlRegisterRevision<MyRevisionedBaseClassRegistered,1>("Test",1,1); diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 0618d2b20f..1aab24841a 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -89,6 +89,14 @@ private: int m_value2; }; +class SomethingUnknown : public QObject { + Q_OBJECT +}; + +class SomethingKnown : public SomethingUnknown { + Q_OBJECT +}; + class MyQmlObject : public QObject, public MyInterface { Q_OBJECT @@ -104,6 +112,7 @@ class MyQmlObject : public QObject, public MyInterface Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal) Q_PROPERTY(int nonScriptable READ nonScriptable WRITE setNonScriptable SCRIPTABLE false) Q_PROPERTY(QJSValue qjsvalue READ qjsvalue WRITE setQJSValue NOTIFY qjsvalueChanged) + Q_PROPERTY(SomethingUnknown* somethingUnknown READ somethingUnknown WRITE setSomethingUnknown NOTIFY somethingUnknownChanged) Q_INTERFACES(MyInterface) public: @@ -151,6 +160,9 @@ public: int childAddedEventCount() const { return m_childAddedEventCount; } + SomethingUnknown* somethingUnknown() const { return nullptr; } + void setSomethingUnknown(SomethingUnknown* something) { Q_UNUSED(something); } + public slots: void basicSlot() { qWarning("MyQmlObject::basicSlot"); } void basicSlotWithArgs(int v) { qWarning("MyQmlObject::basicSlotWithArgs(%d)", v); } @@ -162,6 +174,7 @@ signals: void oddlyNamedNotifySignal(); void signalWithDefaultArg(int parameter = 5); void qjsvalueChanged(); + void somethingUnknownChanged(); protected: virtual bool event(QEvent *event); diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index a54c4b35d4..8adacd8829 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -370,7 +370,8 @@ private: void tst_qqmllanguage::cleanupTestCase() { - QVERIFY(QFile::remove(testFile(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")))); + if (dataDirectoryUrl().scheme() != QLatin1String("qrc")) + QVERIFY(QFile::remove(testFile(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")))); } void tst_qqmllanguage::insertedSemicolon_data() @@ -625,11 +626,24 @@ void tst_qqmllanguage::errors_data() QTest::newRow("bareQmlImport") << "bareQmlImport.qml" << "bareQmlImport.errors.txt" << false; QTest::newRow("typeAnnotations.2") << "typeAnnotations.2.qml" << "typeAnnotations.2.errors.txt" << false; -} + QTest::newRow("propertyUnknownType") << "propertyUnknownType.qml" << "propertyUnknownType.errors.txt" << false; +} void tst_qqmllanguage::errors() { +#ifdef Q_OS_ANDROID + if (qstrcmp(QTest::currentDataTag(), "fuzzed.2") == 0) { + QSKIP("Gives different errors on Android"); + /* Only gives one error on Android: + + qrc:/data/fuzzed.2.qml:1:1: " + import" + ^ + So, it seems to complain about the first import (which is understandable) + */ + } +#endif QFETCH(QString, file); QFETCH(QString, errorFile); QFETCH(bool, create); @@ -2678,11 +2692,15 @@ void tst_qqmllanguage::importsLocal_data() "Test {}" << (!qmlCheckTypes()?"TestType":"") << (!qmlCheckTypes()?"":"Test is ambiguous. Found in org/qtproject/Test/ and in subdir/"); - QTest::newRow("file URL survives percent-encoding") - << "import \"" + QUrl::fromLocalFile(QDir::currentPath() + "/{subdir}").toString() + "\"\n" - "Test {}" - << "QQuickRectangle" - << ""; + + if (dataDirectoryUrl().scheme() != QLatin1String("qrc")) { + // file URL doesn't work with qrc scheme + QTest::newRow("file URL survives percent-encoding") + << "import \"" + QUrl::fromLocalFile(QDir::currentPath() + "/{subdir}").toString() + "\"\n" + "Test {}" + << "QQuickRectangle" + << ""; + } } void tst_qqmllanguage::importsLocal() @@ -3441,7 +3459,11 @@ void tst_qqmllanguage::uncreatableTypesAsProperties() void tst_qqmllanguage::initTestCase() { QQmlDataTest::initTestCase(); - QVERIFY2(QDir::setCurrent(dataDirectory()), qPrintable("Could not chdir to " + dataDirectory())); + if (dataDirectoryUrl().scheme() == QLatin1String("qrc")) + engine.addImportPath(dataDirectory()); + else + QVERIFY2(QDir::setCurrent(dataDirectory()), qPrintable("Could not chdir to " + dataDirectory())); + defaultImportPathList = engine.importPathList(); @@ -3472,11 +3494,13 @@ void tst_qqmllanguage::initTestCase() // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded - QFile in(testFileUrl(QLatin1String("I18nType30.qml")).toLocalFile()); - QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString()))); - QFile out(testFileUrl(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()); - QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString()))); - out.write(in.readAll()); + if (dataDirectoryUrl().scheme() != QLatin1String("qrc")) { + QFile in(testFileUrl(QLatin1String("I18nType30.qml")).toLocalFile()); + QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString()))); + QFile out(testFileUrl(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()); + QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString()))); + out.write(in.readAll()); + } // Register a Composite Singleton. qmlRegisterSingletonType(testFileUrl("singleton/RegisteredCompositeSingletonType.qml"), "org.qtproject.Test", 1, 0, "RegisteredSingleton"); @@ -3988,7 +4012,7 @@ void tst_qqmllanguage::objectDeletionNotify() void tst_qqmllanguage::scopedProperties() { - QQmlComponent component(&engine, testFile("scopedProperties.qml")); + QQmlComponent component(&engine, testFileUrl("scopedProperties.qml")); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -3997,7 +4021,7 @@ void tst_qqmllanguage::scopedProperties() void tst_qqmllanguage::deepProperty() { - QQmlComponent component(&engine, testFile("deepProperty.qml")); + QQmlComponent component(&engine, testFileUrl("deepProperty.qml")); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); QFont font = qvariant_cast<QFont>(qvariant_cast<QObject*>(o->property("someObject"))->property("font")); @@ -4015,7 +4039,7 @@ void tst_qqmllanguage::implicitImportsLast() if (engine.importPathList() == defaultImportPathList) engine.addImportPath(testFile("lib")); - QQmlComponent component(&engine, testFile("localOrderTest.qml")); + QQmlComponent component(&engine, testFileUrl("localOrderTest.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); @@ -4035,7 +4059,7 @@ void tst_qqmllanguage::getSingletonInstance(QQmlEngine& engine, const char* file if (!fileName || !propertyName) return; - QQmlComponent component(&engine, testFile(fileName)); + QQmlComponent component(&engine, testFileUrl(fileName)); VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); @@ -4077,7 +4101,7 @@ void verifyCompositeSingletonPropertyValues(QObject* o, const char* n1, int v1, // Reads values from a composite singleton type void tst_qqmllanguage::compositeSingletonProperties() { - QQmlComponent component(&engine, testFile("singletonTest1.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest1.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4124,14 +4148,14 @@ void tst_qqmllanguage::compositeSingletonDifferentEngine() // pragma Singleton in a non-type qml file fails void tst_qqmllanguage::compositeSingletonNonTypeError() { - QQmlComponent component(&engine, testFile("singletonTest4.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest4.qml")); VERIFY_ERRORS("singletonTest4.error.txt"); } // Loads the singleton using a namespace qualifier void tst_qqmllanguage::compositeSingletonQualifiedNamespace() { - QQmlComponent component(&engine, testFile("singletonTest5.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest5.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4156,7 +4180,7 @@ void tst_qqmllanguage::compositeSingletonModule() { engine.addImportPath(testFile("singleton/module")); - QQmlComponent component(&engine, testFile("singletonTest6.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest6.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4182,7 +4206,7 @@ void tst_qqmllanguage::compositeSingletonModuleVersioned() { engine.addImportPath(testFile("singleton/module")); - QQmlComponent component(&engine, testFile("singletonTest7.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest7.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4208,7 +4232,7 @@ void tst_qqmllanguage::compositeSingletonModuleQualified() { engine.addImportPath(testFile("singleton/module")); - QQmlComponent component(&engine, testFile("singletonTest8.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest8.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4232,14 +4256,14 @@ void tst_qqmllanguage::compositeSingletonModuleQualified() // Tries to instantiate a type with a pragma Singleton and fails void tst_qqmllanguage::compositeSingletonInstantiateError() { - QQmlComponent component(&engine, testFile("singletonTest9.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest9.qml")); VERIFY_ERRORS("singletonTest9.error.txt"); } // Having a composite singleton type as dynamic property type is allowed void tst_qqmllanguage::compositeSingletonDynamicPropertyError() { - QQmlComponent component(&engine, testFile("singletonTest10.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest10.qml")); VERIFY_ERRORS(0); } @@ -4247,7 +4271,7 @@ void tst_qqmllanguage::compositeSingletonDynamicPropertyError() // (like C++ singleton) void tst_qqmllanguage::compositeSingletonDynamicSignal() { - QQmlComponent component(&engine, testFile("singletonTest11.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest11.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4261,21 +4285,21 @@ void tst_qqmllanguage::compositeSingletonQmlRegisterTypeError() { qmlRegisterType(testFileUrl("singleton/registeredComposite/CompositeType.qml"), "CompositeSingletonTest", 1, 0, "RegisteredCompositeType"); - QQmlComponent component(&engine, testFile("singletonTest12.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest12.qml")); VERIFY_ERRORS("singletonTest12.error.txt"); } // Qmldir defines a type as a singleton, but the qml file does not have a pragma Singleton. void tst_qqmllanguage::compositeSingletonQmldirNoPragmaError() { - QQmlComponent component(&engine, testFile("singletonTest13.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest13.qml")); VERIFY_ERRORS("singletonTest13.error.txt"); } // Invalid singleton definition in the qmldir file results in an error void tst_qqmllanguage::compositeSingletonQmlDirError() { - QQmlComponent component(&engine, testFile("singletonTest14.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest14.qml")); VERIFY_ERRORS("singletonTest14.error.txt"); } @@ -4309,7 +4333,7 @@ void tst_qqmllanguage::compositeSingletonRemote() // the pragma Singleton changes. void tst_qqmllanguage::compositeSingletonJavaScriptPragma() { - QQmlComponent component(&engine, testFile("singletonTest16.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest16.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4327,7 +4351,7 @@ void tst_qqmllanguage::compositeSingletonSelectors() QQmlEngine e2; QQmlFileSelector qmlSelector(&e2); qmlSelector.setExtraSelectors(QStringList() << "basicSelector"); - QQmlComponent component(&e2, testFile("singletonTest1.qml")); + QQmlComponent component(&e2, testFileUrl("singletonTest1.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4339,7 +4363,7 @@ void tst_qqmllanguage::compositeSingletonSelectors() // qmlRegisterSingletonType. void tst_qqmllanguage::compositeSingletonRegistered() { - QQmlComponent component(&engine, testFile("singletonTest17.qml")); + QQmlComponent component(&engine, testFileUrl("singletonTest17.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4349,7 +4373,7 @@ void tst_qqmllanguage::compositeSingletonRegistered() void tst_qqmllanguage::compositeSingletonCircular() { - QQmlComponent component(&engine, testFile("circularSingleton.qml")); + QQmlComponent component(&engine, testFileUrl("circularSingleton.qml")); VERIFY_ERRORS(0); QQmlTestMessageHandler messageHandler; @@ -4383,7 +4407,7 @@ void tst_qqmllanguage::singletonsHaveContextAndEngine() void tst_qqmllanguage::customParserBindingScopes() { - QQmlComponent component(&engine, testFile("customParserBindingScopes.qml")); + QQmlComponent component(&engine, testFileUrl("customParserBindingScopes.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4394,7 +4418,7 @@ void tst_qqmllanguage::customParserBindingScopes() void tst_qqmllanguage::customParserEvaluateEnum() { - QQmlComponent component(&engine, testFile("customParserEvaluateEnum.qml")); + QQmlComponent component(&engine, testFileUrl("customParserEvaluateEnum.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4402,7 +4426,7 @@ void tst_qqmllanguage::customParserEvaluateEnum() void tst_qqmllanguage::customParserProperties() { - QQmlComponent component(&engine, testFile("customParserProperties.qml")); + QQmlComponent component(&engine, testFileUrl("customParserProperties.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4416,7 +4440,7 @@ void tst_qqmllanguage::customParserProperties() void tst_qqmllanguage::customParserWithExtendedObject() { - QQmlComponent component(&engine, testFile("customExtendedParserProperties.qml")); + QQmlComponent component(&engine, testFileUrl("customExtendedParserProperties.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4434,7 +4458,7 @@ void tst_qqmllanguage::customParserWithExtendedObject() void tst_qqmllanguage::nestedCustomParsers() { - QQmlComponent component(&engine, testFile("nestedCustomParsers.qml")); + QQmlComponent component(&engine, testFileUrl("nestedCustomParsers.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4448,7 +4472,7 @@ void tst_qqmllanguage::nestedCustomParsers() void tst_qqmllanguage::preservePropertyCacheOnGroupObjects() { - QQmlComponent component(&engine, testFile("preservePropertyCacheOnGroupObjects.qml")); + QQmlComponent component(&engine, testFileUrl("preservePropertyCacheOnGroupObjects.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4467,7 +4491,7 @@ void tst_qqmllanguage::preservePropertyCacheOnGroupObjects() void tst_qqmllanguage::propertyCacheInSync() { - QQmlComponent component(&engine, testFile("propertyCacheInSync.qml")); + QQmlComponent component(&engine, testFileUrl("propertyCacheInSync.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4487,7 +4511,7 @@ void tst_qqmllanguage::propertyCacheInSync() void tst_qqmllanguage::rootObjectInCreationNotForSubObjects() { - QQmlComponent component(&engine, testFile("rootObjectInCreationNotForSubObjects.qml")); + QQmlComponent component(&engine, testFileUrl("rootObjectInCreationNotForSubObjects.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -4513,7 +4537,7 @@ void tst_qqmllanguage::rootObjectInCreationNotForSubObjects() // QTBUG-63036 void tst_qqmllanguage::lazyDeferredSubObject() { - QQmlComponent component(&engine, testFile("lazyDeferredSubObject.qml")); + QQmlComponent component(&engine, testFileUrl("lazyDeferredSubObject.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(!object.isNull()); @@ -4528,7 +4552,7 @@ void tst_qqmllanguage::lazyDeferredSubObject() // QTBUG-63200 void tst_qqmllanguage::deferredProperties() { - QQmlComponent component(&engine, testFile("deferredProperties.qml")); + QQmlComponent component(&engine, testFileUrl("deferredProperties.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(!object.isNull()); @@ -4645,7 +4669,7 @@ static void testExecuteDeferredOnce(const QQmlProperty &property) void tst_qqmllanguage::executeDeferredPropertiesOnce() { - QQmlComponent component(&engine, testFile("deferredProperties.qml")); + QQmlComponent component(&engine, testFileUrl("deferredProperties.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(!object.isNull()); @@ -4745,7 +4769,7 @@ void tst_qqmllanguage::deleteSingletons() QPointer<QObject> singleton; { QQmlEngine tmpEngine; - QQmlComponent component(&tmpEngine, testFile("singletonTest5.qml")); + QQmlComponent component(&tmpEngine, testFileUrl("singletonTest5.qml")); VERIFY_ERRORS(0); QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); @@ -4772,7 +4796,7 @@ void tst_qqmllanguage::arrayBuffer_data() void tst_qqmllanguage::arrayBuffer() { QFETCH(QString, file); - QQmlComponent component(&engine, testFile(file)); + QQmlComponent component(&engine, testFileUrl(file)); VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); diff --git a/tests/auto/qml/qqmlpropertymap/dummy_imports.qml b/tests/auto/qml/qqmlpropertymap/dummy_imports.qml new file mode 100644 index 0000000000..4ae9d3f2cf --- /dev/null +++ b/tests/auto/qml/qqmlpropertymap/dummy_imports.qml @@ -0,0 +1,8 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in the +// C++ code belonging to the test. + +import QtQuick 2.0 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qqmlpropertymap/qqmlpropertymap.pro b/tests/auto/qml/qqmlpropertymap/qqmlpropertymap.pro index 8da300171d..b83e1e0da2 100644 --- a/tests/auto/qml/qqmlpropertymap/qqmlpropertymap.pro +++ b/tests/auto/qml/qqmlpropertymap/qqmlpropertymap.pro @@ -7,3 +7,5 @@ SOURCES += tst_qqmlpropertymap.cpp include (../../shared/util.pri) QT += core-private gui-private qml-private quick-private testlib + +TESTDATA = data/* diff --git a/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml b/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml new file mode 100644 index 0000000000..4ae9d3f2cf --- /dev/null +++ b/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml @@ -0,0 +1,8 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in the +// C++ code belonging to the test. + +import QtQuick 2.0 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qqmltimer/dummy_imports.qml b/tests/auto/qml/qqmltimer/dummy_imports.qml new file mode 100644 index 0000000000..f78e04d489 --- /dev/null +++ b/tests/auto/qml/qqmltimer/dummy_imports.qml @@ -0,0 +1,9 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in the +// C++ code belonging to the test. + +import QtQml 2.0 +import QtQuick 2.0 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qqmltypeloader/dummy_imports.qml b/tests/auto/qml/qqmltypeloader/dummy_imports.qml new file mode 100644 index 0000000000..a4684b2007 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/dummy_imports.qml @@ -0,0 +1,9 @@ +// This file exists for the sole purpose for qmlimportscanner to find +// which modules it needs to extract for deployment. +// Otherwise, it fails to find the imports that are expressed in the +// C++ code belonging to the test. + +import QtQml 2.0 +import QtQuick 2.6 + +QtObject { } // This is needed in order to keep importscanner happy diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 2993b4b3c8..63a43eebad 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -60,10 +60,16 @@ private slots: void implicitComponentModule(); void qrcRootPathUrl(); void implicitImport(); + +private: + void checkSingleton(const QString & dataDirectory); }; void tst_QQMLTypeLoader::testLoadComplete() { +#ifdef Q_OS_ANDROID + QSKIP("Loading dynamic plugins does not work on Android"); +#endif QQuickView *window = new QQuickView(); window->engine()->addImportPath(QT_TESTCASE_BUILDDIR); qDebug() << window->engine()->importPathList(); @@ -157,7 +163,7 @@ void tst_QQMLTypeLoader::trimCache3() QCOMPARE(loader.isTypeLoaded(testFileUrl("ComponentWithIncubator.qml")), false); } -static void checkSingleton(const QString &dataDirectory) +void tst_QQMLTypeLoader::checkSingleton(const QString &dataDirectory) { QQmlEngine engine; engine.addImportPath(dataDirectory); @@ -166,8 +172,8 @@ static void checkSingleton(const QString &dataDirectory) "import QtQuick 2.6\n" "import \"..\"\n" "Item { property int t: ValueSource.something }", - QUrl::fromLocalFile(dataDirectory + "/abc/Xyz.qml")); - QCOMPARE(component.status(), QQmlComponent::Ready); + testFileUrl("abc/Xyz.qml")); + QVERIFY2(component.status() == QQmlComponent::Ready, qPrintable(component.errorString())); QScopedPointer<QObject> o(component.create()); QVERIFY(o.data()); QCOMPARE(o->property("t").toInt(), 10); @@ -389,6 +395,9 @@ public: void tst_QQMLTypeLoader::intercept() { +#ifdef Q_OS_ANDROID + QSKIP("Loading dynamic plugins does not work on Android"); +#endif qmlClearTypeRegistrations(); QQmlEngine engine; @@ -478,6 +487,9 @@ static void checkCleanCacheLoad(const QString &testCase) void tst_QQMLTypeLoader::multiSingletonModule() { +#ifdef Q_OS_ANDROID + QSKIP("Android seems to have problems with QProcess"); +#endif qmlClearTypeRegistrations(); QQmlEngine engine; engine.addImportPath(testFile("imports")); @@ -498,6 +510,9 @@ void tst_QQMLTypeLoader::multiSingletonModule() void tst_QQMLTypeLoader::implicitComponentModule() { +#ifdef Q_OS_ANDROID + QSKIP("Android seems to have problems with QProcess"); +#endif QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("implicitcomponent.qml")); QCOMPARE(component.status(), QQmlComponent::Ready); diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro index 0352561e03..743f7cf3ac 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro @@ -12,3 +12,4 @@ HEADERS += \ include (../../shared/util.pri) +TESTDATA = data/* diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 83a37df797..8a602a0356 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -784,6 +784,7 @@ void tst_qqmlvaluetypes::font() { QQmlComponent component(&engine, testFileUrl("font_read.qml")); MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create()); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); QVERIFY(object != nullptr); QCOMPARE(object->property("f_family").toString(), object->font().family()); @@ -793,8 +794,19 @@ void tst_qqmlvaluetypes::font() QCOMPARE(object->property("f_underline").toBool(), object->font().underline()); QCOMPARE(object->property("f_overline").toBool(), object->font().overline()); QCOMPARE(object->property("f_strikeout").toBool(), object->font().strikeOut()); - QCOMPARE(object->property("f_pointSize").toDouble(), object->font().pointSizeF()); - QCOMPARE(object->property("f_pixelSize").toInt(), int((object->font().pointSizeF() * qt_defaultDpi()) / qreal(72.))); + + // If QFont::pixelSize() was set, QFont::pointSizeF() would return -1. + // If QFont::pointSizeF() was set, QFont::pixelSize() would return -1. + // QQuickFontValueType doesn't follow this semantic (if its -1 it calculates the value of + // the property from the other one) + double expectedPointSizeF = object->font().pointSizeF(); + if (expectedPointSizeF == -1) expectedPointSizeF = object->font().pixelSize() * qreal(72.) / qreal(qt_defaultDpi()); + int expectedPixelSize = object->font().pixelSize(); + if (expectedPixelSize == -1) expectedPixelSize = int((object->font().pointSizeF() * qt_defaultDpi()) / qreal(72.)); + + QCOMPARE(object->property("f_pointSize").toDouble(), expectedPointSizeF); + QCOMPARE(object->property("f_pixelSize").toInt(), expectedPixelSize); + QCOMPARE(object->property("f_capitalization").toInt(), (int)object->font().capitalization()); QCOMPARE(object->property("f_letterSpacing").toDouble(), object->font().letterSpacing()); QCOMPARE(object->property("f_wordSpacing").toDouble(), object->font().wordSpacing()); diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp index 4b2ae45bae..b7600351b7 100644 --- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp +++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp @@ -112,6 +112,10 @@ void tst_qquickfolderlistmodel::initTestCase() void tst_qquickfolderlistmodel::basicProperties() { +#ifdef Q_OS_ANDROID + QSKIP("[QTBUG-77335] Initial folder of FolderListModel on Android does not work properly," + " and from there on it is unreliable to change the folder"); +#endif QQmlComponent component(&engine, testFileUrl("basic.qml")); checkNoErrors(component); @@ -356,6 +360,9 @@ void tst_qquickfolderlistmodel::showDotAndDotDot() void tst_qquickfolderlistmodel::showDotAndDotDot_data() { +#ifdef Q_OS_ANDROID + QSKIP("Resource file system does not list '.' and '..' due to QDir::entryList() behavior"); +#endif QTest::addColumn<QUrl>("folder"); QTest::addColumn<QUrl>("rootFolder"); QTest::addColumn<bool>("showDotAndDotDot"); @@ -411,7 +418,7 @@ void tst_qquickfolderlistmodel::sortCaseSensitive() QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create()); QVERIFY(flm != 0); - flm->setProperty("folder", QUrl::fromLocalFile(dataDirectoryUrl().path() + QLatin1String("/sortdir"))); + flm->setProperty("folder", testFileUrl("sortdir")); flm->setProperty("sortCaseSensitive", sortCaseSensitive); QTRY_COMPARE(flm->property("count").toInt(), 2); // wait for refresh for (int i = 0; i < 2; ++i) diff --git a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp index 392ce16880..5dd8e9dcc0 100644 --- a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp +++ b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp @@ -59,7 +59,7 @@ void tst_QV4Assembler::initTestCase() void tst_QV4Assembler::perfMapFile() { -#if !defined(Q_OS_LINUX) +#if !defined(Q_OS_LINUX) || defined(Q_OS_ANDROID) QSKIP("perf map files are only generated on linux"); #else const QString qmljs = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmljs"; diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp index 1e34b79954..5d635aa63b 100644 --- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp +++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp @@ -136,7 +136,7 @@ void tst_qv4mm::clearICParent() // to change this test. for (uint i = 0; i < 16 * 1024; ++i) { QV4::Scope scope(&engine); - QV4::ScopedString s(scope, identifiers->getIndexed(i)); + QV4::ScopedString s(scope, identifiers->get(i)); QV4::Scoped<QV4::InternalClass> ic(scope, object->internalClass()); QVERIFY(ic->d()->parent != nullptr); object->deleteProperty(s->toPropertyKey()); diff --git a/tests/auto/quick/qquickborderimage/data/multi.ico b/tests/auto/quick/qquickborderimage/data/multi.ico Binary files differnew file mode 100644 index 0000000000..b748ceaa29 --- /dev/null +++ b/tests/auto/quick/qquickborderimage/data/multi.ico diff --git a/tests/auto/quick/qquickborderimage/data/multiframe.qml b/tests/auto/quick/qquickborderimage/data/multiframe.qml new file mode 100644 index 0000000000..8bd32da5a6 --- /dev/null +++ b/tests/auto/quick/qquickborderimage/data/multiframe.qml @@ -0,0 +1,8 @@ +import QtQuick 2.14 + +BorderImage { + source: "multi.ico" + border { left: 19; top: 19; right: 19; bottom: 19 } + width: 160; height: 160 + horizontalTileMode: BorderImage.Stretch +} diff --git a/tests/auto/quick/qquickborderimage/data/multiframeAsync.qml b/tests/auto/quick/qquickborderimage/data/multiframeAsync.qml new file mode 100644 index 0000000000..059e4becf3 --- /dev/null +++ b/tests/auto/quick/qquickborderimage/data/multiframeAsync.qml @@ -0,0 +1,9 @@ +import QtQuick 2.14 + +BorderImage { + source: "multi.ico" + asynchronous: true + border { left: 19; top: 19; right: 19; bottom: 19 } + width: 160; height: 160 + horizontalTileMode: BorderImage.Stretch +} diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp index 9292e1886a..dc3a783600 100644 --- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp +++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp @@ -46,6 +46,8 @@ #include "../../shared/util.h" #include "../shared/visualtestutil.h" +Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") + Q_DECLARE_METATYPE(QQuickImageBase::Status) class tst_qquickborderimage : public QQmlDataTest @@ -79,6 +81,8 @@ private slots: #if QT_CONFIG(opengl) void borderImageMesh(); #endif + void multiFrame_data(); + void multiFrame(); private: QQmlEngine engine; @@ -601,6 +605,67 @@ void tst_qquickborderimage::borderImageMesh() qPrintable(errorMessage)); } #endif + +void tst_qquickborderimage::multiFrame_data() +{ + QTest::addColumn<QString>("qmlfile"); + QTest::addColumn<bool>("asynchronous"); + + QTest::addRow("default") << "multiframe.qml" << false; + QTest::addRow("async") << "multiframeAsync.qml" << true; +} + +void tst_qquickborderimage::multiFrame() +{ + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) + || (QGuiApplication::platformName() == QLatin1String("minimal"))) + QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms"); + + QFETCH(QString, qmlfile); + QFETCH(bool, asynchronous); + Q_UNUSED(asynchronous) + + QQuickView view(testFileUrl(qmlfile)); + QQuickBorderImage *image = qobject_cast<QQuickBorderImage*>(view.rootObject()); + QVERIFY(image); + QSignalSpy countSpy(image, SIGNAL(frameCountChanged())); + QSignalSpy currentSpy(image, SIGNAL(currentFrameChanged())); + if (asynchronous) { + QCOMPARE(image->frameCount(), 0); + QTRY_COMPARE(image->frameCount(), 4); + QCOMPARE(countSpy.count(), 1); + } else { + QCOMPARE(image->frameCount(), 4); + } + QCOMPARE(image->currentFrame(), 0); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QCoreApplication::processEvents(); // Process all queued events + + QImage contents = view.grabWindow(); + if (contents.width() < 160) + QSKIP("Skipping due to grabWindow not functional"); + + // The middle of the first frame looks blue, approximately qRgba(0x43, 0x7e, 0xd6, 0xff) + QColor color = contents.pixelColor(60, 60); + qCDebug(lcTests) << "expected bluish color, got" << color; + QVERIFY(color.redF() < 0.75); + QVERIFY(color.greenF() < 0.75); + QVERIFY(color.blueF() > 0.75); + + image->setCurrentFrame(1); + QTRY_COMPARE(image->status(), QQuickImageBase::Ready); + QCOMPARE(currentSpy.count(), 1); + QCOMPARE(image->currentFrame(), 1); + contents = view.grabWindow(); + // The middle of the second frame looks green, approximately qRgba(0x3a, 0xd2, 0x31, 0xff) + color = contents.pixelColor(60, 60); + qCDebug(lcTests) << "expected greenish color, got" << color; + QVERIFY(color.redF() < 0.75); + QVERIFY(color.green() > 0.75); + QVERIFY(color.blueF() < 0.75); +} + QTEST_MAIN(tst_qquickborderimage) #include "tst_qquickborderimage.moc" diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 2314b82e8c..c104eecbcd 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -874,7 +874,8 @@ void tst_qquickflickable::wheel() // test a vertical flick { QPoint pos(200, 200); - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(), QPoint(0,-120), -120, Qt::Vertical, Qt::NoButton, Qt::NoModifier); + QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(), QPoint(0,-120), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); event.setAccepted(false); QGuiApplication::sendEvent(window.data(), &event); } @@ -897,7 +898,8 @@ void tst_qquickflickable::wheel() // test a horizontal flick { QPoint pos(200, 200); - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(), QPoint(-120,0), -120, Qt::Horizontal, Qt::NoButton, Qt::NoModifier); + QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(), QPoint(-120,0), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); event.setAccepted(false); QGuiApplication::sendEvent(window.data(), &event); @@ -926,7 +928,8 @@ void tst_qquickflickable::trackpad() QPoint pos(200, 200); { - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(0,-100), QPoint(0,-120), -120, Qt::Vertical, Qt::NoButton, Qt::NoModifier, Qt::ScrollBegin); + QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(0,-100), QPoint(0,-120), + Qt::NoButton, Qt::NoModifier, Qt::ScrollBegin, false); event.setAccepted(false); QGuiApplication::sendEvent(window.data(), &event); } @@ -938,7 +941,8 @@ void tst_qquickflickable::trackpad() QCOMPARE(flick->contentY(), qreal(0)); { - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(-100,0), QPoint(-120,0), -120, Qt::Horizontal, Qt::NoButton, Qt::NoModifier, Qt::ScrollUpdate); + QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(-100,0), QPoint(-120,0), + Qt::NoButton, Qt::NoModifier, Qt::ScrollUpdate, false); event.setAccepted(false); QGuiApplication::sendEvent(window.data(), &event); } @@ -947,7 +951,8 @@ void tst_qquickflickable::trackpad() QCOMPARE(flick->contentY(), qreal(0)); { - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(0,0), QPoint(0,0), 0, Qt::Horizontal, Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd); + QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(0,0), QPoint(0,0), + Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd, false); event.setAccepted(false); QGuiApplication::sendEvent(window.data(), &event); } diff --git a/tests/auto/quick/qquickimage/data/multi.ico b/tests/auto/quick/qquickimage/data/multi.ico Binary files differnew file mode 100644 index 0000000000..b748ceaa29 --- /dev/null +++ b/tests/auto/quick/qquickimage/data/multi.ico diff --git a/tests/auto/quick/qquickimage/data/multiframe.qml b/tests/auto/quick/qquickimage/data/multiframe.qml new file mode 100644 index 0000000000..df70bc784c --- /dev/null +++ b/tests/auto/quick/qquickimage/data/multiframe.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +Image { + source: "multi.ico" +} diff --git a/tests/auto/quick/qquickimage/data/multiframeAsync.qml b/tests/auto/quick/qquickimage/data/multiframeAsync.qml new file mode 100644 index 0000000000..167b4a3e57 --- /dev/null +++ b/tests/auto/quick/qquickimage/data/multiframeAsync.qml @@ -0,0 +1,6 @@ +import QtQuick 2.14 + +Image { + source: "multi.ico" + asynchronous: true +} diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 34c18aa64b..abc7cd86bd 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -97,6 +97,8 @@ private slots: void highDpiFillModesAndSizes(); void hugeImages(); void urlInterceptor(); + void multiFrame_data(); + void multiFrame(); private: QQmlEngine engine; @@ -1132,6 +1134,62 @@ void tst_qquickimage::urlInterceptor() QTRY_COMPARE(object->progress(), 1.0); } +void tst_qquickimage::multiFrame_data() +{ + QTest::addColumn<QString>("qmlfile"); + QTest::addColumn<bool>("asynchronous"); + + QTest::addRow("default") << "multiframe.qml" << false; + QTest::addRow("async") << "multiframeAsync.qml" << true; +} + +void tst_qquickimage::multiFrame() +{ + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) + || (QGuiApplication::platformName() == QLatin1String("minimal"))) + QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms"); + + QFETCH(QString, qmlfile); + QFETCH(bool, asynchronous); + Q_UNUSED(asynchronous) + + QQuickView view(testFileUrl(qmlfile)); + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()); + QVERIFY(image); + QSignalSpy countSpy(image, SIGNAL(frameCountChanged())); + QSignalSpy currentSpy(image, SIGNAL(currentFrameChanged())); + if (asynchronous) { + QCOMPARE(image->frameCount(), 0); + QTRY_COMPARE(image->frameCount(), 4); + QCOMPARE(countSpy.count(), 1); + } else { + QCOMPARE(image->frameCount(), 4); + } + QCOMPARE(image->currentFrame(), 0); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QImage contents = view.grabWindow(); + if (contents.width() < 40) + QSKIP("Skipping due to grabWindow not functional"); + // The first frame is a blue ball, approximately qRgba(0x33, 0x6d, 0xcc, 0xff) + QRgb color = contents.pixel(16, 16); + QVERIFY(qRed(color) < 0xc0); + QVERIFY(qGreen(color) < 0xc0); + QVERIFY(qBlue(color) > 0xc0); + + image->setCurrentFrame(1); + QTRY_COMPARE(image->status(), QQuickImageBase::Ready); + QCOMPARE(currentSpy.count(), 1); + QCOMPARE(image->currentFrame(), 1); + contents = view.grabWindow(); + // The second frame is a green ball, approximately qRgba(0x27, 0xc8, 0x22, 0xff) + color = contents.pixel(16, 16); + QVERIFY(qRed(color) < 0xc0); + QVERIFY(qGreen(color) > 0xc0); + QVERIFY(qBlue(color) < 0xc0); +} + QTEST_MAIN(tst_qquickimage) #include "tst_qquickimage.moc" diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 7e132f97b6..b6e40d5117 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -83,8 +83,8 @@ protected: event->accept(); ++wheelCount; timestamp = event->timestamp(); - lastWheelEventPos = event->pos(); - lastWheelEventGlobalPos = event->globalPos(); + lastWheelEventPos = event->position().toPoint(); + lastWheelEventGlobalPos = event->globalPosition().toPoint(); } }; @@ -1462,7 +1462,8 @@ void tst_qquickitem::wheelEvent() QPoint localPoint(width / 2, height / 2); QPoint globalPoint = window.mapToGlobal(localPoint); - QWheelEvent event(localPoint, globalPoint, -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical); + QWheelEvent event(localPoint, globalPoint, QPoint(0, 0), QPoint(0, -120), + Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); event.setTimestamp(123456UL); event.setAccepted(false); QGuiApplication::sendEvent(&window, &event); diff --git a/tests/auto/quick/qquicklistview/data/addoncompleted.qml b/tests/auto/quick/qquicklistview/data/addoncompleted.qml index 57265cb2c0..2341295868 100644 --- a/tests/auto/quick/qquicklistview/data/addoncompleted.qml +++ b/tests/auto/quick/qquicklistview/data/addoncompleted.qml @@ -73,6 +73,9 @@ Rectangle { anchors.fill: parent model: listModel objectName: "view" + // buffered delegates are created asynchronously + // therefore we disable buffering + cacheBuffer: 0 delegate: Rectangle { height: 15 diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index bab2ec34f8..08149a1786 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -8958,6 +8958,7 @@ void tst_QQuickListView::addOnCompleted() y = 9999999; } else { const qreal newY = item->y(); + QVERIFY(newY != 9999999); // once we could not find an item, we shouldn' find any further ones QVERIFY2(newY > y, objName.toUtf8().constData()); y = newY; } diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 4215017db3..5844720aa4 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -1519,7 +1519,7 @@ void tst_QQuickMouseArea::onWheel() QVERIFY(root != nullptr); QWheelEvent wheelEvent(QPoint(10, 32), QPoint(10, 32), QPoint(60, 20), QPoint(0, 120), - 0, Qt::Vertical,Qt::NoButton, Qt::ControlModifier); + Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, false); QGuiApplication::sendEvent(&window, &wheelEvent); QCOMPARE(root->property("angleDeltaY").toInt(), 120); diff --git a/tests/auto/quick/qquickshape/data/multiline.png b/tests/auto/quick/qquickshape/data/multiline.png Binary files differnew file mode 100644 index 0000000000..ae25d111df --- /dev/null +++ b/tests/auto/quick/qquickshape/data/multiline.png diff --git a/tests/auto/quick/qquickshape/data/multiline.qml b/tests/auto/quick/qquickshape/data/multiline.qml new file mode 100644 index 0000000000..ad07506972 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/multiline.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 + +Shape { + width: 200 + height: 150 + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + property alias paths: multiline.paths + property point vertexBeingChecked; + + function checkVertexAt(i, j) { + vertexBeingChecked = multiline.paths[i][j] + } + + ShapePath { + strokeWidth: 4 + strokeColor: "green" + PathMultiline { + id: multiline + } + } +} diff --git a/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml b/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml new file mode 100644 index 0000000000..46d650e053 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/multilineStronglyTyped.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 +import Qt.test 1.0 + +Shape { + width: 200 + height: 150 + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + property alias paths: multiline.paths + property point vertexBeingChecked; + + function checkVertexAt(i, j) { + vertexBeingChecked = multiline.paths[i][j] + } + + PolygonProvider { + id: provider + objectName: "provider" + } + + ShapePath { + strokeWidth: 4 + strokeColor: "green" + PathMultiline { + id: multiline + paths: provider.paths + } + } +} diff --git a/tests/auto/quick/qquickshape/data/polyline.png b/tests/auto/quick/qquickshape/data/polyline.png Binary files differnew file mode 100644 index 0000000000..00123fba44 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/polyline.png diff --git a/tests/auto/quick/qquickshape/data/polyline.qml b/tests/auto/quick/qquickshape/data/polyline.qml new file mode 100644 index 0000000000..e62d952ae7 --- /dev/null +++ b/tests/auto/quick/qquickshape/data/polyline.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.14 +import QtQuick.Shapes 1.14 + +Shape { + width: 200 + height: 150 + vendorExtensionsEnabled: false + objectName: "shape" + id: shape + property alias path: polyline.path + property point vertexBeingChecked; + + function checkVertexAt(i) { + vertexBeingChecked = polyline.path[i] + } + + ShapePath { + strokeWidth: 4 + strokeColor: "green" + PathPolyline { + id: polyline + } + } +} diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp index b3b8d2d148..851475e2cd 100644 --- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp +++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp @@ -43,6 +43,28 @@ using namespace QQuickViewTestUtil; using namespace QQuickVisualTestUtil; +class PolygonProvider : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVector<QPolygonF> paths READ paths WRITE setPaths NOTIFY pathsChanged) + +public: + QVector<QPolygonF> paths() const { return m_paths; } + void setPaths(QVector<QPolygonF> paths) + { + if (m_paths == paths) + return; + m_paths = paths; + emit pathsChanged(); + } + +signals: + void pathsChanged(); + +private: + QVector<QPolygonF> m_paths; +}; + class tst_QQuickShape : public QQmlDataTest { Q_OBJECT @@ -60,6 +82,14 @@ private slots: void conicalGrad(); void renderPolyline(); void renderMultiline(); + void polylineDataTypes_data(); + void polylineDataTypes(); + void multilineDataTypes_data(); + void multilineDataTypes(); + void multilineStronglyTyped(); + +private: + QVector<QPolygonF> m_lowPolyLogo; }; tst_QQuickShape::tst_QQuickShape() @@ -75,6 +105,30 @@ tst_QQuickShape::tst_QQuickShape() qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient"); qmlRegisterType<QQuickShapeConicalGradient>(uri, 1, 0, "ConicalGradient"); qmlRegisterType<QQuickPathPolyline>(uri, 1, 0, "PathPolyline"); + qmlRegisterType<PolygonProvider>("Qt.test", 1, 0, "PolygonProvider"); + + m_lowPolyLogo << (QPolygonF() << + QPointF(20, 0) << + QPointF(140, 0) << + QPointF(140, 80) << + QPointF(120, 100) << + QPointF(0, 100) << + QPointF(0, 20) << + QPointF(20, 0) ) + << (QPolygonF() << QPointF(20, 80) << + QPointF(60, 80) << + QPointF(80, 60) << + QPointF(80, 20) << + QPointF(40, 20) << + QPointF(20, 40) << + QPointF(20, 80) ) + << (QPolygonF() << QPointF(80, 80) << + QPointF(70, 70) ) + << (QPolygonF() << QPointF(120, 80) << + QPointF(100, 60) << + QPointF(100, 20) ) + << (QPolygonF() << QPointF(100, 40) << + QPointF(120, 40) ); } void tst_QQuickShape::initValues() @@ -373,6 +427,286 @@ void tst_QQuickShape::renderMultiline() QVERIFY2(res, qPrintable(errorMessage)); } +void tst_QQuickShape::polylineDataTypes_data() +{ + QTest::addColumn<QVariant>("path"); + + QTest::newRow("polygon") << QVariant::fromValue(m_lowPolyLogo.first()); + { + QVector<QPointF> points; + points << m_lowPolyLogo.first(); + QTest::newRow("vector of points") << QVariant::fromValue(points); + } + { + QList<QPointF> points; + for (const auto &point : m_lowPolyLogo.first()) + points << point; + QTest::newRow("list of points") << QVariant::fromValue(points); + } + { + QVariantList points; + for (const auto &point : m_lowPolyLogo.first()) + points << point; + QTest::newRow("QVariantList of points") << QVariant::fromValue(points); + } + { + QVector<QPoint> points; + for (const auto &point : m_lowPolyLogo.first()) + points << point.toPoint(); + QTest::newRow("vector of QPoint (integer points)") << QVariant::fromValue(points); + } + // Oddly, QPolygon is not supported, even though it's really QVector<QPoint>. + // We don't want to have a special case for it in QQuickPathPolyline::setPath(), + // but it could potentially be supported by fixing one of the QVariant conversions. +} + +void tst_QQuickShape::polylineDataTypes() +{ + QFETCH(QVariant, path); + + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("polyline.qml")); + QQuickShape *shape = qobject_cast<QQuickShape *>(window->rootObject()); + QVERIFY(shape); + shape->setProperty("path", path); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) + || (QGuiApplication::platformName() == QLatin1String("minimal"))) + QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort); + + QImage img = window->grabWindow(); + QVERIFY(!img.isNull()); + + QImage refImg(testFileUrl("polyline.png").toLocalFile()); + QVERIFY(!refImg.isNull()); + + QString errorMessage; + const QImage actualImg = img.convertToFormat(refImg.format()); + const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage); + if (!res) { // For visual inspection purposes. + QTest::qWait(5000); + const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation); + actualImg.save(tempLocation + QLatin1String("/polyline.png")); + } + QVERIFY2(res, qPrintable(errorMessage)); + + QCOMPARE(shape->property("path").value<QVector<QPointF>>(), m_lowPolyLogo.first()); + // Verify that QML sees it as an array of points + int i = 0; + for (QPointF p : m_lowPolyLogo.first()) { + QMetaObject::invokeMethod(shape, "checkVertexAt", Q_ARG(QVariant, QVariant::fromValue<int>(i++))); + QCOMPARE(shape->property("vertexBeingChecked").toPointF(), p); + } +} + +void tst_QQuickShape::multilineDataTypes_data() +{ + QTest::addColumn<QVariant>("paths"); + + QTest::newRow("vector of polygons") << QVariant::fromValue(m_lowPolyLogo); + { + QVector<QVector<QPointF>> paths; + for (const auto &poly : m_lowPolyLogo) { + QVector<QPointF> points; + points << poly; + paths << points; + } + QTest::newRow("vector of point vectors") << QVariant::fromValue(paths); + } + { + QList<QVector<QPointF>> paths; + for (const auto &poly : m_lowPolyLogo) { + QVector<QPointF> points; + points << poly; + paths << points; + } + QTest::newRow("list of point vectors") << QVariant::fromValue(paths); + } + { + QList<QList<QPointF>> paths; + for (const auto &poly : m_lowPolyLogo) { + QList<QPointF> points; + for (const auto &point : poly) + points << point; + paths << points; + } + QTest::newRow("list of point lists") << QVariant::fromValue(paths); + } + { + QVariantList paths; + for (const auto &poly : m_lowPolyLogo) { + QVector<QPointF> points; + points << poly; + paths << QVariant::fromValue(points); + } + QTest::newRow("QVariantList of point vectors") << QVariant::fromValue(paths); + } + { + QVariantList paths; + for (const auto &poly : m_lowPolyLogo) { + QList<QPointF> points; + for (const auto &point : poly) + points << point; + paths << QVariant::fromValue(points); + } + QTest::newRow("QVariantList of point lists") << QVariant::fromValue(paths); + } + { + QVariantList paths; + for (const auto &poly : m_lowPolyLogo) { + QVariantList points; + for (const auto &point : poly) + points << point; + paths << QVariant::fromValue(points); + } + QTest::newRow("QVariantList of QVariantLists") << QVariant::fromValue(paths); + } + /* These could be supported if QVariant knew how to convert lists and vectors of QPolygon to QPolygonF. + But they are omitted for now because we don't want to have special cases for them + in QQuickPathMultiline::setPaths(). Floating point is preferred for geometry in Qt Quick. + { + QList<QPolygon> paths; + for (const auto &poly : m_lowPolyLogo) + paths << poly.toPolygon(); + QTest::newRow("list of QPolygon (integer points)") << QVariant::fromValue(paths); + } + { + QVector<QPolygon> paths; + for (const auto &poly : m_lowPolyLogo) + paths << poly.toPolygon(); + QTest::newRow("vector of QPolygon (integer points)") << QVariant::fromValue(paths); + } + */ + { + QList<QList<QPoint>> paths; + for (const auto &poly : m_lowPolyLogo) { + QList<QPoint> points; + for (const auto &point : poly) + points << point.toPoint(); + paths << points; + } + QTest::newRow("list of integer point lists") << QVariant::fromValue(paths); + } + { + QVector<QList<QPoint>> paths; + for (const auto &poly : m_lowPolyLogo) { + QList<QPoint> points; + for (const auto &point : poly) + points << point.toPoint(); + paths << points; + } + QTest::newRow("vector of integer point lists") << QVariant::fromValue(paths); + } + { + QList<QVector<QPoint>> paths; + for (const auto &poly : m_lowPolyLogo) { + QVector<QPoint> points; + for (const auto &point : poly) + points << point.toPoint(); + paths << points; + } + QTest::newRow("list of integer point vectors") << QVariant::fromValue(paths); + } +} + +void tst_QQuickShape::multilineDataTypes() +{ + QFETCH(QVariant, paths); + + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("multiline.qml")); + QQuickShape *shape = qobject_cast<QQuickShape *>(window->rootObject()); + QVERIFY(shape); + shape->setProperty("paths", paths); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) + || (QGuiApplication::platformName() == QLatin1String("minimal"))) + QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort); + + QImage img = window->grabWindow(); + QVERIFY(!img.isNull()); + + QImage refImg(testFileUrl("multiline.png").toLocalFile()); + QVERIFY(!refImg.isNull()); + + QString errorMessage; + const QImage actualImg = img.convertToFormat(refImg.format()); + const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage); + if (!res) { // For visual inspection purposes. + QTest::qWait(5000); + const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation); + actualImg.save(tempLocation + QLatin1String("/multiline.png")); + } + QVERIFY2(res, qPrintable(errorMessage)); + + QVector<QVector<QPointF>> pointVectors; + for (auto v : m_lowPolyLogo) + pointVectors << v; + QCOMPARE(shape->property("paths").value<QVector<QVector<QPointF>>>(), pointVectors); + // Verify that QML sees it as an array of arrays of points + int i = 0; + for (auto pv : m_lowPolyLogo) { + int j = 0; + for (QPointF p : pv) { + QMetaObject::invokeMethod(shape, "checkVertexAt", Q_ARG(QVariant, QVariant::fromValue<int>(i)), Q_ARG(QVariant, QVariant::fromValue<int>(j++))); + QCOMPARE(shape->property("vertexBeingChecked").toPointF(), p); + } + ++i; + } +} + +void tst_QQuickShape::multilineStronglyTyped() +{ + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("multilineStronglyTyped.qml")); + QQuickShape *shape = qobject_cast<QQuickShape *>(window->rootObject()); + QVERIFY(shape); + PolygonProvider *provider = shape->findChild<PolygonProvider*>("provider"); + QVERIFY(provider); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + provider->setPaths(m_lowPolyLogo); + + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) + || (QGuiApplication::platformName() == QLatin1String("minimal"))) + QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort); + + QImage img = window->grabWindow(); + QVERIFY(!img.isNull()); + + QImage refImg(testFileUrl("multiline.png").toLocalFile()); + QVERIFY(!refImg.isNull()); + + QString errorMessage; + const QImage actualImg = img.convertToFormat(refImg.format()); + const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage); + if (!res) { // For visual inspection purposes. + QTest::qWait(5000); + const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation); + actualImg.save(tempLocation + QLatin1String("/multilineStronglyTyped.png")); + } + QVERIFY2(res, qPrintable(errorMessage)); + + QVector<QVector<QPointF>> pointVectors; + for (auto v : m_lowPolyLogo) + pointVectors << v; + QCOMPARE(shape->property("paths").value<QVector<QVector<QPointF>>>(), pointVectors); + // Verify that QML sees it as an array of arrays of points + int i = 0; + for (auto pv : m_lowPolyLogo) { + int j = 0; + for (QPointF p : pv) { + QMetaObject::invokeMethod(shape, "checkVertexAt", Q_ARG(QVariant, QVariant::fromValue<int>(i)), Q_ARG(QVariant, QVariant::fromValue<int>(j++))); + QCOMPARE(shape->property("vertexBeingChecked").toPointF(), p); + } + ++i; + } +} + QTEST_MAIN(tst_QQuickShape) #include "tst_qquickshape.moc" diff --git a/tests/auto/quick/qquicktext/data/verticallyAlignedImageInTable.qml b/tests/auto/quick/qquicktext/data/verticallyAlignedImageInTable.qml new file mode 100644 index 0000000000..4c00362d15 --- /dev/null +++ b/tests/auto/quick/qquicktext/data/verticallyAlignedImageInTable.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + width: 320 + height: 480 + + Text { + anchors.centerIn: parent + font.family: "Arial" + font.pixelSize: 16 + textFormat: Text.RichText + text: "<table><tr><td/><td valign=\"top\"><img src=\"images/face-sad.png\"></td></tr></table>" + } +} diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index fd0ba0f49b..97107694bd 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -162,6 +162,8 @@ private slots: void initialContentHeight(); + void verticallyAlignedImageInTable(); + private: QStringList standard; QStringList richText; @@ -4415,6 +4417,18 @@ void tst_qquicktext::implicitSizeChangeRewrap() QVERIFY(text->contentWidth() < window->width()); } +void tst_qquicktext::verticallyAlignedImageInTable() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("verticallyAlignedImageInTable.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + // Don't crash +} + QTEST_MAIN(tst_qquicktext) #include "tst_qquicktext.moc" diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST new file mode 100644 index 0000000000..9df9c7d75a --- /dev/null +++ b/tests/auto/quick/qquicktextedit/BLACKLIST @@ -0,0 +1,2 @@ +[mouseSelection] +opensuse-leap diff --git a/tests/auto/quick/qquickview/tst_qquickview.cpp b/tests/auto/quick/qquickview/tst_qquickview.cpp index e259ed1ae7..dbce0d308c 100644 --- a/tests/auto/quick/qquickview/tst_qquickview.cpp +++ b/tests/auto/quick/qquickview/tst_qquickview.cpp @@ -49,6 +49,7 @@ private slots: void errors(); void engine(); void findChild(); + void setInitialProperties(); }; @@ -283,6 +284,17 @@ void tst_QQuickView::findChild() QVERIFY(!view.rootObject()->findChild<QObject *>("rootObject")); // self } +void tst_QQuickView::setInitialProperties() +{ + QQuickView view; + view.setInitialProperties({{"z", 4}, {"width", 100}}); + view.setSource(testFileUrl("resizemodeitem.qml")); + QObject *rootObject = view.rootObject(); + QVERIFY(rootObject); + QCOMPARE(rootObject->property("z").toInt(), 4); + QCOMPARE(rootObject->property("width").toInt(), 100); +} + QTEST_MAIN(tst_QQuickView) #include "tst_qquickview.moc" diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp index 09f16e8635..f0d5a89984 100644 --- a/tests/auto/shared/testhttpserver.cpp +++ b/tests/auto/shared/testhttpserver.cpp @@ -32,6 +32,7 @@ #include <QFile> #include <QTimer> #include <QTest> +#include <QQmlFile> /*! \internal @@ -152,17 +153,17 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod m_state = AwaitingHeader; m_data.clear(); - QFile expectFile(expect.toLocalFile()); + QFile expectFile(QQmlFile::urlToLocalFileOrQrc(expect)); if (!expectFile.open(QIODevice::ReadOnly)) return false; - QFile replyFile(reply.toLocalFile()); + QFile replyFile(QQmlFile::urlToLocalFileOrQrc(reply)); if (!replyFile.open(QIODevice::ReadOnly)) return false; m_bodyData = QByteArray(); if (body.isValid()) { - QFile bodyFile(body.toLocalFile()); + QFile bodyFile(QQmlFile::urlToLocalFileOrQrc(body)); if (!bodyFile.open(QIODevice::ReadOnly)) return false; m_bodyData = bodyFile.readAll(); diff --git a/tests/benchmarks/qml/js/qjsengine/tst_qjsengine.cpp b/tests/benchmarks/qml/js/qjsengine/tst_qjsengine.cpp index d13751385c..cb23d6edbd 100644 --- a/tests/benchmarks/qml/js/qjsengine/tst_qjsengine.cpp +++ b/tests/benchmarks/qml/js/qjsengine/tst_qjsengine.cpp @@ -452,7 +452,7 @@ void tst_QJSEngine::installTranslatorFunctions() { newEngine(); QBENCHMARK { - m_engine->installTranslatorFunctions(); + m_engine->installExtensions(QJSEngine::TranslationExtension); } } @@ -471,7 +471,7 @@ void tst_QJSEngine::translation() QFETCH(QString, text); QFETCH(QString, fileName); newEngine(); - m_engine->installTranslatorFunctions(); + m_engine->installExtensions(QJSEngine::TranslationExtension); QBENCHMARK { (void)m_engine->evaluate(text, fileName); diff --git a/tests/benchmarks/qml/painting/paintbenchmark.cpp b/tests/benchmarks/qml/painting/paintbenchmark.cpp index d195675ab8..1500f39c9a 100644 --- a/tests/benchmarks/qml/painting/paintbenchmark.cpp +++ b/tests/benchmarks/qml/painting/paintbenchmark.cpp @@ -34,7 +34,7 @@ #include <QGLWidget> #include <QTextLayout> #include <QVBoxLayout> -#include <QTime> +#include <QElapsedTimer> #include <QDebug> #include <QRandomGenerator> #include <QStaticText> @@ -328,20 +328,20 @@ public: } void paintEvent(QPaintEvent *) { - static int last = 0; + static qint64 last = 0; static bool firstRun = true; if (firstRun) { timer.start(); firstRun = false; } else { - int elapsed = timer.elapsed(); + qint64 elapsed = timer.elapsed(); qDebug() << "frame elapsed:" << elapsed - last; last = elapsed; } QPainter p(this); p.fillRect(rect(), Qt::white); p.setPen(Qt::black); - QTime drawTimer; + QElapsedTimer drawTimer; drawTimer.start(); testFunc(p); qDebug() << "draw time" << drawTimer.elapsed(); @@ -351,7 +351,7 @@ public: qApp->quit(); } - QTime timer; + QElapsedTimer timer; int frames; }; diff --git a/tests/manual/scenegraph_lancelot/data/text/text_table_vertically_aligned_image.qml b/tests/manual/scenegraph_lancelot/data/text/text_table_vertically_aligned_image.qml new file mode 100644 index 0000000000..d712f94572 --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/text/text_table_vertically_aligned_image.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + width: 320 + height: 480 + + Text { + anchors.centerIn: parent + font.family: "Arial" + font.pixelSize: 16 + textFormat: Text.RichText + text: "<table><tr><td/><td valign=\"top\"><img src=\"data/logo.png\"></td></tr></table>" + } +} |