1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtCore/QProcess>
44 #include <QtCore/QTimer>
45 #include <QtCore/QFileInfo>
46 #include <QtCore/QDir>
47 #include <QtCore/QMutex>
48 #include <QtCore/QLibraryInfo>
49 #include <QtQml/QJSEngine>
52 #include "debugutil_p.h"
53 #include "qqmldebugclient.h"
54 #include "../../../shared/util.h"
56 const char *V8REQUEST = "v8request";
57 const char *V8MESSAGE = "v8message";
58 const char *SEQ = "seq";
59 const char *TYPE = "type";
60 const char *COMMAND = "command";
61 const char *ARGUMENTS = "arguments";
62 const char *STEPACTION = "stepaction";
63 const char *STEPCOUNT = "stepcount";
64 const char *EXPRESSION = "expression";
65 const char *FRAME = "frame";
66 const char *GLOBAL = "global";
67 const char *DISABLEBREAK = "disable_break";
68 const char *HANDLES = "handles";
69 const char *INCLUDESOURCE = "includeSource";
70 const char *FROMFRAME = "fromFrame";
71 const char *TOFRAME = "toFrame";
72 const char *BOTTOM = "bottom";
73 const char *NUMBER = "number";
74 const char *FRAMENUMBER = "frameNumber";
75 const char *TYPES = "types";
76 const char *IDS = "ids";
77 const char *FILTER = "filter";
78 const char *FROMLINE = "fromLine";
79 const char *TOLINE = "toLine";
80 const char *TARGET = "target";
81 const char *LINE = "line";
82 const char *COLUMN = "column";
83 const char *ENABLED = "enabled";
84 const char *CONDITION = "condition";
85 const char *IGNORECOUNT = "ignoreCount";
86 const char *BREAKPOINT = "breakpoint";
87 const char *FLAGS = "flags";
89 const char *CONTINEDEBUGGING = "continue";
90 const char *EVALUATE = "evaluate";
91 const char *LOOKUP = "lookup";
92 const char *BACKTRACE = "backtrace";
93 const char *SCOPE = "scope";
94 const char *SCOPES = "scopes";
95 const char *SCRIPTS = "scripts";
96 const char *SOURCE = "source";
97 const char *SETBREAKPOINT = "setbreakpoint";
98 const char *CHANGEBREAKPOINT = "changebreakpoint";
99 const char *CLEARBREAKPOINT = "clearbreakpoint";
100 const char *SETEXCEPTIONBREAK = "setexceptionbreak";
101 const char *V8FLAGS = "v8flags";
102 const char *VERSION = "version";
103 const char *DISCONNECT = "disconnect";
104 const char *LISTBREAKPOINTS = "listbreakpoints";
105 const char *GARBAGECOLLECTOR = "gc";
106 //const char *PROFILE = "profile";
108 const char *CONNECT = "connect";
109 const char *INTERRUPT = "interrupt";
111 const char *REQUEST = "request";
112 const char *IN = "in";
113 const char *NEXT = "next";
114 const char *OUT = "out";
116 const char *FUNCTION = "function";
117 const char *SCRIPT = "script";
118 const char *SCRIPTREGEXP = "scriptRegExp";
119 const char *EVENT = "event";
121 const char *ALL = "all";
122 const char *UNCAUGHT = "uncaught";
124 //const char *PAUSE = "pause";
125 //const char *RESUME = "resume";
127 const char *BLOCKMODE = "-qmljsdebugger=port:3771,block";
128 const char *NORMALMODE = "-qmljsdebugger=port:3771";
129 const char *TEST_QMLFILE = "test.qml";
130 const char *TEST_JSFILE = "test.js";
131 const char *TIMER_QMLFILE = "timer.qml";
132 const char *LOADJSFILE_QMLFILE = "loadjsfile.qml";
133 const char *EXCEPTION_QMLFILE = "exception.qml";
134 const char *ONCOMPLETED_QMLFILE = "oncompleted.qml";
135 const char *CREATECOMPONENT_QMLFILE = "createComponent.qml";
136 const char *CONDITION_QMLFILE = "condition.qml";
137 const char *CHANGEBREAKPOINT_QMLFILE = "changeBreakpoint.qml";
138 const char *STEPACTION_QMLFILE = "stepAction.qml";
139 const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml";
141 #define VARIANTMAPINIT \
143 QJSValue jsonVal = parser.call(QJSValueList() << obj); \
144 jsonVal.setProperty(SEQ,QJSValue(seq++)); \
145 jsonVal.setProperty(TYPE,REQUEST);
149 #define QVERIFY(statement) \
151 if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\
152 if (QTest::currentTestFailed()) \
153 qDebug().nospace() << "\nDEBUGGEE OUTPUT:\n" << process->output();\
159 class QJSDebugClient;
161 class tst_QQmlDebugJS : public QQmlDataTest
165 bool init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true);
169 void cleanupTestCase();
176 void getVersionWhenAttaching();
184 void listBreakpoints();
186 void setBreakpointInScriptOnCompleted();
187 void setBreakpointInScriptOnComponentCreated();
188 void setBreakpointInScriptOnTimerCallback();
189 void setBreakpointInScriptInDifferentFile();
190 void setBreakpointInScriptOnComment();
191 void setBreakpointInScriptOnEmptyLine();
192 void setBreakpointInScriptOnOptimizedBinding();
193 void setBreakpointInScriptWithCondition();
194 //void setBreakpointInFunction(); //NOT SUPPORTED
195 void setBreakpointOnEvent();
196 void setBreakpointWhenAttaching();
198 void changeBreakpoint();
199 void changeBreakpointOnCondition();
201 void clearBreakpoint();
203 void setExceptionBreak();
206 void stepNextWithCount();
209 void continueDebugging();
213 void getFrameDetails();
215 void getScopeDetails();
217 void evaluateInGlobalScope();
218 void evaluateInLocalScope();
226 // void profile(); //NOT SUPPORTED
228 // void verifyQMLOptimizerDisabled();
231 QQmlDebugProcess *process;
232 QJSDebugClient *client;
233 QQmlDebugConnection *connection;
237 class QJSDebugClient : public QQmlDebugClient
255 // enum ProfileCommand
261 QJSDebugClient(QQmlDebugConnection *connection)
262 : QQmlDebugClient(QLatin1String("V8Debugger"), connection),
265 parser = jsEngine.evaluate(QLatin1String("JSON.parse"));
266 stringify = jsEngine.evaluate(QLatin1String("JSON.stringify"));
272 void continueDebugging(StepAction stepAction, int stepCount = 1);
273 void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
274 void lookup(QList<int> handles, bool includeSource = false);
275 void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
276 void frame(int number = -1);
277 void scope(int number = -1, int frameNumber = -1);
278 void scopes(int frameNumber = -1);
279 void scripts(int types = 4, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
280 void source(int frame = -1, int fromLine = -1, int toLine = -1);
281 void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
282 void changeBreakpoint(int breakpoint, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
283 void clearBreakpoint(int breakpoint);
284 void setExceptionBreak(Exception type, bool enabled = false);
285 void v8flags(QString flags);
287 //void profile(ProfileCommand command); //NOT SUPPORTED
290 void listBreakpoints();
293 //inherited from QQmlDebugClient
294 void stateChanged(State state);
295 void messageReceived(const QByteArray &data);
300 void interruptRequested();
303 void scriptsResult();
304 void evaluateResult();
307 void sendMessage(const QByteArray &);
308 void flushSendBuffer();
309 QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
315 QList<QByteArray> sendBuffer;
323 void QJSDebugClient::connect()
325 sendMessage(packMessage(CONNECT));
328 void QJSDebugClient::interrupt()
330 sendMessage(packMessage(INTERRUPT));
333 void QJSDebugClient::continueDebugging(StepAction action, int count)
335 // { "seq" : <number>,
336 // "type" : "request",
337 // "command" : "continue",
338 // "arguments" : { "stepaction" : <"in", "next" or "out">,
339 // "stepcount" : <number of steps (default 1)>
343 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING)));
345 if (action != Continue) {
346 QJSValue args = parser.call(QJSValueList() << obj);
348 case In: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(IN)));
350 case Out: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(OUT)));
352 case Next: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(NEXT)));
356 if (!args.isUndefined()) {
358 args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count));
359 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
362 QJSValue json = stringify.call(QJSValueList() << jsonVal);
363 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
366 void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/)
368 // { "seq" : <number>,
369 // "type" : "request",
370 // "command" : "evaluate",
371 // "arguments" : { "expression" : <expression to evaluate>,
372 // "frame" : <number>,
373 // "global" : <boolean>,
374 // "disable_break" : <boolean>,
375 // "additional_context" : [
376 // { "name" : <name1>, "handle" : <handle1> },
377 // { "name" : <name2>, "handle" : <handle2> },
383 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE)));
385 QJSValue args = parser.call(QJSValueList() << obj);
386 args.setProperty(QLatin1String(EXPRESSION),QJSValue(expr));
389 args.setProperty(QLatin1String(FRAME),QJSValue(frame));
392 args.setProperty(QLatin1String(GLOBAL),QJSValue(global));
395 args.setProperty(QLatin1String(DISABLEBREAK),QJSValue(disableBreak));
397 if (!args.isUndefined()) {
398 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
401 QJSValue json = stringify.call(QJSValueList() << jsonVal);
402 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
405 void QJSDebugClient::lookup(QList<int> handles, bool includeSource)
407 // { "seq" : <number>,
408 // "type" : "request",
409 // "command" : "lookup",
410 // "arguments" : { "handles" : <array of handles>,
411 // "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
415 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP)));
417 QJSValue args = parser.call(QJSValueList() << obj);
420 QJSValue array = parser.call(QJSValueList() << arr);
422 foreach (int handle, handles) {
423 array.setProperty(index++,QJSValue(handle));
425 args.setProperty(QLatin1String(HANDLES),array);
428 args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
430 if (!args.isUndefined()) {
431 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
434 QJSValue json = stringify.call(QJSValueList() << jsonVal);
435 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
438 void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
440 // { "seq" : <number>,
441 // "type" : "request",
442 // "command" : "backtrace",
443 // "arguments" : { "fromFrame" : <number>
444 // "toFrame" : <number>
445 // "bottom" : <boolean, set to true if the bottom of the stack is requested>
449 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE)));
451 QJSValue args = parser.call(QJSValueList() << obj);
454 args.setProperty(QLatin1String(FROMFRAME),QJSValue(fromFrame));
457 args.setProperty(QLatin1String(TOFRAME),QJSValue(toFrame));
460 args.setProperty(QLatin1String(BOTTOM),QJSValue(bottom));
462 if (!args.isUndefined()) {
463 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
466 QJSValue json = stringify.call(QJSValueList() << jsonVal);
467 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
470 void QJSDebugClient::frame(int number)
472 // { "seq" : <number>,
473 // "type" : "request",
474 // "command" : "frame",
475 // "arguments" : { "number" : <frame number>
479 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME)));
482 QJSValue args = parser.call(QJSValueList() << obj);
483 args.setProperty(QLatin1String(NUMBER),QJSValue(number));
485 if (!args.isUndefined()) {
486 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
490 QJSValue json = stringify.call(QJSValueList() << jsonVal);
491 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
494 void QJSDebugClient::scope(int number, int frameNumber)
496 // { "seq" : <number>,
497 // "type" : "request",
498 // "command" : "scope",
499 // "arguments" : { "number" : <scope number>
500 // "frameNumber" : <frame number, optional uses selected frame if missing>
504 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE)));
507 QJSValue args = parser.call(QJSValueList() << obj);
508 args.setProperty(QLatin1String(NUMBER),QJSValue(number));
510 if (frameNumber != -1)
511 args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
513 if (!args.isUndefined()) {
514 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
518 QJSValue json = stringify.call(QJSValueList() << jsonVal);
519 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
522 void QJSDebugClient::scopes(int frameNumber)
524 // { "seq" : <number>,
525 // "type" : "request",
526 // "command" : "scopes",
527 // "arguments" : { "frameNumber" : <frame number, optional uses selected frame if missing>
531 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES)));
533 if (frameNumber != -1) {
534 QJSValue args = parser.call(QJSValueList() << obj);
535 args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
537 if (!args.isUndefined()) {
538 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
542 QJSValue json = stringify.call(QJSValueList() << jsonVal);
543 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
546 void QJSDebugClient::scripts(int types, QList<int> ids, bool includeSource, QVariant /*filter*/)
548 // { "seq" : <number>,
549 // "type" : "request",
550 // "command" : "scripts",
551 // "arguments" : { "types" : <types of scripts to retrieve
552 // set bit 0 for native scripts
553 // set bit 1 for extension scripts
554 // set bit 2 for normal scripts
555 // (default is 4 for normal scripts)>
556 // "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
557 // "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
558 // "filter" : <string or number: filter string or script id.
559 // If a number is specified, then only the script with the same number as its script id will be retrieved.
560 // If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
564 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS)));
566 QJSValue args = parser.call(QJSValueList() << obj);
567 args.setProperty(QLatin1String(TYPES),QJSValue(types));
571 QJSValue array = parser.call(QJSValueList() << arr);
573 foreach (int id, ids) {
574 array.setProperty(index++,QJSValue(id));
576 args.setProperty(QLatin1String(IDS),array);
580 args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
582 if (!args.isUndefined()) {
583 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
586 QJSValue json = stringify.call(QJSValueList() << jsonVal);
587 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
590 void QJSDebugClient::source(int frame, int fromLine, int toLine)
592 // { "seq" : <number>,
593 // "type" : "request",
594 // "command" : "source",
595 // "arguments" : { "frame" : <frame number (default selected frame)>
596 // "fromLine" : <from line within the source default is line 0>
597 // "toLine" : <to line within the source this line is not included in
598 // the result default is the number of lines in the script>
602 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE)));
604 QJSValue args = parser.call(QJSValueList() << obj);
607 args.setProperty(QLatin1String(FRAME),QJSValue(frame));
610 args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine));
613 args.setProperty(QLatin1String(TOLINE),QJSValue(toLine));
615 if (!args.isUndefined()) {
616 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
619 QJSValue json = stringify.call(QJSValueList() << jsonVal);
620 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
623 void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount)
625 // { "seq" : <number>,
626 // "type" : "request",
627 // "command" : "setbreakpoint",
628 // "arguments" : { "type" : <"function" or "script" or "scriptId" or "scriptRegExp">
629 // "target" : <function expression or script identification>
630 // "line" : <line in script or function>
631 // "column" : <character position within the line>
632 // "enabled" : <initial enabled state. True or false, default is true>
633 // "condition" : <string with break point condition>
634 // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
638 if (type == QLatin1String(EVENT)) {
640 QDataStream rs(&reply, QIODevice::WriteOnly);
641 rs << target.toUtf8() << enabled;
642 sendMessage(packMessage(QByteArray("breakonsignal"), reply));
646 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT)));
648 QJSValue args = parser.call(QJSValueList() << obj);
650 args.setProperty(QLatin1String(TYPE),QJSValue(type));
651 args.setProperty(QLatin1String(TARGET),QJSValue(target));
654 args.setProperty(QLatin1String(LINE),QJSValue(line));
657 args.setProperty(QLatin1String(COLUMN),QJSValue(column));
659 args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
661 if (!condition.isEmpty())
662 args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
664 if (ignoreCount != -1)
665 args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
667 if (!args.isUndefined()) {
668 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
671 QJSValue json = stringify.call(QJSValueList() << jsonVal);
672 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
676 void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount)
678 // { "seq" : <number>,
679 // "type" : "request",
680 // "command" : "changebreakpoint",
681 // "arguments" : { "breakpoint" : <number of the break point to clear>
682 // "enabled" : <initial enabled state. True or false, default is true>
683 // "condition" : <string with break point condition>
684 // "ignoreCount" : <number specifying the number of break point hits }
687 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CHANGEBREAKPOINT)));
689 QJSValue args = parser.call(QJSValueList() << obj);
691 args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
693 args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
695 if (!condition.isEmpty())
696 args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
698 if (ignoreCount != -1)
699 args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
701 if (!args.isUndefined()) {
702 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
705 QJSValue json = stringify.call(QJSValueList() << jsonVal);
706 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
709 void QJSDebugClient::clearBreakpoint(int breakpoint)
711 // { "seq" : <number>,
712 // "type" : "request",
713 // "command" : "clearbreakpoint",
714 // "arguments" : { "breakpoint" : <number of the break point to clear>
718 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT)));
720 QJSValue args = parser.call(QJSValueList() << obj);
722 args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
724 if (!args.isUndefined()) {
725 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
728 QJSValue json = stringify.call(QJSValueList() << jsonVal);
729 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
732 void QJSDebugClient::setExceptionBreak(Exception type, bool enabled)
734 // { "seq" : <number>,
735 // "type" : "request",
736 // "command" : "setexceptionbreak",
737 // "arguments" : { "type" : <string: "all", or "uncaught">,
738 // "enabled" : <optional bool: enables the break type if true>
742 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK)));
744 QJSValue args = parser.call(QJSValueList() << obj);
747 args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
748 else if (type == Uncaught)
749 args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(UNCAUGHT)));
752 args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
754 if (!args.isUndefined()) {
755 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
758 QJSValue json = stringify.call(QJSValueList() << jsonVal);
759 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
762 void QJSDebugClient::v8flags(QString flags)
764 // { "seq" : <number>,
765 // "type" : "request",
766 // "command" : "v8flags",
767 // "arguments" : { "flags" : <string: a sequence of v8 flags just like those used on the command line>
771 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS)));
773 QJSValue args = parser.call(QJSValueList() << obj);
775 args.setProperty(QLatin1String(FLAGS),QJSValue(flags));
777 if (!args.isUndefined()) {
778 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
781 QJSValue json = stringify.call(QJSValueList() << jsonVal);
782 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
785 void QJSDebugClient::version()
787 // { "seq" : <number>,
788 // "type" : "request",
789 // "command" : "version",
792 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION)));
794 QJSValue json = stringify.call(QJSValueList() << jsonVal);
795 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
798 //void QJSDebugClient::profile(ProfileCommand command)
800 //// { "seq" : <number>,
801 //// "type" : "request",
802 //// "command" : "profile",
803 //// "arguments" : { "command" : "resume" or "pause" }
806 // jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE)));
808 // QJSValue args = parser.call(QJSValueList() << obj);
810 // if (command == Resume)
811 // args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(RESUME)));
813 // args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PAUSE)));
815 // args.setProperty(QLatin1String("modules"),QJSValue(1));
816 // if (!args.isUndefined()) {
817 // jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
820 // QJSValue json = stringify.call(QJSValueList() << jsonVal);
821 // sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
824 void QJSDebugClient::disconnect()
826 // { "seq" : <number>,
827 // "type" : "request",
828 // "command" : "disconnect",
831 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT)));
833 QJSValue json = stringify.call(QJSValueList() << jsonVal);
834 sendMessage(packMessage(DISCONNECT, json.toString().toUtf8()));
837 void QJSDebugClient::gc()
839 // { "seq" : <number>,
840 // "type" : "request",
842 // "arguments" : { "type" : <string: "all">,
846 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GARBAGECOLLECTOR)));
848 QJSValue args = parser.call(QJSValueList() << obj);
850 args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
852 if (!args.isUndefined()) {
853 jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
856 QJSValue json = stringify.call(QJSValueList() << jsonVal);
857 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
860 void QJSDebugClient::listBreakpoints()
862 // { "seq" : <number>,
863 // "type" : "request",
864 // "command" : "listbreakpoints",
867 jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS)));
869 QJSValue json = stringify.call(QJSValueList() << jsonVal);
870 sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
873 void QJSDebugClient::stateChanged(State state)
875 if (state == Enabled) {
881 void QJSDebugClient::messageReceived(const QByteArray &data)
883 QDataStream ds(data);
887 if (command == "V8DEBUG") {
889 ds >> type >> response;
891 if (type == CONNECT) {
894 } else if (type == INTERRUPT) {
895 emit interruptRequested();
897 } else if (type == V8MESSAGE) {
898 QString jsonString(response);
899 QVariantMap value = parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
900 QString type = value.value("type").toString();
902 if (type == "response") {
904 if (!value.value("success").toBool()) {
905 // qDebug() << "Error: The test case will fail since no signal is emitted";
909 QString debugCommand(value.value("command").toString());
910 if (debugCommand == "backtrace" ||
911 debugCommand == "lookup" ||
912 debugCommand == "setbreakpoint" ||
913 debugCommand == "evaluate" ||
914 debugCommand == "listbreakpoints" ||
915 debugCommand == "version" ||
916 debugCommand == "v8flags" ||
917 debugCommand == "disconnect" ||
918 debugCommand == "gc" ||
919 debugCommand == "changebreakpoint" ||
920 debugCommand == "clearbreakpoint" ||
921 debugCommand == "frame" ||
922 debugCommand == "scope" ||
923 debugCommand == "scopes" ||
924 debugCommand == "scripts" ||
925 debugCommand == "source" ||
926 debugCommand == "setexceptionbreak" /*||
927 debugCommand == "profile"*/) {
933 //Emit separate signals for scripts ane evaluate
934 //as the associated test cases are flaky
935 if (debugCommand == "scripts")
936 emit scriptsResult();
937 if (debugCommand == "evaluate")
938 emit evaluateResult();
940 } else if (type == QLatin1String(EVENT)) {
941 QString event(value.value(QLatin1String(EVENT)).toString());
943 if (event == "break" ||
944 event == "exception")
952 void QJSDebugClient::sendMessage(const QByteArray &msg)
954 if (state() == Enabled) {
955 QQmlDebugClient::sendMessage(msg);
957 sendBuffer.append(msg);
961 void QJSDebugClient::flushSendBuffer()
963 foreach (const QByteArray &msg, sendBuffer)
964 QQmlDebugClient::sendMessage(msg);
968 QByteArray QJSDebugClient::packMessage(const QByteArray &type, const QByteArray &message)
971 QDataStream rs(&reply, QIODevice::WriteOnly);
972 QByteArray cmd = "V8DEBUG";
973 rs << cmd << type << message;
977 void tst_QQmlDebugJS::initTestCase()
979 QQmlDataTest::initTestCase();
986 void tst_QQmlDebugJS::cleanupTestCase()
999 // qDebug() << "Time Elapsed:" << t.elapsed();
1002 bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode)
1004 connection = new QQmlDebugConnection();
1005 process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
1006 client = new QJSDebugClient(connection);
1009 process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile));
1011 process->start(QStringList() << QLatin1String(NORMALMODE) << testFile(qmlFile));
1013 if (!process->waitForSessionStart()) {
1014 qDebug() << "could not launch application, or did not get 'Waiting for connection'.";
1018 connection->connectToHost("127.0.0.1", 3771);
1019 if (!connection->waitForConnected()) {
1020 qDebug() << "could not connect to host!";
1024 if (client->state() == QQmlDebugClient::Enabled)
1027 return QQmlDebugTest::waitForSignal(client, SIGNAL(enabled()));
1030 void tst_QQmlDebugJS::cleanup()
1032 if (QTest::currentTestFailed()) {
1033 qDebug() << "Process State:" << process->state();
1034 qDebug() << "Application Output:" << process->output();
1053 void tst_QQmlDebugJS::connect()
1059 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1062 void tst_QQmlDebugJS::interrupt()
1069 client->interrupt();
1070 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested())));
1073 void tst_QQmlDebugJS::getVersion()
1079 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1082 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1085 void tst_QQmlDebugJS::getVersionWhenAttaching()
1089 QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1093 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1096 void tst_QQmlDebugJS::applyV8Flags()
1098 //void v8flags(QString flags)
1103 client->v8flags(QString());
1104 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1107 void tst_QQmlDebugJS::disconnect()
1114 client->disconnect();
1115 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1118 void tst_QQmlDebugJS::gc()
1126 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1129 void tst_QQmlDebugJS::listBreakpoints()
1131 //void listBreakpoints()
1133 int sourceLine1 = 53;
1134 int sourceLine2 = 54;
1135 int sourceLine3 = 55;
1140 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1141 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1142 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1143 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1144 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine3, -1, true);
1145 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1146 client->listBreakpoints();
1147 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1149 QString jsonString(client->response);
1150 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1152 QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList();
1154 QCOMPARE(breakpoints.count(), 3);
1157 void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
1159 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1161 int sourceLine = 47;
1162 QVERIFY(init(ONCOMPLETED_QMLFILE));
1164 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1166 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1168 QString jsonString(client->response);
1169 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1171 QVariantMap body = value.value("body").toMap();
1173 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1174 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1177 void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
1179 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1181 int sourceLine = 47;
1182 QVERIFY(init(CREATECOMPONENT_QMLFILE));
1184 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1186 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1188 QString jsonString(client->response);
1189 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1191 QVariantMap body = value.value("body").toMap();
1193 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1194 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1197 void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
1199 int sourceLine = 48;
1200 QVERIFY(init(TIMER_QMLFILE));
1204 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine, -1, true);
1205 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1207 QString jsonString(client->response);
1208 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1210 QVariantMap body = value.value("body").toMap();
1212 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1213 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1216 void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
1218 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1220 int sourceLine = 43;
1221 QVERIFY(init(LOADJSFILE_QMLFILE));
1224 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1225 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1227 QString jsonString(client->response);
1228 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1230 QVariantMap body = value.value("body").toMap();
1232 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1233 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1236 void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
1238 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1240 int sourceLine = 47;
1241 int actualLine = 49;
1242 QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1245 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1246 QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1247 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
1249 QString jsonString(client->response);
1250 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1252 QVariantMap body = value.value("body").toMap();
1254 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1255 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1258 void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
1260 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1262 int sourceLine = 48;
1263 int actualLine = 49;
1264 QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1267 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1268 QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1269 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
1271 QString jsonString(client->response);
1272 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1274 QVariantMap body = value.value("body").toMap();
1276 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1277 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1280 void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
1282 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1284 int sourceLine = 52;
1285 QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1287 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1289 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1291 QString jsonString(client->response);
1292 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1294 QVariantMap body = value.value("body").toMap();
1296 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1297 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1300 void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
1302 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1305 int sourceLine = 50;
1306 QVERIFY(init(CONDITION_QMLFILE));
1309 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10"));
1310 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1312 //Get the frame index
1313 QString jsonString = client->response;
1314 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1316 QVariantMap body = value.value("body").toMap();
1318 int frameIndex = body.value("index").toInt();
1320 //Verify the value of 'result'
1321 client->evaluate(QLatin1String("a"),frameIndex);
1323 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1325 jsonString = client->response;
1326 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1328 body = value.value("body").toMap();
1330 QVERIFY(body.value("value").toInt() > out);
1333 void tst_QQmlDebugJS::setBreakpointWhenAttaching()
1335 int sourceLine = 49;
1336 QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1339 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine);
1340 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1343 //void tst_QQmlDebugJS::setBreakpointInFunction()
1345 // //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1347 // int actualLine = 31;
1349 // client->connect();
1350 // client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
1352 // QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1354 // QString jsonString(client->response);
1355 // QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1357 // QVariantMap body = value.value("body").toMap();
1359 // QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1360 // QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
1363 void tst_QQmlDebugJS::setBreakpointOnEvent()
1365 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1367 QVERIFY(init(TIMER_QMLFILE));
1371 client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true);
1372 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1374 QString jsonString(client->response);
1375 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1377 QVariantMap body = value.value("body").toMap();
1379 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1383 void tst_QQmlDebugJS::changeBreakpoint()
1385 //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1387 int sourceLine1 = 50;
1388 int sourceLine2 = 51;
1389 QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1392 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1393 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1395 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1397 //Will hit 1st brakpoint, change this breakpoint enable = false
1398 QString jsonString(client->response);
1399 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1401 QVariantMap body = value.value("body").toMap();
1402 QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1404 int breakpoint = breakpointsHit.at(0).toInt();
1405 client->changeBreakpoint(breakpoint,false);
1407 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1409 //Continue with debugging
1410 client->continueDebugging(QJSDebugClient::Continue);
1411 //Hit 2nd breakpoint
1412 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1414 //Continue with debugging
1415 client->continueDebugging(QJSDebugClient::Continue);
1416 //Should stop at 2nd breakpoint
1417 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1419 jsonString = client->response;
1420 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1422 body = value.value("body").toMap();
1424 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1427 void tst_QQmlDebugJS::changeBreakpointOnCondition()
1429 //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1431 int sourceLine1 = 50;
1432 int sourceLine2 = 51;
1434 QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1437 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1438 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1440 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1442 //Will hit 1st brakpoint, change this breakpoint enable = false
1443 QString jsonString(client->response);
1444 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1446 QVariantMap body = value.value("body").toMap();
1447 QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1449 int breakpoint = breakpointsHit.at(0).toInt();
1450 client->changeBreakpoint(breakpoint, false, QLatin1String("d == 0"));
1452 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1454 //Continue with debugging
1455 client->continueDebugging(QJSDebugClient::Continue);
1456 //Hit 2nd breakpoint
1457 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1459 //Continue with debugging
1460 client->continueDebugging(QJSDebugClient::Continue);
1461 //Should stop at 2nd breakpoint
1462 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1464 jsonString = client->response;
1465 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1467 body = value.value("body").toMap();
1469 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1473 void tst_QQmlDebugJS::clearBreakpoint()
1475 //void clearBreakpoint(int breakpoint);
1477 int sourceLine1 = 50;
1478 int sourceLine2 = 51;
1479 QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1482 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1483 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1485 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1487 //Will hit 1st brakpoint, change this breakpoint enable = false
1488 QString jsonString(client->response);
1489 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1491 QVariantMap body = value.value("body").toMap();
1492 QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1494 int breakpoint = breakpointsHit.at(0).toInt();
1495 client->clearBreakpoint(breakpoint);
1497 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1499 //Continue with debugging
1500 client->continueDebugging(QJSDebugClient::Continue);
1501 //Hit 2nd breakpoint
1502 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1504 //Continue with debugging
1505 client->continueDebugging(QJSDebugClient::Continue);
1506 //Should stop at 2nd breakpoint
1507 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1509 jsonString = client->response;
1510 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1512 body = value.value("body").toMap();
1514 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1517 void tst_QQmlDebugJS::setExceptionBreak()
1519 //void setExceptionBreak(QString type, bool enabled = false);
1521 QVERIFY(init(EXCEPTION_QMLFILE));
1522 client->setExceptionBreak(QJSDebugClient::All,true);
1524 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1527 void tst_QQmlDebugJS::stepNext()
1529 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1531 int sourceLine = 50;
1532 QVERIFY(init(STEPACTION_QMLFILE));
1534 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1536 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1538 client->continueDebugging(QJSDebugClient::Next);
1539 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1541 QString jsonString(client->response);
1542 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1544 QVariantMap body = value.value("body").toMap();
1546 QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1);
1547 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1550 void tst_QQmlDebugJS::stepNextWithCount()
1552 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1554 int sourceLine = 50;
1555 QVERIFY(init(STEPACTION_QMLFILE));
1558 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1559 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1561 client->continueDebugging(QJSDebugClient::Next, 2);
1562 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1564 QString jsonString(client->response);
1565 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1567 QVariantMap body = value.value("body").toMap();
1569 QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2);
1570 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1573 void tst_QQmlDebugJS::stepIn()
1575 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1577 int sourceLine = 54;
1578 int actualLine = 50;
1579 QVERIFY(init(STEPACTION_QMLFILE));
1582 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
1583 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1585 client->continueDebugging(QJSDebugClient::In);
1586 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1588 QString jsonString(client->response);
1589 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1591 QVariantMap body = value.value("body").toMap();
1593 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1594 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1597 void tst_QQmlDebugJS::stepOut()
1599 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1601 int sourceLine = 50;
1602 int actualLine = 54;
1603 QVERIFY(init(STEPACTION_QMLFILE));
1606 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1607 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1609 client->continueDebugging(QJSDebugClient::Out);
1610 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1612 QString jsonString(client->response);
1613 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1615 QVariantMap body = value.value("body").toMap();
1617 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1618 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1621 void tst_QQmlDebugJS::continueDebugging()
1623 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1625 int sourceLine1 = 54;
1626 int sourceLine2 = 51;
1627 QVERIFY(init(STEPACTION_QMLFILE));
1630 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
1631 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
1632 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1634 client->continueDebugging(QJSDebugClient::Continue);
1635 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1637 QString jsonString(client->response);
1638 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1640 QVariantMap body = value.value("body").toMap();
1642 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1643 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1646 void tst_QQmlDebugJS::backtrace()
1648 //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
1650 int sourceLine = 47;
1651 QVERIFY(init(ONCOMPLETED_QMLFILE));
1653 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1655 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1657 client->backtrace();
1658 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1661 void tst_QQmlDebugJS::getFrameDetails()
1663 //void frame(int number = -1);
1665 int sourceLine = 47;
1666 QVERIFY(init(ONCOMPLETED_QMLFILE));
1668 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1670 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1673 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1676 void tst_QQmlDebugJS::getScopeDetails()
1678 //void scope(int number = -1, int frameNumber = -1);
1680 int sourceLine = 47;
1681 QVERIFY(init(ONCOMPLETED_QMLFILE));
1683 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1685 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1688 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1691 void tst_QQmlDebugJS::evaluateInGlobalScope()
1693 //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1698 client->evaluate(QLatin1String("console.log('Hello World')"), true);
1699 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1701 //Verify the value of 'print'
1702 QString jsonString(client->response);
1703 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1705 QVariantMap body = value.value("body").toMap();
1707 QCOMPARE(body.value("text").toString(),QLatin1String("undefined"));
1710 void tst_QQmlDebugJS::evaluateInLocalScope()
1712 //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1714 int sourceLine = 47;
1715 QVERIFY(init(ONCOMPLETED_QMLFILE));
1717 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1719 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1722 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1724 //Get the frame index
1725 QString jsonString(client->response);
1726 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1728 QVariantMap body = value.value("body").toMap();
1730 int frameIndex = body.value("index").toInt();
1732 client->evaluate(QLatin1String("root.a"), frameIndex);
1733 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1735 //Verify the value of 'timer.interval'
1736 jsonString = client->response;
1737 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1739 body = value.value("body").toMap();
1741 QCOMPARE(body.value("value").toInt(),10);
1744 void tst_QQmlDebugJS::getScopes()
1746 //void scopes(int frameNumber = -1);
1748 int sourceLine = 47;
1749 QVERIFY(init(ONCOMPLETED_QMLFILE));
1751 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1753 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1756 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1759 void tst_QQmlDebugJS::getScripts()
1761 //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
1764 QSKIP("QTBUG-23475 - Unreliable test on Mac OS X");
1772 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult())));
1773 QString jsonString(client->response);
1774 QVariantMap value = client->parser.call(QJSValueList()
1775 << QJSValue(jsonString)).toVariant().toMap();
1777 QList<QVariant> scripts = value.value("body").toList();
1779 QCOMPARE(scripts.count(), 2);
1782 void tst_QQmlDebugJS::getSource()
1784 //void source(int frame = -1, int fromLine = -1, int toLine = -1);
1786 int sourceLine = 47;
1787 QVERIFY(init(ONCOMPLETED_QMLFILE));
1789 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1791 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1794 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1797 QTEST_MAIN(tst_QQmlDebugJS)
1799 #include "tst_qqmldebugjs.moc"