diff options
Diffstat (limited to 'tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp')
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 338 |
1 files changed, 322 insertions, 16 deletions
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index f460dc3cad..8203ab1d33 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -517,6 +517,22 @@ private slots: void argumentsUsageInBindings_data(); void argumentsUsageInBindings(); + void aliasToLargeRevision(); + void propertyCycle(); + + void urlWithFragment(); + + void enumScoping(); + void enumStringToValue(); + void enumValueToString(); + void enumValueToStrings(); + + void enumTypeAnnotations(); + + void assignWrongTypeToObjectList(); + + void variantAssociationHasOwnProperty(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -704,6 +720,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false; QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false; QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.11") << "invalidGroupedProperty.11.qml" << "invalidGroupedProperty.11.errors.txt" << false; QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false; QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false; @@ -2740,8 +2757,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode() QUrl url = testFileUrl("scriptString7.qml"); QScopedPointer<const QV4::CompiledData::Unit, FreeUnitData> readOnlyQmlUnit; { - QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine); - QQmlRefPointer<QQmlTypeData> td = eng->typeLoader.getType(url); + QQmlRefPointer<QQmlTypeData> td = QQmlTypeLoader::get(&engine)->getType(url); Q_ASSERT(td); QVERIFY(!td->backupSourceCode().isValid()); @@ -2942,12 +2958,9 @@ void tst_qqmllanguage::reservedWords_data() QTest::newRow("abstract") << QByteArray("abstract"); QTest::newRow("as") << QByteArray("as"); - QTest::newRow("boolean") << QByteArray("boolean"); QTest::newRow("break") << QByteArray("break"); - QTest::newRow("byte") << QByteArray("byte"); QTest::newRow("case") << QByteArray("case"); QTest::newRow("catch") << QByteArray("catch"); - QTest::newRow("char") << QByteArray("char"); QTest::newRow("class") << QByteArray("class"); QTest::newRow("continue") << QByteArray("continue"); QTest::newRow("const") << QByteArray("const"); @@ -2955,7 +2968,6 @@ void tst_qqmllanguage::reservedWords_data() QTest::newRow("default") << QByteArray("default"); QTest::newRow("delete") << QByteArray("delete"); QTest::newRow("do") << QByteArray("do"); - QTest::newRow("double") << QByteArray("double"); QTest::newRow("else") << QByteArray("else"); QTest::newRow("enum") << QByteArray("enum"); QTest::newRow("export") << QByteArray("export"); @@ -2963,19 +2975,15 @@ void tst_qqmllanguage::reservedWords_data() QTest::newRow("false") << QByteArray("false"); QTest::newRow("final") << QByteArray("final"); QTest::newRow("finally") << QByteArray("finally"); - QTest::newRow("float") << QByteArray("float"); QTest::newRow("for") << QByteArray("for"); QTest::newRow("function") << QByteArray("function"); - QTest::newRow("goto") << QByteArray("goto"); QTest::newRow("if") << QByteArray("if"); QTest::newRow("implements") << QByteArray("implements"); QTest::newRow("import") << QByteArray("import"); QTest::newRow("pragma") << QByteArray("pragma"); QTest::newRow("in") << QByteArray("in"); QTest::newRow("instanceof") << QByteArray("instanceof"); - QTest::newRow("int") << QByteArray("int"); QTest::newRow("interface") << QByteArray("interface"); - QTest::newRow("long") << QByteArray("long"); QTest::newRow("native") << QByteArray("native"); QTest::newRow("new") << QByteArray("new"); QTest::newRow("null") << QByteArray("null"); @@ -2984,7 +2992,6 @@ void tst_qqmllanguage::reservedWords_data() QTest::newRow("protected") << QByteArray("protected"); QTest::newRow("public") << QByteArray("public"); QTest::newRow("return") << QByteArray("return"); - QTest::newRow("short") << QByteArray("short"); QTest::newRow("static") << QByteArray("static"); QTest::newRow("super") << QByteArray("super"); QTest::newRow("switch") << QByteArray("switch"); @@ -6320,12 +6327,12 @@ void tst_qqmllanguage::nonExistingInlineComponent_data() QTest::addColumn<int>("line"); QTest::addColumn<int>("column"); - QTest::newRow("Property type") << testFileUrl("nonExistingICUser1.qml") << QString("Type InlineComponentProvider has no inline component type called NonExisting") << 4 << 5; + QTest::newRow("Property type") << testFileUrl("nonExistingICUser1.qml") << QString("Type InlineComponentProvider has no inline component type called NotExisting") << 4 << 58; QTest::newRow("Instantiation") << testFileUrl("nonExistingICUser2.qml") << QString("Type InlineComponentProvider has no inline component type called NotExisting") << 4 << 5; QTest::newRow("Inheritance") << testFileUrl("nonExistingICUser3.qml") << QString("Type InlineComponentProvider has no inline component type called NotExisting") << 3 << 1; - QTest::newRow("From singleton") << testFileUrl("nonExistingICUser4.qml") << QString("Type MySingleton.SingletonTypeWithIC has no inline component type called NonExisting") << 5 << 5; + QTest::newRow("From singleton") << testFileUrl("nonExistingICUser4.qml") << QString("Type MySingleton.SingletonTypeWithIC has no inline component type called NonExisting") << 5 << 71; - QTest::newRow("Cannot access parent inline components from child") << testFileUrl("nonExistingICUser5.qml") << QString("Type InlineComponentProviderChild has no inline component type called StyledRectangle") << 4 << 5; + QTest::newRow("Cannot access parent inline components from child") << testFileUrl("nonExistingICUser5.qml") << QString("Type InlineComponentProviderChild has no inline component type called StyledRectangle") << 4 << 67; } void tst_qqmllanguage::nonExistingInlineComponent() @@ -8980,8 +8987,8 @@ void tst_qqmllanguage::overrideDefaultProperty() QQmlComponent c(&e, url); QVERIFY(c.isError()); - QCOMPARE(c.errorString(), - url.toString() + QLatin1String(":5 Cannot assign object to list property \"data\"\n")); + QCOMPARE(c.errorString(), url.toString() + QLatin1String( + ":5 Cannot assign object of type \"QQuickItem\" to list property \"data\"; expected \"QVariant\"\n")); } void tst_qqmllanguage::enumScopes() @@ -9767,6 +9774,305 @@ void tst_qqmllanguage::argumentsUsageInBindings() { QCOMPARE(object->property("result").toString(), object->property("expected").toString()); } +void tst_qqmllanguage::aliasToLargeRevision() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("aliasToLargeRevision.qml")); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("aa"), 13); + QCOMPARE(o->property("bb"), 14); + QCOMPARE(o->property("cc"), 15); + QCOMPARE(o->property("dd"), 16); +} + +void tst_qqmllanguage::urlWithFragment() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("urlWithFragment.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->objectName(), "outer"); +} + +void tst_qqmllanguage::enumScoping() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("EnumScoping.qml")); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("qmlAsScoped").toInt(), 1); + QCOMPARE(o->property("qmlAsUnscoped").toInt(), 1); + + QCOMPARE(o->property("cppScopedAsScoped").toInt(), 1); + QCOMPARE(o->property("cppScopedAsUnscoped").toInt(), 1); + + QCOMPARE(o->property("cppUnscopedAsScoped").toInt(), 1); + QCOMPARE(o->property("cppUnscopedAsUnscoped").toInt(), 1); + + QCOMPARE(o->property("nsScopedAsScoped").toInt(), 1); + QCOMPARE(o->property("nsScopedAsUnscoped").toInt(), 1); + + QCOMPARE(o->property("nsUnscopedAsScoped").toInt(), 1); + QCOMPARE(o->property("nsUnscopedAsUnscoped").toInt(), 1); +} + +void tst_qqmllanguage::enumStringToValue() +{ + QQmlEngine engine; + QUrl url(testFileUrl("EnumStringToValue.qml")); + QQmlComponent c(&engine, url); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + // QML + QCOMPARE(o->property("p1").toInt(), 1); + // CppEnum + QCOMPARE(o->property("p2").toInt(), (int)CppEnum::Scoped::S2); + QCOMPARE(o->property("p3").toInt(), (int)CppEnum::Unscoped::U2); + // EnumNamespace + QCOMPARE(o->property("p4").toInt(), (int)EnumNamespace::Scoped::S2); + QCOMPARE(o->property("p5").toInt(), (int)EnumNamespace::Unscoped::U2); + + + // Invalid arg + QCOMPARE(o->property("p7"), QVariant()); + QCOMPARE(o->property("p8"), QVariant()); + + // Conflicts + QCOMPARE(o->property("p9").toInt(), (int)ConflictingEnums::E1::A); + QCOMPARE(o->property("p10").toInt(), (int)ConflictingEnums::E2::A); +} + +void tst_qqmllanguage::enumValueToString() +{ + QQmlEngine engine; + QUrl url(testFileUrl("EnumValueToString.qml")); + QQmlComponent c(&engine, url); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + // QML + QCOMPARE(o->property("p1").toString(), "B"); + QCOMPARE(o->property("p2").toString(), "B"); + + // CppEnum + QCOMPARE(o->property("p3").toString(), "S2"); + QCOMPARE(o->property("p4").toString(), "S2"); + + QCOMPARE(o->property("p5").toString(), "U2"); + QCOMPARE(o->property("p6").toString(), "U2"); + + // EnumNamespace + QCOMPARE(o->property("p7").toString(), "S2"); + QCOMPARE(o->property("p8").toString(), "S2"); + + QCOMPARE(o->property("p9").toString(), "U2"); + QCOMPARE(o->property("p10").toString(), "U2"); + + + // Invalid arg + QCOMPARE(o->property("p11"), QVariant()); + QCOMPARE(o->property("p12"), QVariant()); + QCOMPARE(o->property("p13"), QVariant()); + + // Conflicts + QCOMPARE(o->property("p14"), QVariant("A")); + QCOMPARE(o->property("p15"), QVariant()); +} + +void tst_qqmllanguage::enumValueToStrings() +{ + QQmlEngine engine; + QUrl url(testFileUrl("EnumValueToStrings.qml")); + QQmlComponent c(&engine, url); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + // QML + QList l({ QVariant("A") }); + QCOMPARE(o->property("p1").toList(), l); + + l = QList({ QVariant("B"), QVariant("C") }); + QCOMPARE(o->property("p2").toList(), l); + + // CppEnum + l = QList({ QVariant("S1") }); + QCOMPARE(o->property("p3").toList(), l); + + l = QList({ QVariant("S3"), QVariant("S4") }); + QCOMPARE(o->property("p4").toList(), l); + + l = QList({ QVariant("U1") }); + QCOMPARE(o->property("p5").toList(), l); + + l = QList({ QVariant("U3"), QVariant("U4") }); + QCOMPARE(o->property("p6").toList(), l); + + // EnumNamespace + l = QList({ QVariant("S1") }); + QCOMPARE(o->property("p7").toList(), l); + + l = QList({ QVariant("S3"), QVariant("S4") }); + QCOMPARE(o->property("p8").toList(), l); + + l = QList({ QVariant("U1") }); + QCOMPARE(o->property("p9").toList(), l); + + l = QList({ QVariant("U3"), QVariant("U4") }); + QCOMPARE(o->property("p10").toList(), l); + + + // Invalid arg + QCOMPARE(o->property("p11"), QVariant()); + QCOMPARE(o->property("p12"), QVariant()); + + // Conflicts + l = QList({ QVariant("A") }); + QCOMPARE(o->property("p13").toList(), l); + QCOMPARE(o->property("p14"), QVariant()); +} + +void tst_qqmllanguage::propertyCycle() +{ + QQmlEngine engine; + + + QQmlComponent c1(&engine, testFileUrl("PropertyCycle1.qml")); + QVERIFY2(c1.isReady(), qPrintable(c1.errorString())); + QScopedPointer<QObject> o1(c1.create()); + QVERIFY(!o1.isNull()); + + const QVariant self1 = o1->property("self"); + QVERIFY(QByteArray(self1.metaType().name()).startsWith("PropertyCycle1_QMLTYPE_")); + QCOMPARE(self1.value<QObject *>(), nullptr); + o1->setProperty("self", QVariant::fromValue(o1.data())); + QCOMPARE(o1->property("self").value<QObject *>(), o1.data()); + + const QVariant cycle1 = o1->property("cycle"); + QVERIFY(QByteArray(cycle1.metaType().name()).startsWith("PropertyCycle2_QMLTYPE_")); + QCOMPARE(cycle1.value<QObject *>(), nullptr); + o1->setProperty("cycle", QVariant::fromValue(o1.data())); + QCOMPARE(o1->property("cycle").value<QObject *>(), nullptr); + + + QQmlComponent c2(&engine, testFileUrl("PropertyCycle2.qml")); + QVERIFY2(c2.isReady(), qPrintable(c2.errorString())); + QScopedPointer<QObject> o2(c2.create()); + QVERIFY(!o2.isNull()); + + const QVariant self2 = o2->property("self"); + QVERIFY(QByteArray(self2.metaType().name()).startsWith("PropertyCycle2_QMLTYPE_")); + QCOMPARE(self2.value<QObject *>(), nullptr); + o2->setProperty("self", QVariant::fromValue(o2.data())); + QCOMPARE(o2->property("self").value<QObject *>(), o2.data()); + + const QVariant cycle2 = o2->property("cycle"); + QVERIFY(QByteArray(cycle2.metaType().name()).startsWith("PropertyCycle1_QMLTYPE_")); + QCOMPARE(cycle2.value<QObject *>(), nullptr); + o2->setProperty("cycle", QVariant::fromValue(o2.data())); + QCOMPARE(o2->property("cycle").value<QObject *>(), nullptr); + + + + o1->setProperty("cycle", QVariant::fromValue(o2.data())); + QCOMPARE(o1->property("cycle").value<QObject *>(), o2.data()); + + o2->setProperty("cycle", QVariant::fromValue(o1.data())); + QCOMPARE(o2->property("cycle").value<QObject *>(), o1.data()); +} + +void tst_qqmllanguage::enumTypeAnnotations() +{ + QQmlEngine engine; + QUrl url(testFileUrl("EnumTypeAnnotations.qml")); + QQmlComponent c(&engine, url); + + const auto msg = [&](int line, int function, int param) { + auto where = param == -1 ? QStringLiteral("return type") + : QStringLiteral("parameter ") + QString::number(param); + auto msg = QStringLiteral(" Type annotation for %1 of function %2: Enumerations are not " + "types. Use underlying type (int or double) instead.") + .arg(where, "f"_L1 + QString::number(function)); + + return url.toString() + u':' + QString::number(line) + ":5:"_L1 + msg; + }; + + int ret = -1; + + QTest::ignoreMessage(QtWarningMsg, msg(7, 1, 0).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(8, 2, ret).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(9, 3, ret).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(9, 3, 0).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(10, 4, 1).toStdString().c_str()); + + QTest::ignoreMessage(QtWarningMsg, msg(12, 5, 0).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(13, 6, ret).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(14, 7, ret).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(14, 7, 0).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(15, 8, 1).toStdString().c_str()); + + QTest::ignoreMessage(QtWarningMsg, msg(17, 9, 0).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(18, 10, ret).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(19, 11, ret).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(19, 11, 0).toStdString().c_str()); + QTest::ignoreMessage(QtWarningMsg, msg(20, 12, 1).toStdString().c_str()); + + QTest::ignoreMessage(QtWarningMsg, msg(22, 13, 0).toStdString().c_str()); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); +} + +void tst_qqmllanguage::assignWrongTypeToObjectList() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("assignWrongTypeToObjectList.qml")); + QVERIFY(!component.isReady()); + QVERIFY(QRegularExpression(".*Cannot assign object of type \"QQuickFrameAnimation\""_L1 + + " to list property \"animations\"; expected \"QQuickAbstractAnimation\""_L1).match(component.errorString()).hasMatch()); +} + +class VariantAssociationContainer : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariant variantobj MEMBER m_qvariant) +public: + VariantAssociationContainer() + : m_qvariant(QVariantMap{{"key1", "value1"}, {"key2", "value2"}}) + {} +private: + QVariant m_qvariant; +}; + +void tst_qqmllanguage::variantAssociationHasOwnProperty() +{ + QJSEngine engine; + VariantAssociationContainer obj; + engine.globalObject().setProperty("qobject", engine.newQObject(&obj)); + QCOMPARE(engine.evaluate("typeof qobject.variantobj").toString(), "object"); + QCOMPARE(engine.evaluate("qobject.variantobj.key1").toString(), "value1"); + QCOMPARE(engine.evaluate("qobject.variantobj.key2").toString(), "value2"); + QCOMPARE(engine.evaluate("typeof qobject.variantobj.hasOwnProperty").toString(), "function"); + QVERIFY(engine.evaluate("qobject.variantobj.hasOwnProperty('key1')").toBool()); + QVERIFY(!engine.evaluate("qobject.variantobj.hasOwnProperty('key3')").toBool()); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" |