blob: 32b861a3682d516c10f40f2ea6a672fe2af18fcc [file] [log] [blame]
/****************************************************************************
**
** 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"