From: Aurindam Jana Date: Thu, 1 Sep 2011 10:32:11 +0000 (+0200) Subject: Auto Unit test cases for Javascript Debugging. X-Git-Tag: qt-v5.0.0-alpha1~1742 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d4289798cb2eca6d38ee9e978192b3156d07edd8;p=profile%2Fivi%2Fqtdeclarative.git Auto Unit test cases for Javascript Debugging. Change-Id: Iad2deee390deb916854795d27dc38d70891930f6 Reviewed-on: http://codereview.qt.nokia.com/4067 Reviewed-by: Qt Sanity Bot Reviewed-by: Kai Koehne --- diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index ab7943d..2dbbcb9 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -34,6 +34,7 @@ PRIVATETESTS += \ qdeclarativeenginedebug \ qdeclarativedebugclient \ qdeclarativedebugservice \ + qdeclarativedebugjs \ qdeclarativeecmascript \ qdeclarativeimageprovider \ qdeclarativeinstruction \ diff --git a/tests/auto/declarative/qdeclarativedebugjs/data/test.js b/tests/auto/declarative/qdeclarativedebugjs/data/test.js new file mode 100644 index 0000000..230a4ea --- /dev/null +++ b/tests/auto/declarative/qdeclarativedebugjs/data/test.js @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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$ +** +****************************************************************************/ + +function printMessage(msg) +{ + print(msg); +} + +function add(a,b) +{ + //This is a comment and below is an empty line + + var out = a + b; + return out; +} diff --git a/tests/auto/declarative/qdeclarativedebugjs/data/test.qml b/tests/auto/declarative/qdeclarativedebugjs/data/test.qml new file mode 100644 index 0000000..2ccb0b8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativedebugjs/data/test.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "test.js" as Script + +//DO NOT CHANGE + +Rectangle { + id: root + width: 10; height: 10; + Component.onCompleted: doSomethingElse() + + property int result:0 + + property int someValue: 10 + + function doSomething() { + var a = root.result; + var b = commonFunction(); + var c = [1,2,3]; + var d = Script.add(a,c[2]); + result += d; + } + + Timer { + interval: 200; running: true; repeat: false + onTriggered: { + doSomething(); + Script.printMessage("onTriggered"); + } + } + + function commonFunction() { + console.log("commonFunction"); + return 5; + } + + function doSomethingElse() { + result = Script.add(result,5); + eval("print(root.result)"); + } + + Timer { + interval: 4000; running: true; repeat: true + onTriggered: { + doSomethingElse(); + dummy(); + } + } + + +} + diff --git a/tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro b/tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro new file mode 100644 index 0000000..883f941 --- /dev/null +++ b/tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro @@ -0,0 +1,25 @@ +load(qttest_p4) +QT += declarative network script declarative-private +macx:CONFIG -= app_bundle + +HEADERS += ../shared/debugutil_p.h + +SOURCES += tst_qdeclarativedebugjs.cpp \ + ../shared/debugutil.cpp + +INCLUDEPATH += ../shared + +# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage +# LIBS += -lgcov + +symbian { + importFiles.files = data + importFiles.path = . + DEPLOYMENT += importFiles +} + +OTHER_FILES = data/test.qml \ + data/test.js + + +CONFIG += parallel_test diff --git a/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp b/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp new file mode 100644 index 0000000..1704859 --- /dev/null +++ b/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp @@ -0,0 +1,1681 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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 +#include +#include +#include +#include +#include +#include +#include +#include + +//QDeclarativeDebugTest +#include "../../../shared/util.h" +#include "../shared/debugutil_p.h" + +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 *GC = "gc"; +//const char *PROFILE = "profile"; + +const char *CONNECT = "connect"; +const char *INTERRUPT = "interrupt"; + +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 *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 *QMLFILE = "test.qml"; +const char *JSFILE = "test.js"; + +#define VARIANTMAPINIT \ + QString obj("{}"); \ + QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj); \ + jsonVal.setProperty(SEQ,QJSValue(seq++)); \ + jsonVal.setProperty(TYPE,REQUEST); + +inline QString TEST_FILE(const QString &filename) +{ + QFileInfo fileInfo(__FILE__); + return fileInfo.absoluteDir().filePath("data/" + filename); +} + +class QJSDebugProcess; +class QJSDebugClient; + +class tst_QDeclarativeDebugJS : public QObject +{ + Q_OBJECT + +private slots: + + void initTestCase(); + void cleanupTestCase(); + + void init(); + void cleanup(); + + void getVersion(); + + void applyV8Flags(); + + void disconnect(); + + void gc(); + + void listBreakpoints(); + + void setBreakpointInScriptOnCompleted(); + void setBreakpointInScriptOnTimerCallback(); + void setBreakpointInScriptInDifferentFile(); + void setBreakpointInScriptOnComment(); + void setBreakpointInScriptOnEmptyLine(); + void setBreakpointInScriptWithCondition(); + //void setBreakpointInFunction(); //NOT SUPPORTED + + 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: + QJSDebugProcess *process; + QJSDebugClient *client; + QDeclarativeDebugConnection *connection; +}; + +class QJSDebugProcess : public QObject +{ + Q_OBJECT +public: + QJSDebugProcess(); + ~QJSDebugProcess(); + + void start(const QStringList &arguments); + bool waitForSessionStart(); + +private slots: + void processAppOutput(); + +private: + void stop(); + +private: + QProcess m_process; + QTimer m_timer; + QEventLoop m_eventLoop; + QMutex m_mutex; + bool m_started; +}; + +QJSDebugProcess::QJSDebugProcess() + : m_started(false) +{ + m_process.setProcessChannelMode(QProcess::MergedChannels); + m_timer.setSingleShot(true); + m_timer.setInterval(5000); + connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processAppOutput())); + connect(&m_timer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit())); + +// QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); +// env.insert("QML_DISABLE_OPTIMIZER", "1"); // Add an environment variable +// m_process.setProcessEnvironment(env); + +} + +QJSDebugProcess::~QJSDebugProcess() +{ + stop(); +} + +void QJSDebugProcess::start(const QStringList &arguments) +{ + m_mutex.lock(); + m_process.start(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", arguments); + m_process.waitForStarted(); + m_timer.start(); + m_mutex.unlock(); +} + +void QJSDebugProcess::stop() +{ + if (m_process.state() != QProcess::NotRunning) { + m_process.terminate(); + m_process.waitForFinished(5000); + } +} + +bool QJSDebugProcess::waitForSessionStart() +{ + m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); + + return m_started; +} + +void QJSDebugProcess::processAppOutput() +{ + m_mutex.lock(); + const QString appOutput = m_process.readAll(); + static QRegExp newline("[\n\r]{1,2}"); + QStringList lines = appOutput.split(newline); + foreach (const QString &line, lines) { + if (line.isEmpty()) + continue; + if (line.startsWith("Qml debugging is enabled")) // ignore + continue; + if (line.startsWith("QDeclarativeDebugServer:")) { + if (line.contains("Waiting for connection ")) { + m_started = true; + m_eventLoop.quit(); + continue; + } + if (line.contains("Connection established")) { + continue; + } + } + qDebug() << line; + } + m_mutex.unlock(); +} + +class QJSDebugClient : public QDeclarativeDebugClient +{ + Q_OBJECT +public: + enum StepAction + { + Continue, + In, + Out, + Next + }; + + enum Exception + { + All, + Uncaught + }; + +// enum ProfileCommand +// { +// Pause, +// Resume +// }; + + QJSDebugClient(QDeclarativeDebugConnection *connection) + : QDeclarativeDebugClient(QLatin1String("V8Debugger"), connection), + seq(0) + { + parser = jsEngine.evaluate(QLatin1String("JSON.parse")); + stringify = jsEngine.evaluate(QLatin1String("JSON.stringify")); + } + + void startDebugging(); + void interrupt(); + + 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 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 ids = QList(), 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 QDeclarativeDebugClient + void statusChanged(Status status); + void messageReceived(const QByteArray &data); + +signals: + void enabled(); + void breakpointSet(); + void result(); + void stopped(); + +private: + void sendMessage(const QByteArray &); + void flushSendBuffer(); + QByteArray packMessage(QByteArray message); + +private: + QJSEngine jsEngine; + int seq; + + QList sendBuffer; + +public: + QJSValue parser; + QJSValue stringify; + QByteArray response; + +}; + +void QJSDebugClient::startDebugging() +{ + // { "seq" : , + // "type" : "request", + // "command" : "connect", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONNECT))); + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::interrupt() +{ + // { "seq" : , + // "type" : "request", + // "command" : "interrupt", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(INTERRUPT))); + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::continueDebugging(StepAction action, int count) +{ + // { "seq" : , + // "type" : "request", + // "command" : "continue", + // "arguments" : { "stepaction" : <"in", "next" or "out">, + // "stepcount" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING))); + + if (action != Continue) { + QJSValue args = parser.call(QJSValue(), 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.isValid()) { + if (count != 1) + args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count)); + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/) +{ + // { "seq" : , + // "type" : "request", + // "command" : "evaluate", + // "arguments" : { "expression" : , + // "frame" : , + // "global" : , + // "disable_break" : , + // "additional_context" : [ + // { "name" : , "handle" : }, + // { "name" : , "handle" : }, + // ... + // ] + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE))); + + QJSValue args = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::lookup(QList handles, bool includeSource) +{ + // { "seq" : , + // "type" : "request", + // "command" : "lookup", + // "arguments" : { "handles" : , + // "includeSource" : , + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP))); + + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + + QString arr("[]"); + QJSValue array = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom) +{ + // { "seq" : , + // "type" : "request", + // "command" : "backtrace", + // "arguments" : { "fromFrame" : + // "toFrame" : + // "bottom" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE))); + + QJSValue args = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::frame(int number) +{ + // { "seq" : , + // "type" : "request", + // "command" : "frame", + // "arguments" : { "number" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME))); + + if (number != -1) { + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + args.setProperty(QLatin1String(NUMBER),QJSValue(number)); + + if (args.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::scope(int number, int frameNumber) +{ + // { "seq" : , + // "type" : "request", + // "command" : "scope", + // "arguments" : { "number" : + // "frameNumber" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE))); + + if (number != -1) { + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + args.setProperty(QLatin1String(NUMBER),QJSValue(number)); + + if (frameNumber != -1) + args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber)); + + if (args.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::scopes(int frameNumber) +{ + // { "seq" : , + // "type" : "request", + // "command" : "scopes", + // "arguments" : { "frameNumber" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES))); + + if (frameNumber != -1) { + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber)); + + if (args.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::scripts(int types, QList ids, bool includeSource, QVariant /*filter*/) +{ + // { "seq" : , + // "type" : "request", + // "command" : "scripts", + // "arguments" : { "types" : + // "ids" : + // "includeSource" : + // "filter" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS))); + + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + args.setProperty(QLatin1String(TYPES),QJSValue(types)); + + if (ids.count()) { + QString arr("[]"); + QJSValue array = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::source(int frame, int fromLine, int toLine) +{ + // { "seq" : , + // "type" : "request", + // "command" : "source", + // "arguments" : { "frame" : + // "fromLine" : + // "toLine" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE))); + + QJSValue args = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount) +{ + // { "seq" : , + // "type" : "request", + // "command" : "setbreakpoint", + // "arguments" : { "type" : <"function" or "script" or "scriptId" or "scriptRegExp"> + // "target" : + // "line" : + // "column" : + // "enabled" : + // "condition" : + // "ignoreCount" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT))); + + QJSValue args = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount) +{ + // { "seq" : , + // "type" : "request", + // "command" : "changebreakpoint", + // "arguments" : { "breakpoint" : + // "enabled" : + // "condition" : + // "ignoreCount" : , + // "type" : "request", + // "command" : "clearbreakpoint", + // "arguments" : { "breakpoint" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT))); + + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + + args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint)); + + if (args.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::setExceptionBreak(Exception type, bool enabled) +{ + // { "seq" : , + // "type" : "request", + // "command" : "setexceptionbreak", + // "arguments" : { "type" : , + // "enabled" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK))); + + QJSValue args = parser.call(QJSValue(), 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.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::v8flags(QString flags) +{ + // { "seq" : , + // "type" : "request", + // "command" : "v8flags", + // "arguments" : { "flags" : + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS))); + + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + + args.setProperty(QLatin1String(FLAGS),QJSValue(flags)); + + if (args.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::version() +{ + // { "seq" : , + // "type" : "request", + // "command" : "version", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION))); + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +//void QJSDebugClient::profile(ProfileCommand command) +//{ +//// { "seq" : , +//// "type" : "request", +//// "command" : "profile", +//// "arguments" : { "command" : "resume" or "pause" } +//// } +// VARIANTMAPINIT; +// jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE))); + +// QJSValue args = parser.call(QJSValue(), 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.isValid()) { +// jsonVal.setProperty(QLatin1String(ARGUMENTS),args); +// } + +// QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); +// sendMessage(packMessage(json.toString().toUtf8())); +//} + +void QJSDebugClient::disconnect() +{ + // { "seq" : , + // "type" : "request", + // "command" : "disconnect", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT))); + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::gc() +{ + // { "seq" : , + // "type" : "request", + // "command" : "gc", + // "arguments" : { "type" : , + // } + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GC))); + + QJSValue args = parser.call(QJSValue(), QJSValueList() << obj); + + args.setProperty(QLatin1String(FLAGS),QJSValue(QLatin1String(ALL))); + + if (args.isValid()) { + jsonVal.setProperty(QLatin1String(ARGUMENTS),args); + } + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::listBreakpoints() +{ + // { "seq" : , + // "type" : "request", + // "command" : "listbreakpoints", + // } + VARIANTMAPINIT; + jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS))); + + QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal); + sendMessage(packMessage(json.toString().toUtf8())); +} + +void QJSDebugClient::statusChanged(Status status) +{ + if (status == Enabled) { + flushSendBuffer(); + emit enabled(); + } +} + +void QJSDebugClient::messageReceived(const QByteArray &data) +{ + QDataStream ds(data); + QByteArray command; + ds >> command; + + if (command == "V8DEBUG") { + ds >> response; + QString jsonString(response); + QVariantMap value = parser.call(QJSValue(), 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 == "event") { + QString event(value.value("event").toString()); + + if (event == "break" || + event == "exception") { + emit stopped(); + } + } + } +} + +void QJSDebugClient::sendMessage(const QByteArray &msg) +{ + if (status() == Enabled) { + QDeclarativeDebugClient::sendMessage(msg); + } else { + sendBuffer.append(msg); + } +} + +void QJSDebugClient::flushSendBuffer() +{ + foreach (const QByteArray &msg, sendBuffer) + QDeclarativeDebugClient::sendMessage(msg); + sendBuffer.clear(); +} + +QByteArray QJSDebugClient::packMessage(QByteArray message) +{ + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + QByteArray cmd = "V8DEBUG"; + rs << cmd << message; + return reply; +} + +void tst_QDeclarativeDebugJS::initTestCase() +{ + process = 0; + client = 0; + connection = 0; +} + +void tst_QDeclarativeDebugJS::cleanupTestCase() +{ + if (process) + delete process; + + if (client) + delete client; + + if (connection) + delete connection; +} + +void tst_QDeclarativeDebugJS::init() +{ + connection = new QDeclarativeDebugConnection(); + process = new QJSDebugProcess(); + client = new QJSDebugClient(connection); + + process->start(QStringList() << QLatin1String(BLOCKMODE) << TEST_FILE(QLatin1String(QMLFILE))); + QVERIFY(process->waitForSessionStart()); + + connection->connectToHost("127.0.0.1", 3771); + QVERIFY(connection->waitForConnected()); + + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(enabled()))); +} + +void tst_QDeclarativeDebugJS::cleanup() +{ + if (process) + delete process; + + if (client) + delete client; + + if (connection) + delete connection; + + process = 0; + client = 0; + connection = 0; +} + +void tst_QDeclarativeDebugJS::getVersion() +{ + //void version() + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->version(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::applyV8Flags() +{ + //void v8flags(QString flags) + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->v8flags(QString()); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::disconnect() +{ + //void disconnect() + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->disconnect(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::gc() +{ + //void gc() + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), 2, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->gc(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::listBreakpoints() +{ + //void listBreakpoints() + + int sourceLine1 = 57; + int sourceLine2 = 60; + int sourceLine3 = 67; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true); + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine3, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->listBreakpoints(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QList breakpoints = value.value("body").toMap().value("breakpoints").toList(); + + QCOMPARE(breakpoints.count(), 3); +} + +void tst_QDeclarativeDebugJS::setBreakpointInScriptOnCompleted() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 49; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(QMLFILE)); +} + +void tst_QDeclarativeDebugJS::setBreakpointInScriptOnTimerCallback() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 66; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(QMLFILE)); +} + +void tst_QDeclarativeDebugJS::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; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(JSFILE)); +} + +void tst_QDeclarativeDebugJS::setBreakpointInScriptOnComment() +{ + //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 = 50; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(JSFILE)); +} + +void tst_QDeclarativeDebugJS::setBreakpointInScriptOnEmptyLine() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 49; + int actualLine = 50; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(JSFILE)); +} + +void tst_QDeclarativeDebugJS::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 = 51; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true, QLatin1String("out > 10")); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Verify the value of 'out' + client->evaluate(QLatin1String("out")); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QVERIFY(body.value("value").toInt() > out); +} + +//void tst_QDeclarativeDebugJS::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->startDebugging(); +// client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true); + +// QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + +// QString jsonString(client->response); +// QVariantMap value = client->parser.call(QJSValue(), 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_QDeclarativeDebugJS::changeBreakpoint() +{ + //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine1 = 77; + int sourceLine2 = 78; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Will hit 1st brakpoint, change this breakpoint enable = false + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QList breakpointsHit = body.value("breakpoints").toList(); + + int breakpoint = breakpointsHit.at(0).toInt(); + client->changeBreakpoint(breakpoint,false); + + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Hit 2nd breakpoint + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Should stop at 2nd breakpoint + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + jsonString = client->response; + value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); +} + +void tst_QDeclarativeDebugJS::changeBreakpointOnCondition() +{ + //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine1 = 77; + int sourceLine2 = 78; + int result = 5; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Will hit 1st brakpoint, change this breakpoint enable = false + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QList breakpointsHit = body.value("breakpoints").toList(); + + int breakpoint = breakpointsHit.at(0).toInt(); + client->changeBreakpoint(breakpoint,false,QLatin1String("result > 5")); + + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Hit 2nd breakpoint + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Should stop at 2nd breakpoint + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + jsonString = client->response; + value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); + + //Verify the value of 'result' + client->evaluate(QLatin1String("result")); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + jsonString = client->response; + value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QVERIFY(body.value("value").toInt() > result); +} + +void tst_QDeclarativeDebugJS::clearBreakpoint() +{ + //void clearBreakpoint(int breakpoint); + + int sourceLine1 = 77; + int sourceLine2 = 78; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + //Will hit 1st brakpoint, change this breakpoint enable = false + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QList breakpointsHit = body.value("breakpoints").toList(); + + int breakpoint = breakpointsHit.at(0).toInt(); + client->changeBreakpoint(breakpoint,false,QLatin1String("result > 5")); + + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Hit 2nd breakpoint + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + //Continue with debugging + client->continueDebugging(QJSDebugClient::Continue); + //Should stop at 2nd breakpoint + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + jsonString = client->response; + value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); +} + +void tst_QDeclarativeDebugJS::setExceptionBreak() +{ + //void setExceptionBreak(QString type, bool enabled = false); + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->setExceptionBreak(QJSDebugClient::All,true); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + client->continueDebugging(QJSDebugClient::Continue); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); +} + +void tst_QDeclarativeDebugJS::stepNext() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 72; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Next); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(QMLFILE)); +} + +void tst_QDeclarativeDebugJS::stepNextWithCount() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 59; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Next,2); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(QMLFILE)); +} + +void tst_QDeclarativeDebugJS::stepIn() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 66; + int actualLine = 56; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::In); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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_QDeclarativeDebugJS::stepOut() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine = 56; + int actualLine = 67; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Out); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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_QDeclarativeDebugJS::continueDebugging() +{ + //void continueDebugging(StepAction stepAction, int stepCount = 1); + + int sourceLine1 = 56; + int sourceLine2 = 60; + + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true); + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->continueDebugging(QJSDebugClient::Continue); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), 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(QMLFILE)); +} + +void tst_QDeclarativeDebugJS::backtrace() +{ + //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); + + int sourceLine = 60; + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->backtrace(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::getFrameDetails() +{ + //void frame(int number = -1); + + int sourceLine = 60; + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->frame(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::getScopeDetails() +{ + //void scope(int number = -1, int frameNumber = -1); + + int sourceLine = 60; + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->scope(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::evaluateInGlobalScope() +{ + //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); + + int sourceLine = 49; + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->evaluate(QLatin1String("print('Hello World')"),true); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Verify the value of 'print' + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("text").toString(),QLatin1String("undefined")); +} + +void tst_QDeclarativeDebugJS::evaluateInLocalScope() +{ + //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); + + int sourceLine = 60; + client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->evaluate(QLatin1String("root.someValue")); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); + + //Verify the value of 'root.someValue' + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("value").toInt(),10); +} + +void tst_QDeclarativeDebugJS::getScopes() +{ + //void scopes(int frameNumber = -1); + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->scopes(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::getScripts() +{ + //void scripts(int types = -1, QList ids = QList(), bool includeSource = false, QVariant filter = QVariant()); + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->scripts(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +void tst_QDeclarativeDebugJS::getSource() +{ + //void source(int frame = -1, int fromLine = -1, int toLine = -1); + + client->interrupt(); + client->startDebugging(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + client->source(); + QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result()))); +} + +QTEST_MAIN(tst_QDeclarativeDebugJS) + +#include "tst_qdeclarativedebugjs.moc" +