summaryrefslogtreecommitdiffstats
path: root/old/interpreter/qscriptsystemtest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'old/interpreter/qscriptsystemtest.cpp')
-rw-r--r--old/interpreter/qscriptsystemtest.cpp838
1 files changed, 838 insertions, 0 deletions
diff --git a/old/interpreter/qscriptsystemtest.cpp b/old/interpreter/qscriptsystemtest.cpp
new file mode 100644
index 0000000..641bfb4
--- /dev/null
+++ b/old/interpreter/qscriptsystemtest.cpp
@@ -0,0 +1,838 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of QtUiTest.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptsystemtest.h"
+#include "scriptpreprocessor.h"
+
+#include <QScriptEngine>
+#include <QScriptValue>
+#include <QScriptValueIterator>
+#include <QScriptContextInfo>
+
+//#include <qtestprotocol_p.h>
+#include <qtestide.h>
+#include <QtTest/QtTest>
+
+#include "qtscript_bindings.h"
+#include "qtuitestengineagent.h"
+
+#include <QDebug>
+
+QStringList builtins;
+
+Q_DECLARE_METATYPE(QVariant)
+Q_DECLARE_METATYPE(QList<qint64>)
+
+template <typename Tp>
+QScriptValue qScriptValueFromQObject(QScriptEngine *engine, Tp const &qobject)
+{
+ return engine->newQObject(qobject, QScriptEngine::AutoOwnership);
+}
+
+template <typename Tp>
+void qScriptValueToQObject(const QScriptValue &value, Tp &qobject)
+{ qobject = qobject_cast<Tp>(value.toQObject());
+}
+
+template <typename Tp>
+int qScriptRegisterQObjectMetaType(
+ QScriptEngine *engine,
+ const QScriptValue &prototype = QScriptValue(),
+ Tp * /* dummy */ = 0
+ )
+{
+ return qScriptRegisterMetaType<Tp>(engine, qScriptValueFromQObject,
+ qScriptValueToQObject, prototype);
+}
+
+void setupEnums(QScriptEngine *engine) {
+ QScriptValue qsvObject = engine->newObject();
+#define S(val) qsvObject.setProperty(#val, engine->toScriptValue((int)QScriptValue::val));
+ S(PropertySetter);S(ReadOnly);S(Undeletable);S(SkipInEnumeration);
+ S(PropertyGetter);S(QObjectMember);S(KeepExistingFlags);S(UserRange);
+#undef S
+ engine->globalObject().setProperty("QScriptValue", qsvObject );
+}
+
+static QScriptValue dateToString(QScriptContext *ctx, QScriptEngine *eng)
+{
+ QDateTime dt = ctx->thisObject().toDateTime();
+ QString fmt = ctx->argument(0).toString();
+
+ return eng->toScriptValue(dt.toString(fmt));
+}
+
+static QString findIncludeScript(const QString& name)
+{
+ QList<QDir> includeDirs;
+ foreach (QByteArray const& split, qgetenv("QTUITEST_INCLUDE_PATH").split(':')) {
+ if (split.isEmpty()) continue;
+ QDir dir(split);
+ if (dir.exists()) includeDirs << dir;
+ }
+
+ foreach (QDir const& dir, includeDirs) {
+ QString file = dir.canonicalPath() + "/" + name;
+ if (QFile::exists(file)) {
+ return file;
+ }
+ }
+
+ return QString();
+}
+
+// Include a single script into an engine.
+static QScriptValue includeScriptFunction
+ (QScriptEngine *engine, const QString& name)
+{
+ // Find the script, relative to the entry script.
+ QString script;
+ QtScript::getLocation(engine->currentContext(), &script, 0);
+ QString directory = QFileInfo(QFileInfo(script).canonicalFilePath()).dir().canonicalPath();
+ QDir dir(directory);
+ QFileInfo file(dir, name);
+ QString filename = name;
+ if (file.exists()) filename = file.canonicalFilePath();
+
+ // Check if the script has already been loaded.
+ static const char includesProperty[] = "_qtuitest_includes";
+ QStringList included = qscriptvalue_cast<QStringList>(engine->globalObject().property(includesProperty));
+ if (included.contains(filename)) {
+ return QScriptValue();
+ }
+
+ // Try to load the script into memory.
+ QFile scriptFile(filename);
+ if (!scriptFile.exists() || !scriptFile.open(QIODevice::ReadOnly)) {
+ int pos = directory.indexOf("/interpreter");
+ if (pos > 0) {
+ directory = directory.left(pos) + "/tests/shared";
+ QDir dir(directory);
+ QFileInfo file(dir, name);
+ filename = file.filePath();
+ scriptFile.setFileName(filename);
+ } else {
+ scriptFile.setFileName(findIncludeScript(filename));
+ }
+ }
+
+ if (!scriptFile.exists() || (!scriptFile.isOpen() && !scriptFile.open(QIODevice::ReadOnly))) {
+ return engine->currentContext()->throwError("Could not find " + name + " in either the shared or testcase directory");
+ }
+
+ QString contents = QTextStream(&scriptFile).readAll();
+ scriptFile.close();
+
+ contents.prepend("with(ParentTestMetaObject) {");
+ contents.append("\n}");
+
+ ScriptPreprocessor().preprocess(contents);
+
+ // Evaluate the contents of the script.
+ engine->pushContext()->setActivationObject(engine->globalObject());
+ // Note that we have included this script.
+ if (!engine->globalObject().property(includesProperty).isValid()) {
+ engine->globalObject().setProperty(includesProperty, engine->newArray());
+ }
+ engine->globalObject().property(includesProperty).setProperty(
+ engine->globalObject().property(includesProperty).property("length").toUInt32(),
+ qScriptValueFromValue(engine, filename));
+ QScriptValue ret = engine->evaluate(contents, filename);
+ engine->popContext();
+
+ return ret;
+}
+
+// Implementation of the "include()" function in scripts, which imports scripts.
+static QScriptValue includeFunction
+ (QScriptContext *context, QScriptEngine *engine)
+{
+ QScriptValue value;
+ if (context->argumentCount() == 0) {
+ return context->throwError
+ ("script name must be supplied to include()");
+ }
+ value = context->argument(0);
+ if (!value.isString()) {
+ return context->throwError
+ ("invalid script name supplied to include()");
+ }
+
+ QString name = value.toString();
+ if (name.contains(QChar('*'))) {
+ //FIXME: This path doesn't look in the tests/shared/ directory.
+ // Expand the wildcard and include all matching scripts.
+ QString script;
+ QtScript::getLocation(context, &script, 0);
+ QDir dir(QFileInfo(script).dir());
+ QStringList files = dir.entryList(QStringList(name));
+ foreach (QString filename, files) {
+ value = includeScriptFunction(engine, dir.filePath(filename));
+ if (engine->hasUncaughtException())
+ return value;
+ }
+ return engine->undefinedValue();
+ } else {
+ // Include a single script file.
+ return includeScriptFunction(engine, name);
+ }
+}
+
+static QScriptValue setFlags
+ (QScriptContext *context, QScriptEngine* /*engine*/)
+{
+ Q_ASSERT(context);
+ if (context->argumentCount() != 3) {
+ return context->throwError
+ ("setFlags() needs three arguments");
+ }
+ QScriptValue o = context->argument(0);
+ if (!o.isObject()) return QScriptValue();
+ QString name = context->argument(1).toString();
+ int flags = context->argument(2).toInt32();
+
+ o.setProperty(name, o.property(name), QFlag(flags));
+ return QScriptValue();
+}
+
+
+QScriptSystemTest::QScriptSystemTest()
+ : m_engine(0),
+ m_agent(0),
+ m_contextDepth(0),
+ testObject(0),
+ m_checkOnly(false)
+{
+}
+
+QScriptSystemTest::~QScriptSystemTest()
+{
+}
+
+void QScriptSystemTest::initEngine(bool createNewEngine)
+{
+ if (m_engine) {
+ if (createNewEngine) {
+ delete m_engine;
+ } else {
+ return;
+ }
+ }
+
+ m_engine = new QScriptEngine();
+ m_agent = new QtUiTestEngineAgent(m_engine, this);
+
+ // Ensure we process events periodically.
+ m_engine->setProcessEventsInterval(100);
+
+ m_engine->importExtension("qt.core");
+ setupEnums(m_engine);
+
+ // include() imports scripts directly into the parent script.
+ m_engine->globalObject().setProperty
+ ("include", m_engine->newFunction(includeFunction, 1));
+ m_engine->globalObject().setProperty
+ ("setFlags", m_engine->newFunction(setFlags, 3));
+
+
+ m_engine->globalObject().setProperty("_dateToString", m_engine->newFunction(dateToString));
+ m_engine->evaluate("_old_date_toString = Date.prototype.toString;"
+ "Date.prototype.toString = function() {"
+ " if (arguments[0] == undefined)"
+ " return _old_date_toString.apply(this, arguments);"
+ " return _dateToString.apply(this, arguments);"
+ "}");
+
+ m_engine->globalObject().setProperty("ParentTestObject", m_engine->newQObject(this));
+ m_engine->globalObject().setProperty("ParentTestMetaObject", m_engine->newQMetaObject(metaObject()));
+
+ loadBuiltins(m_engine);
+ importIntoGlobalNamespace(m_engine, "ParentTestObject");
+}
+
+QString QScriptSystemTest::testCaseName() const
+{
+ if (testObject)
+ return testObject->metaObject()->className();
+ return QAbstractTest::testCaseName();
+}
+
+void QScriptSystemTest::loadBuiltins(QScriptEngine *engine)
+{
+ QScriptEngine configEngine;
+ QScriptSystemTest::loadInternalScript("config.js", &configEngine);
+ for (int i = 0; i < configEngine.globalObject().property("builtin_files").property("length").toInt32(); ++i) {
+ QString file = configEngine.globalObject().property("builtin_files").property(i).toString();
+ QtScript::addInternalFile( QScriptSystemTest::loadInternalScript(file, engine, true) );
+ }
+}
+
+void QScriptSystemTest::importIntoGlobalNamespace(QScriptEngine *engine, QString const& object)
+{
+ QScriptValue obj = engine->globalObject().property(object);
+
+ QScriptValueIterator it(obj);
+ while (it.hasNext()) {
+ it.next();
+ QString name = it.name();
+
+ // Transform name of enter(QString,QString) to enter
+ if (it.value().isFunction() && name.contains('(')) {
+ name = name.left(name.indexOf('('));
+ }
+
+ // Import this property into the global object iff one doesn't already
+ // exist with this name
+ if (engine->globalObject().property(name).isValid()) continue;
+
+ // For functions, to keep the QObject slot resolution working right, we
+ // must wrap the property instead of simply copying it.
+ if (it.value().isFunction()) {
+ engine->evaluate(QString("%1 = function(){ return %2.%1.apply(this, arguments); };")
+ .arg(name)
+ .arg(object));
+ } else {
+ engine->globalObject().setProperty(name, it.value());
+ }
+ }
+}
+
+QString QScriptSystemTest::loadInternalScript(QString const &name, QScriptEngine *engine, bool withParentObject)
+{
+ QString filename = QFileInfo(QString::fromAscii(__FILE__)).absolutePath() + "/" + name;
+ if (!QFileInfo(filename).exists()) filename = ":/" + name;
+ QFile f(filename);
+ QString data;
+ if (!f.open(QIODevice::ReadOnly) || (data = QTextStream(&f).readAll()).isEmpty()) {
+ qWarning("QtUiTest: Couldn't load config file '%s' (using '%s')", qPrintable(name), qPrintable(filename));
+ return QString();
+ }
+
+ if (withParentObject) {
+ data.prepend("with(ParentTestMetaObject) {");
+ data.append("\n}");
+ }
+
+ QScriptValue e = engine->evaluate(data, filename);
+ if (e.isError()) {
+ QString backtrace = engine->uncaughtExceptionBacktrace().join("\n");
+ qWarning("In QtUiTest config file %s:\n%s\n%s", qPrintable(filename), qPrintable(e.toString()),
+ qPrintable(backtrace));
+ }
+ builtins << filename;
+ return filename;
+}
+
+QScriptValue variantToScriptValue(QScriptEngine *engine, const QVariant &v)
+{
+ QScriptValue ret;
+ if (v.isNull()) {
+ ret = QScriptValue( engine, QScriptValue::NullValue );
+ } else if (v.canConvert<QStringList>()) {
+ ret = engine->toScriptValue(v.value<QStringList>());
+ } else if (v.canConvert<qreal>()) {
+ ret = engine->toScriptValue(v.value<qreal>());
+ } else if (v.canConvert<int>()) {
+ ret = engine->toScriptValue(v.value<int>());
+ } else if (v.canConvert<QString>()) {
+ ret = engine->toScriptValue(v.value<QString>());
+ } else {
+ ret = engine->newVariant(v);
+ }
+ return ret;
+}
+
+void variantFromScriptValue(const QScriptValue &obj, QVariant &v)
+{
+ v = obj.toVariant();
+}
+
+QString QScriptSystemTest::currentFile()
+{
+ QString fileName = QString();
+ int lineNumber = 0;
+
+ QtScript::getLocation(m_engine->currentContext(), &fileName, &lineNumber);
+
+ return fileName;
+}
+
+int QScriptSystemTest::currentLine()
+{
+ QString fileName = QString();
+ int lineNumber = 0;
+
+ QtScript::getLocation(m_engine->currentContext(), &fileName, &lineNumber);
+
+ return lineNumber;
+}
+
+void QScriptSystemTest::outputBacktrace()
+{
+ QScriptContext *ctx = m_engine->currentContext();
+ QString bt("Backtrace:");
+ while (ctx) {
+ QScriptContextInfo ctxInfo(ctx);
+ QString fn = ctxInfo.fileName();
+ int ln = ctxInfo.lineNumber();
+ if (!fn.isEmpty() && ln != -1)
+ bt += "\n " + fn + "(" + QString::number(ln) + ")";
+ ctx = ctx->parentContext();
+ }
+ QDebug(QtDebugMsg) << qPrintable(bt);
+}
+
+void QScriptSystemTest::skip(QString const &message, QSystemTest::SkipMode mode)
+{
+ QSystemTest::skip(message, mode);
+ m_engine->evaluate("throw new QTestFailure('QSKIP');");
+}
+
+bool QScriptSystemTest::fail(QString const &message)
+{
+ bool ret = QSystemTest::fail( message );
+ if (!ret) {
+ outputBacktrace();
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+ }
+ return ret;
+}
+
+void QScriptSystemTest::verify(bool statement, QString const &message)
+{
+ if (!QTest::qVerify(statement, "<statement>", qPrintable(message), qPrintable(currentFile()), currentLine() )) {
+ outputBacktrace();
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+ }
+}
+
+void QScriptSystemTest::compare(const QString &actual, const QString &expected)
+{
+ if (QSystemTest::runAsManualTest()) {
+ QString act;
+ if (actual == "MAGIC_DATA" || actual.contains("'")) act = actual;
+ else act = "'" + actual + "'";
+ QString exp;
+ if (expected == "MAGIC_DATA" || expected.contains("'")) exp = expected;
+ else exp = "'" + expected + "'";
+ manualTest( QString("verify that %1 is equal to %2").arg(act).arg(exp));
+ return;
+ }
+
+ if (!QTest::qCompare( actual, expected, qPrintable(actual), qPrintable(expected), qPrintable(currentFile()), currentLine() )) {
+ outputBacktrace();
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+ }
+}
+
+void QScriptSystemTest::compare(const QStringList &actual, const QStringList &expected)
+{
+ if (QSystemTest::runAsManualTest()) {
+ QString act = actual.count() > 0 ? actual[0] : "";
+ QString exp = expected.count() > 0 ? expected[0] : "";
+ manualTest( QString("verify that %1 is equal to %2").arg(act).arg(exp));
+ return;
+ }
+
+ if (!QTest::qCompare( actual.count(), expected.count(), qPrintable(actual.join("\n")), qPrintable(expected.join("\n")), qPrintable(currentFile()), currentLine() )) {
+ outputBacktrace();
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+ return;
+ }
+
+ for (int i=0; i<actual.count(); i++) {
+ if (!QTest::qCompare( actual[i], expected[i], qPrintable(actual[i]), qPrintable(expected[i]), qPrintable(currentFile()), currentLine() )) {
+ outputBacktrace();
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+ }
+ }
+}
+
+bool QScriptSystemTest::isFailExpected()
+{
+ return (expect_fail_function == currentTestFunction() && expect_fail_datatag == currentDataTag());
+}
+
+void QScriptSystemTest::expectFail( const QString &reason )
+{
+ expect_fail_function = currentTestFunction();
+ expect_fail_datatag = currentDataTag();
+ expect_fail_reason = reason;
+ int line = currentLine();
+
+ if (testObject) {
+ testObject->setProperty("expectFailLineNumber", line);
+ }
+
+ bool ok = QTest::qExpectFail(currentDataTag().toLatin1(), reason.toLatin1(),
+ QTest::TestFailMode(1),//mode),
+ qPrintable(currentFile()), line);
+ if (!ok)
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+}
+
+bool QScriptSystemTest::setQueryError( const QTestMessage &message )
+{
+ QString errorString = message["status"].toString();
+ QVariant response = message["_q_inResponseTo"];
+ if (response.isValid()) {
+ errorString += QString("\nIn response to message: %2").arg(response.toString());
+ }
+ return setQueryError( errorString );
+}
+
+bool QScriptSystemTest::setQueryError( const QString &errString )
+{
+ if (queryFailed()) return false;
+ QSystemTest::setQueryError(errString);
+ bool ret = fail(errString);
+ if (!ret) {
+ m_engine->evaluate("throw new QTestFailure('QFAIL');");
+ }
+ return ret;
+}
+
+int QScriptSystemTest::runTest(const QString &fname, const QStringList &parameters,
+ const QStringList &environment)
+{
+ m_env = environment;
+ bool createNewEngine = filename == fname;
+ filename = fname;
+
+ QFile file(filename);
+ if (!file.open(QFile::ReadOnly)) {
+ qDebug() << "Can't open " << filename;
+ return -1;
+ }
+
+ QTextStream stream(&file);
+ QString script = stream.readAll();
+
+ ScriptPreprocessor().preprocess(script);
+
+ initEngine(createNewEngine);
+
+ // Allow shebangs without giving syntax errors.
+ if (script.startsWith("#!")) script.prepend("//");
+ script.prepend("with(ParentTestMetaObject){");
+ script.append("\n}");
+
+ QtScriptTest tc(filename, script, m_engine);
+
+ if (tc.status() != QtScriptTest::StatusNormal) {
+ return -1;
+ }
+
+ testObject = &tc;
+
+ qScriptRegisterMetaType(m_engine, variantToScriptValue, variantFromScriptValue);
+ qScriptRegisterSequenceMetaType<QList<qint64> >(m_engine);
+
+ // Only set up the test data path if not explicitly set by user
+ if (!QCoreApplication::arguments().contains("-data")) {
+ setupTestDataPath(qPrintable(filename));
+ }
+
+ enableQueryWarnings(false);
+
+ // If we get here, the syntax of the script is definitely OK
+ // (a syntax error causes a qFatal in the QtScriptTest ctor).
+ if (m_checkOnly)
+ return 0;
+
+ // If an IDE is connected, set the agent to enable script debugging
+ if (QTestIDE::instance()->isConnected()) {
+ m_engine->setAgent(m_agent);
+ }
+
+ if (QTest::testObject()) {
+ qDebug() << "Test already in progress?";
+ return -1;
+ }
+ int retval = QTest::qExec(&tc, parameters);
+
+ testObject = 0;
+
+ // After a full test run, QTestLib sometimes returns 0 or sometimes returns
+ // the number of test failures, depending on how it was compiled. In both
+ // cases, a negative number denotes an error.
+ // We don't want test failures to affect the exit code.
+ return (retval < 0) ? retval : 0;
+}
+
+/*!
+ \internal
+ Send a raw message from within script to the connected system.
+
+ This can be used to extend the API for new messages on the target device
+ without modifying QSystemTest.
+
+ If the message doesn't elicit a response of "OK", the current test fails.
+*/
+QVariantMap QScriptSystemTest::sendRaw(const QString& event, const QScriptValue& object)
+{
+ QVariantMap ret;
+ if (object.isValid() && !object.isObject()) {
+ setQueryError("Second argument to sendRaw must be an object.");
+ return ret;
+ }
+ if (event.isEmpty()) {
+ setQueryError("First argument to sendRaw cannot be an empty string.");
+ return ret;
+ }
+
+ QTestMessage message(event);
+
+ // Treat object like a variant map and load it into message.
+ QScriptValueIterator it(object);
+ while (it.hasNext()) {
+ it.next();
+ QScriptValue v = it.value();
+ // Map must be flat; we don't handle objects within objects.
+ if (v.isObject() && !v.isArray()) {
+ setQueryError("Object passed to sendRaw must not have any child objects.");
+ return ret;
+ }
+ // toVariant appears to flatten stringlists into strings, which we don't want.
+ if (v.isArray()) {
+ QVariantList list;
+ for (int i = 0, max = qscriptvalue_cast<int>(v.property("length")); i < max; ++i)
+ list << v.property(i).toVariant();
+ message[it.name()] = list;
+ } else {
+ message[it.name()] = v.toVariant();
+ }
+ }
+
+ QTestMessage reply;
+ if (!doQuery(message, QString(), &reply)) {
+ setQueryError("Raw " + event + " message failed: " + reply["status"].toString());
+ return ret;
+ }
+
+ foreach (QString const& key, reply.keys())
+ ret[key] = reply[key];
+ return ret;
+}
+
+//#ifndef QTCREATOR_QTEST
+/*!
+ \internal
+ Print any special usage information which should be shown when test is launched
+ with -help.
+*/
+void QScriptSystemTest::printUsage() const
+{
+ QSystemTest::printUsage();
+ qWarning(
+ " Script options:\n"
+ " -c : Check the syntax of the test only. Returns a non-zero exit code if the test\n"
+ " contains any syntax errors.\n"
+ );
+}
+//#endif
+
+/*!
+ \internal
+ If \a func is a function, install it as a handler for all messages received from the test
+ system.
+
+ Whenever a new message is received, \a func will be called with two arguments.
+ The first is the message event as a string.
+ The second is an object containing one property for each parameter of the message.
+
+ If \a func returns true, processing of the message ends.
+*/
+void QScriptSystemTest::installMessageHandler(const QScriptValue& func)
+{
+ if (!func.isFunction()) {
+ setQueryError("Argument to installMessageHandler must be a function.");
+ return;
+ }
+ m_messageHandlers << func;
+}
+
+
+QString qDumpScriptValue(QString const& name, QScriptValue const& v, int indent = 0)
+{
+ const QString spc = QString().fill(' ', indent);
+
+ QString ret;
+
+ ret += spc + name + ": ";
+ if (name != "global" && v.engine()->globalObject().strictlyEquals(v))
+ ret += "global";
+ else if (v.isBoolean())
+ ret += "Boolean:" + v.toString();
+ else if (v.isDate())
+ ret += "Date:" + v.toString();
+ else if (v.isFunction())
+ ret += "Function";
+ else if (v.isNull())
+ ret += "null";
+ else if (v.isNumber())
+ ret += "Number:" + v.toString();
+ else if (v.isString())
+ ret += "String:" + v.toString();
+ else if (v.isUndefined())
+ ret += "undef";
+ else {
+ QString inner;
+ QScriptValueIterator it(v);
+ QString sep;
+ while (it.hasNext()) {
+ it.next();
+ inner += sep + qDumpScriptValue(it.name(), it.value(), indent+2);
+ sep = ",\n";
+ }
+ if (inner.isEmpty()) {
+ ret += "{}";
+ } else {
+ ret += "{\n" + inner + "\n" + spc + "} /* " + name + " */";
+ }
+ }
+
+ return ret;
+}
+
+/*!
+ \internal
+ Write out most of the state of the script engine to stderr.
+*/
+void QScriptSystemTest::dumpEngine()
+{
+ QString state;
+
+ {
+ QScriptContext* ctx = m_engine->currentContext();
+ state += "context: {";
+ int i = 0;
+ QString sep;
+ while (ctx) {
+ state += QString("%1\n %2: {\n").arg(sep).arg(i++);
+ state += " toString: " + ctx->toString() + "\n";
+ state += qDumpScriptValue("activationObject", ctx->activationObject(), 4) + ",\n";
+ state += qDumpScriptValue("thisObject", ctx->thisObject(), 4) + "\n";
+ state += " }";
+ sep = ",";
+ ctx = ctx->parentContext();
+ }
+ state += "\n};\n";
+ }
+
+ state += qDumpScriptValue("global", m_engine->globalObject());
+ state += ";";
+
+ fprintf(stderr, "%s\n", qPrintable(state));
+}
+
+/*!
+ \internal
+ Passes the test message through any installed QtScript message handlers.
+ If none of them handle the message, it will be passed to the superclass.
+*/
+void QScriptSystemTest::processMessage(const QTestMessage& message)
+{
+ if (m_messageHandlers.count()) {
+ QVariantMap map;
+ foreach (QString const& key, message.keys())
+ map[key] = message[key];
+
+ QScriptValueList args;
+ args << m_engine->toScriptValue(message.event());
+ args << m_engine->toScriptValue(map);
+
+ for (int i = 0; i < m_messageHandlers.count(); ++i) {
+ QScriptValue out = m_messageHandlers[i].call(QScriptValue(), args);
+ if (out.isBoolean() && out.toBoolean())
+ return;
+ }
+ }
+
+ QSystemTest::processMessage(message);
+}
+
+/*!
+ \internal
+ Processes the command line parameters.
+*/
+void QScriptSystemTest::processCommandLine( QStringList &args )
+{
+ QMutableStringListIterator it(args);
+
+ while (it.hasNext()) {
+ QString arg = it.next();
+ if (!arg.compare("-c", Qt::CaseInsensitive)) {
+ m_checkOnly = true;
+ it.remove();
+ }
+ }
+
+ QSystemTest::processCommandLine(args);
+}
+
+void QScriptSystemTest::scriptPositionChange(qint64 scriptId, int line, int column)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(line);
+ Q_UNUSED(column);
+
+ QScriptContextInfo ctxInfo(m_engine->currentContext());
+ if (!ctxInfo.fileName().isEmpty() && !builtins.contains(ctxInfo.fileName())) {
+ QString functionName;
+ if (ctxInfo.functionName().isEmpty()) {
+ functionName = currentTestFunction();
+ } else {
+ functionName = ctxInfo.functionName();
+ }
+ if (QTestIDE::instance()->queryBreakpoint(ctxInfo.fileName(), ctxInfo.lineNumber(), functionName, m_contextDepth)) {
+ QTestIDE::instance()->breakpointContext(m_engine->currentContext());
+ }
+ }
+}
+
+void QScriptSystemTest::scriptContextChange(bool isNew)
+{
+ if (isNew)
+ ++m_contextDepth;
+ else
+ --m_contextDepth;
+} \ No newline at end of file