diff options
Diffstat (limited to 'tests/auto/qml')
47 files changed, 843 insertions, 76 deletions
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/quit.js b/tests/auto/qml/debugger/qqmldebugjs/data/quit.js new file mode 100644 index 0000000000..1a45fd5538 --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugjs/data/quit.js @@ -0,0 +1,4 @@ +function quit() { + console.log("hit"); + Qt.quit(); +} diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml b/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml new file mode 100644 index 0000000000..6e4183100b --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "quit.js" as Quit; + +//DO NOT CHANGE + +Item { + Timer { + running: true + triggeredOnStart: true + onTriggered: Quit.quit(); + } +} + diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 255d679b1b..5b6c43bc0c 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -58,6 +58,8 @@ const char *ONCOMPLETED_QMLFILE = "oncompleted.qml"; const char *CREATECOMPONENT_QMLFILE = "createComponent.qml"; const char *CONDITION_QMLFILE = "condition.qml"; const char *QUIT_QMLFILE = "quit.qml"; +const char *QUITINJS_QMLFILE = "quitInJS.qml"; +const char *QUIT_JSFILE = "quit.js"; const char *CHANGEBREAKPOINT_QMLFILE = "changeBreakpoint.qml"; const char *STEPACTION_QMLFILE = "stepAction.qml"; const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml"; @@ -109,8 +111,10 @@ private slots: void setBreakpointInScriptOnOptimizedBinding(); void setBreakpointInScriptWithCondition_data() { targetData(); } void setBreakpointInScriptWithCondition(); - void setBreakpointInScriptThatQuits_data() { targetData(); } + void setBreakpointInScriptThatQuits_data() { targetData(); }; void setBreakpointInScriptThatQuits(); + void setBreakpointInJavaScript_data(); + void setBreakpointInJavaScript(); void setBreakpointWhenAttaching(); void clearBreakpoint_data() { targetData(); } @@ -450,6 +454,48 @@ void tst_QQmlDebugJS::setBreakpointInScriptThatQuits() QCOMPARE(m_process->exitStatus(), QProcess::NormalExit); } +void tst_QQmlDebugJS::setBreakpointInJavaScript_data() +{ + QTest::addColumn<bool>("qmlscene"); + QTest::addColumn<bool>("seedCache"); + QTest::newRow("custom / immediate") << false << false; + QTest::newRow("qmlscene / immediate") << true << false; + QTest::newRow("custom / seeded") << false << true; + QTest::newRow("qmlscene / seeded") << true << true; +} + +void tst_QQmlDebugJS::setBreakpointInJavaScript() +{ + QFETCH(bool, qmlscene); + QFETCH(bool, seedCache); + + if (seedCache) { // Make sure there is a qmlc file that the engine should _not_ laod. + QProcess process; + process.start(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", + { testFile(QUITINJS_QMLFILE) }); + QTRY_COMPARE(process.state(), QProcess::NotRunning); + } + + QCOMPARE(init(qmlscene, QUITINJS_QMLFILE), ConnectSuccess); + + const int sourceLine = 2; + + m_client->setBreakpoint(QLatin1String(QUIT_JSFILE), sourceLine, -1, true); + m_client->connect(); + QVERIFY(waitForClientSignal(SIGNAL(stopped()))); + + const QJsonObject body = m_client->response().body.toObject(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine); + QCOMPARE(QFileInfo(body.value("script").toObject().value("name").toString()).fileName(), + QLatin1String(QUIT_JSFILE)); + + m_client->continueDebugging(QV4DebugClient::Continue); + + QVERIFY(m_process->waitForFinished()); + QCOMPARE(m_process->exitStatus(), QProcess::NormalExit); +} + void tst_QQmlDebugJS::setBreakpointWhenAttaching() { int sourceLine = 35; diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 1c895eb793..f1ff396d4f 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -4888,6 +4888,7 @@ void tst_QJSEngine::interrupt_data() QTest::addRow("labeled continue / %s", mode) << i << "a: while (true) { for (;;) { continue a; } }"; QTest::addRow("labeled break / %s", mode) << i << "while (true) { a: for (;;) { break a; } }"; QTest::addRow("tail call / %s", mode) << i << "'use strict';\nfunction x() { return x(); }; x();"; + QTest::addRow("huge array join / %s", mode) << i << "Array(1E9)|1"; } } diff --git a/tests/auto/qml/qmlcachegen/data/parameterAdjustment.qml b/tests/auto/qml/qmlcachegen/data/parameterAdjustment.qml new file mode 100644 index 0000000000..2128a54d81 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/parameterAdjustment.qml @@ -0,0 +1,7 @@ +import QtQml 2.12 + +QtObject { + signal testSignal(string a, int b, string c, bool d, bool e, real f, real g, bool h, int i, int j, string k, int l, string m, string n) + onTestSignal: {} + Component.onCompleted: testSignal("a", 1, "b", true, true, 0.1, 0.1, true, 1, 1, "a", 1, "a", "a") +} diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro index 1a334b68ce..452bd7d04a 100644 --- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro +++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro @@ -17,7 +17,8 @@ RESOURCES += \ data/jsmoduleimport.qml \ data/script.mjs \ data/module.mjs \ - data/utils.mjs + data/utils.mjs \ + data/parameterAdjustment.qml workerscripts_test.files = \ data/worker.js \ diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 5d87c319f3..f940f9c476 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -73,6 +73,8 @@ private slots: void reproducibleCache_data(); void reproducibleCache(); + + void parameterAdjustment(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -664,6 +666,14 @@ void tst_qmlcachegen::reproducibleCache() QCOMPARE(contents1, contents2); } +void tst_qmlcachegen::parameterAdjustment() +{ + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/parameterAdjustment.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); // Doesn't crash +} + QTEST_GUILESS_MAIN(tst_qmlcachegen) #include "tst_qmlcachegen.moc" diff --git a/tests/auto/qml/qmllint/data/esmodule.mjs b/tests/auto/qml/qmllint/data/esmodule.mjs new file mode 100644 index 0000000000..50a53be2b1 --- /dev/null +++ b/tests/auto/qml/qmllint/data/esmodule.mjs @@ -0,0 +1,2 @@ + +export function test() { console.log("hello world"); } diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 04f554ac48..e3c297fa0f 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -158,6 +158,7 @@ void TestQmllint::cleanQmlCode_data() QTest::newRow("catchIdentifier") << QStringLiteral("catchIdentifierNoWarning.qml"); QTest::newRow("qmldirAndQmltypes") << QStringLiteral("qmldirAndQmltypes.qml"); QTest::newRow("forLoop") << QStringLiteral("forLoop.qml"); + QTest::newRow("esmodule") << QStringLiteral("esmodule.mjs"); } void TestQmllint::cleanQmlCode() diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index 79a73299a4..e7498a8583 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -130,6 +130,7 @@ 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/fuzzed.3.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 diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/Derived.qml b/tests/auto/qml/qmlplugindump/data/dumper/Imports/Derived.qml new file mode 100644 index 0000000000..2f0ac401d7 --- /dev/null +++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/Derived.qml @@ -0,0 +1,6 @@ +pragma Singleton +import dumper.Imports 1.0 + +Imports { + property int something: 2 +} diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.pro b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.pro index d20ea967ea..b4bd9baf5b 100644 --- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.pro +++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.pro @@ -17,7 +17,7 @@ HEADERS += \ imports.h !equals(_PRO_FILE_PWD_, $$OUT_PWD) { - cp.files = qmldir plugins.qmltypes CompositeImports.qml + cp.files = qmldir plugins.qmltypes CompositeImports.qml Derived.qml cp.path = $$OUT_PWD COPIES += cp } diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/plugins.qmltypes b/tests/auto/qml/qmlplugindump/data/dumper/Imports/plugins.qmltypes index 937dd60a9e..fb13928ba0 100644 --- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/plugins.qmltypes +++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/plugins.qmltypes @@ -14,4 +14,14 @@ Module { exports: ["dumper.Imports/Imports 1.0"] exportMetaObjectRevisions: [0] } + Component { + prototype: "Imports" + name: "dumper.Imports/Derived 1.0" + exports: ["dumper.Imports/Derived 1.0"] + exportMetaObjectRevisions: [0] + isComposite: true + isCreatable: false + isSingleton: true + Property { name: "something"; type: "int" } + } } diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/qmldir b/tests/auto/qml/qmlplugindump/data/dumper/Imports/qmldir index c9058a7f95..f84fca1d75 100644 --- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/qmldir +++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/qmldir @@ -1,3 +1,4 @@ module dumper.Imports plugin Imports CompositeImports 1.0 CompositeImports.qml +singleton Derived 1.0 Derived.qml diff --git a/tests/auto/qml/qqmlbinding/data/nanPropertyToInt.qml b/tests/auto/qml/qqmlbinding/data/nanPropertyToInt.qml new file mode 100644 index 0000000000..366dbf0464 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/nanPropertyToInt.qml @@ -0,0 +1,14 @@ +import QtQuick 2.11 + +Item { + visible: true + width: 320 + height: 200 + property int val: other.val + + Rectangle { + id: other + anchors.fill: parent; + property int val: undefined / 2 + } +} diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp index 2c2d311ff7..2610402455 100644 --- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -56,6 +56,7 @@ private slots: void bindingOverwriting(); void bindToQmlComponent(); void bindingDoesNoWeirdConversion(); + void bindNaNToInt(); private: QQmlEngine engine; @@ -398,6 +399,16 @@ void tst_qqmlbinding::bindingDoesNoWeirdConversion() QVERIFY(colorLabel); } +//QTBUG-72442 +void tst_qqmlbinding::bindNaNToInt() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("nanPropertyToInt.qml")); + QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create())); + + QVERIFY(item != nullptr); + QCOMPARE(item->property("val").toInt(), 0); +} QTEST_MAIN(tst_qqmlbinding) #include "tst_qqmlbinding.moc" diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp index d9cb6673df..6754f22049 100644 --- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp @@ -895,16 +895,27 @@ void tst_qqmlcontext::contextObjectHierarchy() void tst_qqmlcontext::destroyContextProperty() { - QQmlEngine engine; - QQmlContext context(&engine); - + QScopedPointer<QQmlContext> context; + QScopedPointer<QObject> objectThatOutlivesEngine(new QObject); { - QObject object; - context.setContextProperty(QLatin1String("a"), &object); - QCOMPARE(qvariant_cast<QObject *>(context.contextProperty(QLatin1String("a"))), &object); + QQmlEngine engine; + context.reset(new QQmlContext(&engine)); + + { + QObject object; + context->setContextProperty(QLatin1String("a"), &object); + QCOMPARE(qvariant_cast<QObject *>(context->contextProperty(QLatin1String("a"))), &object); + } + + QCOMPARE(qvariant_cast<QObject *>(context->contextProperty(QLatin1String("a"))), nullptr); + context->setContextProperty(QLatin1String("b"), objectThatOutlivesEngine.data()); } - QCOMPARE(qvariant_cast<QObject *>(context.contextProperty(QLatin1String("a"))), nullptr); + // dropDestroyedObject() should not crash, even if the engine is gone. + objectThatOutlivesEngine.reset(); + + // We're not allowed to call context->contextProperty("b") anymore. + // TODO: Or are we? } QTEST_MAIN(tst_qqmlcontext) diff --git a/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml new file mode 100644 index 0000000000..01ebfd8e1e --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQml.Models 2.15 +import QtQuick 2.15 + +import Test 1.0 + +DelegateModel { + model: AbstractItemModel {} + delegate: Item {} +} diff --git a/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml new file mode 100644 index 0000000000..f6cd886e09 --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQml.Models 2.15 +import QtQuick 2.15 + +DelegateModel { + model: 100 + delegate: Item {} +} diff --git a/tests/auto/qml/qqmldelegatemodel/data/listModel.qml b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml new file mode 100644 index 0000000000..1ee8bcac72 --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQml.Models 2.15 +import QtQuick 2.15 + +DelegateModel { + model: ListModel { + ListElement { + name: "Item 0" + } + ListElement { + name: "Item 1" + } + ListElement { + name: "Item 2" + } + } + delegate: Item {} +} diff --git a/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro new file mode 100644 index 0000000000..7fdd3ab5f1 --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro @@ -0,0 +1,13 @@ +CONFIG += testcase +TARGET = tst_qqmldelegatemodel +macos:CONFIG -= app_bundle + +QT += qml testlib core-private qml-private qmlmodels-private + +SOURCES += tst_qqmldelegatemodel.cpp + +include (../../shared/util.pri) + +TESTDATA = data/* + +OTHER_FILES += data/* diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp new file mode 100644 index 0000000000..87f42c0c8a --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/qtest.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQmlModels/private/qqmldelegatemodel_p.h> + +#include "../../shared/util.h" + +class tst_QQmlDelegateModel : public QQmlDataTest +{ + Q_OBJECT + +public: + tst_QQmlDelegateModel(); + +private slots: + void valueWithoutCallingObjectFirst_data(); + void valueWithoutCallingObjectFirst(); +}; + +class AbstractItemModel : public QAbstractItemModel +{ + Q_OBJECT +public: + AbstractItemModel() + { + for (int i = 0; i < 3; ++i) + mValues.append(QString::fromLatin1("Item %1").arg(i)); + } + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override + { + if (parent.isValid()) + return QModelIndex(); + + return createIndex(row, column); + } + + QModelIndex parent(const QModelIndex &) const override + { + return QModelIndex(); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const override + { + if (parent.isValid()) + return 0; + + return mValues.count(); + } + + int columnCount(const QModelIndex &parent) const override + { + if (parent.isValid()) + return 0; + + return 1; + } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override + { + if (role != Qt::DisplayRole) + return QVariant(); + + return mValues.at(index.row()); + } + +private: + QVector<QString> mValues; +}; + +tst_QQmlDelegateModel::tst_QQmlDelegateModel() +{ + qmlRegisterType<AbstractItemModel>("Test", 1, 0, "AbstractItemModel"); +} + +void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst_data() +{ + QTest::addColumn<QUrl>("qmlFileUrl"); + QTest::addColumn<int>("index"); + QTest::addColumn<QString>("role"); + QTest::addColumn<QVariant>("expectedValue"); + + QTest::addRow("integer") << testFileUrl("integerModel.qml") + << 50 << QString::fromLatin1("modelData") << QVariant(50); + QTest::addRow("ListModel") << testFileUrl("listModel.qml") + << 1 << QString::fromLatin1("name") << QVariant(QLatin1String("Item 1")); + QTest::addRow("QAbstractItemModel") << testFileUrl("abstractItemModel.qml") + << 1 << QString::fromLatin1("display") << QVariant(QLatin1String("Item 1")); +} + +// Tests that it's possible to call variantValue() without creating +// costly delegate items first via object(). +void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst() +{ + QFETCH(const QUrl, qmlFileUrl); + QFETCH(const int, index); + QFETCH(const QString, role); + QFETCH(const QVariant, expectedValue); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(qmlFileUrl); + QScopedPointer<QObject> root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + QQmlDelegateModel *model = qobject_cast<QQmlDelegateModel*>(root.data()); + QVERIFY(model); + QCOMPARE(model->variantValue(index, role), expectedValue); +} + +QTEST_MAIN(tst_QQmlDelegateModel) + +#include "tst_qqmldelegatemodel.moc" diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index f4de83eb87..a002658fee 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -5737,7 +5737,7 @@ void tst_qqmlecmascript::sequenceConversionRead() QVERIFY(seq != nullptr); // we haven't registered QList<NonRegisteredType> as a sequence type. - QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QList<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'"); + QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QVector<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'"); QString warningTwo = qmlFile.toString() + QLatin1String(":18: TypeError: Cannot read property 'length' of undefined"); QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData()); QTest::ignoreMessage(QtWarningMsg, warningTwo.toLatin1().constData()); @@ -5747,7 +5747,7 @@ void tst_qqmlecmascript::sequenceConversionRead() // QList<NonRegisteredType> has not been registered as a sequence type. QCOMPARE(object->property("pointListLength").toInt(), 0); QVERIFY(!object->property("pointList").isValid()); - QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QList<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'"); + QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QVector<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'"); QQmlProperty seqProp(seq, "typeListProperty", &engine); QVERIFY(!seqProp.read().isValid()); // not a valid/known sequence type @@ -5790,7 +5790,7 @@ void tst_qqmlecmascript::sequenceConversionWrite() QVERIFY(seq != nullptr); // we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work. - QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to QList<QPoint>"); + QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to QVector<QPoint>"); QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData()); QMetaObject::invokeMethod(object, "performTest"); @@ -5904,7 +5904,7 @@ void tst_qqmlecmascript::sequenceConversionBindings() { QUrl qmlFile = testFileUrl("sequenceConversion.bindings.error.qml"); - QString warning = QString(QLatin1String("%1:17:9: Unable to assign QList<int> to QList<bool>")).arg(qmlFile.toString()); + QString warning = QString(QLatin1String("%1:17:9: Unable to assign QVector<int> to QVector<bool>")).arg(qmlFile.toString()); QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); QQmlComponent component(&engine, qmlFile); QObject *object = component.create(); diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp index ca1e52ad2c..9c865b3f73 100644 --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp @@ -32,6 +32,7 @@ #include <QtQuick/qquickview.h> #include <QtQuick/qquickitem.h> #include <private/qqmlimport_p.h> +#include <private/qqmlengine_p.h> #include "../../shared/util.h" class tst_QQmlImport : public QQmlDataTest @@ -46,6 +47,7 @@ private slots: void completeQmldirPaths(); void interceptQmldir(); void singletonVersionResolution(); + void removeDynamicPlugin(); void cleanup(); }; @@ -260,6 +262,25 @@ void tst_QQmlImport::singletonVersionResolution() } } +void tst_QQmlImport::removeDynamicPlugin() +{ + qmlClearTypeRegistrations(); + QQmlEngine engine; + { + // Load something that adds a dynamic plugin + QQmlComponent component(&engine); + component.setData(QByteArray("import QtTest 1.0; TestResult{}"), QUrl()); + QVERIFY(component.isReady()); + } + QQmlImportDatabase *imports = &QQmlEnginePrivate::get(&engine)->importDatabase; + const QStringList &plugins = imports->dynamicPlugins(); + QVERIFY(!plugins.isEmpty()); + for (const QString &plugin : plugins) + QVERIFY(imports->removeDynamicPlugin(plugin)); + QVERIFY(imports->dynamicPlugins().isEmpty()); + qmlClearTypeRegistrations(); +} + QTEST_MAIN(tst_QQmlImport) diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp index 756b3b1d7c..549aae8c2b 100644 --- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp +++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp @@ -149,7 +149,7 @@ void tst_qqmlincubator::objectDeleted() QVERIFY(!SelfRegisteringType::me()); while (SelfRegisteringOuterType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -157,14 +157,14 @@ void tst_qqmlincubator::objectDeleted() QVERIFY(incubator.isLoading()); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } delete SelfRegisteringType::me(); { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -205,7 +205,7 @@ void tst_qqmlincubator::clear() component.create(incubator); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -224,7 +224,7 @@ void tst_qqmlincubator::clear() component.create(incubator); { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -318,7 +318,7 @@ void tst_qqmlincubator::forceCompletion() QVERIFY(incubator.isLoading()); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -377,7 +377,7 @@ void tst_qqmlincubator::setInitialState() MyIncubator incubator(QQmlIncubator::Asynchronous); component.create(incubator); QVERIFY(incubator.isLoading()); - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); QVERIFY(incubator.isReady()); QVERIFY(incubator.object()); @@ -414,7 +414,7 @@ void tst_qqmlincubator::clearDuringCompletion() QVERIFY(!CompletionRegisteringType::me()); while (CompletionRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -453,7 +453,7 @@ void tst_qqmlincubator::objectDeletionAfterInit() component.create(incubator); while (!incubator.obj && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -552,7 +552,7 @@ void tst_qqmlincubator::statusChanged() QCOMPARE(incubator.statuses.at(0), int(QQmlIncubator::Loading)); { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -574,7 +574,7 @@ void tst_qqmlincubator::statusChanged() QCOMPARE(incubator.statuses.at(0), int(QQmlIncubator::Loading)); { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -622,7 +622,7 @@ void tst_qqmlincubator::asynchronousIfNested() QVERIFY(incubator.isLoading()); QVERIFY(!SelfRegisteringType::me()); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -635,7 +635,7 @@ void tst_qqmlincubator::asynchronousIfNested() while (nested.isLoading()) { QVERIFY(incubator.isLoading()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -643,7 +643,7 @@ void tst_qqmlincubator::asynchronousIfNested() QVERIFY(incubator.isLoading()); { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -742,7 +742,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNested() QVERIFY(!SelfRegisteringType::me()); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -779,7 +779,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNested() QVERIFY(incubator1.isLoading()); QVERIFY(incubator2.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -792,14 +792,14 @@ void tst_qqmlincubator::chainedAsynchronousIfNested() QVERIFY(incubator1.isReady()); QVERIFY(incubator2.isLoading()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } QVERIFY(incubator1.isReady()); QVERIFY(incubator2.isReady()); if (incubator.isLoading()) { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -856,7 +856,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted() QVERIFY(!SelfRegisteringType::me()); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -876,7 +876,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted() QVERIFY(incubator2.isNull()); QVERIFY(incubator3.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -891,7 +891,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted() QVERIFY(incubator2.isNull()); QVERIFY(incubator3.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -906,7 +906,7 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted() QVERIFY(incubator2.isLoading()); QVERIFY(incubator3.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -921,12 +921,12 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted() QVERIFY(incubator2.isReady()); QVERIFY(incubator3.isLoading()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -984,7 +984,7 @@ void tst_qqmlincubator::chainedAsynchronousClear() QVERIFY(!SelfRegisteringType::me()); while (SelfRegisteringType::me() == nullptr && incubator.isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -1004,7 +1004,7 @@ void tst_qqmlincubator::chainedAsynchronousClear() QVERIFY(incubator2.isNull()); QVERIFY(incubator3.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -1019,7 +1019,7 @@ void tst_qqmlincubator::chainedAsynchronousClear() QVERIFY(incubator2.isNull()); QVERIFY(incubator3.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -1034,7 +1034,7 @@ void tst_qqmlincubator::chainedAsynchronousClear() QVERIFY(incubator2.isLoading()); QVERIFY(incubator3.isNull()); - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -1078,7 +1078,7 @@ void tst_qqmlincubator::selfDelete() #define DELETE_TEST(status, mode) { \ bool done = false; \ component.create(*(new MyIncubator(&done, status, mode))); \ - bool True = true; \ + std::atomic<bool> True{true}; \ controller.incubateWhile(&True); \ QVERIFY(done == true); \ } @@ -1107,7 +1107,7 @@ void tst_qqmlincubator::selfDelete() QVERIFY(!SelfRegisteringType::me()); while (SelfRegisteringType::me() == nullptr && incubator->isLoading()) { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } @@ -1121,7 +1121,7 @@ void tst_qqmlincubator::selfDelete() delete SelfRegisteringType::me(); { - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); } @@ -1142,7 +1142,7 @@ void tst_qqmlincubator::contextDelete() delete context; { - bool b = false; + std::atomic<bool> b{false}; controller.incubateWhile(&b); } } @@ -1155,7 +1155,7 @@ void tst_qqmlincubator::garbageCollection() engine.collectGarbage(); - bool b = true; + std::atomic<bool> b{true}; controller.incubateWhile(&b); // verify incubation completed (the incubator was not prematurely collected) diff --git a/tests/auto/qml/qqmlitemmodels/qtestmodel.h b/tests/auto/qml/qqmlitemmodels/qtestmodel.h index 6a022b3135..de42253708 100644 --- a/tests/auto/qml/qqmlitemmodels/qtestmodel.h +++ b/tests/auto/qml/qqmlitemmodels/qtestmodel.h @@ -31,6 +31,8 @@ #include <QtCore/qabstractitemmodel.h> +#include <limits.h> + class TestModel: public QAbstractItemModel { Q_OBJECT diff --git a/tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt new file mode 100644 index 0000000000..dfd077941e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.errors.txt @@ -0,0 +1 @@ +3:29:SelfInstantiation is instantiated recursively diff --git a/tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml new file mode 100644 index 0000000000..b2e4e453a0 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SelfInstantiation.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 +QtObject { + property QtObject self: SelfInstantiation { + } +} diff --git a/tests/auto/qml/qqmllanguage/data/SelfReference.qml b/tests/auto/qml/qqmllanguage/data/SelfReference.qml new file mode 100644 index 0000000000..129a171d77 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SelfReference.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 +QtObject { + property SelfReference self + signal blah(selfParam: SelfReference) + function returnSelf() : SelfReference { + return this; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt b/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt deleted file mode 100644 index 90a3ea4317..0000000000 --- a/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt +++ /dev/null @@ -1 +0,0 @@ -10:34:References to other aliases within the same object are not supported at the moment diff --git a/tests/auto/qml/qqmllanguage/data/alias.18.errors.txt b/tests/auto/qml/qqmllanguage/data/alias.18.errors.txt new file mode 100644 index 0000000000..dda3e7a174 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/alias.18.errors.txt @@ -0,0 +1 @@ +7:24:Duplicate alias name diff --git a/tests/auto/qml/qqmllanguage/data/alias.18.qml b/tests/auto/qml/qqmllanguage/data/alias.18.qml new file mode 100644 index 0000000000..a9be937975 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/alias.18.qml @@ -0,0 +1,9 @@ +import QtQml 2.14 + +QtObject { + id: root + property QtObject o1: QtObject { + property alias a: root + property alias a: root + } +} diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml b/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml Binary files differindex e726f6783c..f164ec98ea 100644 --- a/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml +++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.3.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.3.errors.txt new file mode 100644 index 0000000000..da17dc5599 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/fuzzed.3.errors.txt @@ -0,0 +1,2 @@ +3:2:Unexpected token `version number' +1:1:Expected a qualified name id or a string literal diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.3.qml b/tests/auto/qml/qqmllanguage/data/fuzzed.3.qml Binary files differnew file mode 100644 index 0000000000..6861ebf8a9 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/fuzzed.3.qml diff --git a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt index 043f714636..887d87b9fb 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 "MyTypeObject" to property "x", expecting "int" +4:18:Cannot assign value of type "MyTypeObject" to property "x", expecting "int" diff --git a/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml new file mode 100644 index 0000000000..f70a3b1fea --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/TestSingleton.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 +import selfreferencingsingletonmodule 1.0 +pragma Singleton +QtObject { + property SelfReferencingSingleton self + property int dummy: 42 +} diff --git a/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir new file mode 100644 index 0000000000..617861b00b --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/selfreferencingsingletonmodule/qmldir @@ -0,0 +1 @@ +singleton SelfReferencingSingleton 1.0 TestSingleton.qml diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index e2032c3b86..7fff982cde 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -306,6 +306,9 @@ private slots: void extendedForeignTypes(); + void selfReference(); + void selfReferencingSingleton(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -624,12 +627,15 @@ void tst_qqmllanguage::errors_data() QTest::newRow("fuzzed.1") << "fuzzed.1.qml" << "fuzzed.1.errors.txt" << false; QTest::newRow("fuzzed.2") << "fuzzed.2.qml" << "fuzzed.2.errors.txt" << false; + QTest::newRow("fuzzed.3") << "fuzzed.3.qml" << "fuzzed.3.errors.txt" << false; QTest::newRow("bareQmlImport") << "bareQmlImport.qml" << "bareQmlImport.errors.txt" << false; QTest::newRow("typeAnnotations.2") << "typeAnnotations.2.qml" << "typeAnnotations.2.errors.txt" << false; QTest::newRow("propertyUnknownType") << "propertyUnknownType.qml" << "propertyUnknownType.errors.txt" << false; + + QTest::newRow("selfInstantiation") << "SelfInstantiation.qml" << "SelfInstantiation.errors.txt" << false; } void tst_qqmllanguage::errors() @@ -1955,7 +1961,6 @@ void tst_qqmllanguage::aliasProperties() // "Nested" aliases within an object that require iterative resolution { - // This is known to fail at the moment. QQmlComponent component(&engine, testFileUrl("alias.14.qml")); VERIFY_ERRORS(0); @@ -2054,6 +2059,11 @@ void tst_qqmllanguage::aliasProperties() auto text = myText->property("text").toString(); QCOMPARE(text, "alias:\n20"); } + + { + QQmlComponent component(&engine, testFileUrl("alias.18.qml")); + VERIFY_ERRORS("alias.18.errors.txt"); + } } // QTBUG-13374 Test that alias properties and signals can coexist @@ -4728,11 +4738,13 @@ static void beginDeferredOnce(QQmlEnginePrivate *enginePriv, typedef QMultiHash<int, const QV4::CompiledData::Binding *> QV4PropertyBindingHash; auto it = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.second); auto last = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.first); + state->creator->beginPopulateDeferred(deferData->context); while (it != last) { - if (!state->creator->populateDeferredBinding(property, deferData, *it)) - state->errors << state->creator->errors; + state->creator->populateDeferredBinding(property, deferData->deferredIdx, *it); ++it; } + state->creator->finalizePopulateDeferred(); + state->errors << state->creator->errors; deferredState->constructionStates += state; @@ -4957,24 +4969,24 @@ void tst_qqmllanguage::instanceof_data() // assert that basic types don't convert to QObject QTest::newRow("1 instanceof QtObject") << testFileUrl("instanceof_qtqml.qml") - << QVariant("TypeError: Type error"); + << QVariant(false); QTest::newRow("true instanceof QtObject") << testFileUrl("instanceof_qtqml.qml") - << QVariant("TypeError: Type error"); + << QVariant(false); QTest::newRow("\"foobar\" instanceof QtObject") << testFileUrl("instanceof_qtqml.qml") - << QVariant("TypeError: Type error"); + << QVariant(false); // assert that Managed don't either QTest::newRow("new String(\"foobar\") instanceof QtObject") << testFileUrl("instanceof_qtqml.qml") - << QVariant("TypeError: Type error"); + << QVariant(false); QTest::newRow("new Object() instanceof QtObject") << testFileUrl("instanceof_qtqml.qml") - << QVariant("TypeError: Type error"); + << QVariant(false); QTest::newRow("new Date() instanceof QtObject") << testFileUrl("instanceof_qtqml.qml") - << QVariant("TypeError: Type error"); + << QVariant(false); // test that simple QtQml comparisons work QTest::newRow("qtobjectInstance instanceof QtObject") @@ -5274,6 +5286,69 @@ void tst_qqmllanguage::extendedForeignTypes() QCOMPARE(o->property("foreignExtendedObjectName").toString(), QLatin1String("foreignExtended")); } +void tst_qqmllanguage::selfReference() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("SelfReference.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + + QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component); + auto compilationUnit = componentPrivate->compilationUnit; + QVERIFY(compilationUnit); + + const QMetaObject *metaObject = o->metaObject(); + QMetaProperty selfProperty = metaObject->property(metaObject->indexOfProperty("self")); + QCOMPARE(selfProperty.userType(), compilationUnit->metaTypeId); + + QByteArray typeName = selfProperty.typeName(); + QVERIFY(typeName.endsWith('*')); + typeName = typeName.chopped(1); + QCOMPARE(typeName, metaObject->className()); + + QMetaMethod selfFunction = metaObject->method(metaObject->indexOfMethod("returnSelf()")); + QVERIFY(selfFunction.isValid()); + QCOMPARE(selfFunction.returnType(), compilationUnit->metaTypeId); + + QMetaMethod selfSignal; + + for (int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i) { + QMetaMethod method = metaObject->method(i); + if (method.isValid() && method.name().startsWith("blah")) { + selfSignal = method; + break; + } + } + + QVERIFY(selfSignal.isValid()); + QCOMPARE(selfSignal.parameterCount(), 1); + QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaTypeId); +} + +void tst_qqmllanguage::selfReferencingSingleton() +{ + QQmlEngine engine; + engine.addImportPath(dataDirectory()); + + QPointer<QObject> singletonPointer; + { + QQmlComponent component(&engine); + component.setData(QByteArray(R"(import QtQml 2.0 + import selfreferencingsingletonmodule 1.0 + QtObject { + property SelfReferencingSingleton singletonPointer: SelfReferencingSingleton + })"), QUrl()); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + singletonPointer = o->property("singletonPointer").value<QObject*>(); + } + + QVERIFY(!singletonPointer.isNull()); + QCOMPARE(singletonPointer->property("dummy").toInt(), 42); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlproperty/data/interfaceBinding.qml b/tests/auto/qml/qqmlproperty/data/interfaceBinding.qml new file mode 100644 index 0000000000..4e72a75f42 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/interfaceBinding.qml @@ -0,0 +1,27 @@ +import QtQuick 2.12 +import io.qt.bugreports 1.0 +Item { + InterfaceConsumer { + objectName: "a1" + i: A { + property int i: 42 + } + } + + InterfaceConsumer { + objectName: "a2" + property A a: A { + property int i: 43 + } + i: a + } + + InterfaceConsumer { + objectName: "a3" + property A a: A { + id : aa + property int i: 44 + } + i: aa + } +} diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 1a5927fa74..f039ccc110 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -40,6 +40,8 @@ #endif #include <QtCore/private/qobject_p.h> #include "../../shared/util.h" +#include "qobject.h" +#include <QtQml/QQmlPropertyMap> #include <QDebug> class MyQmlObject : public QObject @@ -148,6 +150,7 @@ private slots: void readOnlyDynamicProperties(); void aliasToIdWithMatchingQmlFileNameOnCaseInsensitiveFileSystem(); void nullPropertyBinding(); + void interfaceBinding(); void floatToStringPrecision_data(); void floatToStringPrecision(); @@ -155,6 +158,8 @@ private slots: void copy(); void bindingToAlias(); + + void nestedQQmlPropertyMap(); private: QQmlEngine engine; }; @@ -2083,6 +2088,83 @@ void tst_qqmlproperty::nullPropertyBinding() QMetaObject::invokeMethod(root.get(), "tog"); } +struct Interface { +}; + +QT_BEGIN_NAMESPACE +#define MyInterface_iid "io.qt.bugreports.Interface" +Q_DECLARE_INTERFACE(Interface, MyInterface_iid); +QT_END_NAMESPACE + +class A : public QObject, Interface { + Q_OBJECT + Q_INTERFACES(Interface) +}; + +class B : public QObject, Interface { + Q_OBJECT + Q_INTERFACES(Interface) +}; + +class C : public QObject { + Q_OBJECT +}; + +class InterfaceConsumer : public QObject { + Q_OBJECT + Q_PROPERTY(Interface* i READ interface WRITE setInterface NOTIFY interfaceChanged) + Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) + + +public: + + Interface* interface() const + { + return m_interface; + } + void setInterface(Interface* interface) + { + QObject* object = reinterpret_cast<QObject*>(interface); + m_testValue = object->property("i").toInt(); + emit testValueChanged(); + if (m_interface == interface) + return; + + m_interface = interface; + emit interfaceChanged(); + } + + int testValue() { + return m_testValue; + } + +signals: + void interfaceChanged(); + void testValueChanged(); + +private: + Interface* m_interface = nullptr; + int m_testValue = 0; +}; +void tst_qqmlproperty::interfaceBinding() +{ + + qmlRegisterInterface<Interface>("Interface"); + qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A"); + qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B"); + qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C"); + qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer"); + + const QUrl url = testFileUrl("interfaceBinding.qml"); + QQmlEngine engine; + QQmlComponent component(&engine, url); + QScopedPointer<QObject> root(component.create()); + QVERIFY(root); + QCOMPARE(root->findChild<QObject*>("a1")->property("testValue").toInt(), 42); + QCOMPARE(root->findChild<QObject*>("a2")->property("testValue").toInt(), 43); + QCOMPARE(root->findChild<QObject*>("a3")->property("testValue").toInt(), 44); +} + void tst_qqmlproperty::floatToStringPrecision_data() { QTest::addColumn<QString>("propertyName"); @@ -2139,6 +2221,24 @@ void tst_qqmlproperty::bindingToAlias() QVERIFY(!o.isNull()); } +void tst_qqmlproperty::nestedQQmlPropertyMap() +{ + QQmlPropertyMap mainPropertyMap; + QQmlPropertyMap nestedPropertyMap; + QQmlPropertyMap deeplyNestedPropertyMap; + + mainPropertyMap.insert("nesting1", QVariant::fromValue(&nestedPropertyMap)); + nestedPropertyMap.insert("value", 42); + nestedPropertyMap.insert("nesting2", QVariant::fromValue(&deeplyNestedPropertyMap)); + deeplyNestedPropertyMap.insert("value", "success"); + + QQmlProperty value{&mainPropertyMap, "nesting1.value"}; + QCOMPARE(value.read().toInt(), 42); + + QQmlProperty success{&mainPropertyMap, "nesting1.nesting2.value"}; + QCOMPARE(success.read().toString(), QLatin1String("success")); +} + QTEST_MAIN(tst_qqmlproperty) #include "tst_qqmlproperty.moc" diff --git a/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro b/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro index 9d298dfdf2..11b11132aa 100644 --- a/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro +++ b/tests/auto/qml/qqmltablemodel/qqmltablemodel.pro @@ -7,4 +7,4 @@ include (../../shared/util.pri) TESTDATA = data/* -QT += core gui qml-private qml quick-private quick testlib qmlmodels-private +QT += core gui qml-private qml quick-private quick testlib diff --git a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp index d913bcdf9a..5457597df3 100644 --- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp +++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp @@ -29,8 +29,8 @@ #include <QtTest/qtest.h> #include <QtTest/qsignalspy.h> #include <QtCore/qregularexpression.h> +#include <QtCore/qabstractitemmodel.h> #include <QtQml/private/qqmlengine_p.h> -#include <QtQmlModels/private/qqmltablemodel_p.h> #include <QtQml/qqmlcomponent.h> #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> @@ -68,7 +68,7 @@ void tst_QQmlTableModel::appendRemoveRow() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel") .value<QAbstractTableModel *>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -213,7 +213,7 @@ void tst_QQmlTableModel::appendRowToEmptyModel() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 0); QCOMPARE(model->columnCount(), 2); @@ -248,7 +248,7 @@ void tst_QQmlTableModel::clear() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -287,7 +287,7 @@ void tst_QQmlTableModel::getRow() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -318,7 +318,7 @@ void tst_QQmlTableModel::insertRow() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -474,7 +474,7 @@ void tst_QQmlTableModel::moveRow() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->columnCount(), 2); QCOMPARE(model->rowCount(), 2); @@ -602,7 +602,7 @@ void tst_QQmlTableModel::setRow() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->columnCount(), 2); QCOMPARE(model->rowCount(), 2); @@ -762,7 +762,7 @@ void tst_QQmlTableModel::setDataThroughDelegate() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -825,7 +825,7 @@ void tst_QQmlTableModel::setRowsImperatively() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 0); QCOMPARE(model->columnCount(), 2); @@ -862,7 +862,7 @@ void tst_QQmlTableModel::setRowsMultipleTimes() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("testModel").value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -919,7 +919,7 @@ void tst_QQmlTableModel::dataAndEditing() view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); - QQmlTableModel *model = view.rootObject()->property("model").value<QQmlTableModel*>(); + auto *model = view.rootObject()->property("model").value<QAbstractTableModel*>(); QVERIFY(model); const QHash<int, QByteArray> roleNames = model->roleNames(); @@ -939,7 +939,7 @@ void tst_QQmlTableModel::omitTableModelColumnIndex() QQmlComponent component(&engine, testFileUrl("omitTableModelColumnIndex.qml")); QCOMPARE(component.status(), QQmlComponent::Ready); - QScopedPointer<QQmlTableModel> model(qobject_cast<QQmlTableModel*>(component.create())); + QScopedPointer<QAbstractTableModel> model(qobject_cast<QAbstractTableModel*>(component.create())); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); @@ -963,7 +963,7 @@ void tst_QQmlTableModel::complexRow() QCOMPARE(tableView->rows(), 2); QCOMPARE(tableView->columns(), 2); - QQmlTableModel *model = tableView->model().value<QQmlTableModel*>(); + auto *model = tableView->model().value<QAbstractTableModel*>(); QVERIFY(model); QCOMPARE(model->rowCount(), 2); QCOMPARE(model->columnCount(), 2); diff --git a/tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml b/tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml new file mode 100644 index 0000000000..9061f3beb5 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/declarativeCppType.qml @@ -0,0 +1,6 @@ +import QtQml 2.0 +import declarative.import.for.typeloader.test 3.2 + +DeclarativeTestType { + objectName: "ddddd" +} diff --git a/tests/auto/qml/qqmltypeloader/declarativetesttype.h b/tests/auto/qml/qqmltypeloader/declarativetesttype.h new file mode 100644 index 0000000000..a21cdcfd1d --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/declarativetesttype.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DECLARATIVETESTTYPE_H +#define DECLARATIVETESTTYPE_H + +#include <QObject> +#include <qqml.h> + +class DeclarativeTestType : public QObject +{ + Q_OBJECT + QML_ELEMENT + +public: + explicit DeclarativeTestType(QObject *parent = nullptr) : QObject(parent) {} +}; + +#endif // DECLARATIVETESTTYPE_H diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 07f67c7843..d529600723 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -61,7 +61,7 @@ private slots: void qrcRootPathUrl(); void implicitImport(); void compositeSingletonCycle(); - + void declarativeCppType(); private: void checkSingleton(const QString & dataDirectory); }; @@ -100,6 +100,8 @@ void tst_QQMLTypeLoader::trimCache() { QQmlEngine engine; QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader; + QVector<QQmlTypeData *> releaseLater; + QVector<QV4::ExecutableCompilationUnit *> releaseCompilationUnitLater; for (int i = 0; i < 256; ++i) { QUrl url = testFileUrl("trim_cache.qml"); url.setQuery(QString::number(i)); @@ -112,8 +114,10 @@ void tst_QQMLTypeLoader::trimCache() // QQmlTypeData or its compiledData() should prevent the trimming. if (i % 10 == 0) { // keep ref on data, don't add ref on data->compiledData() + releaseLater.append(data); } else if (i % 5 == 0) { data->compilationUnit()->addref(); + releaseCompilationUnitLater.append(data->compilationUnit()); data->release(); } else { data->release(); @@ -129,6 +133,12 @@ void tst_QQMLTypeLoader::trimCache() QVERIFY(!loader.isTypeLoaded(url)); // The cache is free to keep the others. } + + for (auto *data : qAsConst(releaseCompilationUnitLater)) + data->release(); + + for (auto *data : qAsConst(releaseLater)) + data->release(); } void tst_QQMLTypeLoader::trimCache2() @@ -557,6 +567,15 @@ void tst_QQMLTypeLoader::compositeSingletonCycle() QCOMPARE(qvariant_cast<QColor>(object->property("color")), QColorConstants::Black); } +void tst_QQMLTypeLoader::declarativeCppType() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("declarativeCppType.qml")); + QCOMPARE(component.status(), QQmlComponent::Ready); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro index 743f7cf3ac..c868474b5b 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro @@ -1,4 +1,4 @@ -CONFIG += testcase +CONFIG += testcase qmltypes TARGET = tst_qqmltypeloader QT += qml testlib qml-private quick macx:CONFIG -= app_bundle @@ -8,7 +8,11 @@ SOURCES += \ ../../shared/testhttpserver.cpp HEADERS += \ - ../../shared/testhttpserver.h + ../../shared/testhttpserver.h \ + declarativetesttype.h + +QML_IMPORT_VERSION = 3.2 +QML_IMPORT_NAME = "declarative.import.for.typeloader.test" include (../../shared/util.pri) |