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()) {
1017 connection->connectToHost("127.0.0.1", 3771);
1018 if (!connection->waitForConnected())
1021 return QQmlDebugTest::waitForSignal(client, SIGNAL(enabled()));
1024 void tst_QQmlDebugJS::cleanup()
1042 void tst_QQmlDebugJS::connect()
1048 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1051 void tst_QQmlDebugJS::interrupt()
1058 client->interrupt();
1059 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested())));
1062 void tst_QQmlDebugJS::getVersion()
1068 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1071 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1074 void tst_QQmlDebugJS::getVersionWhenAttaching()
1078 QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1082 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1085 void tst_QQmlDebugJS::applyV8Flags()
1087 //void v8flags(QString flags)
1092 client->v8flags(QString());
1093 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1096 void tst_QQmlDebugJS::disconnect()
1103 client->disconnect();
1104 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1107 void tst_QQmlDebugJS::gc()
1115 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1118 void tst_QQmlDebugJS::listBreakpoints()
1120 //void listBreakpoints()
1122 int sourceLine1 = 53;
1123 int sourceLine2 = 54;
1124 int sourceLine3 = 55;
1129 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1130 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1131 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1132 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1133 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine3, -1, true);
1134 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1135 client->listBreakpoints();
1136 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1138 QString jsonString(client->response);
1139 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1141 QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList();
1143 QCOMPARE(breakpoints.count(), 3);
1146 void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
1148 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1150 int sourceLine = 47;
1151 QVERIFY(init(ONCOMPLETED_QMLFILE));
1153 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1155 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1157 QString jsonString(client->response);
1158 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1160 QVariantMap body = value.value("body").toMap();
1162 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1163 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1166 void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
1168 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1170 int sourceLine = 47;
1171 QVERIFY(init(CREATECOMPONENT_QMLFILE));
1173 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1175 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1177 QString jsonString(client->response);
1178 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1180 QVariantMap body = value.value("body").toMap();
1182 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1183 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1186 void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
1188 int sourceLine = 48;
1189 QVERIFY(init(TIMER_QMLFILE));
1193 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine, -1, true);
1194 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1196 QString jsonString(client->response);
1197 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1199 QVariantMap body = value.value("body").toMap();
1201 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1202 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1205 void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
1207 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1209 int sourceLine = 43;
1210 QVERIFY(init(LOADJSFILE_QMLFILE));
1213 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1214 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1216 QString jsonString(client->response);
1217 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1219 QVariantMap body = value.value("body").toMap();
1221 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1222 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1225 void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
1227 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1229 int sourceLine = 47;
1230 int actualLine = 49;
1231 QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1234 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1235 QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1236 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
1238 QString jsonString(client->response);
1239 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1241 QVariantMap body = value.value("body").toMap();
1243 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1244 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1247 void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
1249 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1251 int sourceLine = 48;
1252 int actualLine = 49;
1253 QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1256 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1257 QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1258 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
1260 QString jsonString(client->response);
1261 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1263 QVariantMap body = value.value("body").toMap();
1265 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1266 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1269 void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
1271 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1273 int sourceLine = 52;
1274 QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1276 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1278 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1280 QString jsonString(client->response);
1281 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1283 QVariantMap body = value.value("body").toMap();
1285 QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1286 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1289 void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
1291 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1294 int sourceLine = 50;
1295 QVERIFY(init(CONDITION_QMLFILE));
1298 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10"));
1299 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1301 //Get the frame index
1302 QString jsonString = client->response;
1303 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1305 QVariantMap body = value.value("body").toMap();
1307 int frameIndex = body.value("index").toInt();
1309 //Verify the value of 'result'
1310 client->evaluate(QLatin1String("a"),frameIndex);
1312 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1314 jsonString = client->response;
1315 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1317 body = value.value("body").toMap();
1319 QVERIFY(body.value("value").toInt() > out);
1322 void tst_QQmlDebugJS::setBreakpointWhenAttaching()
1324 int sourceLine = 49;
1325 QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1328 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine);
1329 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1332 //void tst_QQmlDebugJS::setBreakpointInFunction()
1334 // //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1336 // int actualLine = 31;
1338 // client->connect();
1339 // client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
1341 // QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1343 // QString jsonString(client->response);
1344 // QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1346 // QVariantMap body = value.value("body").toMap();
1348 // QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1349 // QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
1352 void tst_QQmlDebugJS::setBreakpointOnEvent()
1354 //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1356 QVERIFY(init(TIMER_QMLFILE));
1360 client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true);
1361 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1363 QString jsonString(client->response);
1364 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1366 QVariantMap body = value.value("body").toMap();
1368 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1372 void tst_QQmlDebugJS::changeBreakpoint()
1374 //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1376 int sourceLine1 = 50;
1377 int sourceLine2 = 51;
1378 QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1381 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1382 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1384 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1386 //Will hit 1st brakpoint, change this breakpoint enable = false
1387 QString jsonString(client->response);
1388 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1390 QVariantMap body = value.value("body").toMap();
1391 QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1393 int breakpoint = breakpointsHit.at(0).toInt();
1394 client->changeBreakpoint(breakpoint,false);
1396 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1398 //Continue with debugging
1399 client->continueDebugging(QJSDebugClient::Continue);
1400 //Hit 2nd breakpoint
1401 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1403 //Continue with debugging
1404 client->continueDebugging(QJSDebugClient::Continue);
1405 //Should stop at 2nd breakpoint
1406 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1408 jsonString = client->response;
1409 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1411 body = value.value("body").toMap();
1413 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1416 void tst_QQmlDebugJS::changeBreakpointOnCondition()
1418 //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1420 int sourceLine1 = 50;
1421 int sourceLine2 = 51;
1423 QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1426 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1427 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1429 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1431 //Will hit 1st brakpoint, change this breakpoint enable = false
1432 QString jsonString(client->response);
1433 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1435 QVariantMap body = value.value("body").toMap();
1436 QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1438 int breakpoint = breakpointsHit.at(0).toInt();
1439 client->changeBreakpoint(breakpoint, false, QLatin1String("d == 0"));
1441 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1443 //Continue with debugging
1444 client->continueDebugging(QJSDebugClient::Continue);
1445 //Hit 2nd breakpoint
1446 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1448 //Continue with debugging
1449 client->continueDebugging(QJSDebugClient::Continue);
1450 //Should stop at 2nd breakpoint
1451 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1453 jsonString = client->response;
1454 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1456 body = value.value("body").toMap();
1458 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1462 void tst_QQmlDebugJS::clearBreakpoint()
1464 //void clearBreakpoint(int breakpoint);
1466 int sourceLine1 = 50;
1467 int sourceLine2 = 51;
1468 QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1471 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1472 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1474 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1476 //Will hit 1st brakpoint, change this breakpoint enable = false
1477 QString jsonString(client->response);
1478 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1480 QVariantMap body = value.value("body").toMap();
1481 QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1483 int breakpoint = breakpointsHit.at(0).toInt();
1484 client->clearBreakpoint(breakpoint);
1486 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1488 //Continue with debugging
1489 client->continueDebugging(QJSDebugClient::Continue);
1490 //Hit 2nd breakpoint
1491 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1493 //Continue with debugging
1494 client->continueDebugging(QJSDebugClient::Continue);
1495 //Should stop at 2nd breakpoint
1496 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1498 jsonString = client->response;
1499 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1501 body = value.value("body").toMap();
1503 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1506 void tst_QQmlDebugJS::setExceptionBreak()
1508 //void setExceptionBreak(QString type, bool enabled = false);
1510 QVERIFY(init(EXCEPTION_QMLFILE));
1511 client->setExceptionBreak(QJSDebugClient::All,true);
1513 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1516 void tst_QQmlDebugJS::stepNext()
1518 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1520 int sourceLine = 50;
1521 QVERIFY(init(STEPACTION_QMLFILE));
1523 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1525 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1527 client->continueDebugging(QJSDebugClient::Next);
1528 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1530 QString jsonString(client->response);
1531 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1533 QVariantMap body = value.value("body").toMap();
1535 QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1);
1536 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1539 void tst_QQmlDebugJS::stepNextWithCount()
1541 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1543 int sourceLine = 50;
1544 QVERIFY(init(STEPACTION_QMLFILE));
1547 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1548 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1550 client->continueDebugging(QJSDebugClient::Next, 2);
1551 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1553 QString jsonString(client->response);
1554 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1556 QVariantMap body = value.value("body").toMap();
1558 QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2);
1559 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1562 void tst_QQmlDebugJS::stepIn()
1564 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1566 int sourceLine = 54;
1567 int actualLine = 50;
1568 QVERIFY(init(STEPACTION_QMLFILE));
1571 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
1572 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1574 client->continueDebugging(QJSDebugClient::In);
1575 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1577 QString jsonString(client->response);
1578 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1580 QVariantMap body = value.value("body").toMap();
1582 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1583 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1586 void tst_QQmlDebugJS::stepOut()
1588 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1590 int sourceLine = 50;
1591 int actualLine = 54;
1592 QVERIFY(init(STEPACTION_QMLFILE));
1595 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1596 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1598 client->continueDebugging(QJSDebugClient::Out);
1599 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1601 QString jsonString(client->response);
1602 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1604 QVariantMap body = value.value("body").toMap();
1606 QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1607 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1610 void tst_QQmlDebugJS::continueDebugging()
1612 //void continueDebugging(StepAction stepAction, int stepCount = 1);
1614 int sourceLine1 = 54;
1615 int sourceLine2 = 51;
1616 QVERIFY(init(STEPACTION_QMLFILE));
1619 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
1620 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
1621 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1623 client->continueDebugging(QJSDebugClient::Continue);
1624 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1626 QString jsonString(client->response);
1627 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1629 QVariantMap body = value.value("body").toMap();
1631 QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1632 QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1635 void tst_QQmlDebugJS::backtrace()
1637 //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
1639 int sourceLine = 47;
1640 QVERIFY(init(ONCOMPLETED_QMLFILE));
1642 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1644 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1646 client->backtrace();
1647 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1650 void tst_QQmlDebugJS::getFrameDetails()
1652 //void frame(int number = -1);
1654 int sourceLine = 47;
1655 QVERIFY(init(ONCOMPLETED_QMLFILE));
1657 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1659 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1662 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1665 void tst_QQmlDebugJS::getScopeDetails()
1667 //void scope(int number = -1, int frameNumber = -1);
1669 int sourceLine = 47;
1670 QVERIFY(init(ONCOMPLETED_QMLFILE));
1672 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1674 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1677 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1680 void tst_QQmlDebugJS::evaluateInGlobalScope()
1682 //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1687 client->evaluate(QLatin1String("console.log('Hello World')"), true);
1688 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1690 //Verify the value of 'print'
1691 QString jsonString(client->response);
1692 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1694 QVariantMap body = value.value("body").toMap();
1696 QCOMPARE(body.value("text").toString(),QLatin1String("undefined"));
1699 void tst_QQmlDebugJS::evaluateInLocalScope()
1701 //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1703 int sourceLine = 47;
1704 QVERIFY(init(ONCOMPLETED_QMLFILE));
1706 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1708 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1711 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1713 //Get the frame index
1714 QString jsonString(client->response);
1715 QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1717 QVariantMap body = value.value("body").toMap();
1719 int frameIndex = body.value("index").toInt();
1721 client->evaluate(QLatin1String("root.a"), frameIndex);
1722 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1724 //Verify the value of 'timer.interval'
1725 jsonString = client->response;
1726 value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1728 body = value.value("body").toMap();
1730 QCOMPARE(body.value("value").toInt(),10);
1733 void tst_QQmlDebugJS::getScopes()
1735 //void scopes(int frameNumber = -1);
1737 int sourceLine = 47;
1738 QVERIFY(init(ONCOMPLETED_QMLFILE));
1740 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1742 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1745 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1748 void tst_QQmlDebugJS::getScripts()
1750 //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
1753 QSKIP("QTBUG-23475 - Unreliable test on Mac OS X");
1761 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult())));
1762 QString jsonString(client->response);
1763 QVariantMap value = client->parser.call(QJSValueList()
1764 << QJSValue(jsonString)).toVariant().toMap();
1766 QList<QVariant> scripts = value.value("body").toList();
1768 QCOMPARE(scripts.count(), 2);
1771 void tst_QQmlDebugJS::getSource()
1773 //void source(int frame = -1, int fromLine = -1, int toLine = -1);
1775 int sourceLine = 47;
1776 QVERIFY(init(ONCOMPLETED_QMLFILE));
1778 client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1780 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1783 QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1786 QTEST_MAIN(tst_QQmlDebugJS)
1788 #include "tst_qqmldebugjs.moc"