| /**************************************************************************** |
| ** |
| ** Copyright (C) 2018 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/QtTest> |
| |
| #include <QtScript/qscriptcontextinfo.h> |
| #include <QtScript/qscriptcontext.h> |
| #include <QtScript/qscriptengine.h> |
| #include <QtScript/qscriptable.h> |
| #include <QtScript/qscriptengineagent.h> |
| |
| Q_DECLARE_METATYPE(QScriptValue) |
| Q_DECLARE_METATYPE(QScriptContextInfo) |
| Q_DECLARE_METATYPE(QList<QScriptContextInfo>) |
| |
| class tst_QScriptContextInfo : public QObject, public QScriptable |
| { |
| Q_OBJECT |
| Q_PROPERTY(QScriptValue testProperty READ testProperty WRITE setTestProperty) |
| public: |
| tst_QScriptContextInfo(); |
| virtual ~tst_QScriptContextInfo(); |
| |
| QScriptValue testProperty() const |
| { |
| return engine()->globalObject().property("getContextInfoList").call(); |
| } |
| |
| QScriptValue setTestProperty(const QScriptValue &) const |
| { |
| return engine()->globalObject().property("getContextInfoList").call(); |
| } |
| |
| public slots: |
| QScriptValue testSlot(double a, double b) |
| { |
| Q_UNUSED(a); Q_UNUSED(b); |
| return engine()->globalObject().property("getContextInfoList").call(); |
| } |
| |
| QScriptValue testSlot(const QString &s) |
| { |
| Q_UNUSED(s); |
| return engine()->globalObject().property("getContextInfoList").call(); |
| } |
| |
| private slots: |
| void nativeFunction(); |
| void scriptFunction(); |
| void qtFunction(); |
| void qtPropertyFunction(); |
| void nullContext(); |
| void streaming(); |
| void comparison_null(); |
| void assignmentAndComparison(); |
| }; |
| |
| tst_QScriptContextInfo::tst_QScriptContextInfo() |
| { |
| } |
| |
| tst_QScriptContextInfo::~tst_QScriptContextInfo() |
| { |
| } |
| |
| static QScriptValue getContextInfoList(QScriptContext *ctx, QScriptEngine *eng) |
| { |
| QList<QScriptContextInfo> lst; |
| while (ctx) { |
| QScriptContextInfo info(ctx); |
| lst.append(info); |
| ctx = ctx->parentContext(); |
| } |
| return qScriptValueFromValue(eng, lst); |
| } |
| |
| void tst_QScriptContextInfo::nativeFunction() |
| { |
| QScriptEngine eng; |
| eng.globalObject().setProperty("getContextInfoList", eng.newFunction(getContextInfoList)); |
| |
| QString fileName = "foo.qs"; |
| int lineNumber = 123; |
| QScriptValue ret = eng.evaluate("getContextInfoList()", fileName, lineNumber); |
| QList<QScriptContextInfo> lst = qscriptvalue_cast<QList<QScriptContextInfo> >(ret); |
| QCOMPARE(lst.size(), 2); |
| |
| { |
| // getContextInfoList() |
| QScriptContextInfo info = lst.at(0); |
| QVERIFY(!info.isNull()); |
| QCOMPARE(info.functionType(), QScriptContextInfo::NativeFunction); |
| QCOMPARE(info.scriptId(), (qint64)-1); |
| QCOMPARE(info.fileName(), QString()); |
| QCOMPARE(info.lineNumber(), -1); |
| QCOMPARE(info.columnNumber(), -1); |
| QCOMPARE(info.functionName(), QString()); |
| QCOMPARE(info.functionEndLineNumber(), -1); |
| QCOMPARE(info.functionStartLineNumber(), -1); |
| QCOMPARE(info.functionParameterNames().size(), 0); |
| QCOMPARE(info.functionMetaIndex(), -1); |
| } |
| |
| { |
| // evaluate() |
| QScriptContextInfo info = lst.at(1); |
| QVERIFY(!info.isNull()); |
| QCOMPARE(info.functionType(), QScriptContextInfo::NativeFunction); |
| QVERIFY(info.scriptId() != -1); |
| QCOMPARE(info.fileName(), fileName); |
| QCOMPARE(info.lineNumber(), lineNumber); |
| QEXPECT_FAIL("", "QTBUG-17602: columnNumber doesn't work", Continue); |
| QCOMPARE(info.columnNumber(), 1); |
| QCOMPARE(info.functionName(), QString()); |
| QCOMPARE(info.functionEndLineNumber(), -1); |
| QCOMPARE(info.functionStartLineNumber(), -1); |
| QCOMPARE(info.functionParameterNames().size(), 0); |
| QCOMPARE(info.functionMetaIndex(), -1); |
| } |
| } |
| |
| void tst_QScriptContextInfo::scriptFunction() |
| { |
| QScriptEngine eng; |
| eng.globalObject().setProperty("getContextInfoList", eng.newFunction(getContextInfoList)); |
| |
| QString fileName = "ciao.qs"; |
| int lineNumber = 456; |
| QScriptValue ret = eng.evaluate("function bar(a, b, c) {\n return getContextInfoList();\n}\nbar()", |
| fileName, lineNumber); |
| QList<QScriptContextInfo> lst = qscriptvalue_cast<QList<QScriptContextInfo> >(ret); |
| QCOMPARE(lst.size(), 3); |
| |
| // getContextInfoList() |
| QCOMPARE(lst.at(0).functionType(), QScriptContextInfo::NativeFunction); |
| |
| { |
| // bar() |
| QScriptContextInfo info = lst.at(1); |
| QCOMPARE(info.functionType(), QScriptContextInfo::ScriptFunction); |
| QVERIFY(info.scriptId() != -1); |
| QCOMPARE(info.fileName(), fileName); |
| QCOMPARE(info.lineNumber(), lineNumber + 1); |
| QEXPECT_FAIL("", "QTBUG-17602: columnNumber doesn't work", Continue); |
| QCOMPARE(info.columnNumber(), 2); |
| QCOMPARE(info.functionName(), QString::fromLatin1("bar")); |
| QCOMPARE(info.functionStartLineNumber(), lineNumber); |
| QCOMPARE(info.functionEndLineNumber(), lineNumber + 2); |
| QCOMPARE(info.functionParameterNames().size(), 3); |
| QCOMPARE(info.functionParameterNames().at(0), QString::fromLatin1("a")); |
| QCOMPARE(info.functionParameterNames().at(1), QString::fromLatin1("b")); |
| QCOMPARE(info.functionParameterNames().at(2), QString::fromLatin1("c")); |
| QCOMPARE(info.functionMetaIndex(), -1); |
| } |
| |
| { |
| // evaluate() |
| QScriptContextInfo info = lst.at(2); |
| QCOMPARE(info.functionType(), QScriptContextInfo::NativeFunction); |
| QVERIFY(info.scriptId() != -1); |
| QCOMPARE(info.fileName(), fileName); |
| QCOMPARE(info.lineNumber(), lineNumber + 3); |
| QEXPECT_FAIL("", "QTBUG-17602: columnNumber doesn't work", Continue); |
| QCOMPARE(info.columnNumber(), 1); |
| QCOMPARE(info.functionName(), QString()); |
| QCOMPARE(info.functionEndLineNumber(), -1); |
| QCOMPARE(info.functionStartLineNumber(), -1); |
| QCOMPARE(info.functionParameterNames().size(), 0); |
| QCOMPARE(info.functionMetaIndex(), -1); |
| } |
| } |
| |
| void tst_QScriptContextInfo::qtFunction() |
| { |
| QScriptEngine eng; |
| eng.globalObject().setProperty("getContextInfoList", eng.newFunction(getContextInfoList)); |
| eng.globalObject().setProperty("qobj", eng.newQObject(this)); |
| |
| for (int x = 0; x < 2; ++x) { // twice to test overloaded slot as well |
| QString code; |
| const char *sig; |
| QStringList pnames; |
| if (x == 0) { |
| code = "qobj.testSlot(1, 2)"; |
| sig = "testSlot(double,double)"; |
| pnames << "a" << "b"; |
| } else { |
| code = "qobj.testSlot('ciao')"; |
| sig = "testSlot(QString)"; |
| pnames << "s"; |
| } |
| QScriptValue ret = eng.evaluate(code); |
| QList<QScriptContextInfo> lst = qscriptvalue_cast<QList<QScriptContextInfo> >(ret); |
| QCOMPARE(lst.size(), 3); |
| |
| // getContextInfoList() |
| QCOMPARE(lst.at(0).functionType(), QScriptContextInfo::NativeFunction); |
| |
| { |
| // testSlot(double a, double b) |
| QScriptContextInfo info = lst.at(1); |
| QCOMPARE(info.functionType(), QScriptContextInfo::QtFunction); |
| QCOMPARE(info.scriptId(), (qint64)-1); |
| QCOMPARE(info.fileName(), QString()); |
| QCOMPARE(info.lineNumber(), -1); |
| QCOMPARE(info.columnNumber(), -1); |
| QCOMPARE(info.functionName(), QString::fromLatin1("testSlot")); |
| QCOMPARE(info.functionEndLineNumber(), -1); |
| QCOMPARE(info.functionStartLineNumber(), -1); |
| QCOMPARE(info.functionParameterNames().size(), pnames.size()); |
| QCOMPARE(info.functionParameterNames(), pnames); |
| QCOMPARE(info.functionMetaIndex(), metaObject()->indexOfMethod(sig)); |
| } |
| |
| // evaluate() |
| QCOMPARE(lst.at(0).functionType(), QScriptContextInfo::NativeFunction); |
| } |
| } |
| |
| void tst_QScriptContextInfo::qtPropertyFunction() |
| { |
| QScriptEngine eng; |
| eng.globalObject().setProperty("getContextInfoList", eng.newFunction(getContextInfoList)); |
| eng.globalObject().setProperty("qobj", eng.newQObject(this)); |
| |
| QScriptValue ret = eng.evaluate("qobj.testProperty"); |
| QList<QScriptContextInfo> lst = qscriptvalue_cast<QList<QScriptContextInfo> >(ret); |
| QCOMPARE(lst.size(), 3); |
| |
| // getContextInfoList() |
| QCOMPARE(lst.at(0).functionType(), QScriptContextInfo::NativeFunction); |
| |
| { |
| // testProperty() |
| QScriptContextInfo info = lst.at(1); |
| QCOMPARE(info.functionType(), QScriptContextInfo::QtPropertyFunction); |
| QCOMPARE(info.scriptId(), (qint64)-1); |
| QCOMPARE(info.fileName(), QString()); |
| QCOMPARE(info.lineNumber(), -1); |
| QCOMPARE(info.columnNumber(), -1); |
| QCOMPARE(info.functionName(), QString::fromLatin1("testProperty")); |
| QCOMPARE(info.functionEndLineNumber(), -1); |
| QCOMPARE(info.functionStartLineNumber(), -1); |
| QCOMPARE(info.functionParameterNames().size(), 0); |
| QCOMPARE(info.functionMetaIndex(), metaObject()->indexOfProperty("testProperty")); |
| } |
| |
| // evaluate() |
| QCOMPARE(lst.at(0).functionType(), QScriptContextInfo::NativeFunction); |
| } |
| |
| void tst_QScriptContextInfo::nullContext() |
| { |
| QScriptContextInfo info((QScriptContext*)0); |
| QVERIFY(info.isNull()); |
| QCOMPARE(info.columnNumber(), -1); |
| QCOMPARE(info.scriptId(), (qint64)-1); |
| QCOMPARE(info.fileName(), QString()); |
| QCOMPARE(info.functionEndLineNumber(), -1); |
| QCOMPARE(info.functionMetaIndex(), -1); |
| QCOMPARE(info.functionName(), QString()); |
| QCOMPARE(info.functionParameterNames().size(), 0); |
| QCOMPARE(info.functionStartLineNumber(), -1); |
| QCOMPARE(info.functionType(), QScriptContextInfo::NativeFunction); |
| } |
| |
| void tst_QScriptContextInfo::streaming() |
| { |
| { |
| QScriptContextInfo info((QScriptContext*)0); |
| QByteArray ba; |
| QDataStream stream(&ba, QIODevice::ReadWrite); |
| stream << info; |
| stream.device()->seek(0); |
| QScriptContextInfo info2; |
| stream >> info2; |
| QVERIFY(stream.device()->atEnd()); |
| QCOMPARE(info.functionType(), info2.functionType()); |
| QCOMPARE(info.scriptId(), info2.scriptId()); |
| QCOMPARE(info.fileName(), info2.fileName()); |
| QCOMPARE(info.lineNumber(), info2.lineNumber()); |
| QCOMPARE(info.columnNumber(), info2.columnNumber()); |
| QCOMPARE(info.functionName(), info2.functionName()); |
| QCOMPARE(info.functionEndLineNumber(), info2.functionEndLineNumber()); |
| QCOMPARE(info.functionStartLineNumber(), info2.functionStartLineNumber()); |
| QCOMPARE(info.functionParameterNames(), info2.functionParameterNames()); |
| QCOMPARE(info.functionMetaIndex(), info2.functionMetaIndex()); |
| } |
| { |
| QScriptEngine eng; |
| eng.globalObject().setProperty("getContextInfoList", eng.newFunction(getContextInfoList)); |
| |
| QString fileName = "ciao.qs"; |
| int lineNumber = 456; |
| QScriptValue ret = eng.evaluate("function bar(a, b, c) {\n return getContextInfoList();\n}\nbar()", |
| fileName, lineNumber); |
| QList<QScriptContextInfo> lst = qscriptvalue_cast<QList<QScriptContextInfo> >(ret); |
| QCOMPARE(lst.size(), 3); |
| for (int i = 0; i < lst.size(); ++i) { |
| const QScriptContextInfo &info = lst.at(i); |
| QByteArray ba; |
| QDataStream stream(&ba, QIODevice::ReadWrite); |
| stream << info; |
| stream.device()->seek(0); |
| QScriptContextInfo info2; |
| stream >> info2; |
| QVERIFY(stream.device()->atEnd()); |
| QCOMPARE(info.functionType(), info2.functionType()); |
| QCOMPARE(info.scriptId(), info2.scriptId()); |
| QCOMPARE(info.fileName(), info2.fileName()); |
| QCOMPARE(info.lineNumber(), info2.lineNumber()); |
| QCOMPARE(info.columnNumber(), info2.columnNumber()); |
| QCOMPARE(info.functionName(), info2.functionName()); |
| QCOMPARE(info.functionEndLineNumber(), info2.functionEndLineNumber()); |
| QCOMPARE(info.functionStartLineNumber(), info2.functionStartLineNumber()); |
| QCOMPARE(info.functionParameterNames(), info2.functionParameterNames()); |
| QCOMPARE(info.functionMetaIndex(), info2.functionMetaIndex()); |
| } |
| } |
| } |
| |
| void tst_QScriptContextInfo::comparison_null() |
| { |
| QScriptContextInfo info1, info2, info3(0); |
| QCOMPARE(info1, info2); |
| QCOMPARE(info1, info3); |
| } |
| |
| void tst_QScriptContextInfo::assignmentAndComparison() |
| { |
| QScriptEngine eng; |
| eng.globalObject().setProperty("getContextInfoList", eng.newFunction(getContextInfoList)); |
| QString fileName = "ciao.qs"; |
| int lineNumber = 456; |
| QScriptValue ret = eng.evaluate("function bar(a, b, c) {\n return getContextInfoList();\n}\nbar()", |
| fileName, lineNumber); |
| QList<QScriptContextInfo> lst = qscriptvalue_cast<QList<QScriptContextInfo> >(ret); |
| QCOMPARE(lst.size(), 3); |
| QScriptContextInfo ci = lst.at(0); |
| QScriptContextInfo same = ci; |
| QVERIFY(ci == same); |
| QVERIFY(!(ci != same)); |
| QScriptContextInfo other = lst.at(1); |
| QVERIFY(!(ci == other)); |
| QVERIFY(ci != other); |
| } |
| |
| QTEST_MAIN(tst_QScriptContextInfo) |
| #include "tst_qscriptcontextinfo.moc" |