diff options
Diffstat (limited to 'tests/auto/qml/qjsengine/tst_qjsengine.cpp')
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 208 |
1 files changed, 187 insertions, 21 deletions
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 75fa2216f7..9c3316e39f 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -66,6 +66,10 @@ private slots: void newArray(); void newArray_HooliganTask218092(); void newArray_HooliganTask233836(); + void toScriptValue_data(); + void toScriptValue(); + void toScriptValuenotroundtripped_data(); + void toScriptValuenotroundtripped(); void newVariant(); void newVariant_valueOfToString(); void newVariant_valueOfEnum(); @@ -94,6 +98,7 @@ private slots: void valueConversion_basic2(); void valueConversion_dateTime(); void valueConversion_regExp(); + void valueConversion_RegularExpression(); void castWithMultipleInheritance(); void collectGarbage(); void gcWithNestedDataStructure(); @@ -135,6 +140,8 @@ private slots: void qRegExpInport_data(); void qRegExpInport(); + void qRegularExpressionImport_data(); + void qRegularExpressionImport(); void dateRoundtripJSQtJS(); void dateRoundtripQtJSQt(); void dateConversionJSQt(); @@ -481,17 +488,97 @@ void tst_QJSEngine::newArray_HooliganTask233836() } } +void tst_QJSEngine::toScriptValue_data() +{ + QTest::addColumn<QVariant>("input"); + + QTest::newRow("UnknownType") << QVariant(int(QMetaType::UnknownType), nullptr); + QTest::newRow("Nullptr") << QVariant(int(QMetaType::Nullptr), nullptr); + QTest::newRow("true") << QVariant(true); + QTest::newRow("false") << QVariant(false); + QTest::newRow("int") << QVariant(int(42)); + QTest::newRow("uint") << QVariant(uint(42)); + QTest::newRow("longlong") << QVariant(qlonglong(4242)); + QTest::newRow("ulonglong") << QVariant(qulonglong(4242)); + QTest::newRow("double") << QVariant(double(42.42)); + QTest::newRow("float") << QVariant(float(42.42)); + QTest::newRow("qstring") << QVariant(QString::fromLatin1("hello")); + QTest::newRow("qbytearray") << QVariant(QByteArray("hello")); + QTest::newRow("short") << QVariant(short('r')); + QTest::newRow("ushort") << QVariant(short('b')); + QTest::newRow("char") << QVariant(char('r')); + QTest::newRow("uchar") << QVariant(uchar('b')); + QTest::newRow("qchar") << QVariant(QString::fromUtf8("å").at(0)); + QTest::newRow("qdate") << QVariant(QDate(1925, 5, 8)); + QTest::newRow("qtime") << QVariant(QTime(4, 5, 6)); + QTest::newRow("qregularexpression") << QVariant(QRegularExpression(".*")); + QTest::newRow("qpointf") << QVariant(QPointF(42, 24)); + QTest::newRow("qvariantlist") << QVariant(QVariantList() << 42.24 << 5 << "hello"); + QTest::newRow("qvariantlist_point") << QVariant(QVariantList() << 42.24 << QPointF(42.24, 24.42) << QPointF(24.42, 42.24)); + QVariantMap vm; vm.insert("test", 55); vm.insert("abc", 42.42);; + QTest::newRow("qvariantmap") << QVariant(vm); + vm.clear(); vm.insert("point1", QPointF(42.24, 24.42)); vm.insert("point2", QPointF(42.24, 24.42)); + QTest::newRow("qvariantmap_point") << QVariant(vm); + QTest::newRow("qvariant") << QVariant(QVariant(42)); + QTest::newRow("QList<int>") << QVariant::fromValue(QList<int>() << 1 << 2 << 3 << 4); + QTest::newRow("QVector<int>") << QVariant::fromValue(QVector<int>() << 1 << 2 << 3 << 4); + QTest::newRow("QList<QString>") << QVariant::fromValue(QVector<QString>() << "1" << "2" << "3" << "4"); + QTest::newRow("QStringList") << QVariant::fromValue(QStringList() << "1" << "2" << "3" << "4"); + QTest::newRow("QMap<QString, QString>") << QVariant::fromValue(QMap<QString, QString>{{ "1", "2" }, { "3", "4" }}); + QTest::newRow("QHash<QString, QString>") << QVariant::fromValue(QHash<QString, QString>{{ "1", "2" }, { "3", "4" }}); + QTest::newRow("QMap<QString, QPointF>") << QVariant::fromValue(QMap<QString, QPointF>{{ "1", { 42.24, 24.42 } }, { "3", { 24.42, 42.24 } }}); + QTest::newRow("QHash<QString, QPointF>") << QVariant::fromValue(QHash<QString, QPointF>{{ "1", { 42.24, 24.42 } }, { "3", { 24.42, 42.24 } }}); +} + +void tst_QJSEngine::toScriptValue() +{ + QFETCH(QVariant, input); + + QJSEngine engine; + QJSValue outputJS = engine.toScriptValue(input); + QVariant output = engine.fromScriptValue<QVariant>(outputJS); + + QCOMPARE(input, output); +} + +void tst_QJSEngine::toScriptValuenotroundtripped_data() +{ + QTest::addColumn<QVariant>("input"); + QTest::addColumn<QVariant>("output"); + + QTest::newRow("QList<QObject*>") << QVariant::fromValue(QList<QObject*>() << this) << QVariant(QVariantList() << QVariant::fromValue(this)); + QTest::newRow("QObjectList") << QVariant::fromValue(QObjectList() << this) << QVariant(QVariantList() << QVariant::fromValue(this)); + QTest::newRow("QList<QPoint>") << QVariant::fromValue(QList<QPointF>() << QPointF(42.24, 24.42) << QPointF(42.24, 24.42)) << QVariant(QVariantList() << QPointF(42.24, 24.42) << QPointF(42.24, 24.42)); + QTest::newRow("QVector<QPoint>") << QVariant::fromValue(QVector<QPointF>() << QPointF(42.24, 24.42) << QPointF(42.24, 24.42)) << QVariant(QVariantList() << QPointF(42.24, 24.42) << QPointF(42.24, 24.42)); + QTest::newRow("VoidStar") << QVariant(int(QMetaType::VoidStar), nullptr) << QVariant(int(QMetaType::Nullptr), nullptr); + QTest::newRow("qregex") << QVariant(QRegExp(".*", Qt::CaseSensitive, QRegExp::RegExp2)) << QVariant(QRegularExpression(".*")); +} + +// This is almost the same as toScriptValue, but the inputs don't roundtrip to +// exactly the same value. +void tst_QJSEngine::toScriptValuenotroundtripped() +{ + QFETCH(QVariant, input); + QFETCH(QVariant, output); + + QJSEngine engine; + QJSValue outputJS = engine.toScriptValue(input); + QVariant actualOutput = engine.fromScriptValue<QVariant>(outputJS); + + QCOMPARE(actualOutput, output); +} + void tst_QJSEngine::newVariant() { QJSEngine eng; { QJSValue opaque = eng.toScriptValue(QVariant(QPoint(1, 2))); QVERIFY(!opaque.isUndefined()); - QCOMPARE(opaque.isVariant(), true); + QCOMPARE(opaque.isVariant(), false); QVERIFY(!opaque.isCallable()); QCOMPARE(opaque.isObject(), true); QVERIFY(!opaque.prototype().isUndefined()); - QCOMPARE(opaque.prototype().isVariant(), true); + QCOMPARE(opaque.prototype().isVariant(), false); QVERIFY(opaque.property("valueOf").callWithInstance(opaque).equals(opaque)); } } @@ -505,7 +592,7 @@ void tst_QJSEngine::newVariant_valueOfToString() QJSValue value = object.property("valueOf").callWithInstance(object); QVERIFY(value.isObject()); QVERIFY(value.strictlyEquals(object)); - QCOMPARE(object.toString(), QString::fromLatin1("QVariant(QPoint, QPoint(10,20))")); + QCOMPARE(object.toString(), QString::fromLatin1("QPoint(10, 20)")); } } @@ -523,22 +610,27 @@ void tst_QJSEngine::newVariant_valueOfEnum() void tst_QJSEngine::newRegExp() { QJSEngine eng; - QJSValue rexp = eng.toScriptValue(QRegExp("foo")); - QVERIFY(!rexp.isUndefined()); - QCOMPARE(rexp.isRegExp(), true); - QCOMPARE(rexp.isObject(), true); - QCOMPARE(rexp.isCallable(), false); - // prototype should be RegExp.prototype - QVERIFY(!rexp.prototype().isUndefined()); - QCOMPARE(rexp.prototype().isObject(), true); - // Get [[Class]] internal property of RegExp Prototype Object. - // See ECMA-262 Section 8.6.2, "Object Internal Properties and Methods". - // See ECMA-262 Section 15.10.6, "Properties of the RegExp Prototype Object". - QJSValue r = eng.evaluate("Object.prototype.toString.call(RegExp.prototype)"); - QCOMPARE(r.toString(), QString::fromLatin1("[object Object]")); - QCOMPARE(rexp.prototype().strictlyEquals(eng.evaluate("RegExp.prototype")), true); + QJSValue rexps[] = { + eng.toScriptValue(QRegularExpression("foo")), + eng.toScriptValue(QRegExp("foo")) + }; + for (const auto &rexp : rexps) { + QVERIFY(!rexp.isUndefined()); + QCOMPARE(rexp.isRegExp(), true); + QCOMPARE(rexp.isObject(), true); + QCOMPARE(rexp.isCallable(), false); + // prototype should be RegExp.prototype + QVERIFY(!rexp.prototype().isUndefined()); + QCOMPARE(rexp.prototype().isObject(), true); + // Get [[Class]] internal property of RegExp Prototype Object. + // See ECMA-262 Section 8.6.2, "Object Internal Properties and Methods". + // See ECMA-262 Section 15.10.6, "Properties of the RegExp Prototype Object". + QJSValue r = eng.evaluate("Object.prototype.toString.call(RegExp.prototype)"); + QCOMPARE(r.toString(), QString::fromLatin1("[object Object]")); + QCOMPARE(rexp.prototype().strictlyEquals(eng.evaluate("RegExp.prototype")), true); - QCOMPARE(qjsvalue_cast<QRegExp>(rexp).pattern(), QRegExp("foo").pattern()); + QCOMPARE(qjsvalue_cast<QRegExp>(rexp).pattern(), QRegExp("foo").pattern()); + } } void tst_QJSEngine::jsRegExp() @@ -1490,15 +1582,15 @@ void tst_QJSEngine::valueConversion_QVariant() QCOMPARE(val.toString(), str); } { - QJSValue val = eng.toScriptValue(qVariantFromValue((QObject*)this)); + QJSValue val = eng.toScriptValue(QVariant::fromValue((QObject*)this)); QVERIFY(!val.isVariant()); QVERIFY(val.isQObject()); QCOMPARE(val.toQObject(), (QObject*)this); } { - QVariant var = qVariantFromValue(QPoint(123, 456)); + QVariant var = QVariant::fromValue(QPoint(123, 456)); QJSValue val = eng.toScriptValue(var); - QVERIFY(val.isVariant()); + QVERIFY(!val.isVariant()); QCOMPARE(val.toVariant(), var); } @@ -1604,6 +1696,28 @@ void tst_QJSEngine::valueConversion_regExp() } } +void tst_QJSEngine::valueConversion_RegularExpression() +{ + QJSEngine eng; + { + QRegularExpression in = QRegularExpression("foo"); + QJSValue val = eng.toScriptValue(in); + QVERIFY(val.isRegExp()); + QRegularExpression out = qjsvalue_cast<QRegularExpression>(val); + QCOMPARE(out.pattern(), in.pattern()); + QCOMPARE(out.patternOptions(), in.patternOptions()); + } + { + QRegularExpression in = QRegularExpression("foo", + QRegularExpression::CaseInsensitiveOption); + QJSValue val = eng.toScriptValue(in); + QVERIFY(val.isRegExp()); + QCOMPARE(qjsvalue_cast<QRegularExpression>(val), in); + QRegularExpression out = qjsvalue_cast<QRegularExpression>(val); + QCOMPARE(out.patternOptions(), in.patternOptions()); + } +} + Q_DECLARE_METATYPE(QGradient) Q_DECLARE_METATYPE(QGradient*) Q_DECLARE_METATYPE(QLinearGradient) @@ -2953,6 +3067,8 @@ void tst_QJSEngine::reentrancy_objectCreation() QJSValue r2 = eng2.evaluate("new RegExp('foo', 'gim')"); QCOMPARE(qjsvalue_cast<QRegExp>(r1), qjsvalue_cast<QRegExp>(r2)); QCOMPARE(qjsvalue_cast<QRegExp>(r2), qjsvalue_cast<QRegExp>(r1)); + QCOMPARE(qjsvalue_cast<QRegularExpression>(r1), qjsvalue_cast<QRegularExpression>(r2)); + QCOMPARE(qjsvalue_cast<QRegularExpression>(r2), qjsvalue_cast<QRegularExpression>(r1)); } { QJSValue o1 = eng1.newQObject(temp); @@ -3148,6 +3264,56 @@ void tst_QJSEngine::qRegExpInport() } } +void tst_QJSEngine::qRegularExpressionImport_data() +{ + QTest::addColumn<QRegularExpression>("rx"); + QTest::addColumn<QString>("string"); + QTest::addColumn<QString>("matched"); + + QTest::newRow("normal") << QRegularExpression("(test|foo)") << "test _ foo _ test _ Foo"; + QTest::newRow("normal2") << QRegularExpression("(Test|Foo)") << "test _ foo _ test _ Foo"; + QTest::newRow("case insensitive") << QRegularExpression("(test|foo)", QRegularExpression::CaseInsensitiveOption) << "test _ foo _ test _ Foo"; + QTest::newRow("case insensitive2") << QRegularExpression("(Test|Foo)", QRegularExpression::CaseInsensitiveOption) << "test _ foo _ test _ Foo"; + QTest::newRow("b(a*)(b*)") << QRegularExpression("b(a*)(b*)", QRegularExpression::CaseInsensitiveOption) << "aaabbBbaAabaAaababaaabbaaab"; + QTest::newRow("greedy") << QRegularExpression("a*(a*)", QRegularExpression::CaseInsensitiveOption) << "aaaabaaba"; + QTest::newRow("wildcard") << QRegularExpression(".*\\.txt") << "file.txt"; + QTest::newRow("wildcard 2") << QRegularExpression("a.b\\.txt") << "ab.txt abb.rtc acb.txt"; + QTest::newRow("slash") << QRegularExpression("g/.*/s", QRegularExpression::CaseInsensitiveOption) << "string/string/string"; + QTest::newRow("slash2") << QRegularExpression("g / .* / s", QRegularExpression::CaseInsensitiveOption) << "string / string / string"; + QTest::newRow("fixed") << QRegularExpression("a\\*aa\\.a\\(ba\\)\\*a\\\\ba", QRegularExpression::CaseInsensitiveOption) << "aa*aa.a(ba)*a\\ba"; + QTest::newRow("fixed insensitive") << QRegularExpression("A\\*A", QRegularExpression::CaseInsensitiveOption) << "a*A A*a A*A a*a"; + QTest::newRow("fixed sensitive") << QRegularExpression("A\\*A") << "a*A A*a A*A a*a"; + QTest::newRow("html") << QRegularExpression("<b>(.*)</b>") << "<b>bold</b><i>italic</i><b>bold</b>"; + QTest::newRow("html minimal") << QRegularExpression("^<b>(.*)</b>$") << "<b>bold</b><i>italic</i><b>bold</b>"; + QTest::newRow("aaa") << QRegularExpression("a{2,5}") << "aAaAaaaaaAa"; + QTest::newRow("aaa minimal") << QRegularExpression("^a{2,5}$") << "aAaAaaaaaAa"; + QTest::newRow("minimal") << QRegularExpression("^.*\\} [*8]$") << "}?} ?} *"; + QTest::newRow(".? minimal") << QRegularExpression("^.?$") << ".?"; + QTest::newRow(".+ minimal") << QRegularExpression("^.+$") << ".+"; + QTest::newRow("[.?] minimal") << QRegularExpression("^[.?]$") << ".?"; + QTest::newRow("[.+] minimal") << QRegularExpression("^[.+]$") << ".+"; +} + +void tst_QJSEngine::qRegularExpressionImport() +{ + QFETCH(QRegularExpression, rx); + QFETCH(QString, string); + + QJSEngine eng; + QJSValue rexp; + rexp = eng.toScriptValue(rx); + + QCOMPARE(rexp.isRegExp(), true); + QCOMPARE(rexp.isCallable(), false); + + QJSValue func = eng.evaluate("(function(string, regexp) { return string.match(regexp); })"); + QJSValue result = func.call(QJSValueList() << string << rexp); + + const QRegularExpressionMatch match = rx.match(string); + for (int i = 0; i <= match.lastCapturedIndex(); i++) + QCOMPARE(result.property(i).toString(), match.captured(i)); +} + // QScriptValue::toDateTime() returns a local time, whereas JS dates // are always stored as UTC. Qt Script must respect the current time // zone, and correctly adjust for daylight saving time that may be in |