diff options
Diffstat (limited to 'tests/auto/qml')
153 files changed, 1586 insertions, 306 deletions
diff --git a/tests/auto/qml/qmlcachegen/data/module.mjs b/tests/auto/qml/qmlcachegen/data/module.mjs new file mode 100644 index 0000000000..6838766329 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/module.mjs @@ -0,0 +1,6 @@ + +import { helper } from "utils.mjs" + +export function entry() { + return helper() +} diff --git a/tests/auto/qml/qmlcachegen/retain.qrc b/tests/auto/qml/qmlcachegen/data/retain.qrc index e5eed9b12f..e1b9045fbe 100644 --- a/tests/auto/qml/qmlcachegen/retain.qrc +++ b/tests/auto/qml/qmlcachegen/data/retain.qrc @@ -1,5 +1,5 @@ <RCC> <qresource prefix="/"> - <file alias="Retain.qml">data/Retain.qml</file> + <file alias="Retain.qml">Retain.qml</file> </qresource> </RCC> diff --git a/tests/auto/qml/qmlcachegen/data/utils.mjs b/tests/auto/qml/qmlcachegen/data/utils.mjs new file mode 100644 index 0000000000..25a1f38709 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/utils.mjs @@ -0,0 +1,4 @@ + +export function helper() { + return "ok" +} diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro index 7bd4414302..1a334b68ce 100644 --- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro +++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro @@ -15,7 +15,9 @@ RESOURCES += \ data/Enums.qml \ data/componentInItem.qml \ data/jsmoduleimport.qml \ - data/script.mjs + data/script.mjs \ + data/module.mjs \ + data/utils.mjs workerscripts_test.files = \ data/worker.js \ @@ -25,7 +27,7 @@ workerscripts_test.prefix = /workerscripts RESOURCES += \ workerscripts_test \ trickypaths.qrc \ - retain.qrc + data/retain.qrc # QTBUG-46375 !win32: RESOURCES += trickypaths_umlaut.qrc diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 102acf73d6..5d87c319f3 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -65,6 +65,7 @@ private slots: void qrcScriptImport(); void fsScriptImport(); void moduleScriptImport(); + void esModulesViaQJSEngine(); void enums(); @@ -360,7 +361,7 @@ static QQmlPrivate::CachedQmlUnit *temporaryModifiedCachedUnit = nullptr; void tst_qmlcachegen::versionChecksForAheadOfTimeUnits() { QVERIFY(QFile::exists(":/data/versionchecks.qml")); - QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0); + QVERIFY(QFileInfo(":/data/versionchecks.qml").size() > 0); Q_ASSERT(!temporaryModifiedCachedUnit); QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError; @@ -387,12 +388,8 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits() { QQmlEngine engine; - QQmlComponent component(&engine, QUrl("qrc:/data/versionchecks.qml")); - QCOMPARE(component.status(), QQmlComponent::Error); - QCOMPARE(component.errorString(), - QString("qrc:/data/versionchecks.qml:-1 File was compiled ahead of time with an " - "incompatible version of Qt and the original file cannot be found. Please " - "recompile\n")); + CleanlyLoadingComponent component(&engine, QUrl("qrc:/data/versionchecks.qml")); + QCOMPARE(component.status(), QQmlComponent::Ready); } Q_ASSERT(temporaryModifiedCachedUnit); @@ -414,7 +411,7 @@ void tst_qmlcachegen::workerScripts() { QVERIFY(QFile::exists(":/workerscripts/data/worker.js")); QVERIFY(QFile::exists(":/workerscripts/data/worker.qml")); - QCOMPARE(QFileInfo(":/workerscripts/data/worker.js").size(), 0); + QVERIFY(QFileInfo(":/workerscripts/data/worker.js").size() > 0); QQmlEngine engine; CleanlyLoadingComponent component(&engine, QUrl("qrc:///workerscripts/data/worker.qml")); @@ -503,7 +500,7 @@ void tst_qmlcachegen::trickyPaths() { QFETCH(QString, filePath); QVERIFY2(QFile::exists(filePath), qPrintable(filePath)); - QCOMPARE(QFileInfo(filePath).size(), 0); + QVERIFY(QFileInfo(filePath).size() > 0); QQmlEngine engine; QQmlComponent component(&engine, QUrl("qrc" + filePath)); QScopedPointer<QObject> obj(component.create()); @@ -584,7 +581,7 @@ void tst_qmlcachegen::moduleScriptImport() QTRY_VERIFY(obj->property("ok").toBool()); QVERIFY(QFile::exists(":/data/script.mjs")); - QCOMPARE(QFileInfo(":/data/script.mjs").size(), 0); + QVERIFY(QFileInfo(":/data/script.mjs").size() > 0); { auto componentPrivate = QQmlComponentPrivate::get(&component); @@ -605,6 +602,14 @@ void tst_qmlcachegen::moduleScriptImport() } } +void tst_qmlcachegen::esModulesViaQJSEngine() +{ + QJSEngine engine; + QJSValue module = engine.importModule(":/data/module.mjs"); + QJSValue result = module.property("entry").call(); + QCOMPARE(result.toString(), "ok"); +} + void tst_qmlcachegen::enums() { QQmlEngine engine; @@ -617,7 +622,7 @@ void tst_qmlcachegen::enums() void tst_qmlcachegen::sourceFileIndices() { QVERIFY(QFile::exists(":/data/versionchecks.qml")); - QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0); + QVERIFY(QFileInfo(":/data/versionchecks.qml").size() > 0); QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError; const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit( @@ -632,8 +637,7 @@ void tst_qmlcachegen::reproducibleCache_data() QTest::addColumn<QString>("filePath"); QDir dir(dataDirectory()); - for (const QString &entry : dir.entryList(QDir::Files)) { - QVERIFY(entry.endsWith(".qml") || entry.endsWith(".js") || entry.endsWith(".mjs")); + for (const QString &entry : dir.entryList((QStringList() << "*.qml" << "*.js" << "*.mjs"), QDir::Files)) { QTest::newRow(entry.toUtf8().constData()) << dir.filePath(entry); } } diff --git a/tests/auto/qml/qmllint/data/Form.ui.qml b/tests/auto/qml/qmllint/data/Form.ui.qml new file mode 100644 index 0000000000..459c82afbb --- /dev/null +++ b/tests/auto/qml/qmllint/data/Form.ui.qml @@ -0,0 +1,4 @@ +import QtQuick 2.0 + +Item { +} diff --git a/tests/auto/qml/qmllint/data/FormUser.qml b/tests/auto/qml/qmllint/data/FormUser.qml new file mode 100644 index 0000000000..ea3621586f --- /dev/null +++ b/tests/auto/qml/qmllint/data/FormUser.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 + +Form { + x: 12 + y: 13 + objectName: "horst" +} diff --git a/tests/auto/qml/qmllint/data/ImportWithPrefix.qml b/tests/auto/qml/qmllint/data/ImportWithPrefix.qml new file mode 100644 index 0000000000..6d070da21a --- /dev/null +++ b/tests/auto/qml/qmllint/data/ImportWithPrefix.qml @@ -0,0 +1,5 @@ +import "." as MyStuff + +MyStuff.Simple { + property bool something: contains(Qt.point(12, 34)) +} diff --git a/tests/auto/qml/qmllint/data/MethodInItem.qml b/tests/auto/qml/qmllint/data/MethodInItem.qml new file mode 100644 index 0000000000..dbdaf8bcc1 --- /dev/null +++ b/tests/auto/qml/qmllint/data/MethodInItem.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + function doThings() { console.log("things") } +} diff --git a/tests/auto/qml/qmllint/data/MethodInScope.qml b/tests/auto/qml/qmllint/data/MethodInScope.qml new file mode 100644 index 0000000000..7ba0829f61 --- /dev/null +++ b/tests/auto/qml/qmllint/data/MethodInScope.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +MethodInItem { + Component.onCompleted: doThings() +} diff --git a/tests/auto/qml/qmllint/data/Things/SomethingElse.qml b/tests/auto/qml/qmllint/data/Things/SomethingElse.qml new file mode 100644 index 0000000000..0e69012662 --- /dev/null +++ b/tests/auto/qml/qmllint/data/Things/SomethingElse.qml @@ -0,0 +1,2 @@ +import QtQml 2.0 +QtObject {} diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes new file mode 100644 index 0000000000..00cda191cc --- /dev/null +++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes @@ -0,0 +1,16 @@ +import QtQuick.tooling 1.2 +Module { + dependencies: [] + Component { + name: "SomethingEntirelyStrange" + prototype: "QObject" + Enum { + name: "AnEnum" + values: { + "AAA": 0, + "BBB": 1, + "CCC": 2 + } + } + } +} diff --git a/tests/auto/qml/qmllint/data/Things/qmldir b/tests/auto/qml/qmllint/data/Things/qmldir new file mode 100644 index 0000000000..c53af3a340 --- /dev/null +++ b/tests/auto/qml/qmllint/data/Things/qmldir @@ -0,0 +1,3 @@ +module Things +Something 1.0 SomethingElse.qml +plugin doesNotExistPlugin diff --git a/tests/auto/qml/qmllint/data/UnmatchedSignalHandler.qml b/tests/auto/qml/qmllint/data/UnmatchedSignalHandler.qml new file mode 100644 index 0000000000..064444e182 --- /dev/null +++ b/tests/auto/qml/qmllint/data/UnmatchedSignalHandler.qml @@ -0,0 +1,15 @@ +import QtQuick 2.12 + +Item { + width: 640 + height: 480 + + MouseArea { + anchors.fill: parent + onClicked: console.log("okok") + + Connections { + onClicked: console.log(mouse.x) + } + } +} diff --git a/tests/auto/qml/qmllint/data/forLoop.qml b/tests/auto/qml/qmllint/data/forLoop.qml new file mode 100644 index 0000000000..be8b12409b --- /dev/null +++ b/tests/auto/qml/qmllint/data/forLoop.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 + +QtObject { + Component.onCompleted: { + var stuff = [1, 2, 3, 4] + for (var a in stuff) + console.log(a); + } +} diff --git a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml new file mode 100644 index 0000000000..4847fc9196 --- /dev/null +++ b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml @@ -0,0 +1,6 @@ +import Things 1.0 + +Something { + property var a: SomethingEntirelyStrange {} + property var b: SomethingEntirelyStrange.AAA +} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 582f146dca..04f554ac48 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -38,13 +38,21 @@ class TestQmllint: public QQmlDataTest private Q_SLOTS: void initTestCase() override; - void test(); - void test_data(); + void testUnqualified(); void testUnqualified_data(); + + void cleanQmlCode_data(); + void cleanQmlCode(); + + void dirtyQmlCode_data(); + void dirtyQmlCode(); + void testUnqualifiedNoSpuriousParentWarning(); - void catchIdentifierNoFalsePositive(); + private: + QString runQmllint(const QString &fileToLint, bool shouldSucceed); + QString m_qmllintPath; }; @@ -61,37 +69,14 @@ void TestQmllint::initTestCase() } } -void TestQmllint::test_data() -{ - QTest::addColumn<QString>("filename"); - QTest::addColumn<bool>("isValid"); - - // Valid files: - QTest::newRow("Simple_QML") << QStringLiteral("Simple.qml") << true; - QTest::newRow("QML_importing_JS") << QStringLiteral("importing_js.qml") << true; - QTest::newRow("QTBUG-45916_JS_with_pragma_and_import") << QStringLiteral("QTBUG-45916.js") << true; - - // Invalid files: - QTest::newRow("Invalid_syntax_QML") << QStringLiteral("failure1.qml") << false; - QTest::newRow("Invalid_syntax_JS") << QStringLiteral("failure1.js") << false; -} - void TestQmllint::testUnqualified() { - auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); QFETCH(QString, filename); QFETCH(QString, warningMessage); QFETCH(int, warningLine); QFETCH(int, warningColumn); - QStringList args; - args << QStringLiteral("-U") << testFile(filename) << QStringLiteral("-I") << qmlImportDir; - - QProcess process; - process.start(m_qmllintPath, args); - QVERIFY(process.waitForFinished()); - QVERIFY(process.exitStatus() == QProcess::NormalExit); - QVERIFY(process.exitCode()); - QString output = process.readAllStandardError(); + + const QString output = runQmllint(filename, false); QVERIFY(output.contains(QString::asprintf("Warning: unqualified access at %d:%d", warningLine, warningColumn))); QVERIFY(output.contains(warningMessage)); } @@ -118,56 +103,97 @@ void TestQmllint::testUnqualified_data() 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; + + QTest::newRow("NonSpuriousParent") << QStringLiteral("nonSpuriousParentWarning.qml") << QStringLiteral("property int x: <id>.parent.x") << 6 << 25; } void TestQmllint::testUnqualifiedNoSpuriousParentWarning() { - auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); - { - QString filename = testFile("spuriousParentWarning.qml"); - 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); - } - { - QString filename = testFile("nonSpuriousParentWarning.qml"); - 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()); - } + const QString unknownNotFound = runQmllint("spuriousParentWarning.qml", true); + QVERIFY(unknownNotFound.contains( + QStringLiteral("warning: Unknown was not found. Did you add all import paths?"))); } -void TestQmllint::catchIdentifierNoFalsePositive() +void TestQmllint::dirtyQmlCode_data() { - 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); + QTest::addColumn<QString>("filename"); + QTest::addColumn<QString>("warningMessage"); + QTest::addColumn<QString>("notContained"); + + QTest::newRow("Invalid_syntax_QML") + << QStringLiteral("failure1.qml") + << QStringLiteral("failure1.qml:4 : Expected token `:'") + << QString(); + QTest::newRow("Invalid_syntax_JS") + << QStringLiteral("failure1.js") + << QStringLiteral("failure1.js:4 : Expected token `;'") + << QString(); + QTest::newRow("UnmatchedSignalHandler") + << QStringLiteral("UnmatchedSignalHandler.qml") + << QString("Warning: no matching signal found for handler \"onClicked\" at 12:13") + << QStringLiteral("onMouseXChanged"); } -void TestQmllint::test() +void TestQmllint::dirtyQmlCode() { QFETCH(QString, filename); - QFETCH(bool, isValid); - QStringList args; - args << QStringLiteral("--silent") << testFile(filename); + QFETCH(QString, warningMessage); + QFETCH(QString, notContained); + + const QString output = runQmllint(filename, false); + QVERIFY(output.contains(warningMessage)); + if (!notContained.isEmpty()) + QVERIFY(!output.contains(notContained)); +} + +void TestQmllint::cleanQmlCode_data() +{ + QTest::addColumn<QString>("filename"); + QTest::newRow("Simple_QML") << QStringLiteral("Simple.qml"); + QTest::newRow("QML_importing_JS") << QStringLiteral("importing_js.qml"); + QTest::newRow("JS_with_pragma_and_import") << QStringLiteral("QTBUG-45916.js"); + QTest::newRow("uiQml") << QStringLiteral("FormUser.qml"); + QTest::newRow("methodInScope") << QStringLiteral("MethodInScope.qml"); + QTest::newRow("importWithPrefix") << QStringLiteral("ImportWithPrefix.qml"); + QTest::newRow("catchIdentifier") << QStringLiteral("catchIdentifierNoWarning.qml"); + QTest::newRow("qmldirAndQmltypes") << QStringLiteral("qmldirAndQmltypes.qml"); + QTest::newRow("forLoop") << QStringLiteral("forLoop.qml"); +} + +void TestQmllint::cleanQmlCode() +{ + QFETCH(QString, filename); + const QString warnings = runQmllint(filename, true); + QVERIFY(warnings.isEmpty()); +} - bool success = QProcess::execute(m_qmllintPath, args) == 0; - QCOMPARE(success, isValid); +QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed) +{ + auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); + QStringList args; + args << QStringLiteral("-U") << testFile(fileToLint) + << QStringLiteral("-I") << qmlImportDir + << QStringLiteral("-I") << dataDirectory() + << QStringLiteral("--silent"); + QString errors; + auto verify = [&](bool isSilent) { + QProcess process; + process.start(m_qmllintPath, args); + QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + if (shouldSucceed) + QCOMPARE(process.exitCode(), 0); + else + QVERIFY(process.exitCode() != 0); + errors = process.readAllStandardError(); + + if (isSilent) + QVERIFY(errors.isEmpty()); + }; + verify(true); + args.removeLast(); + verify(false); + return errors; } QTEST_MAIN(TestQmllint) diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index cae833cd60..79a73299a4 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -130,6 +130,8 @@ void tst_qmlmin::initTestCase() invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js"; invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml"; invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml"; + invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml"; + invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml"; // generatorFunction.qml is not invalid per se, but the minifier cannot handle yield statements invalidFiles << "tests/auto/qml/qqmlecmascript/data/generatorFunction.qml"; #endif diff --git a/tests/auto/qml/qqmlbinding/data/noUnexpectedStringConversion.qml b/tests/auto/qml/qqmlbinding/data/noUnexpectedStringConversion.qml new file mode 100644 index 0000000000..d0f30c5da5 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/noUnexpectedStringConversion.qml @@ -0,0 +1,30 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 + +Window { +visible: true +width: 640 +height: 480 +title: qsTr("Hello World") + + Rectangle { + id: colorRect + objectName: "colorRect" + anchors.fill: parent + Text { + objectName: "colorLabel" + id: colorLabel + } + } + + Binding { + target: colorLabel + property: "text" + value: "red" + } + Binding { + target: colorRect + property: "color" + value: "red" + } +} diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp index 9b66cd828a..2c2d311ff7 100644 --- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -55,6 +55,7 @@ private slots: void delayed(); void bindingOverwriting(); void bindToQmlComponent(); + void bindingDoesNoWeirdConversion(); private: QQmlEngine engine; @@ -68,7 +69,7 @@ void tst_qqmlbinding::binding() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("test-binding.qml")); - QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create()); + QScopedPointer<QQuickRectangle> rect { qobject_cast<QQuickRectangle*>(c.create()) }; QVERIFY(rect != nullptr); QQmlBind *binding3 = qobject_cast<QQmlBind*>(rect->findChild<QQmlBind*>("binding3")); @@ -85,18 +86,16 @@ void tst_qqmlbinding::binding() QQmlBind *binding = qobject_cast<QQmlBind*>(rect->findChild<QQmlBind*>("binding1")); QVERIFY(binding != nullptr); - QCOMPARE(binding->object(), qobject_cast<QObject*>(rect)); + QCOMPARE(binding->object(), qobject_cast<QObject*>(rect.get())); QCOMPARE(binding->property(), QLatin1String("text")); QCOMPARE(binding->value().toString(), QLatin1String("Hello")); - - delete rect; } void tst_qqmlbinding::whenAfterValue() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("test-binding2.qml")); - QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create()); + QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())}; QVERIFY(rect != nullptr); QCOMPARE(rect->color(), QColor("yellow")); @@ -104,15 +103,13 @@ void tst_qqmlbinding::whenAfterValue() rect->setProperty("changeColor", true); QCOMPARE(rect->color(), QColor("red")); - - delete rect; } void tst_qqmlbinding::restoreBinding() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("restoreBinding.qml")); - QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create()); + QScopedPointer<QQuickRectangle> rect { qobject_cast<QQuickRectangle*>(c.create()) }; QVERIFY(rect != nullptr); QQuickRectangle *myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem")); @@ -134,8 +131,6 @@ void tst_qqmlbinding::restoreBinding() //original binding restored myItem->setY(49); QCOMPARE(myItem->x(), qreal(100-49)); - - delete rect; } void tst_qqmlbinding::restoreBindingValue() @@ -214,7 +209,7 @@ void tst_qqmlbinding::restoreBindingWithLoop() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("restoreBindingWithLoop.qml")); - QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create()); + QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())}; QVERIFY(rect != nullptr); QQuickRectangle *myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem")); @@ -242,15 +237,13 @@ void tst_qqmlbinding::restoreBindingWithLoop() myItem->setY(49); QCOMPARE(myItem->x(), qreal(49 + 100)); - - delete rect; } void tst_qqmlbinding::restoreBindingWithoutCrash() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("restoreBindingWithoutCrash.qml")); - QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create()); + QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())}; QVERIFY(rect != nullptr); QQuickRectangle *myItem = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("myItem")); @@ -281,8 +274,6 @@ void tst_qqmlbinding::restoreBindingWithoutCrash() //original binding restored myItem->setY(49); QCOMPARE(myItem->x(), qreal(100-49)); - - delete rect; } //QTBUG-20692 @@ -290,15 +281,13 @@ void tst_qqmlbinding::deletedObject() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("deletedObject.qml")); - QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create()); + QScopedPointer<QQuickRectangle> rect {qobject_cast<QQuickRectangle*>(c.create())}; QVERIFY(rect != nullptr); QGuiApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); //don't crash rect->setProperty("activateBinding", true); - - delete rect; } void tst_qqmlbinding::warningOnUnknownProperty() @@ -307,9 +296,8 @@ void tst_qqmlbinding::warningOnUnknownProperty() QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("unknownProperty.qml")); - QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) }; QVERIFY(item); - delete item; QCOMPARE(messageHandler.messages().count(), 1); @@ -323,9 +311,8 @@ void tst_qqmlbinding::warningOnReadOnlyProperty() QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("readonlyProperty.qml")); - QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) }; QVERIFY(item); - delete item; QCOMPARE(messageHandler.messages().count(), 1); @@ -339,9 +326,8 @@ void tst_qqmlbinding::disabledOnUnknownProperty() QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("disabledUnknown.qml")); - QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) }; QVERIFY(item); - delete item; QCOMPARE(messageHandler.messages().count(), 0); } @@ -352,10 +338,8 @@ void tst_qqmlbinding::disabledOnReadonlyProperty() QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("disabledReadonly.qml")); - QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QScopedPointer<QQuickItem> item { qobject_cast<QQuickItem *>(c.create()) }; QVERIFY(item); - delete item; - QCOMPARE(messageHandler.messages().count(), 0); } @@ -363,21 +347,19 @@ void tst_qqmlbinding::delayed() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("delayed.qml")); - QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())}; QVERIFY(item != nullptr); // update on creation QCOMPARE(item->property("changeCount").toInt(), 1); - QMetaObject::invokeMethod(item, "updateText"); + QMetaObject::invokeMethod(item.get(), "updateText"); // doesn't update immediately QCOMPARE(item->property("changeCount").toInt(), 1); QCoreApplication::processEvents(); // only updates once (non-delayed would update twice) QCOMPARE(item->property("changeCount").toInt(), 2); - - delete item; } void tst_qqmlbinding::bindingOverwriting() @@ -387,9 +369,8 @@ void tst_qqmlbinding::bindingOverwriting() QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("bindingOverwriting.qml")); - QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())}; QVERIFY(item); - delete item; QLoggingCategory::setFilterRules(QString()); QCOMPARE(messageHandler.messages().count(), 2); @@ -402,6 +383,21 @@ void tst_qqmlbinding::bindToQmlComponent() QVERIFY(c.create()); } +// QTBUG-78943 +void tst_qqmlbinding::bindingDoesNoWeirdConversion() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("noUnexpectedStringConversion.qml")); + QScopedPointer<QObject> o {c.create()}; + QVERIFY(o); + QObject *colorRect = o->findChild<QObject*>("colorRect"); + QVERIFY(colorRect); + QCOMPARE(qvariant_cast<QColor>(colorRect->property("color")), QColorConstants::Red); + QObject *colorLabel = o->findChild<QObject*>("colorLabel"); + QCOMPARE(colorLabel->property("text").toString(), QLatin1String("red")); + QVERIFY(colorLabel); +} + QTEST_MAIN(tst_qqmlbinding) #include "tst_qqmlbinding.moc" diff --git a/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml b/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml new file mode 100644 index 0000000000..f693cb4c2e --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml @@ -0,0 +1,10 @@ +import QtQuick 2.13 + +Item { + property alias i_alias: sub.i + + Item { + id: sub + required property int i + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml b/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml new file mode 100644 index 0000000000..0ce61c8d9d --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml @@ -0,0 +1,6 @@ +import QtQuick 2.14 + +Item { + id: base + required property int i +} diff --git a/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml b/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml new file mode 100644 index 0000000000..527eb417e5 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.13 + +AliasToSubcomponentRequiredBase { +} diff --git a/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml b/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml new file mode 100644 index 0000000000..60a2077606 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml @@ -0,0 +1,11 @@ +import QtQuick 2.14 + +Item { + id: root + property Item it + Component.onCompleted: function() { + let component = Qt.createComponent("requiredNotSet.qml", Component.PreferSynchronous, root) + console.assert(component.status == Component.Ready) + it = component.createObject(component, {i: 42}) + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml b/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml new file mode 100644 index 0000000000..e09ddcccc1 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml @@ -0,0 +1,11 @@ +import QtQuick 2.14 + +Item { + id: root + property Item it + Component.onCompleted: function() { + let component = Qt.createComponent("requiredNotSet.qml", Component.PreferSynchronous, root) + console.assert(component.status == Component.Ready) + root.it = component.createObject(component) + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml b/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml new file mode 100644 index 0000000000..c0b5d695f1 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +Item { + required property int i +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml new file mode 100644 index 0000000000..76dfcd87e5 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml @@ -0,0 +1,6 @@ +import QtQuick 2.14 + +Item { + required property int i + i: 42 +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml new file mode 100644 index 0000000000..3b7811e453 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +BaseWithRequired { + i: 13 +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml new file mode 100644 index 0000000000..163616bc8a --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml @@ -0,0 +1,8 @@ +import QtQuick 2.14 + +Item { + id: withAlias + j: 42 + required property int i + property alias j: withAlias.i +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml new file mode 100644 index 0000000000..e59bccf379 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml @@ -0,0 +1,8 @@ +import QtQuick 2.14 + +Item { + id: withAlias + required property int i + j: 42 + property alias j: withAlias.i +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml new file mode 100644 index 0000000000..0bc2f8a7df --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml @@ -0,0 +1,7 @@ +import QtQuick 2.14 + +BaseWithRequired { + id: withAlias + property alias j: withAlias.i + j: 42 +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml new file mode 100644 index 0000000000..45cf02d3d8 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml @@ -0,0 +1,9 @@ +import QtQml 2.12 + +QtObject { + id: stuff + required property int x; + property alias y: stuff.x + property alias z: stuff.y + z: 5 +} diff --git a/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml b/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml new file mode 100644 index 0000000000..2dc182ea82 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml @@ -0,0 +1,5 @@ +import QtQuick 2.13 + +AliasToSubcomponentRequiredBase { + i_alias: 42 +} diff --git a/tests/auto/qml/qqmlcomponent/data/shadowing.qml b/tests/auto/qml/qqmlcomponent/data/shadowing.qml new file mode 100644 index 0000000000..4d119d8884 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/shadowing.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +BaseWithRequired { + property int i: 13 +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 79ec507388..2acc62ca28 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -121,6 +121,9 @@ private slots: void relativeUrl_data(); void relativeUrl(); void setDataNoEngineNoSegfault(); + void testRequiredProperties_data(); + void testRequiredProperties(); + void testRequiredPropertiesFromQml(); void testSetInitialProperties(); private: @@ -222,12 +225,12 @@ void tst_qqmlcomponent::qmlCreateObjectAutoParent() QVERIFY(window_item); QVERIFY(window_window); - QCOMPARE(qtobject_item->metaObject()->className(), "QQuickItem"); - QCOMPARE(qtobject_window->metaObject()->className(), "QQuickWindow"); - QCOMPARE(item_item->metaObject()->className(), "QQuickItem"); - QCOMPARE(item_window->metaObject()->className(), "QQuickWindow"); - QCOMPARE(window_item->metaObject()->className(), "QQuickItem"); - QCOMPARE(window_window->metaObject()->className(), "QQuickWindow"); + QVERIFY(QByteArray(qtobject_item->metaObject()->className()).startsWith("QQuickItem")); + QVERIFY(QByteArray(qtobject_window->metaObject()->className()).startsWith("QQuickWindow")); + QVERIFY(QByteArray(item_item->metaObject()->className()).startsWith("QQuickItem")); + QVERIFY(QByteArray(item_window->metaObject()->className()).startsWith("QQuickWindow")); + QVERIFY(QByteArray(window_item->metaObject()->className()).startsWith("QQuickItem")); + QVERIFY(QByteArray(window_window->metaObject()->className()).startsWith("QQuickWindow")); QCOMPARE(qtobject_qtobject->parent(), qtobjectParent); QCOMPARE(qtobject_item->parent(), qtobjectParent); @@ -668,35 +671,80 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault() QVERIFY(!c); } -void tst_qqmlcomponent::testSetInitialProperties() +void tst_qqmlcomponent::testRequiredProperties_data() +{ + QTest::addColumn<QUrl>("testFile"); + QTest::addColumn<bool>("shouldSucceed"); + QTest::addColumn<QString>("errorMsg"); + + QTest::addRow("requiredSetViaChainedAlias") << testFileUrl("requiredSetViaChainedAlias.qml") << true << ""; + QTest::addRow("requiredNotSet") << testFileUrl("requiredNotSet.qml") << false << "Required property i was not initialized"; + QTest::addRow("requiredSetInSameFile") << testFileUrl("requiredSetInSameFile.qml") << true << ""; + QTest::addRow("requiredSetViaAlias1") << testFileUrl("requiredSetViaAliasBeforeSameFile.qml") << true << ""; + QTest::addRow("requiredSetViaAlias2") << testFileUrl("requiredSetViaAliasAfterSameFile.qml") << true << ""; + QTest::addRow("requiredSetViaAlias3") << testFileUrl("requiredSetViaAliasParentFile.qml") << true << ""; + QTest::addRow("shadowing") << testFileUrl("shadowing.qml") << false << "Required property i was not initialized"; + QTest::addRow("setLater") << testFileUrl("requiredSetLater.qml") << true << ""; + QTest::addRow("setViaAliasToSubcomponent") << testFileUrl("setViaAliasToSubcomponent.qml") << true << ""; + QTest::addRow("aliasToSubcomponentNotSet") << testFileUrl("aliasToSubcomponentNotSet.qml") << false << "It can be set via the alias property i_alias"; +} + + +void tst_qqmlcomponent::testRequiredProperties() +{ + QQmlEngine eng; + using QScopedObjPointer = QScopedPointer<QObject>; + QFETCH(QUrl, testFile); + QFETCH(bool, shouldSucceed); + QQmlComponent comp(&eng); + comp.loadUrl(testFile); + QScopedObjPointer obj {comp.create()}; + if (shouldSucceed) + QVERIFY(obj); + else { + QVERIFY(!obj); + QFETCH(QString, errorMsg); + QVERIFY(comp.errorString().contains(errorMsg)); + } +} + +void tst_qqmlcomponent::testRequiredPropertiesFromQml() { QQmlEngine eng; { - // JSON based initialization QQmlComponent comp(&eng); - comp.loadUrl(testFileUrl("allJSONTypes.qml")); - QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) }; + comp.loadUrl(testFileUrl("createdFromQml.qml")); + QScopedPointer<QObject> obj { comp.create() }; 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)); + auto root = qvariant_cast<QQuickItem*>(obj->property("it")); + QVERIFY(root); + QCOMPARE(root->property("i").toInt(), 42); } { - // QVariant + QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(".*requiredNotSet.qml:4:5: Required property i was not initialized")); QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("createdFromQmlFail.qml")); + QScopedPointer<QObject> obj { comp.create() }; + QVERIFY(obj); + QCOMPARE(qvariant_cast<QQuickItem *>(obj->property("it")), nullptr); + } +} + +struct ComponentWithPublicSetInitial : QQmlComponent +{ + using QQmlComponent::QQmlComponent; + void setInitialProperties(QObject *o, QVariantMap map) + { + QQmlComponent::setInitialProperties(o, map); + } +}; + +void tst_qqmlcomponent::testSetInitialProperties() +{ + QQmlEngine eng; + { + // QVariant + ComponentWithPublicSetInitial comp(&eng); comp.loadUrl(testFileUrl("variantBasedInitialization.qml")); QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) }; QVERIFY(obj); @@ -728,8 +776,6 @@ void tst_qqmlcomponent::testSetInitialProperties() }); #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); @@ -751,13 +797,20 @@ void tst_qqmlcomponent::testSetInitialProperties() } { + // createWithInitialProperties convenience function + QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("requiredNotSet.qml")); + QScopedPointer<QObject> obj {comp.createWithInitialProperties( QVariantMap { {QLatin1String("i"), QJsonValue{42}} })}; + QVERIFY(obj); + QCOMPARE(obj->property("i"), 42); + } + { // 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")); } diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index cf0f3c7bb3..07af519a3d 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -470,7 +470,7 @@ void tst_qqmlconnections::noAcceleratedGlobalLookup() QVERIFY(c.isReady()); QScopedPointer<QObject> object(c.create()); const QVariant val = object->property("testEnum"); - QCOMPARE(val.type(), int(QMetaType::Int)); + QCOMPARE(val.type(), QVariant::Int); QCOMPARE(val.toInt(), int(Proxy::EnumValue)); } diff --git a/tests/auto/qml/qqmlconsole/data/logging.qml b/tests/auto/qml/qqmlconsole/data/logging.qml index 1f929d311b..f5eaeb442a 100644 --- a/tests/auto/qml/qqmlconsole/data/logging.qml +++ b/tests/auto/qml/qqmlconsole/data/logging.qml @@ -31,6 +31,8 @@ import QtQuick 2.0 QtObject { id:root + required property var customObject + required property var stringListProperty function consoleCount() { console.count("console.count", "Ignore additional argument"); @@ -67,7 +69,7 @@ QtObject { console.log(1, "pong!", new Object); console.log(1, ["ping","pong"], new Object, 2); - console.log(contextStringListProperty); + console.log(stringListProperty); console.log(customObject); console.log([[1,2,3,[2,2,2,2],4],[5,6,7,8]]); diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp index b157314071..48613d04f1 100644 --- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp +++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp @@ -95,16 +95,16 @@ void tst_qqmlconsole::logging() QTest::ignoreMessage(QtDebugMsg, "QVariant(CustomObject, MY OBJECT)"); QTest::ignoreMessage(QtDebugMsg, "[[1,2,3,[2,2,2,2],4],[5,6,7,8]]"); - QScopedPointer<QQmlContext> loggingContext(new QQmlContext(engine.rootContext())); QStringList stringList; stringList << QStringLiteral("Hello") << QStringLiteral("World"); - loggingContext->setContextProperty("contextStringListProperty", stringList); CustomObject customObject; QVERIFY(QMetaType::registerDebugStreamOperator<CustomObject>()); - loggingContext->setContextProperty("customObject", QVariant::fromValue(customObject)); QQmlComponent component(&engine, testUrl); - QScopedPointer<QObject> object(component.create(loggingContext.data())); + QScopedPointer<QObject> object(component.createWithInitialProperties({ + {"customObject", QVariant::fromValue(customObject)}, + {"stringListProperty", stringList} + })); QVERIFY(object != nullptr); } diff --git a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp index 99cabb4b09..13e4d4c53b 100644 --- a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp +++ b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp @@ -71,7 +71,7 @@ void tst_qqmlcpputils::fastConnect() { MyObject obj; - qmlobject_connect(&obj, MyObject, SIGNAL(signal1()), &obj, MyObject, SLOT(slot1())) + qmlobject_connect(&obj, MyObject, SIGNAL(signal1()), &obj, MyObject, SLOT(slot1())); obj.signal1(); QCOMPARE(obj.slotCount, 1); diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml new file mode 100644 index 0000000000..6686831e1c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDate-October.qml @@ -0,0 +1,12 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + // QTBUG-78996 + dateProperty = new Date(2019, 9, 3) + boolProperty = (dateProperty.getFullYear() == 2019 + && dateProperty.getMonth() == 9 + && dateProperty.getDate() == 3) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml new file mode 100644 index 0000000000..29ec40ffbd --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-Feb.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date(2019, 2, 0) // Feb 28th + boolProperty = (dateProperty.getFullYear() == 2019 + && dateProperty.getMonth() == 1 + && dateProperty.getDate() == 28) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml new file mode 100644 index 0000000000..7fc8bf43bd --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-March.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date(2019, 1, 29) // March 1st + boolProperty = (dateProperty.getFullYear() == 2019 + && dateProperty.getMonth() == 2 + && dateProperty.getDate() == 1) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml new file mode 100644 index 0000000000..6dd84810e6 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-leap.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date(2020, 2, 0) // Feb 29th + boolProperty = (dateProperty.getFullYear() == 2020 + && dateProperty.getMonth() == 1 + && dateProperty.getDate() == 29) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml new file mode 100644 index 0000000000..ddb79727ef --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-wrap.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date(2017, 40, -61) // 2020, Feb 29th + boolProperty = (dateProperty.getFullYear() == 2020 + && dateProperty.getMonth() == 1 + && dateProperty.getDate() == 29) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml new file mode 100644 index 0000000000..90514c39c8 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDate-denormal-year.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date(2019, 12, 0) // Dec 31 + boolProperty = (dateProperty.getFullYear() == 2019 + && dateProperty.getMonth() == 11 + && dateProperty.getDate() == 31) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml new file mode 100644 index 0000000000..c97076f887 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-October.qml @@ -0,0 +1,16 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + // QTBUG-78996 + dateTimeProperty = new Date(2019, 9, 3, 12) + boolProperty = (dateTimeProperty.getFullYear() == 2019 + && dateTimeProperty.getMonth() == 9 + && dateTimeProperty.getDate() == 3 + && dateTimeProperty.getHours() == 12 + && dateTimeProperty.getMinutes() == 0 + && dateTimeProperty.getSeconds() == 0 + && dateTimeProperty.getMilliseconds() == 0) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml new file mode 100644 index 0000000000..2b6b9af3e1 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-March.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateTimeProperty = new Date(2019, 1, 28, 23, 59, 59, 1001) // 2019-3-1 0:0:0.001 + boolProperty = (dateTimeProperty.getFullYear() == 2019 + && dateTimeProperty.getMonth() == 2 + && dateTimeProperty.getDate() == 1 + && dateTimeProperty.getHours() == 0 + && dateTimeProperty.getMinutes() == 0 + && dateTimeProperty.getSeconds() == 0 + && dateTimeProperty.getMilliseconds() == 1) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml new file mode 100644 index 0000000000..7d018e2904 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-hours.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateTimeProperty = new Date(2019, 11, 31, 1440) // 2020-2-29 0:0:0 + boolProperty = (dateTimeProperty.getFullYear() == 2020 + && dateTimeProperty.getMonth() == 1 + && dateTimeProperty.getDate() == 29 + && dateTimeProperty.getHours() == 0 + && dateTimeProperty.getMinutes() == 0 + && dateTimeProperty.getSeconds() == 0 + && dateTimeProperty.getMilliseconds() == 0) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml new file mode 100644 index 0000000000..0a7687c669 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-leap.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateTimeProperty = new Date(2020, 2, 1, 0, 0, 0, -1) // 2020-2-29 23:59:59.999 + boolProperty = (dateTimeProperty.getFullYear() == 2020 + && dateTimeProperty.getMonth() == 1 + && dateTimeProperty.getDate() == 29 + && dateTimeProperty.getHours() == 23 + && dateTimeProperty.getMinutes() == 59 + && dateTimeProperty.getSeconds() == 59 + && dateTimeProperty.getMilliseconds() == 999) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml new file mode 100644 index 0000000000..738d603b4b --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-minutes.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateTimeProperty = new Date(2020, 1, 28, 0, 1440) // 2020-2-29 0:0:0 + boolProperty = (dateTimeProperty.getFullYear() == 2020 + && dateTimeProperty.getMonth() == 1 + && dateTimeProperty.getDate() == 29 + && dateTimeProperty.getHours() == 0 + && dateTimeProperty.getMinutes() == 0 + && dateTimeProperty.getSeconds() == 0 + && dateTimeProperty.getMilliseconds() == 0) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml new file mode 100644 index 0000000000..d48534f0d0 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/checkDateTime-denormal-seconds.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateTimeProperty = new Date(2020, 1, 28, 23, 0, 3600) // 2020-2-29 0:0:0 + boolProperty = (dateTimeProperty.getFullYear() == 2020 + && dateTimeProperty.getMonth() == 1 + && dateTimeProperty.getDate() == 29 + && dateTimeProperty.getHours() == 0 + && dateTimeProperty.getMinutes() == 0 + && dateTimeProperty.getSeconds() == 0 + && dateTimeProperty.getMilliseconds() == 0) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml index 54d29dfc94..9fdb7f92f3 100644 --- a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml +++ b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml @@ -1,4 +1,5 @@ import Qt.test 1.0 +import QtQuick 2.0 // We need the the QtQuick color provider for colorProperty MyQmlObject { diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 730dc7cab8..3233e7f105 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1098,13 +1098,11 @@ class MyItemUsingRevisionedObject : public QObject Q_PROPERTY(MyRevisionedClass *revisioned READ revisioned) public: - MyItemUsingRevisionedObject() { - m_revisioned = new MyRevisionedClass; - } + MyItemUsingRevisionedObject() : m_revisioned (new MyRevisionedClass) {} - MyRevisionedClass *revisioned() const { return m_revisioned; } + MyRevisionedClass *revisioned() const { return m_revisioned.get(); } private: - MyRevisionedClass *m_revisioned; + QScopedPointer<MyRevisionedClass> m_revisioned; }; QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 269d90c891..f4de83eb87 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -79,6 +79,10 @@ private slots: void assignDate(); void exportDate_data(); void exportDate(); + void checkDate_data(); + void checkDate(); + void checkDateTime_data(); + void checkDateTime(); void idShortcutInvalidates(); void boolPropertiesEvaluateAsBool(); void methods(); @@ -568,6 +572,82 @@ void tst_qqmlecmascript::exportDate() QCOMPARE(object->boolProperty(), true); } +void tst_qqmlecmascript::checkDate_data() +{ + QTest::addColumn<QUrl>("source"); + QTest::addColumn<QDate>("date"); + // NB: JavaScript month-indices are Jan = 0 to Dec = 11; QDate's are Jan = 1 to Dec = 12. + QTest::newRow("denormal-March") + << testFileUrl("checkDate-denormal-March.qml") + << QDate(2019, 3, 1); + QTest::newRow("denormal-leap") + << testFileUrl("checkDate-denormal-leap.qml") + << QDate(2020, 2, 29); + QTest::newRow("denormal-Feb") + << testFileUrl("checkDate-denormal-Feb.qml") + << QDate(2019, 2, 28); + QTest::newRow("denormal-year") + << testFileUrl("checkDate-denormal-year.qml") + << QDate(2019, 12, 31); + QTest::newRow("denormal-wrap") + << testFileUrl("checkDate-denormal-wrap.qml") + << QDate(2020, 2, 29); + QTest::newRow("October") + << testFileUrl("checkDate-October.qml") + << QDate(2019, 10, 3); +} + +void tst_qqmlecmascript::checkDate() +{ + QFETCH(const QUrl, source); + QFETCH(const QDate, date); + QQmlEngine e; + QQmlComponent component(&e, source); + QScopedPointer<QObject> obj(component.create()); + MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data()); + QVERIFY(object != nullptr); + QCOMPARE(object->dateProperty(), date); + QVERIFY(object->boolProperty()); +} + +void tst_qqmlecmascript::checkDateTime_data() +{ + QTest::addColumn<QUrl>("source"); + QTest::addColumn<QDateTime>("when"); + // NB: JavaScript month-indices are Jan = 0 to Dec = 11; QDate's are Jan = 1 to Dec = 12. + QTest::newRow("denormal-March") + << testFileUrl("checkDateTime-denormal-March.qml") + << QDateTime(QDate(2019, 3, 1), QTime(0, 0, 0, 1), Qt::LocalTime); + QTest::newRow("denormal-leap") + << testFileUrl("checkDateTime-denormal-leap.qml") + << QDateTime(QDate(2020, 2, 29), QTime(23, 59, 59, 999), Qt::LocalTime); + QTest::newRow("denormal-hours") + << testFileUrl("checkDateTime-denormal-hours.qml") + << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime); + QTest::newRow("denormal-minutes") + << testFileUrl("checkDateTime-denormal-minutes.qml") + << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime); + QTest::newRow("denormal-seconds") + << testFileUrl("checkDateTime-denormal-seconds.qml") + << QDateTime(QDate(2020, 2, 29), QTime(0, 0), Qt::LocalTime); + QTest::newRow("October") + << testFileUrl("checkDateTime-October.qml") + << QDateTime(QDate(2019, 10, 3), QTime(12, 0), Qt::LocalTime); +} + +void tst_qqmlecmascript::checkDateTime() +{ + QFETCH(const QUrl, source); + QFETCH(const QDateTime, when); + QQmlEngine e; + QQmlComponent component(&e, source); + QScopedPointer<QObject> obj(component.create()); + MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data()); + QVERIFY(object != nullptr); + QCOMPARE(object->dateTimeProperty(), when); + QVERIFY(object->boolProperty()); +} + void tst_qqmlecmascript::idShortcutInvalidates() { QQmlEngine engine; @@ -1693,10 +1773,10 @@ void tst_qqmlecmascript::componentCreation() } QQmlComponent component(&engine, testUrl); - MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create()); + QScopedPointer<MyTypeObject> object(qobject_cast<MyTypeObject*>(component.create())); QVERIFY(object != nullptr); - QMetaObject::invokeMethod(object, method.toUtf8()); + QMetaObject::invokeMethod(object.get(), method.toUtf8()); QQmlComponent *created = object->componentProperty(); if (creationError.isEmpty()) { @@ -1704,7 +1784,7 @@ void tst_qqmlecmascript::componentCreation() QObject *expectedParent = reinterpret_cast<QObject *>(quintptr(-1)); if (createdParent == QLatin1String("obj")) { - expectedParent = object; + expectedParent = object.get(); } else if ((createdParent == QLatin1String("null")) || createdParent.isEmpty()) { expectedParent = nullptr; } @@ -2050,7 +2130,7 @@ void tst_qqmlecmascript::functionErrors() QObject *resource = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>()); warning = url + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function"); - warning = warning.arg(QString::number((quintptr)resource, 16)); + warning = warning.arg(QString::number(quintptr(resource), 16)); QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed. QMetaObject::invokeMethod(object, "retrieveScarceResource"); delete object; @@ -3124,13 +3204,13 @@ void tst_qqmlecmascript::callQtInvokables() void tst_qqmlecmascript::resolveClashingProperties() { - ClashingNames *o = new ClashingNames(); + QScopedPointer<ClashingNames> o(new ClashingNames()); QQmlEngine qmlengine; QV4::ExecutionEngine *engine = qmlengine.handle(); QV4::Scope scope(engine); - QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o)); + QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o.get())); QV4::ObjectIterator it(scope, object->as<QV4::Object>(), QV4::ObjectIterator::EnumerableOnly); QV4::ScopedValue name(scope); QV4::ScopedValue value(scope); @@ -4575,7 +4655,7 @@ void tst_qqmlecmascript::scarceResources_other() eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>()); QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. expectedWarning = varComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function"); - expectedWarning = expectedWarning.arg(QString::number((quintptr)eo, 16)); + expectedWarning = expectedWarning.arg(QString::number(quintptr(eo), 16)); QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. QMetaObject::invokeMethod(object, "retrieveScarceResource"); QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred. @@ -4649,7 +4729,7 @@ void tst_qqmlecmascript::scarceResources_other() eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>()); QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage. expectedWarning = variantComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function"); - expectedWarning = expectedWarning.arg(QString::number((quintptr)eo, 16)); + expectedWarning = expectedWarning.arg(QString::number(quintptr(eo), 16)); QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. QMetaObject::invokeMethod(object, "retrieveScarceResource"); QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred. @@ -6093,7 +6173,7 @@ void tst_qqmlecmascript::variants() QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("variants.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); QCOMPARE(object->property("undefinedVariant").type(), QVariant::Invalid); @@ -6102,13 +6182,13 @@ void tst_qqmlecmascript::variants() QCOMPARE(object->property("doubleVariant").type(), QVariant::Double); QVariant result; - QMetaObject::invokeMethod(object, "checkNull", Q_RETURN_ARG(QVariant, result)); + QMetaObject::invokeMethod(object.get(), "checkNull", Q_RETURN_ARG(QVariant, result)); QCOMPARE(result.toBool(), true); - QMetaObject::invokeMethod(object, "checkUndefined", Q_RETURN_ARG(QVariant, result)); + QMetaObject::invokeMethod(object.get(), "checkUndefined", Q_RETURN_ARG(QVariant, result)); QCOMPARE(result.toBool(), true); - QMetaObject::invokeMethod(object, "checkNumber", Q_RETURN_ARG(QVariant, result)); + QMetaObject::invokeMethod(object.get(), "checkNumber", Q_RETURN_ARG(QVariant, result)); QCOMPARE(result.toBool(), true); } @@ -6357,6 +6437,8 @@ void tst_qqmlecmascript::topLevelGeneratorFunction() QQmlComponent component(&engine, testFileUrl("generatorFunction.qml")); QScopedPointer<QObject> o {component.create()}; + if (!o) + qDebug() << component.errorString(); QVERIFY(o != nullptr); // check that generator works correctly in QML @@ -6998,12 +7080,12 @@ void tst_qqmlecmascript::realToInt() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("realToInt.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); - QMetaObject::invokeMethod(object, "test1"); + QMetaObject::invokeMethod(object.get(), "test1"); QCOMPARE(object->value(), int(4)); - QMetaObject::invokeMethod(object, "test2"); + QMetaObject::invokeMethod(object.get(), "test2"); QCOMPARE(object->value(), int(7)); } @@ -7012,7 +7094,7 @@ void tst_qqmlecmascript::urlProperty() QQmlEngine engine; { QQmlComponent component(&engine, testFileUrl("urlProperty.1.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); object->setStringProperty("http://qt-project.org"); QCOMPARE(object->urlProperty(), QUrl("http://qt-project.org/index.html")); @@ -7027,7 +7109,7 @@ void tst_qqmlecmascript::urlPropertyWithEncoding() QQmlEngine engine; { QQmlComponent component(&engine, testFileUrl("urlProperty.2.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); object->setStringProperty("http://qt-project.org"); const QUrl encoded = QUrl::fromEncoded("http://qt-project.org/?get%3cDATA%3e", QUrl::TolerantMode); @@ -7062,7 +7144,7 @@ void tst_qqmlecmascript::dynamicString() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("dynamicString.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); QCOMPARE(object->property("stringProperty").toString(), QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!")); @@ -7072,7 +7154,7 @@ void tst_qqmlecmascript::deleteLaterObjectMethodCall() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("deleteLaterObjectMethodCall.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -7080,7 +7162,7 @@ void tst_qqmlecmascript::automaticSemicolon() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("automaticSemicolon.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -7088,7 +7170,7 @@ void tst_qqmlecmascript::compatibilitySemicolon() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("compatibilitySemicolon.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -7096,7 +7178,7 @@ void tst_qqmlecmascript::incrDecrSemicolon1() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon1.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -7104,7 +7186,7 @@ void tst_qqmlecmascript::incrDecrSemicolon2() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon2.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -7120,7 +7202,7 @@ void tst_qqmlecmascript::unaryExpression() { QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("unaryExpression.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -7260,7 +7342,7 @@ void tst_qqmlecmascript::switchStatement() QQmlEngine engine; { QQmlComponent component(&engine, testFileUrl("switchStatement.1.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); // `object->value()' is the number of executed statements @@ -7283,7 +7365,7 @@ void tst_qqmlecmascript::switchStatement() { QQmlComponent component(&engine, testFileUrl("switchStatement.2.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); // `object->value()' is the number of executed statements @@ -7306,7 +7388,7 @@ void tst_qqmlecmascript::switchStatement() { QQmlComponent component(&engine, testFileUrl("switchStatement.3.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); // `object->value()' is the number of executed statements @@ -7333,7 +7415,7 @@ void tst_qqmlecmascript::switchStatement() QString warning = component.url().toString() + ":4:5: Unable to assign [undefined] to int"; QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); // `object->value()' is the number of executed statements @@ -7357,7 +7439,7 @@ void tst_qqmlecmascript::switchStatement() { QQmlComponent component(&engine, testFileUrl("switchStatement.5.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); // `object->value()' is the number of executed statements @@ -7380,7 +7462,7 @@ void tst_qqmlecmascript::switchStatement() { QQmlComponent component(&engine, testFileUrl("switchStatement.6.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); // `object->value()' is the number of executed statements @@ -7408,7 +7490,7 @@ void tst_qqmlecmascript::withStatement() { QUrl url = testFileUrl("withStatement.1.qml"); QQmlComponent component(&engine, url); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); QCOMPARE(object->value(), 123); @@ -7420,7 +7502,7 @@ void tst_qqmlecmascript::tryStatement() QQmlEngine engine; { QQmlComponent component(&engine, testFileUrl("tryStatement.1.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); QCOMPARE(object->value(), 123); @@ -7428,7 +7510,7 @@ void tst_qqmlecmascript::tryStatement() { QQmlComponent component(&engine, testFileUrl("tryStatement.2.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); QCOMPARE(object->value(), 321); @@ -7436,7 +7518,7 @@ void tst_qqmlecmascript::tryStatement() { QQmlComponent component(&engine, testFileUrl("tryStatement.3.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); QVERIFY(object->qjsvalue().isUndefined()); @@ -7444,7 +7526,7 @@ void tst_qqmlecmascript::tryStatement() { QQmlComponent component(&engine, testFileUrl("tryStatement.4.qml")); - MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject*>(component.create())); QVERIFY(object != nullptr); QVERIFY(object->qjsvalue().isUndefined()); @@ -7585,7 +7667,7 @@ void tst_qqmlecmascript::onDestruction() // component instance. This shouldn't crash. QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("onDestruction.qml")); - QObject *obj = c.create(); + QScopedPointer<QObject> obj(c.create()); QVERIFY(obj != nullptr); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); } @@ -7926,19 +8008,19 @@ void tst_qqmlecmascript::dateParse() QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("date.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); if (object == nullptr) qDebug() << component.errorString(); QVERIFY(object != nullptr); QVariant q; - QMetaObject::invokeMethod(object, "test_is_invalid_jsDateTime", Q_RETURN_ARG(QVariant, q)); + QMetaObject::invokeMethod(object.get(), "test_is_invalid_jsDateTime", Q_RETURN_ARG(QVariant, q)); QVERIFY(q.toBool()); - QMetaObject::invokeMethod(object, "test_is_invalid_qtDateTime", Q_RETURN_ARG(QVariant, q)); + QMetaObject::invokeMethod(object.get(), "test_is_invalid_qtDateTime", Q_RETURN_ARG(QVariant, q)); QVERIFY(q.toBool()); - QMetaObject::invokeMethod(object, "test_rfc2822_date", Q_RETURN_ARG(QVariant, q)); + QMetaObject::invokeMethod(object.get(), "test_rfc2822_date", Q_RETURN_ARG(QVariant, q)); QCOMPARE(q.toLongLong(), 1379512851000LL); } @@ -7947,14 +8029,14 @@ void tst_qqmlecmascript::utcDate() QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("utcdate.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); if (object == nullptr) qDebug() << component.errorString(); QVERIFY(object != nullptr); QVariant q; QVariant val = QString::fromLatin1("2014-07-16T23:30:31"); - QMetaObject::invokeMethod(object, "check_utc", Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, val)); + QMetaObject::invokeMethod(object.get(), "check_utc", Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, val)); QVERIFY(q.toBool()); } @@ -7963,20 +8045,20 @@ void tst_qqmlecmascript::negativeYear() QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("negativeyear.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); if (object == nullptr) qDebug() << component.errorString(); QVERIFY(object != nullptr); QVariant q; - QMetaObject::invokeMethod(object, "check_negative_tostring", Q_RETURN_ARG(QVariant, q)); + QMetaObject::invokeMethod(object.get(), "check_negative_tostring", Q_RETURN_ARG(QVariant, q)); // Only check for the year. We hope that every language writes the year in arabic numerals and // in relation to a specific dude's date of birth. We also hope that no language adds a "-2001" // junk string somewhere in the middle. QVERIFY(q.toString().indexOf(QStringLiteral("-2001")) != -1); - QMetaObject::invokeMethod(object, "check_negative_toisostring", Q_RETURN_ARG(QVariant, q)); + QMetaObject::invokeMethod(object.get(), "check_negative_toisostring", Q_RETURN_ARG(QVariant, q)); QCOMPARE(q.toString().left(16), QStringLiteral("result: -002000-")); } @@ -8019,6 +8101,7 @@ void tst_qqmlecmascript::jsOwnedObjectsDeletedOnEngineDestroy() QCOMPARE(spy1.count(), 1); QCOMPARE(spy2.count(), 1); + deleteObject.deleteNestedObject(); delete object; } @@ -8030,7 +8113,7 @@ void tst_qqmlecmascript::updateCall() QString file("updateCall.qml"); QQmlEngine engine; QQmlComponent component(&engine, testFileUrl(file)); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } @@ -8041,7 +8124,7 @@ void tst_qqmlecmascript::numberParsing() QString file("numberParsing.%1.qml"); file = file.arg(i); QQmlComponent component(&engine, testFileUrl(file)); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); } for (int i = 1; i < 3; ++i) { @@ -8224,8 +8307,8 @@ void tst_qqmlecmascript::idsAsLValues() QString err = QString(QLatin1String("%1:5: Error: left-hand side of assignment operator is not an lvalue")).arg(testFileUrl("idAsLValue.qml").toString()); QQmlComponent component(&engine, testFileUrl("idAsLValue.qml")); QTest::ignoreMessage(QtWarningMsg, qPrintable(err)); - MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); - QVERIFY(!object); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!qobject_cast<MyQmlObject*>(object.get())); } void tst_qqmlecmascript::qtbug_34792() @@ -8440,10 +8523,10 @@ void tst_qqmlecmascript::readUnregisteredQObjectProperty() qmlRegisterType<ObjectContainer>("Test", 1, 0, "ObjectContainer"); QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("accessUnregisteredQObjectProperty.qml")); - QObject *root = component.create(); + QScopedPointer<QObject> root(component.create()); QVERIFY(root); - QMetaObject::invokeMethod(root, "readProperty"); + QMetaObject::invokeMethod(root.get(), "readProperty"); QCOMPARE(root->property("container").value<ObjectContainer*>()->mGetterCalled, true); } @@ -8452,10 +8535,10 @@ void tst_qqmlecmascript::writeUnregisteredQObjectProperty() qmlRegisterType<ObjectContainer>("Test", 1, 0, "ObjectContainer"); QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("accessUnregisteredQObjectProperty.qml")); - QObject *root = component.create(); + QScopedPointer<QObject> root(component.create()); QVERIFY(root); - QMetaObject::invokeMethod(root, "writeProperty"); + QMetaObject::invokeMethod(root.get(), "writeProperty"); QCOMPARE(root->property("container").value<ObjectContainer*>()->mSetterCalled, true); } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml index 812242f146..a37461a173 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml index a171ee6b28..1dc06ee6ae 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml index de40284452..ea945eebb0 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml index 4939087b31..9a4fc53833 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyAggregateVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml index 5cee0341fe..155dbdcb91 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml index 2a13822fab..940d54be90 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml index 2f238175fa..46d20e38bb 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml index d36e95fec3..ffdb30f072 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml index 53dd5a17e9..ca669a9708 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml index e5cd7d60de..a93c3b302c 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyExtendVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml index d98aef2932..5930e12df6 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml index 7f438aa995..8f929c20b2 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml index 83d6226e83..20bde6d0af 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml index 98dfb7241b..10ae369459 100644 --- a/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testEmptyPropertyVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml b/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml index 50af9c4f16..422637fe31 100644 --- a/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml +++ b/tests/auto/qml/qqmlengine/data/testIncubatedComponent.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml b/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml index a04ca41c26..67d7ddd1c9 100644 --- a/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml +++ b/tests/auto/qml/qqmlengine/data/testLoaderComponent.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testReloadComponent.qml b/tests/auto/qml/qqmlengine/data/testReloadComponent.qml index 74442108cd..79d4f29db0 100644 --- a/tests/auto/qml/qqmlengine/data/testReloadComponent.qml +++ b/tests/auto/qml/qqmlengine/data/testReloadComponent.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testScriptComponent.qml b/tests/auto/qml/qqmlengine/data/testScriptComponent.qml index b33eb48461..4952a08a6c 100644 --- a/tests/auto/qml/qqmlengine/data/testScriptComponent.qml +++ b/tests/auto/qml/qqmlengine/data/testScriptComponent.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml b/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml index 6cf8ec4203..a6a1f4d4d3 100644 --- a/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml +++ b/tests/auto/qml/qqmlengine/data/testTopLevelComponent.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml b/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml index d3e6ffd7cf..c661cb6fe4 100644 --- a/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testTransientComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml b/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml index acb0113e61..8b6c7eda4d 100644 --- a/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testTransientComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml index a5beede469..8c0596eae4 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml index 4c8e52f251..39b604d42f 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml index 983d6e824c..807203b6c7 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml index fc8e5a0cd4..100b287cfd 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEAggregateVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml index fcfd05c51f..dddf51b926 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml index f434406eec..fa508f16ac 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml index 1dcaec90e6..b36d6ebf14 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml index fd7d7e454c..fce617046b 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEExtendEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml index d2dab32fc9..39629d47df 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml index 813e43896c..a4c947cc17 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEExtendVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml index c6f0b7928b..a87372cd27 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml index 255138520c..c4b16d8ec9 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml index 0ad59b32d3..a18a88884c 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml index 60f72a92fe..eb042e82f8 100644 --- a/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMEPropertyVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml index 6c7f959f49..1f97e587e0 100644 --- a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml index 86060c3998..794686494b 100644 --- a/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMETransientEmptyComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml index c50fd70dec..f442500c7f 100644 --- a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml +++ b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.1.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml index 120d249bc0..d57cd8a739 100644 --- a/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml +++ b/tests/auto/qml/qqmlengine/data/testVMETransientVMEComponent.2.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 Item { property bool success: false + required property QtObject componentCache function reportError(s) { console.warn(s) } diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index aae42e9ebb..2a3b945509 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -424,12 +424,13 @@ void tst_qqmlengine::trimComponentCache() QQmlEngine engine; ComponentCacheFunctions componentCache(engine); - engine.rootContext()->setContextProperty("componentCache", &componentCache); engine.setIncubationController(&componentCache); QQmlComponent component(&engine, testFileUrl(file)); QVERIFY2(component.isReady(), qPrintable(component.errorString())); - QScopedPointer<QObject> object(component.create()); + QScopedPointer<QObject> object(component.createWithInitialProperties({ + {"componentCache", QVariant::fromValue(&componentCache)} + })); QVERIFY(object != nullptr); QCOMPARE(object->property("success").toBool(), true); } @@ -511,6 +512,7 @@ void tst_qqmlengine::failedCompilation() QQmlEngine engine; QQmlComponent component(&engine, testFileUrl(file)); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QQmlComponent: Component is not ready"); QVERIFY(!component.isReady()); QScopedPointer<QObject> object(component.create()); QVERIFY(object.isNull()); @@ -601,11 +603,10 @@ void tst_qqmlengine::objectOwnership() { QQmlEngine engine; QQmlComponent c(&engine); - engine.rootContext()->setContextProperty("test", this); QQmlEngine::setObjectOwnership(ptr, QQmlEngine::JavaScriptOwnership); - c.setData("import QtQuick 2.0; Item { property int data: test.createAQObjectForOwnershipTest() ? 0 : 1 }", QUrl()); + c.setData("import QtQuick 2.0; Item { required property QtObject test; property int data: test.createAQObjectForOwnershipTest() ? 0 : 1 }", QUrl()); QVERIFY(c.isReady()); - QObject *o = c.create(); + QObject *o = c.createWithInitialProperties( {{"test", QVariant::fromValue(this)}} ); QVERIFY(o != nullptr); } QTRY_VERIFY(spy.count()); @@ -616,13 +617,13 @@ void tst_qqmlengine::objectOwnership() { QQmlEngine engine; QQmlComponent c(&engine); - engine.rootContext()->setContextProperty("test", ptr); QQmlEngine::setObjectOwnership(ptr, QQmlEngine::JavaScriptOwnership); - c.setData("import QtQuick 2.0; QtObject { property var object: { var i = test; test ? 0 : 1 } }", QUrl()); + c.setData("import QtQuick 2.0; QtObject { required property QtObject test; property var object: { var i = test; test ? 0 : 1 } }", QUrl()); QVERIFY(c.isReady()); - QObject *o = c.create(); + QObject *o = c.createWithInitialProperties({{"test", QVariant::fromValue(ptr)}}); QVERIFY(o != nullptr); - engine.rootContext()->setContextProperty("test", nullptr); + QQmlProperty testProp(o, "test"); + testProp.write(QVariant::fromValue<QObject*>(nullptr)); } QTRY_VERIFY(spy.count()); } @@ -772,6 +773,7 @@ public: }; Q_DECLARE_METATYPE(QList<QQmlAbstractUrlInterceptor::DataType>); + void tst_qqmlengine::urlInterceptor_data() { QTest::addColumn<QUrl>("testFile"); @@ -940,14 +942,15 @@ void tst_qqmlengine::cppSignalAndEval() { ObjectCaller objectCaller; QQmlEngine engine; - engine.rootContext()->setContextProperty(QLatin1String("CallerCpp"), &objectCaller); + qmlRegisterSingletonInstance("Test", 1, 0, "CallerCpp", &objectCaller); QQmlComponent c(&engine); c.setData("import QtQuick 2.9\n" + "import Test 1.0\n" "Item {\n" " property var r: 0\n" " Connections {\n" " target: CallerCpp;\n" - " onDoubleReply: {\n" + " function onDoubleReply() {\n" " eval('var z = 1');\n" " r = a;\n" " }\n" @@ -1107,6 +1110,16 @@ void tst_qqmlengine::singletonInstance() SomeQObjectClass * instance = engine.singletonInstance<SomeQObjectClass*>(cppSingletonTypeId); QVERIFY(!instance); } + + { + // deleted object + auto dayfly = new QObject{}; + auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly); + delete dayfly; + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine."); + QObject *instance = engine.singletonInstance<QObject*>(id); + QVERIFY(!instance); + } } void tst_qqmlengine::aggressiveGc() diff --git a/tests/auto/qml/qqmlincubator/data/requiredProperty.qml b/tests/auto/qml/qqmlincubator/data/requiredProperty.qml new file mode 100644 index 0000000000..9e355dce72 --- /dev/null +++ b/tests/auto/qml/qqmlincubator/data/requiredProperty.qml @@ -0,0 +1,5 @@ +import QtQuick 2.12 + +Item { + required property int requiredProperty +} diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp index 8e25079703..756b3b1d7c 100644 --- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp +++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp @@ -70,6 +70,7 @@ private slots: void selfDelete(); void contextDelete(); void garbageCollection(); + void requiredProperties(); private: QQmlIncubationController controller; @@ -1174,6 +1175,44 @@ void tst_qqmlincubator::garbageCollection() QVERIFY(weakIncubatorRef.isNullOrUndefined()); } +void tst_qqmlincubator::requiredProperties() +{ + { + QQmlComponent component(&engine, testFileUrl("requiredProperty.qml")); + QVERIFY(component.isReady()); + // forceCompletion immediately after creating an asynchronous object completes it + QQmlIncubator incubator; + incubator.setInitialProperties({{"requiredProperty", 42}}); + QVERIFY(incubator.isNull()); + component.create(incubator); + QVERIFY(incubator.isLoading()); + + incubator.forceCompletion(); + + QVERIFY(incubator.isReady()); + QVERIFY(incubator.object() != nullptr); + QCOMPARE(incubator.object()->property("requiredProperty").toInt(), 42); + + delete incubator.object(); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperty.qml")); + QVERIFY(component.isReady()); + // forceCompletion immediately after creating an asynchronous object completes it + QQmlIncubator incubator; + QVERIFY(incubator.isNull()); + component.create(incubator); + QVERIFY(incubator.isLoading()); + + incubator.forceCompletion(); + + QVERIFY(incubator.isError()); + auto error = incubator.errors().first(); + QVERIFY(error.description().contains(QLatin1String("Required property requiredProperty was not initialized"))); + QVERIFY(incubator.object() == nullptr); + } +} + QTEST_MAIN(tst_qqmlincubator) #include "tst_qqmlincubator.moc" diff --git a/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml b/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml index 5dd322b5f5..40e996ee4a 100644 --- a/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml +++ b/tests/auto/qml/qqmlinstantiator/data/createAndRemove.qml @@ -1,18 +1,19 @@ import QtQml 2.1 import QtQuick 2.1 +import Test 1.0 Rectangle { Instantiator { objectName: "instantiator1" - model: model1 + model: Model1 delegate: QtObject { property string datum: model.text } } Component.onCompleted: { - model1.add("Delta"); - model1.add("Gamma"); - model1.add("Beta"); - model1.add("Alpha"); + Model1.add("Delta"); + Model1.add("Gamma"); + Model1.add("Beta"); + Model1.add("Alpha"); } } diff --git a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp index 9c5e09c77c..84e08c471a 100644 --- a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp +++ b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp @@ -190,9 +190,9 @@ void tst_qqmlinstantiator::intModelChange() void tst_qqmlinstantiator::createAndRemove() { QQmlEngine engine; + QScopedPointer<StringModel> model {new StringModel("model1")}; + qmlRegisterSingletonInstance("Test", 1, 0, "Model1", model.get()); QQmlComponent component(&engine, testFileUrl("createAndRemove.qml")); - StringModel *model = new StringModel("model1"); - engine.rootContext()->setContextProperty("model1", model); QObject *rootObject = component.create(); QVERIFY(rootObject != nullptr); diff --git a/tests/auto/qml/qqmllanguage/data/alias.17.qml b/tests/auto/qml/qqmllanguage/data/alias.17.qml new file mode 100644 index 0000000000..a76dd120b6 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/alias.17.qml @@ -0,0 +1,31 @@ +import QtQuick 2.12 + +Item { + id: root + anchors.fill: parent + width: 100 + height: 100 + property bool success: checkValue === aliasUser.topMargin + property int checkValue: 42 + Rectangle { + id: myItem + objectName: "myItem" + color: "blue" + anchors.topMargin: root.checkValue + width: 50 + height: 50 + Text {text: "source:\n" + myItem.anchors.topMargin} + } + + Rectangle { + property alias topMargin: myItem.anchors.topMargin + id: aliasUser + objectName: "aliasUser" + color: "red" + anchors.left: myItem.right + width: 50 + height: 50 + Text {objectName: "myText"; text: "alias:\n" + aliasUser.topMargin} + } +} + diff --git a/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt index 30748234bc..5a144f2db5 100644 --- a/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt +++ b/tests/auto/qml/qqmllanguage/data/fakeDotProperty.errors.txt @@ -1 +1 @@ -3:5:Invalid grouped property access +3:5:Invalid grouped property access: Property "value" with primitive type "int". diff --git a/tests/auto/qml/qqmllanguage/data/foreignExtended.qml b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml new file mode 100644 index 0000000000..182d60fd02 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml @@ -0,0 +1,20 @@ +import QtQml 2.12 +import Test 1.0 + +QtObject { + property Foreign foreign: Foreign { + objectName: "foreign" + } + property Extended extended: Extended {} + property ForeignExtended foreignExtended: ForeignExtended { + objectName: "foreignExtended" + } + + property int extendedBase: extended.base + + property int extendedExtension: extended.extension + property int foreignExtendedExtension: foreignExtended.extension + + property string foreignObjectName: foreign.objectName + property string foreignExtendedObjectName: foreignExtended.objectName +} diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt index 92ce4c649f..8dca84b34e 100644 --- a/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt +++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt @@ -1,2 +1 @@ 5:1:TetZ$ is not a type --1:-1:Invalid QML type name "TetZ$" diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt index 810fd31b41..5deec4ccf9 100644 --- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt +++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.errors.txt @@ -1 +1 @@ -5:5:Invalid grouped property access +5:5:Invalid grouped property access: Property "o" with primitive type "int". diff --git a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt index 945dacf8ab..043f714636 100644 --- a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt +++ b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt @@ -1 +1 @@ -4:18:Can not assign value of type "int" to property "x", expecting an object +4:18:Can not assign value of type "MyTypeObject" to property "x", expecting "int" diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml new file mode 100644 index 0000000000..dac43c6d88 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.1.qml @@ -0,0 +1,8 @@ +import QtQuick 2.13 +Item { + property var required: 32 // required is still allowed as an identifier for properties + function f(required) { // for javascript + required = required + required; + console.log(required); + } +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml new file mode 100644 index 0000000000..4c12c7b602 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml @@ -0,0 +1,4 @@ +import QtQuick 2.13 +Item { + required property int test: 42 // cannot specify value for required property +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml new file mode 100644 index 0000000000..534322215f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml @@ -0,0 +1,4 @@ +import QtQuick 2.13 +Item { + default required property int test // cannot have required default property +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 6956533196..462745eb93 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -57,7 +57,7 @@ void registerTypes() qmlRegisterType<MyNamespace::MySecondNamespacedType>("Test",1,0,"MySecondNamespacedType"); qmlRegisterUncreatableMetaObject(MyNamespace::staticMetaObject, "Test", 1, 0, "MyNamespace", "Access to enums & flags only"); qmlRegisterType<MyParserStatus>("Test",1,0,"MyParserStatus"); - qmlRegisterType<MyGroupedObject>(); + qmlRegisterAnonymousType<MyGroupedObject>("Test", 1); qmlRegisterType<MyRevisionedClass>("Test",1,0,"MyRevisionedClass"); qmlRegisterType<MyRevisionedClass,1>("Test",1,1,"MyRevisionedClass"); qmlRegisterType<MyRevisionedIllegalOverload>("Test",1,0,"MyRevisionedIllegalOverload"); @@ -118,6 +118,8 @@ void registerTypes() qmlRegisterType<LazyDeferredSubObject>("Test", 1, 0, "LazyDeferredSubObject"); qmlRegisterType<DeferredProperties>("Test", 1, 0, "DeferredProperties"); + + qmlRegisterTypesAndRevisions<Extended, Foreign, ForeignExtended>("Test", 1); } QVariant myCustomVariantTypeConverter(const QString &data) diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 1aab24841a..bfbd3e66f5 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1420,6 +1420,40 @@ public: enum class OtherScopedEnum : int { ScopedVal1, ScopedVal2, ScopedVal3 }; }; +class Extension : public QObject +{ + Q_OBJECT + Q_PROPERTY(int extension READ extension CONSTANT) +public: + Extension(QObject *parent = nullptr) : QObject(parent) {} + int extension() const { return 42; } +}; + +class Extended : public QObject +{ + Q_OBJECT + QML_EXTENDED(Extension) + QML_NAMED_ELEMENT(Extended) + Q_PROPERTY(int base READ base CONSTANT) + +public: + int base() const { return 43; } +}; + +class Foreign +{ + Q_GADGET + QML_FOREIGN(QObject) + QML_NAMED_ELEMENT(Foreign) +}; + +class ForeignExtended +{ + Q_GADGET + QML_FOREIGN(QObject) + QML_NAMED_ELEMENT(ForeignExtended) + QML_EXTENDED(Extension) +}; void registerTypes(); diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 8adacd8829..e2032c3b86 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -132,6 +132,7 @@ private slots: void autoComponentCreation(); void autoComponentCreationInGroupProperty(); void propertyValueSource(); + void requiredProperty(); void attachedProperties(); void dynamicObjects(); void customVariantTypes(); @@ -243,12 +244,11 @@ private slots: void compositeSingletonModuleQualified(); void compositeSingletonInstantiateError(); void compositeSingletonDynamicPropertyError(); - void compositeSingletonDynamicSignal(); + void compositeSingletonDynamicSignalAndJavaScriptPragma(); void compositeSingletonQmlRegisterTypeError(); void compositeSingletonQmldirNoPragmaError(); void compositeSingletonQmlDirError(); void compositeSingletonRemote(); - void compositeSingletonJavaScriptPragma(); void compositeSingletonSelectors(); void compositeSingletonRegistered(); void compositeSingletonCircular(); @@ -304,6 +304,8 @@ private slots: void typeWrapperToVariant(); + void extendedForeignTypes(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -1634,6 +1636,25 @@ void tst_qqmllanguage::propertyValueSource() } } +void tst_qqmllanguage::requiredProperty() +{ + QQmlEngine engine; + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.1.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.2.qml")); + QVERIFY(!component.errors().empty()); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.3.qml")); + QVERIFY(!component.errors().empty()); + } +} + void tst_qqmllanguage::attachedProperties() { QQmlComponent component(&engine, testFileUrl("attachedProperties.qml")); @@ -1970,6 +1991,69 @@ void tst_qqmllanguage::aliasProperties() QScopedPointer<QObject> object(component.create()); QVERIFY(!object.isNull()); } + + // Alias to grouped property + { + QQmlComponent component(&engine, testFileUrl("alias.17.qml")); + VERIFY_ERRORS(0); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QVERIFY(object->property("success").toBool()); + } + + // Alias to grouped property updates + { + QQmlComponent component(&engine, testFileUrl("alias.17.qml")); + VERIFY_ERRORS(0); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QObject *aliasUser = object->findChild<QObject*>(QLatin1String("aliasUser")); + QVERIFY(aliasUser); + QQmlProperty checkValueProp(object.get(), "checkValue"); + QVERIFY(checkValueProp.isValid()); + checkValueProp.write(777); + QCOMPARE(object->property("checkValue").toInt(), 777); + QCOMPARE(aliasUser->property("topMargin").toInt(), 777); + } + + // Write to alias to grouped property + { + QQmlComponent component(&engine, testFileUrl("alias.17.qml")); + VERIFY_ERRORS(0); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QObject *aliasUser = object->findChild<QObject*>(QLatin1String("aliasUser")); + QVERIFY(aliasUser); + QQmlProperty topMarginProp {aliasUser, "topMargin"}; + QVERIFY(topMarginProp.isValid()); + topMarginProp.write(777); + QObject *myItem = object->findChild<QObject*>(QLatin1String("myItem")); + QVERIFY(myItem); + auto anchors = myItem->property("anchors").value<QObject*>(); + QVERIFY(anchors); + QCOMPARE(anchors->property("topMargin").toInt(), 777); + } + + // Binding to alias to grouped property gets updated + { + QQmlComponent component(&engine, testFileUrl("alias.17.qml")); + VERIFY_ERRORS(0); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QObject *aliasUser = object->findChild<QObject*>(QLatin1String("aliasUser")); + QVERIFY(aliasUser); + QQmlProperty topMarginProp {aliasUser, "topMargin"}; + QVERIFY(topMarginProp.isValid()); + topMarginProp.write(20); + QObject *myText = object->findChild<QObject*>(QLatin1String("myText")); + QVERIFY(myText); + auto text = myText->property("text").toString(); + QCOMPARE(text, "alias:\n20"); + } } // QTBUG-13374 Test that alias properties and signals can coexist @@ -2500,7 +2584,15 @@ void tst_qqmllanguage::testType(const QString& qml, const QString& type, const Q VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QCOMPARE(QString(object->metaObject()->className()), type); + const QMetaObject *meta = object->metaObject(); + for (; meta; meta = meta->superClass()) { + const QString className(meta->className()); + if (!className.contains("_QMLTYPE_") && !className.contains("_QML_")) { + QCOMPARE(className, type); + break; + } + } + QVERIFY(meta != nullptr); } engine.setImportPathList(defaultImportPathList); @@ -4043,10 +4135,12 @@ void tst_qqmllanguage::implicitImportsLast() VERIFY_ERRORS(0); QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QVERIFY(QString(object->metaObject()->className()).startsWith(QLatin1String("QQuickMouseArea"))); + QVERIFY(QString(object->metaObject()->superClass()->superClass()->className()) + .startsWith(QLatin1String("QQuickMouseArea"))); QObject* object2 = object->property("item").value<QObject*>(); QVERIFY(object2 != nullptr); - QCOMPARE(QString(object2->metaObject()->className()), QLatin1String("QQuickRectangle")); + QCOMPARE(QString(object2->metaObject()->superClass()->className()), + QLatin1String("QQuickRectangle")); engine.setImportPathList(defaultImportPathList); } @@ -4267,16 +4361,35 @@ void tst_qqmllanguage::compositeSingletonDynamicPropertyError() VERIFY_ERRORS(0); } -// Having a composite singleton type as dynamic signal parameter succeeds -// (like C++ singleton) -void tst_qqmllanguage::compositeSingletonDynamicSignal() +void tst_qqmllanguage::compositeSingletonDynamicSignalAndJavaScriptPragma() { - QQmlComponent component(&engine, testFileUrl("singletonTest11.qml")); - VERIFY_ERRORS(0); - QScopedPointer<QObject> o(component.create()); - QVERIFY(o != nullptr); + { + // Having a composite singleton type as dynamic signal parameter succeeds + // (like C++ singleton) - verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", -55); + QQmlComponent component(&engine, testFileUrl("singletonTest11.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(o != nullptr); + + verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", -55); + } + { + // Load a composite singleton type and a javascript file that has .pragma library + // in it. This will make sure that the javascript .pragma does not get mixed with + // the pragma Singleton changes. + + QQmlComponent component(&engine, testFileUrl("singletonTest16.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(o != nullptr); + + // The value1 that is read from the SingletonType was changed from 125 to 99 + // above. As the type is a singleton and + // the engine has not been destroyed, we just retrieve the old instance and + // the value is still 99. + verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", 333); + } } // Use qmlRegisterType to register a qml composite type with pragma Singleton defined in it. @@ -4328,23 +4441,6 @@ void tst_qqmllanguage::compositeSingletonRemote() verifyCompositeSingletonPropertyValues(o.data(), "value1", 525, "value2", 355); } -// Load a composite singleton type and a javascript file that has .pragma library -// in it. This will make sure that the javascript .pragma does not get mixed with -// the pragma Singleton changes. -void tst_qqmllanguage::compositeSingletonJavaScriptPragma() -{ - QQmlComponent component(&engine, testFileUrl("singletonTest16.qml")); - VERIFY_ERRORS(0); - QScopedPointer<QObject> o(component.create()); - QVERIFY(o != nullptr); - - // The value1 that is read from the SingletonType was changed from 125 to 99 - // in compositeSingletonDynamicSignal() above. As the type is a singleton and - // the engine has not been destroyed, we just retrieve the old instance and - // the value is still 99. - verifyCompositeSingletonPropertyValues(o.data(), "value1", 99, "value2", 333); -} - // Reads values from a Singleton accessed through selectors. void tst_qqmllanguage::compositeSingletonSelectors() { @@ -5030,7 +5126,6 @@ void tst_qqmllanguage::instanceof() if (QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomRectangle") || QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomImport.CustomRectangle")) - QEXPECT_FAIL("", "QTBUG-58477: QML type rules are a little lax", Continue); QCOMPARE(returnValue, expectedValue.toBool()); } else { QVERIFY(expr.hasError()); @@ -5066,7 +5161,8 @@ void tst_qqmllanguage::accessDeletedObject() { QQmlEngine engine; - engine.rootContext()->setContextProperty("objectCreator", new ObjectCreator); + QScopedPointer<ObjectCreator> creator(new ObjectCreator); + engine.rootContext()->setContextProperty("objectCreator", creator.get()); QQmlComponent component(&engine, testFileUrl("accessDeletedObject.qml")); VERIFY_ERRORS(0); @@ -5163,6 +5259,21 @@ void tst_qqmllanguage::typeWrapperToVariant() QVERIFY(target); } +void tst_qqmllanguage::extendedForeignTypes() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("foreignExtended.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("extendedBase").toInt(), 43); + QCOMPARE(o->property("extendedExtension").toInt(), 42); + QCOMPARE(o->property("foreignExtendedExtension").toInt(), 42); + QCOMPARE(o->property("foreignObjectName").toString(), QLatin1String("foreign")); + QCOMPARE(o->property("foreignExtendedObjectName").toString(), QLatin1String("foreignExtended")); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 77ab0ecbc0..75a932b6f4 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -128,6 +128,8 @@ private slots: void qobjectTrackerForDynamicModelObjects(); void crash_append_empty_array(); void dynamic_roles_crash_QTBUG_38907(); + void nestedListModelIteration(); + void undefinedAppendShouldCauseError(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1667,6 +1669,61 @@ void tst_qqmllistmodel::dynamic_roles_crash_QTBUG_38907() QVERIFY(retVal.toBool()); } +void tst_qqmllistmodel::nestedListModelIteration() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + QTest::ignoreMessage(QtMsgType::QtDebugMsg ,R"({"subItems":[{"a":1,"b":0,"c":0},{"a":0,"b":2,"c":0},{"a":0,"b":0,"c":3}]})"); + component.setData( + R"(import QtQuick 2.5 + Item { + visible: true + width: 640 + height: 480 + ListModel { + id : model + } + Component.onCompleted: { + var tempData = { + subItems: [{a: 1}, {b: 2}, {c: 3}] + } + model.insert(0, tempData) + console.log(JSON.stringify(model.get(0))) + } + })", + QUrl()); + QScopedPointer<QObject>(component.create()); +} + +// QTBUG-63569 +void tst_qqmllistmodel::undefinedAppendShouldCauseError() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData( + R"(import QtQuick 2.5 + Item { + width: 640 + height: 480 + ListModel { + id : model + } + Component.onCompleted: { + var tempData = { + faulty: undefined + } + model.insert(0, tempData) + tempData.faulty = null + model.insert(0, tempData) + } + })", + QUrl()); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: faulty is undefined. Adding an object with a undefined member does not create a role for it."); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: faulty is null. Adding an object with a null member does not create a role for it."); + QScopedPointer<QObject>(component.create()); +} + + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp index 199f7bc7e4..8efaedf5b5 100644 --- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp +++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp @@ -87,7 +87,7 @@ public: void tst_qqmllistreference::initTestCase() { QQmlDataTest::initTestCase(); - qmlRegisterType<TestType>(); + qmlRegisterAnonymousType<TestType>("Test", 1); } void tst_qqmllistreference::qmllistreference() diff --git a/tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml b/tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml new file mode 100644 index 0000000000..2fc2e9f076 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/multiSingleton.qml @@ -0,0 +1,6 @@ +import org.qtproject.ModuleWithQmlSingleton 1.0 +import QtQuick 2.0 + +Item { + Component.onCompleted: MySingleton +} diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml new file mode 100644 index 0000000000..258667be18 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton.qml @@ -0,0 +1,17 @@ +pragma Singleton +import QtQuick 2.0 +import Test 1.0 + +QtObject { + property Loader _loader: Loader { + source: "internal/InternalType.qml" + } + + Component.onCompleted: { + if (Tracker.objectName === "first") + Tracker.objectName = "second" + else + Tracker.objectName = "first" + //console.log("created singleton", this) + } +} diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml new file mode 100644 index 0000000000..9be34eb061 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/MySingleton2.qml @@ -0,0 +1,6 @@ +pragma Singleton +import QtQuick 2.0 +import org.qtproject.ModuleWithQmlSingleton 1.0 +import "." + +QtObject {} diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml new file mode 100644 index 0000000000..4a8badefd2 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/internal/InternalType.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import ".." + +QtObject { + Component.onCompleted: MySingleton +} diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro new file mode 100644 index 0000000000..b16e0743c8 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/moduleWithQmlSingleton.pro @@ -0,0 +1,18 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/org/qtproject/ModuleWithQmlSingleton + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir \ + MySingleton.qml \ + MySingleton2.qml + +include (../../../shared/imports.pri) + +subfiles.files = internal/InternalType.qml +subfiles.path = $$DESTDIR/internal +COPIES += subfiles diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp new file mode 100644 index 0000000000..6329927c34 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** 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 <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDir> +#include <QDebug> + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "org.qtproject.ModuleWithQmlSingleton"); + qmlRegisterSingletonType(baseUrl().resolved(QUrl("ModuleWithQmlSingleton/MySingleton.qml")), uri, 1, 0, "MySingleton"); + qmlRegisterSingletonType(baseUrl().resolved(QUrl("ModuleWithQmlSingleton/MySingleton2.qml")), uri, 1, 0, "MySingleton2"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir new file mode 100644 index 0000000000..3483f80ab1 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/qmldir @@ -0,0 +1,2 @@ +module org.qtproject.ModuleWithQmlSingleton +plugin moduleWithQmlSingleton diff --git a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp index ae8c231aab..bb5bb00adb 100644 --- a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp @@ -47,9 +47,9 @@ public: void registerTypes(const char *uri) { - // Because the module is protected, this plugin should never be loaded + // The module is protected. The plugin can still be loaded, but it cannot register + // any types. Q_UNUSED(uri); - Q_ASSERT(0); } }; diff --git a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro index ae13a041cc..44b3ab14e6 100644 --- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro +++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro @@ -20,7 +20,8 @@ SUBDIRS =\ plugin/childplugin\ plugin.2/childplugin\ plugin.2.1/childplugin\ - plugin.2.2 + plugin.2.2\ + moduleWithQmlSingleton tst_qqmlmoduleplugin_pro.depends += plugin SUBDIRS += tst_qqmlmoduleplugin.pro diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index 82aa265465..f15d53d022 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -82,6 +82,7 @@ private slots: void importsChildPlugin2(); void importsChildPlugin21(); void parallelPluginImport(); + void multiSingleton(); private: QString m_importsDirectory; @@ -627,7 +628,7 @@ void tst_qqmlmoduleplugin::importStrictModule_data() << "import org.qtproject.NonstrictModule 1.0\n" "MyPluginType {}" << "Module 'org.qtproject.NonstrictModule' does not contain a module identifier directive - it cannot be protected from external registrations." - << ":1:1: plugin cannot be loaded for module \"org.qtproject.NonstrictModule\": Cannot install element 'MyPluginType' into protected namespace 'org.qtproject.StrictModule'"; + << ":1:1: plugin cannot be loaded for module \"org.qtproject.NonstrictModule\": Cannot install element 'MyPluginType' into protected module 'org.qtproject.StrictModule' version '1'"; QTest::newRow("non-strict preemption") << "import org.qtproject.PreemptiveModule 1.0\n" @@ -791,6 +792,20 @@ void tst_qqmlmoduleplugin::parallelPluginImport() worker.wait(); } +void tst_qqmlmoduleplugin::multiSingleton() +{ + QQmlEngine engine; + QObject obj; + qmlRegisterSingletonInstance("Test", 1, 0, "Tracker", &obj); + engine.addImportPath(m_importsDirectory); + QQmlComponent component(&engine, testFileUrl("multiSingleton.qml")); + QObject *object = component.create(); + QVERIFY(object != nullptr); + QCOMPARE(obj.objectName(), QLatin1String("first")); + delete object; +} + + QTEST_MAIN(tst_qqmlmoduleplugin) #include "tst_qqmlmoduleplugin.moc" diff --git a/tests/auto/qml/qqmlnotifier/data/connectnotify.qml b/tests/auto/qml/qqmlnotifier/data/connectnotify.qml index 35226ee5ab..34e70e6afe 100644 --- a/tests/auto/qml/qqmlnotifier/data/connectnotify.qml +++ b/tests/auto/qml/qqmlnotifier/data/connectnotify.qml @@ -3,6 +3,7 @@ import Test 1.0 Item { id: root + required property ExportedClass exportedObject ExportedClass { id: exportedClass objectName: "exportedClass" @@ -22,7 +23,7 @@ Item { } property int foo: exportedClass.qmlObjectProp - property int baz: _exportedObject.cppObjectProp + property int baz: exportedObject.cppObjectProp // v4 bindings that could share a subscription. They don't, though, and the code // relies on that diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp index de762d66c5..836b94ad45 100644 --- a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp +++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp @@ -185,8 +185,7 @@ void tst_qqmlnotifier::createObjects() QQmlComponent component(&engine, testFileUrl("connectnotify.qml")); exportedObject = new ExportedClass(); exportedObject->setObjectName("exportedObject"); - engine.rootContext()->setContextProperty("_exportedObject", exportedObject); - root = component.create(); + root = component.createWithInitialProperties({{"exportedObject", QVariant::fromValue(exportedObject)}}); QVERIFY(root != nullptr); exportedClass = qobject_cast<ExportedClass *>( @@ -324,12 +323,12 @@ void tst_qqmlnotifier::lotsOfBindings() TestObject o; QQmlEngine *e = new QQmlEngine; - e->rootContext()->setContextProperty(QStringLiteral("test"), &o); + qmlRegisterSingletonInstance("Test", 1, 0, "Test", &o); QList<QQmlComponent *> components; for (int i = 0; i < 20000; ++i) { QQmlComponent *component = new QQmlComponent(e); - component->setData("import QtQuick 2.0; Item { width: test.a; }", QUrl()); + component->setData("import QtQuick 2.0; import Test 1.0; Item {width: Test.a; }", QUrl()); component->create(e->rootContext()); components.append(component); } diff --git a/tests/auto/qml/qqmlpromise/data/promisehandlerthrows.qml b/tests/auto/qml/qqmlpromise/data/promisehandlerthrows.qml new file mode 100644 index 0000000000..d23ea43e74 --- /dev/null +++ b/tests/auto/qml/qqmlpromise/data/promisehandlerthrows.qml @@ -0,0 +1,17 @@ +import QtQuick 2.12 + +Item { + id: root + property string errorMessage + Component.onCompleted: () => { + let prom = Promise.reject("Some error") + .then( + o => {console.log("Never reached");}, + err => { + console.log("Rethrowing err"); + throw err; + } + ) + .catch(err => root.errorMessage = err) + } +} diff --git a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp index 41850d0263..b430434526 100644 --- a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp +++ b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp @@ -83,6 +83,7 @@ private slots: void then_reject_non_callable(); void then_resolve_multiple_then(); void promiseChain(); + void promiseHandlerThrows(); private: void execute_test(QString testName); @@ -285,6 +286,17 @@ void tst_qqmlpromise::promiseChain() } +void tst_qqmlpromise::promiseHandlerThrows() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("promisehandlerthrows.qml")); + QVERIFY(component.isReady()); + QTest::ignoreMessage(QtDebugMsg, "Rethrowing err"); + QScopedPointer<QObject> root(component.create()); + QVERIFY(root); + QTRY_VERIFY(root->property("errorMessage") == QLatin1String("Some error")); +} + QTEST_MAIN(tst_qqmlpromise) diff --git a/tests/auto/qml/qqmlproperty/data/aliasToBinding.qml b/tests/auto/qml/qqmlproperty/data/aliasToBinding.qml new file mode 100644 index 0000000000..54f9e3f944 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/aliasToBinding.qml @@ -0,0 +1,23 @@ +import QtQuick 2.7 + +Item { + id: _window + property bool userFontStrikeout: true + + Component.onCompleted: { + _box.font.strikeout = Qt.binding(function() { return _window.userFontStrikeout; }); + } + + Rectangle { + id: _box + width: 100 + height: 100 + property alias font: _text.font + + Text { + id: _text + anchors.fill: parent + text: "Text" + } + } +} diff --git a/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml b/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml index a9e51c1255..440f07ac87 100644 --- a/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml +++ b/tests/auto/qml/qqmlproperty/data/assignEmptyVariantMap.qml @@ -1,5 +1,6 @@ import QtQuick 2.0 Item { + required property QtObject o Component.onCompleted: { o.variantMap = {}; } } diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 67da768f73..1a5927fa74 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -35,6 +35,9 @@ #include <private/qqmlboundsignal_p.h> #include <QtCore/qfileinfo.h> #include <QtCore/qdir.h> +#if QT_CONFIG(regularexpression) +#include <QtCore/qregularexpression.h> +#endif #include <QtCore/private/qobject_p.h> #include "../../shared/util.h" @@ -150,6 +153,8 @@ private slots: void floatToStringPrecision(); void copy(); + + void bindingToAlias(); private: QQmlEngine engine; }; @@ -1989,11 +1994,9 @@ void tst_qqmlproperty::assignEmptyVariantMap() QCOMPARE(o.variantMap().count(), 1); QCOMPARE(o.variantMap().isEmpty(), false); - QQmlContext context(&engine); - context.setContextProperty("o", &o); QQmlComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml")); - QObject *obj = component.create(&context); + QObject *obj = component.createWithInitialProperties({{"o", QVariant::fromValue(&o)}}); QVERIFY(obj); QCOMPARE(o.variantMap().count(), 0); @@ -2015,9 +2018,13 @@ void tst_qqmlproperty::warnOnInvalidBinding() expectedWarning = testUrl.toString() + QString::fromLatin1(":7:5: Unable to assign QQuickText to QQuickRectangle"); QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData()); +#if QT_CONFIG(regularexpression) // V8 error message for invalid binding to anchor - expectedWarning = testUrl.toString() + QString::fromLatin1(":14:9: Unable to assign QQuickItem_QML_8 to QQuickAnchorLine"); - QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData()); + const QRegularExpression warning( + "^" + testUrl.toString() + + ":14:9: Unable to assign QQuickItem_QML_\\d+ to QQuickAnchorLine$"); + QTest::ignoreMessage(QtWarningMsg, warning); +#endif QQmlComponent component(&engine, testUrl); QObject *obj = component.create(); @@ -2123,6 +2130,15 @@ void tst_qqmlproperty::initTestCase() qmlRegisterType<MyContainer>("Test",1,0,"MyContainer"); } +// QTBUG-60908 +void tst_qqmlproperty::bindingToAlias() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("aliasToBinding.qml")); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); +} + QTEST_MAIN(tst_qqmlproperty) #include "tst_qqmlproperty.moc" diff --git a/tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml b/tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml new file mode 100644 index 0000000000..9559bc0b5f --- /dev/null +++ b/tests/auto/qml/qqmlpropertycache/data/SpecialObject1.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + readonly property bool fakeProperty: false +} diff --git a/tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml b/tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml new file mode 100644 index 0000000000..ed4ad04fef --- /dev/null +++ b/tests/auto/qml/qqmlpropertycache/data/SpecialObject2.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + objectName: "special" +} diff --git a/tests/auto/qml/qqmlpropertycache/data/noDuckType.qml b/tests/auto/qml/qqmlpropertycache/data/noDuckType.qml new file mode 100644 index 0000000000..5e1ea233b9 --- /dev/null +++ b/tests/auto/qml/qqmlpropertycache/data/noDuckType.qml @@ -0,0 +1,7 @@ +import QtQml 2.9 + +QtObject { + property SpecialObject1 obj1: SpecialObject1 {} + property SpecialObject2 obj2: SpecialObject2 {} + property string result: (obj1 instanceof SpecialObject2) ? "bad" : "good" +} diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp index 9a1e4667dd..c9e92cd3c9 100644 --- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp +++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp @@ -54,6 +54,7 @@ private slots: void metaObjectSize_data(); void metaObjectSize(); void metaObjectChecksum(); + void metaObjectsForRootElements(); private: QQmlEngine engine; @@ -543,4 +544,14 @@ void tst_qqmlpropertycache::metaObjectChecksum() } } +void tst_qqmlpropertycache::metaObjectsForRootElements() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("noDuckType.qml")); + QVERIFY(c.isReady()); + QScopedPointer<QObject> obj(c.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("result").toString(), QString::fromLatin1("good")); +} + QTEST_MAIN(tst_qqmlpropertycache) diff --git a/tests/auto/qml/qqmlqt/data/formatting.qml b/tests/auto/qml/qqmlqt/data/formatting.qml index 7a462c8eeb..f2d1e1b5c8 100644 --- a/tests/auto/qml/qqmlqt/data/formatting.qml +++ b/tests/auto/qml/qqmlqt/data/formatting.qml @@ -41,4 +41,9 @@ QtObject { property string err_dateTime1: Qt.formatDateTime() property string err_dateTime2: Qt.formatDateTime(new Date, new Object) + + property var qdate + property var qtime + property var qdatetime + property var qvariant } diff --git a/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml b/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml index 9d73640c87..65732442af 100644 --- a/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml +++ b/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml @@ -1,6 +1,8 @@ import QtQuick 2.0 +import Test 1.0 QtObject { + required property TimeProvider tp Component.onCompleted: { var t = tp.time; tp.time = t; diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index 2d8115e867..15ef31464b 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -777,10 +777,6 @@ void tst_qqmlqt::dateTimeFormatting() QQmlEngine eng; - eng.rootContext()->setContextProperty("qdate", date); - eng.rootContext()->setContextProperty("qtime", time); - eng.rootContext()->setContextProperty("qdatetime", dateTime); - QQmlComponent component(&eng, testFileUrl("formatting.qml")); QStringList warnings; @@ -794,7 +790,11 @@ void tst_qqmlqt::dateTimeFormatting() foreach (const QString &warning, warnings) QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); - QObject *object = component.create(); + QObject *object = component.createWithInitialProperties({ + {"qdate", date}, + {"qtime", time}, + {"qdatetime", dateTime} + }); QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); QVERIFY(object != nullptr); @@ -853,7 +853,6 @@ void tst_qqmlqt::dateTimeFormattingVariants() QFETCH(QStringList, expectedResults); QQmlEngine eng; - eng.rootContext()->setContextProperty("qvariant", variant); QQmlComponent component(&eng, testFileUrl("formatting.qml")); QStringList warnings; @@ -867,7 +866,7 @@ void tst_qqmlqt::dateTimeFormattingVariants() foreach (const QString &warning, warnings) QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); - QObject *object = component.create(); + QObject *object = component.createWithInitialProperties({{"qvariant", variant}}); QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); QVERIFY(object != nullptr); @@ -1174,6 +1173,7 @@ void tst_qqmlqt::qtObjectContents() class TimeProvider: public QObject { Q_OBJECT + QML_NAMED_ELEMENT(TimeProvider) Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged) public: @@ -1254,13 +1254,14 @@ void tst_qqmlqt::timeRoundtrip() TimeZoneSwitch tzs(QTest::currentDataTag()); QFETCH(QTime, time); + qmlRegisterTypesAndRevisions<TimeProvider>("Test", 1); TimeProvider tp(time); QQmlEngine eng; - eng.rootContext()->setContextProperty(QLatin1String("tp"), &tp); + //qmlRegisterSingletonInstance("Test", 1, 0, "TimeProvider", &tp); QQmlComponent component(&eng, testFileUrl("timeRoundtrip.qml")); - QObject *obj = component.create(); + QObject *obj = component.createWithInitialProperties({{"tp", QVariant::fromValue(&tp)}}); QVERIFY(obj != nullptr); // QML reads m_getTime and saves the result as m_putTime; this should come out the same, without diff --git a/tests/auto/qml/qqmltranslation/data/mylibrary.js b/tests/auto/qml/qqmltranslation/data/mylibrary.js new file mode 100644 index 0000000000..5903db3b4b --- /dev/null +++ b/tests/auto/qml/qqmltranslation/data/mylibrary.js @@ -0,0 +1,5 @@ +Qt.include("nested_js_translation.js") + +function translation_success() { + return qsTr("English in mylibrary"); +} diff --git a/tests/auto/qml/qqmltranslation/data/nested_js_translation.js b/tests/auto/qml/qqmltranslation/data/nested_js_translation.js new file mode 100644 index 0000000000..336cdedfea --- /dev/null +++ b/tests/auto/qml/qqmltranslation/data/nested_js_translation.js @@ -0,0 +1,3 @@ +function translation_fail() { + return qsTr("English in translation") +} diff --git a/tests/auto/qml/qqmltranslation/data/preferjs.qml b/tests/auto/qml/qqmltranslation/data/preferjs.qml new file mode 100644 index 0000000000..040fa12e4e --- /dev/null +++ b/tests/auto/qml/qqmltranslation/data/preferjs.qml @@ -0,0 +1,8 @@ +import QtQml 2.12 + +import "mylibrary.js" as Lib + +QtObject { + property string german1: Lib.translation_fail() + property string german2: Lib.translation_success() +} diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp index dcfe914af6..a75a00bd01 100644 --- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp +++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp @@ -46,6 +46,7 @@ private slots: void translation(); void idTranslation(); void translationChange(); + void preferJSContext(); }; void tst_qqmltranslation::translation_data() @@ -175,6 +176,10 @@ class DummyTranslator : public QTranslator Q_UNUSED(n); if (!qstrcmp(sourceText, "translate me")) return QString::fromUtf8("xxx"); + if (!qstrcmp(sourceText, "English in mylibrary") && !qstrcmp(context, "mylibrary")) + return QString::fromUtf8("Deutsch in mylibrary"); + if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "nested_js_translation")) + return QString::fromUtf8("Deutsch in Setzung"); return QString(); } @@ -213,6 +218,24 @@ void tst_qqmltranslation::translationChange() QCoreApplication::removeTranslator(&translator); } +void tst_qqmltranslation::preferJSContext() +{ + DummyTranslator translator; + QCoreApplication::installTranslator(&translator); + + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("preferjs.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + QCOMPARE(object->property("german1").toString(), + QStringLiteral("Deutsch in Setzung")); + QCOMPARE(object->property("german2").toString(), + QStringLiteral("Deutsch in mylibrary")); + + QCoreApplication::removeTranslator(&translator); +} + QTEST_MAIN(tst_qqmltranslation) #include "tst_qqmltranslation.moc" diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml new file mode 100644 index 0000000000..28521e3af2 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml @@ -0,0 +1,5 @@ +import QtQuick 2.6 + +Item { + +} diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml new file mode 100644 index 0000000000..b20a2def11 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml @@ -0,0 +1,7 @@ +import QtQuick 2.6 +import Com.Orga 1.0 + +Rectangle { + color: Style.name + Text {text: "Hello world!"} +} diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir new file mode 100644 index 0000000000..368cb65b35 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir @@ -0,0 +1,2 @@ +module Com.Orga.Handlers +Handler 1.0 Handler.qml diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml new file mode 100644 index 0000000000..7951f5e768 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml @@ -0,0 +1,6 @@ +pragma Singleton +import QtQuick 2.6 + +BaseStyle { + property color name: "black" +} diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir b/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir new file mode 100644 index 0000000000..9c5560b323 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir @@ -0,0 +1,2 @@ +singleton Style 1.0 Style.qml +BaseStyle 1.0 BaseStyle.qml diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 63a43eebad..07f67c7843 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -60,6 +60,7 @@ private slots: void implicitComponentModule(); void qrcRootPathUrl(); void implicitImport(); + void compositeSingletonCycle(); private: void checkSingleton(const QString & dataDirectory); @@ -443,7 +444,7 @@ void tst_QQMLTypeLoader::redirect() component.loadUrl(server.urlString("/Load.qml"), QQmlComponent::Asynchronous); QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); - QObject *object = component.create(); + QScopedPointer<QObject> object {component.create()}; QTRY_COMPARE(object->property("xy").toInt(), 323232); } @@ -539,6 +540,23 @@ void tst_QQMLTypeLoader::implicitImport() QVERIFY(!obj.isNull()); } +void tst_QQMLTypeLoader::compositeSingletonCycle() +{ + TestHTTPServer server; + QVERIFY2(server.listen(), qPrintable(server.errorString())); + QVERIFY(server.serveDirectory(dataDirectory())); + + QQmlEngine engine; + QQmlComponent component(&engine); + engine.addImportPath(server.baseUrl().toString()); + component.loadUrl(server.urlString("Com/Orga/Handlers/Handler.qml"), QQmlComponent::Asynchronous); + QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> object {component.create()}; + QVERIFY(object); + QCOMPARE(qvariant_cast<QColor>(object->property("color")), QColorConstants::Black); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml index d2f748c4c4..2aa03ed39f 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml +++ b/tests/auto/qml/qqmlvaluetypeproviders/data/userType.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 import Test 1.0 Item { + required property TestValueExporter testValueExporter property bool success: false // Test user value type stored as both var and variant diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp index 22074602b7..b44889798c 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp +++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp @@ -256,6 +256,7 @@ class TestValueExporter : public QObject { Q_OBJECT Q_PROPERTY(TestValue testValue READ testValue WRITE setTestValue) + QML_NAMED_ELEMENT(TestValueExporter) public: TestValue testValue() const { return m_testValue; } void setTestValue(const TestValue &v) { m_testValue = v; } @@ -275,15 +276,14 @@ void tst_qqmlvaluetypeproviders::userType() qRegisterMetaType<TestValue>(); QMetaType::registerComparators<TestValue>(); - qmlRegisterType<TestValueExporter>("Test", 1, 0, "TestValueExporter"); + qmlRegisterTypesAndRevisions<TestValueExporter>("Test", 1); TestValueExporter exporter; QQmlEngine e; - e.rootContext()->setContextProperty("testValueExporter", &exporter); QQmlComponent component(&e, testFileUrl("userType.qml")); - QScopedPointer<QObject> obj(component.create()); + QScopedPointer<QObject> obj(component.createWithInitialProperties({{"testValueExporter", QVariant::fromValue(&exporter)}})); QVERIFY(obj != nullptr); QCOMPARE(obj->property("success").toBool(), true); } diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml index 73d2b921a7..a2d303b507 100644 --- a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml +++ b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml @@ -12,4 +12,7 @@ MyTypeObject { property real hsl_s: color.hslSaturation property real hsl_l: color.hslLightness property variant copy: color + + property bool valid: color.valid + property bool invalid: invalidColor.valid } diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h index bcfe4028c6..798c96e188 100644 --- a/tests/auto/qml/qqmlvaluetypes/testtypes.h +++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h @@ -69,6 +69,7 @@ class MyTypeObject : public QObject Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY changed) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed) + Q_PROPERTY(QColor invalidColor READ invalidColor CONSTANT) Q_PROPERTY(QVariant variant READ variant NOTIFY changed) public: @@ -168,6 +169,8 @@ public: QColor color() const { return m_color; } void setColor(const QColor &v) { m_color = v; emit changed(); } + QColor invalidColor() const { return QColor(); } + QVariant variant() const { return sizef(); } void emitRunScript() { emit runScript(); } diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 8a602a0356..3e9047cc5a 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -97,6 +97,7 @@ private slots: void enumerableProperties(); void enumProperties(); void scarceTypes(); + void nonValueTypes(); private: QQmlEngine engine; @@ -934,6 +935,11 @@ void tst_qqmlvaluetypes::color() QCOMPARE(qRound(object->property("hsl_s").toDouble() * 100), 74); QCOMPARE(qRound(object->property("hsl_l").toDouble() * 100), 54); + QCOMPARE(object->property("valid").userType(), QMetaType::Bool); + QVERIFY(object->property("valid").toBool()); + QCOMPARE(object->property("invalid").userType(), QMetaType::Bool); + QVERIFY(!object->property("invalid").toBool()); + QColor comparison; comparison.setRedF(0.2); comparison.setGreenF(0.88); @@ -1844,6 +1850,16 @@ void tst_qqmlvaluetypes::scarceTypes() QCOMPARE(QByteArray(pixmapValue->vtable()->className), QByteArray("VariantObject")); } +#define CHECK_TYPE_IS_NOT_VALUETYPE(Type, typeId, cppType) \ + QVERIFY(!QQmlValueTypeFactory::isValueType(QMetaType::Type)); + +void tst_qqmlvaluetypes::nonValueTypes() +{ + CHECK_TYPE_IS_NOT_VALUETYPE(UnknownType, 0, void) + QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(CHECK_TYPE_IS_NOT_VALUETYPE); +} + +#undef CHECK_TYPE_IS_NOT_VALUETYPE QTEST_MAIN(tst_qqmlvaluetypes) diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp index b7600351b7..ae99e35467 100644 --- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp +++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp @@ -75,6 +75,7 @@ private slots: void introspectQrc(); void sortCaseSensitive_data(); void sortCaseSensitive(); + void updateProperties(); private: void checkNoErrors(const QQmlComponent& component); QQmlEngine engine; @@ -425,6 +426,47 @@ void tst_qquickfolderlistmodel::sortCaseSensitive() QTRY_COMPARE(flm->data(flm->index(i),FileNameRole).toString(), expectedOrder.at(i)); } +void tst_qquickfolderlistmodel::updateProperties() +{ + QQmlComponent component(&engine, testFileUrl("basic.qml")); + checkNoErrors(component); + + QObject *folderListModel = component.create(); + QVERIFY(folderListModel); + + QVariant caseSensitive = folderListModel->property("caseSensitive"); + QVERIFY(caseSensitive.isValid()); + QCOMPARE(caseSensitive.toBool(), true); + folderListModel->setProperty("caseSensitive", false); + caseSensitive = folderListModel->property("caseSensitive"); + QVERIFY(caseSensitive.isValid()); + QCOMPARE(caseSensitive.toBool(), false); + + QVariant showOnlyReadable = folderListModel->property("showOnlyReadable"); + QVERIFY(showOnlyReadable.isValid()); + QCOMPARE(showOnlyReadable.toBool(), false); + folderListModel->setProperty("showOnlyReadable", true); + showOnlyReadable = folderListModel->property("showOnlyReadable"); + QVERIFY(showOnlyReadable.isValid()); + QCOMPARE(showOnlyReadable.toBool(), true); + + QVariant showDotAndDotDot = folderListModel->property("showDotAndDotDot"); + QVERIFY(showDotAndDotDot.isValid()); + QCOMPARE(showDotAndDotDot.toBool(), false); + folderListModel->setProperty("showDotAndDotDot", true); + showDotAndDotDot = folderListModel->property("showDotAndDotDot"); + QVERIFY(showDotAndDotDot.isValid()); + QCOMPARE(showDotAndDotDot.toBool(), true); + + QVariant showHidden = folderListModel->property("showHidden"); + QVERIFY(showHidden.isValid()); + QCOMPARE(showHidden.toBool(), false); + folderListModel->setProperty("showHidden", true); + showHidden = folderListModel->property("showHidden"); + QVERIFY(showHidden.isValid()); + QCOMPARE(showHidden.toBool(), true); +} + QTEST_MAIN(tst_qquickfolderlistmodel) #include "tst_qquickfolderlistmodel.moc" diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp index 308fba9049..157d0f2a62 100644 --- a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp +++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 basysKom GmbH. ** Contact: https://www.qt.io/licensing/ ** @@ -110,8 +111,8 @@ void tst_qv4identifiertable::sweepCenterEntryInBucket() table.asPropertyKey(entry2); table.asPropertyKey(entry3); - QCOMPARE(table.size, 3); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 3u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -153,8 +154,8 @@ void tst_qv4identifiertable::sweepLastEntryInBucket() table.asPropertyKey(entry2); table.asPropertyKey(entry3); - QCOMPARE(table.size, 3); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 3u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -193,8 +194,8 @@ void tst_qv4identifiertable::sweepFirstEntryInSameBucketWithDifferingHash() table.asPropertyKey(entry1); table.asPropertyKey(entry2); - QCOMPARE(table.size, 2); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 2u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -231,8 +232,8 @@ void tst_qv4identifiertable::dontSweepAcrossBucketBoundaries() table.asPropertyKey(entry1); table.asPropertyKey(entry2); - QCOMPARE(table.size, 2); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 2u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -279,8 +280,8 @@ void tst_qv4identifiertable::sweepAcrossBucketBoundariesIfFirstBucketFull() table.asPropertyKey(entry3); table.asPropertyKey(entry4); - QCOMPARE(table.size, 4); - QCOMPARE(table.alloc, 11); + QCOMPARE(table.size, 4u); + QCOMPARE(table.alloc, 11u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -336,8 +337,8 @@ void tst_qv4identifiertable::sweepBucketGap() table.asPropertyKey(entry3); table.asPropertyKey(entry4); - QCOMPARE(table.size, 4); - QCOMPARE(table.alloc, 11); + QCOMPARE(table.size, 4u); + QCOMPARE(table.alloc, 11u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); |