diff options
Diffstat (limited to 'tests/auto/qml')
9 files changed, 234 insertions, 21 deletions
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml new file mode 100644 index 0000000000..c3e7687831 --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml @@ -0,0 +1,15 @@ +import QtQml 2.15 +Timer { + Component.onCompleted: { + console.log('0') + console.log('1') + console.log('2') + console.log('3') + console.log('4') + console.log('5') + running = true + } + + interval: 0 + onTriggered: Qt.quit() +} diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml b/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml new file mode 100644 index 0000000000..1715992490 --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml @@ -0,0 +1,16 @@ +import QtQml 2.15 + +Timer { + Component.onCompleted: { + var a = 97 + var b = 98 + var c = 99 + let d = 100 + const e = 101 + console.log("onClicked") // Set breakpoint + running = true + } + + interval: 0 + onTriggered: Qt.quit() +} diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 91470e0651..43c81ee515 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -65,6 +65,8 @@ const char *STEPACTION_QMLFILE = "stepAction.qml"; const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml"; const char *ENCODEQMLSCOPE_QMLFILE = "encodeQmlScope.qml"; const char *BREAKONANCHOR_QMLFILE = "breakOnAnchor.qml"; +const char *BREAKPOINTIDS_QMLFILE = "breakPointIds.qml"; +const char *LETCONSTLOCALS_QMLFILE = "letConstLocals.qml"; #undef QVERIFY #define QVERIFY(statement) \ @@ -156,6 +158,9 @@ private slots: void encodeQmlScope(); void breakOnAnchor(); + void breakPointIds(); + void letConstLocals(); + private: ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true, bool restrictServices = false); @@ -165,10 +170,11 @@ private: void targetData(); bool waitForClientSignal(const char *signal, int timeout = 30000); void checkVersionParameters(); + int setBreakPoint(const QString &file, int sourceLine, bool enabled); + void clearBreakPoint(int id); }; - void tst_QQmlDebugJS::initTestCase() { QQmlDebugTest::initTestCase(); @@ -566,7 +572,8 @@ void tst_QQmlDebugJS::changeBreakpoint() int sourceLine2 = 37; int sourceLine1 = 38; - QCOMPARE(init(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess); + const QString file = QLatin1String(CHANGEBREAKPOINT_QMLFILE); + QCOMPARE(init(qmlscene, file), ConnectSuccess); bool isStopped = false; QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { isStopped = true; }); @@ -589,27 +596,13 @@ void tst_QQmlDebugJS::changeBreakpoint() return breakpointsHit[0].toInt(); }; - auto setBreakPoint = [&](int sourceLine, bool enabled) { - int id = -1; - auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() { - id = extractBody().value("breakpoint").toInt(); - }); - - m_client->setBreakpoint(QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine, -1, enabled); - bool success = QTest::qWaitFor([&]() { return id >= 0; }); - Q_UNUSED(success); - - QObject::disconnect(connection); - return id; - }; - //The breakpoints are in a timer loop so we can set them after connect(). //Furthermore the breakpoints should be hit in the right order because setting of breakpoints //can only occur in the QML event loop. (see QCOMPARE for sourceLine2 below) - const int breakpoint1 = setBreakPoint(sourceLine1, false); + const int breakpoint1 = setBreakPoint(file, sourceLine1, false); QVERIFY(breakpoint1 >= 0); - const int breakpoint2 = setBreakPoint(sourceLine2, true); + const int breakpoint2 = setBreakPoint(file, sourceLine2, true); QVERIFY(breakpoint2 >= 0); auto verifyBreakpoint = [&](int sourceLine, int breakpointId) { @@ -1026,6 +1019,96 @@ void tst_QQmlDebugJS::breakOnAnchor() QCOMPARE(breaks, 2); } +void tst_QQmlDebugJS::breakPointIds() +{ + QString file(BREAKPOINTIDS_QMLFILE); + QCOMPARE(init(true, file), ConnectSuccess); + + int breaks = 0; + int breakPointIds[] = { -1, -1, -1, -1, -1, -1}; + + QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { + const QJsonObject body = m_client->response().body.toObject(); + QCOMPARE(body.value("sourceLine").toInt(), breaks + 4); + const QJsonArray breakpointsHit = body.value("breakpoints").toArray(); + QVERIFY(breakpointsHit.size() > 0); + QCOMPARE(breakpointsHit[0].toInt(), breakPointIds[breaks]); + ++breaks; + m_client->continueDebugging(QV4DebugClient::Continue); + }); + + for (int i = 0; i < 6; ++i) + breakPointIds[i] = setBreakPoint(file, i + 4, true); + + clearBreakPoint(breakPointIds[2]); + breakPointIds[2] = setBreakPoint(file, 6, true); + + QTRY_COMPARE(m_process->state(), QProcess::Running); + m_client->connect(); + + QTRY_COMPARE(m_process->state(), QProcess::NotRunning); + QCOMPARE(m_process->exitStatus(), QProcess::NormalExit); + + QCOMPARE(breaks, 6); +} + +void tst_QQmlDebugJS::letConstLocals() +{ + QString file(LETCONSTLOCALS_QMLFILE); + QCOMPARE(init(true, file), ConnectSuccess); + + QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { + m_client->frame(); + }); + + int numScopes = 0; + QString expectedMembers = QStringLiteral("abcde"); + QObject::connect(m_client.data(), &QV4DebugClient::result, this, [&]() { + const auto value = m_client->response(); + if (value.command == QStringLiteral("frame")) { + const auto scopes = value.body.toObject().value(QStringLiteral("scopes")).toArray(); + for (const auto &scope : scopes) { + const auto scopeObject = scope.toObject(); + const int type = scopeObject.value("type").toInt(); + if (type == 1 || type == 4) { + m_client->scope(scopeObject.value("index").toInt()); + ++numScopes; + } + } + QVERIFY(numScopes > 0); + } else if (value.command == QStringLiteral("scope")) { + const auto props = value.body.toObject().value(QStringLiteral("object")).toObject() + .value(QStringLiteral("properties")).toArray(); + for (const auto &prop : props) { + const auto propObj = prop.toObject(); + const QString name = propObj.value(QStringLiteral("name")).toString(); + if (name == QStringLiteral("onCompleted")) + continue; + QVERIFY(name.length() == 1); + auto i = expectedMembers.indexOf(name.at(0)); + QVERIFY(i != -1); + expectedMembers.remove(i, 1); + QCOMPARE(propObj.value(QStringLiteral("type")).toString(), + QStringLiteral("number")); + QCOMPARE(propObj.value(QStringLiteral("value")).toInt(), + int(name.at(0).toLatin1())); + } + if (--numScopes == 0) { + QVERIFY(expectedMembers.isEmpty()); + m_client->continueDebugging(QV4DebugClient::Continue); + } + } + }); + + setBreakPoint(file, 10, true); + + QTRY_COMPARE(m_process->state(), QProcess::Running); + m_client->connect(); + + QTRY_COMPARE(m_process->state(), QProcess::NotRunning); + QCOMPARE(m_process->exitStatus(), QProcess::NormalExit); +} + QList<QQmlDebugClient *> tst_QQmlDebugJS::createClients() { m_client = new QV4DebugClient(m_connection); @@ -1054,6 +1137,35 @@ void tst_QQmlDebugJS::checkVersionParameters() QCOMPARE(body.value("ChangeBreakpoint").toBool(), true); } +int tst_QQmlDebugJS::setBreakPoint(const QString &file, int sourceLine, bool enabled) +{ + int id = -1; + auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() { + id = m_client->response().body.toObject().value("breakpoint").toInt(); + }); + + m_client->setBreakpoint(file, sourceLine, -1, enabled); + bool success = QTest::qWaitFor([&]() { return id >= 0; }); + Q_UNUSED(success); + + QObject::disconnect(connection); + return id; +} + +void tst_QQmlDebugJS::clearBreakPoint(int id) +{ + bool ok = false; + auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() { + ok = true; + }); + + m_client->clearBreakpoint(id); + bool success = QTest::qWaitFor([&]() { return ok; }); + Q_UNUSED(success); + + QObject::disconnect(connection); +} + QTEST_MAIN(tst_QQmlDebugJS) #include "tst_qqmldebugjs.moc" diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index e3cbeb9891..e4e7728508 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -575,21 +575,29 @@ void tst_qv4debugger::readLocals() QString script = "var f = function(a, b) {\n" " var c = a + b\n" + " let e = 'jaja'\n" + " const ff = 'nenene'\n" " var d = a - b\n" // breakpoint, c should be set, d should be undefined " return c === d\n" "}\n" "f(1, 2, 3);\n"; - debugger()->addBreakPoint("readLocals", 3); + debugger()->addBreakPoint("readLocals", 5); evaluateJavaScript(script, "readLocals"); QVERIFY(m_debuggerAgent->m_wasPaused); QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1); const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0); - QCOMPARE(frame0.size(), 5); // locals and parameters + QCOMPARE(frame0.size(), 7); // locals and parameters QVERIFY(frame0.contains("c")); QCOMPARE(frame0.type("c"), QStringLiteral("number")); QCOMPARE(frame0.value("c").toDouble(), 3.0); QVERIFY(frame0.contains("d")); QCOMPARE(frame0.type("d"), QStringLiteral("undefined")); + QVERIFY(frame0.contains("e")); + QCOMPARE(frame0.type("e"), QStringLiteral("string")); + QCOMPARE(frame0.value("e").toString(), QStringLiteral("jaja")); + QVERIFY(frame0.contains("ff")); + QCOMPARE(frame0.type("ff"), QStringLiteral("string")); + QCOMPARE(frame0.value("ff").toString(), QStringLiteral("nenene")); } void tst_qv4debugger::readObject() diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 43cbd93396..544569de5f 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -828,7 +828,7 @@ void tst_qqmlcomponent::testSetInitialProperties() comp.createWithInitialProperties(QVariantMap { {"notThePropertiesYoureLookingFor", 42} }) }; QVERIFY(obj); - QVERIFY(comp.errorString().contains("Could not set property notThePropertiesYoureLookingFor")); + QVERIFY(comp.errorString().contains("Setting initial properties failed: Item does not have a property called notThePropertiesYoureLookingFor")); } } diff --git a/tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml b/tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml new file mode 100644 index 0000000000..02d737e37f --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml @@ -0,0 +1,32 @@ +import QtQuick 2.8 +import QtQml.Models 2.1 + +DelegateModel { + id: visualModel + model: ListModel { + id: myLM + ListElement { + name: "Apple" + } + ListElement { + name: "Orange" + } + } + + filterOnGroup: "selected" + + groups: [ + DelegateModelGroup { + name: "selected" + includeByDefault: true + } + ] + + delegate: Text { + Component.onCompleted: { + DelegateModel.inPersistedItems = true + DelegateModel.inSelected = false + } + text: "item " + index + } +} diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp index 71550a50f3..9bc359d243 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -45,6 +45,7 @@ private slots: void valueWithoutCallingObjectFirst_data(); void valueWithoutCallingObjectFirst(); void filterOnGroup_removeWhenCompleted(); + void qtbug_86017(); }; class AbstractItemModel : public QAbstractItemModel @@ -147,6 +148,20 @@ void tst_QQmlDelegateModel::filterOnGroup_removeWhenCompleted() QQmlDelegateModel *model = root->findChild<QQmlDelegateModel*>(); QVERIFY(model); QTest::qWaitFor([=]{ return model->count() == 2; } ); + +void tst_QQmlDelegateModel::qtbug_86017() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("qtbug_86017.qml")); + QScopedPointer<QObject> root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + QTRY_VERIFY(component.isReady()); + QQmlDelegateModel *model = qobject_cast<QQmlDelegateModel*>(root.data()); + + QVERIFY(model); + QCOMPARE(model->count(), 2); + QCOMPARE(model->filterGroup(), "selected"); } QTEST_MAIN(tst_QQmlDelegateModel) diff --git a/tests/auto/qml/qqmllanguage/data/hangOnWarning.qml b/tests/auto/qml/qqmllanguage/data/hangOnWarning.qml new file mode 100644 index 0000000000..51943c3839 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/hangOnWarning.qml @@ -0,0 +1,3 @@ +import QtQml 2.15 + +QtObject["foobar"] {} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index de8b2ef7eb..94ecd6862a 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -334,6 +334,8 @@ private slots: void accessNullPointerPropertyCache(); void bareInlineComponent(); + void hangOnWarning(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -5841,6 +5843,16 @@ void tst_qqmllanguage::bareInlineComponent() QVERIFY(tab1Found); } +void tst_qqmllanguage::hangOnWarning() +{ + QTest::ignoreMessage(QtWarningMsg, + qPrintable(QStringLiteral("%1:3 : Ignored annotation") + .arg(testFileUrl("hangOnWarning.qml").toString()))); + QQmlComponent component(&engine, testFileUrl("hangOnWarning.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object != nullptr); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" |