diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-02-16 14:43:03 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-24 04:51:31 +0100 |
commit | b855240b782395f94315f43ea3e7e182299fac48 (patch) | |
tree | bc594c04449be8cd14cd0ab0bb72dafc2be0ffb2 /tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp | |
parent | 6a42a6e0a9a1abdda0d07a5a20b4ac7e45348684 (diff) |
Rename QDeclarative symbols to QQuick and QQml
Symbols beginning with QDeclarative are already exported
by the quick1 module.
Users can apply the bin/rename-qtdeclarative-symbols.sh
script to modify client code using the previous names of the
renamed symbols.
Task-number: QTBUG-23737
Change-Id: Ifaa482663767634931e8711a8e9bf6e404859e66
Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp')
-rw-r--r-- | tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp | 1790 |
1 files changed, 1790 insertions, 0 deletions
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp new file mode 100644 index 0000000000..9a8b00bb6c --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -0,0 +1,1790 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtCore/QProcess> +#include <QtCore/QTimer> +#include <QtCore/QFileInfo> +#include <QtCore/QDir> +#include <QtCore/QMutex> +#include <QtCore/QLibraryInfo> +#include <QtQml/private/qqmldebugclient_p.h> +#include <QtQml/QJSEngine> + +//QQmlDebugTest +#include "../shared/debugutil_p.h" +#include "../../../shared/util.h" + +const char *V8REQUEST = "v8request"; +const char *V8MESSAGE = "v8message"; +const char *SEQ = "seq"; +const char *TYPE = "type"; +const char *COMMAND = "command"; +const char *ARGUMENTS = "arguments"; +const char *STEPACTION = "stepaction"; +const char *STEPCOUNT = "stepcount"; +const char *EXPRESSION = "expression"; +const char *FRAME = "frame"; +const char *GLOBAL = "global"; +const char *DISABLEBREAK = "disable_break"; +const char *HANDLES = "handles"; +const char *INCLUDESOURCE = "includeSource"; +const char *FROMFRAME = "fromFrame"; +const char *TOFRAME = "toFrame"; +const char *BOTTOM = "bottom"; +const char *NUMBER = "number"; +const char *FRAMENUMBER = "frameNumber"; +const char *TYPES = "types"; +const char *IDS = "ids"; +const char *FILTER = "filter"; +const char *FROMLINE = "fromLine"; +const char *TOLINE = "toLine"; +const char *TARGET = "target"; +const char *LINE = "line"; +const char *COLUMN = "column"; +const char *ENABLED = "enabled"; +const char *CONDITION = "condition"; +const char *IGNORECOUNT = "ignoreCount"; +const char *BREAKPOINT = "breakpoint"; +const char *FLAGS = "flags"; + +const char *CONTINEDEBUGGING = "continue"; +const char *EVALUATE = "evaluate"; +const char *LOOKUP = "lookup"; +const char *BACKTRACE = "backtrace"; +const char *SCOPE = "scope"; +const char *SCOPES = "scopes"; +const char *SCRIPTS = "scripts"; +const char *SOURCE = "source"; +const char *SETBREAKPOINT = "setbreakpoint"; +const char *CHANGEBREAKPOINT = "changebreakpoint"; +const char *CLEARBREAKPOINT = "clearbreakpoint"; +const char *SETEXCEPTIONBREAK = "setexceptionbreak"; +const char *V8FLAGS = "v8flags"; +const char *VERSION = "version"; +const char *DISCONNECT = "disconnect"; +const char *LISTBREAKPOINTS = "listbreakpoints"; +const char *GARBAGECOLLECTOR = "gc"; +//const char *PROFILE = "profile"; + +const char *CONNECT = "connect"; +const char *INTERRUPT = "interrupt"; +const char *BREAKAFTERCOMPILE = "breakaftercompile"; + +const char *REQUEST = "request"; +const char *IN = "in"; +const char *NEXT = "next"; +const char *OUT = "out"; + +const char *FUNCTION = "function"; +const char *SCRIPT = "script"; +const char *SCRIPTREGEXP = "scriptRegExp"; +const char *EVENT = "event"; + +const char *ALL = "all"; +const char *UNCAUGHT = "uncaught"; + +//const char *PAUSE = "pause"; +//const char *RESUME = "resume"; + +const char *BLOCKMODE = "-qmljsdebugger=port:3771,block"; +const char *NORMALMODE = "-qmljsdebugger=port:3771"; +const char *TEST_QMLFILE = "test.qml"; +const char *TEST_JSFILE = "test.js"; +const char *TIMER_QMLFILE = "timer.qml"; +const char *LOADJSFILE_QMLFILE = "loadjsfile.qml"; +const char *EXCEPTION_QMLFILE = "exception.qml"; +const char *ONCOMPLETED_QMLFILE = "oncompleted.qml"; +const char *CREATECOMPONENT_QMLFILE = "createComponent.qml"; +const char *CONDITION_QMLFILE = "condition.qml"; +const char *CHANGEBREAKPOINT_QMLFILE = "changeBreakpoint.qml"; +const char *STEPACTION_QMLFILE = "stepAction.qml"; +const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml"; + +#define VARIANTMAPINIT \ + QString obj("{}"); \ + QJSValue jsonVal = parser.call(QJSValueList() << obj); \ + jsonVal.setProperty(SEQ,QJSValue(seq++)); \ + jsonVal.setProperty(TYPE,REQUEST); + + +#undef QVERIFY +#define QVERIFY(statement) \ +do {\ + if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\ + if (QTest::currentTestFailed()) \ + qDebug().nospace() << "\nDEBUGGEE OUTPUT:\n" << process->output();\ + return;\ + }\ +} while (0) + + +class QJSDebugClient; + +class tst_QQmlDebugJS : public QQmlDataTest +{ + Q_OBJECT + + bool init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true); + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void cleanup(); + + void connect(); + void interrupt(); + void breakAfterCompile(); + void getVersion(); + void getVersionWhenAttaching(); + + void applyV8Flags(); + + void disconnect(); + + void gc(); + + void listBreakpoints(); + + void setBreakpointInScriptOnCompleted(); + void setBreakpointInScriptOnComponentCreated(); + void setBreakpointInScriptOnTimerCallback(); + void setBreakpointInScriptInDifferentFile(); + void setBreakpointInScriptOnComment(); + void setBreakpointInScriptOnEmptyLine(); + void setBreakpointInScriptWithCondition(); + //void setBreakpointInFunction(); //NOT SUPPORTED + void setBreakpointOnEvent(); + void setBreakpointWhenAttaching(); + + void changeBreakpoint(); + void changeBreakpointOnCondition(); + + void clearBreakpoint(); + + void setExceptionBreak(); + + void stepNext(); + void stepNextWithCount(); + void stepIn(); + void stepOut(); + void continueDebugging(); + + void backtrace(); + + void getFrameDetails(); + + void getScopeDetails(); + + void evaluateInGlobalScope(); + void evaluateInLocalScope(); + + void getScopes(); + + void getScripts(); + + void getSource(); + + // void profile(); //NOT SUPPORTED + + // void verifyQMLOptimizerDisabled(); + +private: + QQmlDebugProcess *process; + QJSDebugClient *client; + QQmlDebugConnection *connection; + QTime t; +}; + +class QJSDebugClient : public QQmlDebugClient +{ + Q_OBJECT +public: + enum StepAction + { + Continue, + In, + Out, + Next + }; + + enum Exception + { + All, + Uncaught + }; + +// enum ProfileCommand +// { +// Pause, +// Resume +// }; + + QJSDebugClient(QQmlDebugConnection *connection) + : QQmlDebugClient(QLatin1String("V8Debugger"), connection), + seq(0) + { + parser = jsEngine.evaluate(QLatin1String("JSON.parse")); + stringify = jsEngine.evaluate(QLatin1String("JSON.stringify")); + } + + void connect(); + void interrupt(); + void breakAfterCompile(bool enabled); + + void continueDebugging(StepAction stepAction, int stepCount = 1); + void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); + void lookup(QList<int> handles, bool includeSource = false); + void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); + void frame(int number = -1); + void scope(int number = -1, int frameNumber = -1); + void scopes(int frameNumber = -1); + void scripts(int types = 4, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant()); + void source(int frame = -1, int fromLine = -1, int toLine = -1); + void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = true, QString condition = QString(), int ignoreCount = -1); + void changeBreakpoint(int breakpoint, bool enabled = true, QString condition = QString(), int ignoreCount = -1); + void clearBreakpoint(int breakpoint); + void setExceptionBreak(Exception type, bool enabled = false); + void v8flags(QString flags); + void version(); + //void profile(ProfileCommand command); //NOT SUPPORTED + void disconnect(); + void gc(); + void listBreakpoints(); + +protected: + //inherited from QQmlDebugClient + void stateChanged(State state); + void messageReceived(const QByteArray &data); + +signals: + void enabled(); + void connected(); + void interruptRequested(); + void breakAfterCompileRequested(); + void result(); + void stopped(); + +private: + void sendMessage(const QByteArray &); + void flushSendBuffer(); + QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray()); + +private: + QJSEngine jsEngine; + int seq; + + QList<QByteArray> sendBuffer; +public: + QJSValue parser; + QJSValue stringify; + QByteArray response; + +}; + +void QJSDebugClient::connect() +{ + sendMessage(packMessage(CONNECT)); +} + +void QJSDebugClient::interrupt() +{ + sendMessage(packMessage(INTERRUPT)); +} + +void QJSDebugClient::breakAfterCompile(bool enabled) +{ + QByteArray request; + QDataStream rs(&request, QIODevice::WriteOnly); + rs << enabled; + sendMessage(packMessage(BREAKAFTERCOMPILE, request)); +} + +void QJSDebugClient::continueDebugging(StepAction action, int count) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "continue", + // "arguments" : { "stepaction" : <"in", "next" or "out">, + // "stepcount" : <number of steps (default 1)> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING))); + + if (action != Continue) { + QJSValue args = parser.call(QJSValueList() << obj); + switch (action) { + case In: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(IN))); + break; + case Out: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(OUT))); + break; + case Next: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(NEXT))); + break; + default:break; + } + if (!args.isUndefined()) { + if (count != 1) + args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count)); + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "evaluate", + // "arguments" : { "expression" : <expression to evaluate>, + // "frame" : <number>, + // "global" : <boolean>, + // "disable_break" : <boolean>, + // "additional_context" : [ + // { "name" : <name1>, "handle" : <handle1> }, + // { "name" : <name2>, "handle" : <handle2> }, + // ... + // ] + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE))); + + QJSValue args = parser.call(QJSValueList() << obj); + args.setProperty(QLatin1String(EXPRESSION),QJSValue(expr)); + + if (frame != -1) + args.setProperty(QLatin1String(FRAME),QJSValue(frame)); + + if (global) + args.setProperty(QLatin1String(GLOBAL),QJSValue(global)); + + if (disableBreak) + args.setProperty(QLatin1String(DISABLEBREAK),QJSValue(disableBreak)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::lookup(QList<int> handles, bool includeSource) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "lookup", + // "arguments" : { "handles" : <array of handles>, + // "includeSource" : <boolean indicating whether the source will be included when script objects are returned>, + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP))); + + QJSValue args = parser.call(QJSValueList() << obj); + + QString arr("[]"); + QJSValue array = parser.call(QJSValueList() << arr); + int index = 0; + foreach (int handle, handles) { + array.setProperty(index++,QJSValue(handle)); + } + args.setProperty(QLatin1String(HANDLES),array); + + if (includeSource) + args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "backtrace", + // "arguments" : { "fromFrame" : <number> + // "toFrame" : <number> + // "bottom" : <boolean, set to true if the bottom of the stack is requested> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE))); + + QJSValue args = parser.call(QJSValueList() << obj); + + if (fromFrame != -1) + args.setProperty(QLatin1String(FROMFRAME),QJSValue(fromFrame)); + + if (toFrame != -1) + args.setProperty(QLatin1String(TOFRAME),QJSValue(toFrame)); + + if (bottom) + args.setProperty(QLatin1String(BOTTOM),QJSValue(bottom)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::frame(int number) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "frame", + // "arguments" : { "number" : <frame number> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME))); + + if (number != -1) { + QJSValue args = parser.call(QJSValueList() << obj); + args.setProperty(QLatin1String(NUMBER),QJSValue(number)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::scope(int number, int frameNumber) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "scope", + // "arguments" : { "number" : <scope number> + // "frameNumber" : <frame number, optional uses selected frame if missing> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE))); + + if (number != -1) { + QJSValue args = parser.call(QJSValueList() << obj); + args.setProperty(QLatin1String(NUMBER),QJSValue(number)); + + if (frameNumber != -1) + args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::scopes(int frameNumber) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "scopes", + // "arguments" : { "frameNumber" : <frame number, optional uses selected frame if missing> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES))); + + if (frameNumber != -1) { + QJSValue args = parser.call(QJSValueList() << obj); + args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::scripts(int types, QList<int> ids, bool includeSource, QVariant /*filter*/) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "scripts", + // "arguments" : { "types" : <types of scripts to retrieve + // set bit 0 for native scripts + // set bit 1 for extension scripts + // set bit 2 for normal scripts + // (default is 4 for normal scripts)> + // "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned> + // "includeSource" : <boolean indicating whether the source code should be included for the scripts returned> + // "filter" : <string or number: filter string or script id. + // If a number is specified, then only the script with the same number as its script id will be retrieved. + // If a string is specified, then only scripts whose names contain the filter string will be retrieved.> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS))); + + QJSValue args = parser.call(QJSValueList() << obj); + args.setProperty(QLatin1String(TYPES),QJSValue(types)); + + if (ids.count()) { + QString arr("[]"); + QJSValue array = parser.call(QJSValueList() << arr); + int index = 0; + foreach (int id, ids) { + array.setProperty(index++,QJSValue(id)); + } + args.setProperty(QLatin1String(IDS),array); + } + + if (includeSource) + args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::source(int frame, int fromLine, int toLine) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "source", + // "arguments" : { "frame" : <frame number (default selected frame)> + // "fromLine" : <from line within the source default is line 0> + // "toLine" : <to line within the source this line is not included in + // the result default is the number of lines in the script> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE))); + + QJSValue args = parser.call(QJSValueList() << obj); + + if (frame != -1) + args.setProperty(QLatin1String(FRAME),QJSValue(frame)); + + if (fromLine != -1) + args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine)); + + if (toLine != -1) + args.setProperty(QLatin1String(TOLINE),QJSValue(toLine)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "setbreakpoint", + // "arguments" : { "type" : <"function" or "script" or "scriptId" or "scriptRegExp"> + // "target" : <function expression or script identification> + // "line" : <line in script or function> + // "column" : <character position within the line> + // "enabled" : <initial enabled state. True or false, default is true> + // "condition" : <string with break point condition> + // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0> + // } + // } + + if (type == QLatin1String(EVENT)) { + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + rs << target.toUtf8() << enabled; + sendMessage(packMessage(QByteArray("breakonsignal"), reply)); + + } else { + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT))); + + QJSValue args = parser.call(QJSValueList() << obj); + + args.setProperty(QLatin1String(TYPE),QJSValue(type)); + args.setProperty(QLatin1String(TARGET),QJSValue(target)); + + if (line != -1) + args.setProperty(QLatin1String(LINE),QJSValue(line)); + + if (column != -1) + args.setProperty(QLatin1String(COLUMN),QJSValue(column)); + + args.setProperty(QLatin1String(ENABLED),QJSValue(enabled)); + + if (!condition.isEmpty()) + args.setProperty(QLatin1String(CONDITION),QJSValue(condition)); + + if (ignoreCount != -1) + args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); + } +} + +void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "changebreakpoint", + // "arguments" : { "breakpoint" : <number of the break point to clear> + // "enabled" : <initial enabled state. True or false, default is true> + // "condition" : <string with break point condition> + // "ignoreCount" : <number specifying the number of break point hits } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CHANGEBREAKPOINT))); + + QJSValue args = parser.call(QJSValueList() << obj); + + args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint)); + + args.setProperty(QLatin1String(ENABLED),QJSValue(enabled)); + + if (!condition.isEmpty()) + args.setProperty(QLatin1String(CONDITION),QJSValue(condition)); + + if (ignoreCount != -1) + args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::clearBreakpoint(int breakpoint) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "clearbreakpoint", + // "arguments" : { "breakpoint" : <number of the break point to clear> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT))); + + QJSValue args = parser.call(QJSValueList() << obj); + + args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::setExceptionBreak(Exception type, bool enabled) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "setexceptionbreak", + // "arguments" : { "type" : <string: "all", or "uncaught">, + // "enabled" : <optional bool: enables the break type if true> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK))); + + QJSValue args = parser.call(QJSValueList() << obj); + + if (type == All) + args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL))); + else if (type == Uncaught) + args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(UNCAUGHT))); + + if (enabled) + args.setProperty(QLatin1String(ENABLED),QJSValue(enabled)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::v8flags(QString flags) +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "v8flags", + // "arguments" : { "flags" : <string: a sequence of v8 flags just like those used on the command line> + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS))); + + QJSValue args = parser.call(QJSValueList() << obj); + + args.setProperty(QLatin1String(FLAGS),QJSValue(flags)); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::version() +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "version", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION))); + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +//void QJSDebugClient::profile(ProfileCommand command) +//{ +//// { "seq" : <number>, +//// "type" : "request", +//// "command" : "profile", +//// "arguments" : { "command" : "resume" or "pause" } +//// } +// VARIANTMAPINIT; +// jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE))); + +// QJSValue args = parser.call(QJSValueList() << obj); + +// if (command == Resume) +// args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(RESUME))); +// else +// args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PAUSE))); + +// args.setProperty(QLatin1String("modules"),QJSValue(1)); +// if (!args.isUndefined()) { +// jsonVal.setProperty(QLatin1String(ARGUMENTS),args); +// } + +// QJSValue json = stringify.call(QJSValueList() << jsonVal); +// sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +//} + +void QJSDebugClient::disconnect() +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "disconnect", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT))); + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(DISCONNECT, json.toString().toUtf8())); +} + +void QJSDebugClient::gc() +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "gc", + // "arguments" : { "type" : <string: "all">, + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GARBAGECOLLECTOR))); + + QJSValue args = parser.call(QJSValueList() << obj); + + args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL))); + + if (!args.isUndefined()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::listBreakpoints() +{ + // { "seq" : <number>, + // "type" : "request", + // "command" : "listbreakpoints", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS))); + + QJSValue json = stringify.call(QJSValueList() << jsonVal); + sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); +} + +void QJSDebugClient::stateChanged(State state) +{ + if (state == Enabled) { + flushSendBuffer(); + emit enabled(); + } +} + +void QJSDebugClient::messageReceived(const QByteArray &data) +{ + QDataStream ds(data); + QByteArray command; + ds >> command; + + if (command == "V8DEBUG") { + QByteArray type; + ds >> type >> response; + + if (type == CONNECT) { + emit connected(); + + } else if (type == INTERRUPT) { + emit interruptRequested(); + + } else if (type == V8MESSAGE) { + QString jsonString(response); + QVariantMap value = parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + QString type = value.value("type").toString(); + + if (type == "response") { + + if (!value.value("success").toBool()) { +// qDebug() << "Error: The test case will fail since no signal is emitted"; + return; + } + + QString debugCommand(value.value("command").toString()); + if (debugCommand == "backtrace" || + debugCommand == "lookup" || + debugCommand == "setbreakpoint" || + debugCommand == "evaluate" || + debugCommand == "listbreakpoints" || + debugCommand == "version" || + debugCommand == "v8flags" || + debugCommand == "disconnect" || + debugCommand == "gc" || + debugCommand == "changebreakpoint" || + debugCommand == "clearbreakpoint" || + debugCommand == "frame" || + debugCommand == "scope" || + debugCommand == "scopes" || + debugCommand == "scripts" || + debugCommand == "source" || + debugCommand == "setexceptionbreak" /*|| + debugCommand == "profile"*/) { + emit result(); + + } else { + // DO NOTHING + } + + } else if (type == QLatin1String(EVENT)) { + QString event(value.value(QLatin1String(EVENT)).toString()); + + if (event == "break" || + event == "exception") + emit stopped(); + } + + } else if (type == BREAKAFTERCOMPILE) { + emit breakAfterCompileRequested(); + + } + } +} + +void QJSDebugClient::sendMessage(const QByteArray &msg) +{ + if (state() == Enabled) { + QQmlDebugClient::sendMessage(msg); + } else { + sendBuffer.append(msg); + } +} + +void QJSDebugClient::flushSendBuffer() +{ + foreach (const QByteArray &msg, sendBuffer) + QQmlDebugClient::sendMessage(msg); + sendBuffer.clear(); +} + +QByteArray QJSDebugClient::packMessage(const QByteArray &type, const QByteArray &message) +{ + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + QByteArray cmd = "V8DEBUG"; + rs << cmd << type << message; + return reply; +} + +void tst_QQmlDebugJS::initTestCase() +{ + QQmlDataTest::initTestCase(); + t.start(); + process = 0; + client = 0; + connection = 0; +} + +void tst_QQmlDebugJS::cleanupTestCase() +{ + if (process) { + process->stop(); + delete process; + } + + if (client) + delete client; + + if (connection) + delete connection; + +// qDebug() << "Time Elapsed:" << t.elapsed(); +} + +bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode) +{ + connection = new QQmlDebugConnection(); + process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene"); + client = new QJSDebugClient(connection); + + QStringList systemEnvironment = QProcess::systemEnvironment(); + systemEnvironment << "QML_DISABLE_OPTIMIZER=1"; + process->setEnvironment(systemEnvironment); + if (blockMode) + process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile)); + else + process->start(QStringList() << QLatin1String(NORMALMODE) << testFile(qmlFile)); + + if (!process->waitForSessionStart()) { + return false; + } + + connection->connectToHost("127.0.0.1", 3771); + if (!connection->waitForConnected()) + return false; + + return QQmlDebugTest::waitForSignal(client, SIGNAL(enabled())); +} + +void tst_QQmlDebugJS::cleanup() +{ + if (process) { + process->stop(); + delete process; + } + + if (client) + delete client; + + if (connection) + delete connection; + + process = 0; + client = 0; + connection = 0; +} + +void tst_QQmlDebugJS::connect() +{ + //void connect() + + QVERIFY(init()); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected()))); +} + +void tst_QQmlDebugJS::interrupt() +{ + //void connect() + + QVERIFY(init()); + client->connect(); + + client->interrupt(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested()))); +} + +void tst_QQmlDebugJS::breakAfterCompile() +{ + //void breakAfterCompile(bool enabled) + + QVERIFY(init()); + client->breakAfterCompile(true); + client->connect(); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(breakAfterCompileRequested()))); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); +} + +void tst_QQmlDebugJS::getVersion() +{ + //void version() + + QVERIFY(init()); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected()))); + + client->version(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::getVersionWhenAttaching() +{ + //void version() + + QVERIFY(init(QLatin1String(TIMER_QMLFILE), false)); + client->connect(); + + client->version(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::applyV8Flags() +{ + //void v8flags(QString flags) + + QVERIFY(init()); + client->connect(); + + client->v8flags(QString()); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::disconnect() +{ + //void disconnect() + + QVERIFY(init()); + client->connect(); + + client->disconnect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::gc() +{ + //void gc() + + QVERIFY(init()); + client->connect(); + + client->gc(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::listBreakpoints() +{ + //void listBreakpoints() + + int sourceLine1 = 47; + int sourceLine2 = 48; + int sourceLine3 = 49; + + QVERIFY(init()); + client->connect(); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine3, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + client->listBreakpoints(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList(); + + QCOMPARE(breakpoints.count(), 3); +} + +void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE)); +} + +void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 47; + QVERIFY(init(CREATECOMPONENT_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE)); +} + +void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback() +{ + int sourceLine = 48; + QVERIFY(init(TIMER_QMLFILE)); + + client->connect(); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE)); +} + +void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 43; + QVERIFY(init(LOADJSFILE_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE)); +} + +void tst_QQmlDebugJS::setBreakpointInScriptOnComment() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 47; + int actualLine = 49; + QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true); + QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1)); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), actualLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE)); +} + +void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 48; + int actualLine = 49; + QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true); + QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1)); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), actualLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE)); +} + +void tst_QQmlDebugJS::setBreakpointInScriptWithCondition() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int out = 10; + int sourceLine = 50; + QVERIFY(init(CONDITION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10")); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Get the frame index + QString jsonString = client->response; + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + int frameIndex = body.value("index").toInt(); + + //Verify the value of 'result' + client->evaluate(QLatin1String("a"),frameIndex); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + jsonString = client->response; + value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QVERIFY(body.value("value").toInt() > out); +} + +void tst_QQmlDebugJS::setBreakpointWhenAttaching() +{ + int sourceLine = 49; + QVERIFY(init(QLatin1String(TIMER_QMLFILE), false)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); +} + +//void tst_QQmlDebugJS::setBreakpointInFunction() +//{ +// //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + +// int actualLine = 31; + +// client->connect(); +// client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true); + +// QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + +// QString jsonString(client->response); +// QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + +// QVariantMap body = value.value("body").toMap(); + +// QCOMPARE(body.value("sourceLine").toInt(), actualLine); +// QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE)); +//} + +void tst_QQmlDebugJS::setBreakpointOnEvent() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + QVERIFY(init(TIMER_QMLFILE)); + + client->connect(); + + client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE)); +} + + +void tst_QQmlDebugJS::changeBreakpoint() +{ + //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine1 = 50; + int sourceLine2 = 51; + QVERIFY(init(CHANGEBREAKPOINT_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Will hit 1st brakpoint, change this breakpoint enable = false + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QList<QVariant> breakpointsHit = body.value("breakpoints").toList(); + + int breakpoint = breakpointsHit.at(0).toInt(); + client->changeBreakpoint(breakpoint,false); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Hit 2nd breakpoint + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Should stop at 2nd breakpoint + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + jsonString = client->response; + value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); +} + +void tst_QQmlDebugJS::changeBreakpointOnCondition() +{ + //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine1 = 50; + int sourceLine2 = 51; + + QVERIFY(init(CHANGEBREAKPOINT_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Will hit 1st brakpoint, change this breakpoint enable = false + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QList<QVariant> breakpointsHit = body.value("breakpoints").toList(); + + int breakpoint = breakpointsHit.at(0).toInt(); + client->changeBreakpoint(breakpoint, false, QLatin1String("d == 0")); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Hit 2nd breakpoint + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Should stop at 2nd breakpoint + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + jsonString = client->response; + value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); + +} + +void tst_QQmlDebugJS::clearBreakpoint() +{ + //void clearBreakpoint(int breakpoint); + + int sourceLine1 = 50; + int sourceLine2 = 51; + QVERIFY(init(CHANGEBREAKPOINT_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Will hit 1st brakpoint, change this breakpoint enable = false + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QList<QVariant> breakpointsHit = body.value("breakpoints").toList(); + + int breakpoint = breakpointsHit.at(0).toInt(); + client->clearBreakpoint(breakpoint); + + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Hit 2nd breakpoint + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Should stop at 2nd breakpoint + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + jsonString = client->response; + value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); +} + +void tst_QQmlDebugJS::setExceptionBreak() +{ + //void setExceptionBreak(QString type, bool enabled = false); + + QVERIFY(init(EXCEPTION_QMLFILE)); + client->setExceptionBreak(QJSDebugClient::All,true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); +} + +void tst_QQmlDebugJS::stepNext() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 50; + QVERIFY(init(STEPACTION_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Next); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); +} + +void tst_QQmlDebugJS::stepNextWithCount() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 50; + QVERIFY(init(STEPACTION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Next, 2); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); +} + +void tst_QQmlDebugJS::stepIn() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 54; + int actualLine = 50; + QVERIFY(init(STEPACTION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::In); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), actualLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); +} + +void tst_QQmlDebugJS::stepOut() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 50; + int actualLine = 54; + QVERIFY(init(STEPACTION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Out); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), actualLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); +} + +void tst_QQmlDebugJS::continueDebugging() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine1 = 54; + int sourceLine2 = 51; + QVERIFY(init(STEPACTION_QMLFILE)); + + client->connect(); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Continue); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); +} + +void tst_QQmlDebugJS::backtrace() +{ + //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->backtrace(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::getFrameDetails() +{ + //void frame(int number = -1); + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->frame(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::getScopeDetails() +{ + //void scope(int number = -1, int frameNumber = -1); + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->scope(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::evaluateInGlobalScope() +{ + //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); + + QVERIFY(init()); + + client->connect(); + client->evaluate(QLatin1String("print('Hello World')"), true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Verify the value of 'print' + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("text").toString(),QLatin1String("undefined")); +} + +void tst_QQmlDebugJS::evaluateInLocalScope() +{ + //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->frame(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Get the frame index + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + int frameIndex = body.value("index").toInt(); + + client->evaluate(QLatin1String("root.a"), frameIndex); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Verify the value of 'timer.interval' + jsonString = client->response; + value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("value").toInt(),10); +} + +void tst_QQmlDebugJS::getScopes() +{ + //void scopes(int frameNumber = -1); + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->scopes(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QQmlDebugJS::getScripts() +{ + //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant()); + +#ifdef Q_OS_MAC + QSKIP("QTBUG-23475 - Unreliable test on Mac OS X"); +#endif + + QVERIFY(init()); + + client->connect(); + + client->scripts(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() + << QJSValue(jsonString)).toVariant().toMap(); + + QList<QVariant> scripts = value.value("body").toList(); + + QCOMPARE(scripts.count(), 2); +} + +void tst_QQmlDebugJS::getSource() +{ + //void source(int frame = -1, int fromLine = -1, int toLine = -1); + + int sourceLine = 47; + QVERIFY(init(ONCOMPLETED_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->source(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +QTEST_MAIN(tst_QQmlDebugJS) + +#include "tst_qqmldebugjs.moc" + |