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";
110
const char *BREAKAFTERCOMPILE = "breakaftercompile";
112
const char *REQUEST = "request";
113
const char *IN = "in";
114
const char *NEXT = "next";
115
const char *OUT = "out";
117
const char *FUNCTION = "function";
118
const char *SCRIPT = "script";
119
const char *SCRIPTREGEXP = "scriptRegExp";
120
const char *EVENT = "event";
122
const char *ALL = "all";
123
const char *UNCAUGHT = "uncaught";
125
//const char *PAUSE = "pause";
126
//const char *RESUME = "resume";
128
const char *BLOCKMODE = "-qmljsdebugger=port:3771,block";
129
const char *NORMALMODE = "-qmljsdebugger=port:3771";
130
const char *TEST_QMLFILE = "test.qml";
131
const char *TEST_JSFILE = "test.js";
132
const char *TIMER_QMLFILE = "timer.qml";
133
const char *LOADJSFILE_QMLFILE = "loadjsfile.qml";
134
const char *EXCEPTION_QMLFILE = "exception.qml";
135
const char *ONCOMPLETED_QMLFILE = "oncompleted.qml";
136
const char *CREATECOMPONENT_QMLFILE = "createComponent.qml";
137
const char *CONDITION_QMLFILE = "condition.qml";
138
const char *CHANGEBREAKPOINT_QMLFILE = "changeBreakpoint.qml";
139
const char *STEPACTION_QMLFILE = "stepAction.qml";
140
const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml";
142
#define VARIANTMAPINIT \
144
QJSValue jsonVal = parser.call(QJSValueList() << obj); \
145
jsonVal.setProperty(SEQ,QJSValue(seq++)); \
146
jsonVal.setProperty(TYPE,REQUEST);
150
#define QVERIFY(statement) \
152
if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\
153
if (QTest::currentTestFailed()) \
154
qDebug().nospace() << "\nDEBUGGEE OUTPUT:\n" << process->output();\
160
class QJSDebugClient;
162
class tst_QQmlDebugJS : public QQmlDataTest
166
bool init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true);
170
void cleanupTestCase();
176
void breakAfterCompile();
178
void getVersionWhenAttaching();
186
void listBreakpoints();
188
void setBreakpointInScriptOnCompleted();
189
void setBreakpointInScriptOnComponentCreated();
190
void setBreakpointInScriptOnTimerCallback();
191
void setBreakpointInScriptInDifferentFile();
192
void setBreakpointInScriptOnComment();
193
void setBreakpointInScriptOnEmptyLine();
194
void setBreakpointInScriptOnOptimizedBinding();
195
void setBreakpointInScriptWithCondition();
196
//void setBreakpointInFunction(); //NOT SUPPORTED
197
void setBreakpointOnEvent();
198
void setBreakpointWhenAttaching();
200
void changeBreakpoint();
201
void changeBreakpointOnCondition();
203
void clearBreakpoint();
205
void setExceptionBreak();
208
void stepNextWithCount();
211
void continueDebugging();
215
void getFrameDetails();
217
void getScopeDetails();
219
void evaluateInGlobalScope();
220
void evaluateInLocalScope();
228
// void profile(); //NOT SUPPORTED
230
// void verifyQMLOptimizerDisabled();
233
QQmlDebugProcess *process;
234
QJSDebugClient *client;
235
QQmlDebugConnection *connection;
239
class QJSDebugClient : public QQmlDebugClient
257
// enum ProfileCommand
263
QJSDebugClient(QQmlDebugConnection *connection)
264
: QQmlDebugClient(QLatin1String("V8Debugger"), connection),
267
parser = jsEngine.evaluate(QLatin1String("JSON.parse"));
268
stringify = jsEngine.evaluate(QLatin1String("JSON.stringify"));
273
void breakAfterCompile(bool enabled);
275
void continueDebugging(StepAction stepAction, int stepCount = 1);
276
void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
277
void lookup(QList<int> handles, bool includeSource = false);
278
void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
279
void frame(int number = -1);
280
void scope(int number = -1, int frameNumber = -1);
281
void scopes(int frameNumber = -1);
282
void scripts(int types = 4, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
283
void source(int frame = -1, int fromLine = -1, int toLine = -1);
284
void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
285
void changeBreakpoint(int breakpoint, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
286
void clearBreakpoint(int breakpoint);
287
void setExceptionBreak(Exception type, bool enabled = false);
288
void v8flags(QString flags);
290
//void profile(ProfileCommand command); //NOT SUPPORTED
293
void listBreakpoints();
296
//inherited from QQmlDebugClient
297
void stateChanged(State state);
298
void messageReceived(const QByteArray &data);
303
void interruptRequested();
304
void breakAfterCompileRequested();
307
void scriptsResult();
308
void evaluateResult();
311
void sendMessage(const QByteArray &);
312
void flushSendBuffer();
313
QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
319
QList<QByteArray> sendBuffer;
327
void QJSDebugClient::connect()
329
sendMessage(packMessage(CONNECT));
332
void QJSDebugClient::interrupt()
334
sendMessage(packMessage(INTERRUPT));
337
void QJSDebugClient::breakAfterCompile(bool enabled)
340
QDataStream rs(&request, QIODevice::WriteOnly);
342
sendMessage(packMessage(BREAKAFTERCOMPILE, request));
345
void QJSDebugClient::continueDebugging(StepAction action, int count)
347
// { "seq" : <number>,
348
// "type" : "request",
349
// "command" : "continue",
350
// "arguments" : { "stepaction" : <"in", "next" or "out">,
351
// "stepcount" : <number of steps (default 1)>
355
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING)));
357
if (action != Continue) {
358
QJSValue args = parser.call(QJSValueList() << obj);
360
case In: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(IN)));
362
case Out: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(OUT)));
364
case Next: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(NEXT)));
368
if (!args.isUndefined()) {
370
args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count));
371
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
374
QJSValue json = stringify.call(QJSValueList() << jsonVal);
375
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
378
void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/)
380
// { "seq" : <number>,
381
// "type" : "request",
382
// "command" : "evaluate",
383
// "arguments" : { "expression" : <expression to evaluate>,
384
// "frame" : <number>,
385
// "global" : <boolean>,
386
// "disable_break" : <boolean>,
387
// "additional_context" : [
388
// { "name" : <name1>, "handle" : <handle1> },
389
// { "name" : <name2>, "handle" : <handle2> },
395
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE)));
397
QJSValue args = parser.call(QJSValueList() << obj);
398
args.setProperty(QLatin1String(EXPRESSION),QJSValue(expr));
401
args.setProperty(QLatin1String(FRAME),QJSValue(frame));
404
args.setProperty(QLatin1String(GLOBAL),QJSValue(global));
407
args.setProperty(QLatin1String(DISABLEBREAK),QJSValue(disableBreak));
409
if (!args.isUndefined()) {
410
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
413
QJSValue json = stringify.call(QJSValueList() << jsonVal);
414
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
417
void QJSDebugClient::lookup(QList<int> handles, bool includeSource)
419
// { "seq" : <number>,
420
// "type" : "request",
421
// "command" : "lookup",
422
// "arguments" : { "handles" : <array of handles>,
423
// "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
427
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP)));
429
QJSValue args = parser.call(QJSValueList() << obj);
432
QJSValue array = parser.call(QJSValueList() << arr);
434
foreach (int handle, handles) {
435
array.setProperty(index++,QJSValue(handle));
437
args.setProperty(QLatin1String(HANDLES),array);
440
args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
442
if (!args.isUndefined()) {
443
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
446
QJSValue json = stringify.call(QJSValueList() << jsonVal);
447
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
450
void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
452
// { "seq" : <number>,
453
// "type" : "request",
454
// "command" : "backtrace",
455
// "arguments" : { "fromFrame" : <number>
456
// "toFrame" : <number>
457
// "bottom" : <boolean, set to true if the bottom of the stack is requested>
461
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE)));
463
QJSValue args = parser.call(QJSValueList() << obj);
466
args.setProperty(QLatin1String(FROMFRAME),QJSValue(fromFrame));
469
args.setProperty(QLatin1String(TOFRAME),QJSValue(toFrame));
472
args.setProperty(QLatin1String(BOTTOM),QJSValue(bottom));
474
if (!args.isUndefined()) {
475
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
478
QJSValue json = stringify.call(QJSValueList() << jsonVal);
479
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
482
void QJSDebugClient::frame(int number)
484
// { "seq" : <number>,
485
// "type" : "request",
486
// "command" : "frame",
487
// "arguments" : { "number" : <frame number>
491
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME)));
494
QJSValue args = parser.call(QJSValueList() << obj);
495
args.setProperty(QLatin1String(NUMBER),QJSValue(number));
497
if (!args.isUndefined()) {
498
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
502
QJSValue json = stringify.call(QJSValueList() << jsonVal);
503
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
506
void QJSDebugClient::scope(int number, int frameNumber)
508
// { "seq" : <number>,
509
// "type" : "request",
510
// "command" : "scope",
511
// "arguments" : { "number" : <scope number>
512
// "frameNumber" : <frame number, optional uses selected frame if missing>
516
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE)));
519
QJSValue args = parser.call(QJSValueList() << obj);
520
args.setProperty(QLatin1String(NUMBER),QJSValue(number));
522
if (frameNumber != -1)
523
args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
525
if (!args.isUndefined()) {
526
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
530
QJSValue json = stringify.call(QJSValueList() << jsonVal);
531
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
534
void QJSDebugClient::scopes(int frameNumber)
536
// { "seq" : <number>,
537
// "type" : "request",
538
// "command" : "scopes",
539
// "arguments" : { "frameNumber" : <frame number, optional uses selected frame if missing>
543
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES)));
545
if (frameNumber != -1) {
546
QJSValue args = parser.call(QJSValueList() << obj);
547
args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
549
if (!args.isUndefined()) {
550
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
554
QJSValue json = stringify.call(QJSValueList() << jsonVal);
555
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
558
void QJSDebugClient::scripts(int types, QList<int> ids, bool includeSource, QVariant /*filter*/)
560
// { "seq" : <number>,
561
// "type" : "request",
562
// "command" : "scripts",
563
// "arguments" : { "types" : <types of scripts to retrieve
564
// set bit 0 for native scripts
565
// set bit 1 for extension scripts
566
// set bit 2 for normal scripts
567
// (default is 4 for normal scripts)>
568
// "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
569
// "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
570
// "filter" : <string or number: filter string or script id.
571
// If a number is specified, then only the script with the same number as its script id will be retrieved.
572
// If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
576
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS)));
578
QJSValue args = parser.call(QJSValueList() << obj);
579
args.setProperty(QLatin1String(TYPES),QJSValue(types));
583
QJSValue array = parser.call(QJSValueList() << arr);
585
foreach (int id, ids) {
586
array.setProperty(index++,QJSValue(id));
588
args.setProperty(QLatin1String(IDS),array);
592
args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
594
if (!args.isUndefined()) {
595
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
598
QJSValue json = stringify.call(QJSValueList() << jsonVal);
599
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
602
void QJSDebugClient::source(int frame, int fromLine, int toLine)
604
// { "seq" : <number>,
605
// "type" : "request",
606
// "command" : "source",
607
// "arguments" : { "frame" : <frame number (default selected frame)>
608
// "fromLine" : <from line within the source default is line 0>
609
// "toLine" : <to line within the source this line is not included in
610
// the result default is the number of lines in the script>
614
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE)));
616
QJSValue args = parser.call(QJSValueList() << obj);
619
args.setProperty(QLatin1String(FRAME),QJSValue(frame));
622
args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine));
625
args.setProperty(QLatin1String(TOLINE),QJSValue(toLine));
627
if (!args.isUndefined()) {
628
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
631
QJSValue json = stringify.call(QJSValueList() << jsonVal);
632
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
635
void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount)
637
// { "seq" : <number>,
638
// "type" : "request",
639
// "command" : "setbreakpoint",
640
// "arguments" : { "type" : <"function" or "script" or "scriptId" or "scriptRegExp">
641
// "target" : <function expression or script identification>
642
// "line" : <line in script or function>
643
// "column" : <character position within the line>
644
// "enabled" : <initial enabled state. True or false, default is true>
645
// "condition" : <string with break point condition>
646
// "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
650
if (type == QLatin1String(EVENT)) {
652
QDataStream rs(&reply, QIODevice::WriteOnly);
653
rs << target.toUtf8() << enabled;
654
sendMessage(packMessage(QByteArray("breakonsignal"), reply));
658
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT)));
660
QJSValue args = parser.call(QJSValueList() << obj);
662
args.setProperty(QLatin1String(TYPE),QJSValue(type));
663
args.setProperty(QLatin1String(TARGET),QJSValue(target));
666
args.setProperty(QLatin1String(LINE),QJSValue(line));
669
args.setProperty(QLatin1String(COLUMN),QJSValue(column));
671
args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
673
if (!condition.isEmpty())
674
args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
676
if (ignoreCount != -1)
677
args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
679
if (!args.isUndefined()) {
680
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
683
QJSValue json = stringify.call(QJSValueList() << jsonVal);
684
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
688
void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount)
690
// { "seq" : <number>,
691
// "type" : "request",
692
// "command" : "changebreakpoint",
693
// "arguments" : { "breakpoint" : <number of the break point to clear>
694
// "enabled" : <initial enabled state. True or false, default is true>
695
// "condition" : <string with break point condition>
696
// "ignoreCount" : <number specifying the number of break point hits }
699
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CHANGEBREAKPOINT)));
701
QJSValue args = parser.call(QJSValueList() << obj);
703
args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
705
args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
707
if (!condition.isEmpty())
708
args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
710
if (ignoreCount != -1)
711
args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
713
if (!args.isUndefined()) {
714
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
717
QJSValue json = stringify.call(QJSValueList() << jsonVal);
718
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
721
void QJSDebugClient::clearBreakpoint(int breakpoint)
723
// { "seq" : <number>,
724
// "type" : "request",
725
// "command" : "clearbreakpoint",
726
// "arguments" : { "breakpoint" : <number of the break point to clear>
730
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT)));
732
QJSValue args = parser.call(QJSValueList() << obj);
734
args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
736
if (!args.isUndefined()) {
737
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
740
QJSValue json = stringify.call(QJSValueList() << jsonVal);
741
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
744
void QJSDebugClient::setExceptionBreak(Exception type, bool enabled)
746
// { "seq" : <number>,
747
// "type" : "request",
748
// "command" : "setexceptionbreak",
749
// "arguments" : { "type" : <string: "all", or "uncaught">,
750
// "enabled" : <optional bool: enables the break type if true>
754
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK)));
756
QJSValue args = parser.call(QJSValueList() << obj);
759
args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
760
else if (type == Uncaught)
761
args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(UNCAUGHT)));
764
args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
766
if (!args.isUndefined()) {
767
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
770
QJSValue json = stringify.call(QJSValueList() << jsonVal);
771
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
774
void QJSDebugClient::v8flags(QString flags)
776
// { "seq" : <number>,
777
// "type" : "request",
778
// "command" : "v8flags",
779
// "arguments" : { "flags" : <string: a sequence of v8 flags just like those used on the command line>
783
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS)));
785
QJSValue args = parser.call(QJSValueList() << obj);
787
args.setProperty(QLatin1String(FLAGS),QJSValue(flags));
789
if (!args.isUndefined()) {
790
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
793
QJSValue json = stringify.call(QJSValueList() << jsonVal);
794
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
797
void QJSDebugClient::version()
799
// { "seq" : <number>,
800
// "type" : "request",
801
// "command" : "version",
804
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION)));
806
QJSValue json = stringify.call(QJSValueList() << jsonVal);
807
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
810
//void QJSDebugClient::profile(ProfileCommand command)
812
//// { "seq" : <number>,
813
//// "type" : "request",
814
//// "command" : "profile",
815
//// "arguments" : { "command" : "resume" or "pause" }
818
// jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE)));
820
// QJSValue args = parser.call(QJSValueList() << obj);
822
// if (command == Resume)
823
// args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(RESUME)));
825
// args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PAUSE)));
827
// args.setProperty(QLatin1String("modules"),QJSValue(1));
828
// if (!args.isUndefined()) {
829
// jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
832
// QJSValue json = stringify.call(QJSValueList() << jsonVal);
833
// sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
836
void QJSDebugClient::disconnect()
838
// { "seq" : <number>,
839
// "type" : "request",
840
// "command" : "disconnect",
843
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT)));
845
QJSValue json = stringify.call(QJSValueList() << jsonVal);
846
sendMessage(packMessage(DISCONNECT, json.toString().toUtf8()));
849
void QJSDebugClient::gc()
851
// { "seq" : <number>,
852
// "type" : "request",
854
// "arguments" : { "type" : <string: "all">,
858
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GARBAGECOLLECTOR)));
860
QJSValue args = parser.call(QJSValueList() << obj);
862
args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
864
if (!args.isUndefined()) {
865
jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
868
QJSValue json = stringify.call(QJSValueList() << jsonVal);
869
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
872
void QJSDebugClient::listBreakpoints()
874
// { "seq" : <number>,
875
// "type" : "request",
876
// "command" : "listbreakpoints",
879
jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS)));
881
QJSValue json = stringify.call(QJSValueList() << jsonVal);
882
sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
885
void QJSDebugClient::stateChanged(State state)
887
if (state == Enabled) {
893
void QJSDebugClient::messageReceived(const QByteArray &data)
895
QDataStream ds(data);
899
if (command == "V8DEBUG") {
901
ds >> type >> response;
903
if (type == CONNECT) {
906
} else if (type == INTERRUPT) {
907
emit interruptRequested();
909
} else if (type == V8MESSAGE) {
910
QString jsonString(response);
911
QVariantMap value = parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
912
QString type = value.value("type").toString();
914
if (type == "response") {
916
if (!value.value("success").toBool()) {
917
// qDebug() << "Error: The test case will fail since no signal is emitted";
921
QString debugCommand(value.value("command").toString());
922
if (debugCommand == "backtrace" ||
923
debugCommand == "lookup" ||
924
debugCommand == "setbreakpoint" ||
925
debugCommand == "evaluate" ||
926
debugCommand == "listbreakpoints" ||
927
debugCommand == "version" ||
928
debugCommand == "v8flags" ||
929
debugCommand == "disconnect" ||
930
debugCommand == "gc" ||
931
debugCommand == "changebreakpoint" ||
932
debugCommand == "clearbreakpoint" ||
933
debugCommand == "frame" ||
934
debugCommand == "scope" ||
935
debugCommand == "scopes" ||
936
debugCommand == "scripts" ||
937
debugCommand == "source" ||
938
debugCommand == "setexceptionbreak" /*||
939
debugCommand == "profile"*/) {
945
//Emit separate signals for scripts ane evaluate
946
//as the associated test cases are flaky
947
if (debugCommand == "scripts")
948
emit scriptsResult();
949
if (debugCommand == "evaluate")
950
emit evaluateResult();
952
} else if (type == QLatin1String(EVENT)) {
953
QString event(value.value(QLatin1String(EVENT)).toString());
955
if (event == "break" ||
956
event == "exception")
960
} else if (type == BREAKAFTERCOMPILE) {
961
emit breakAfterCompileRequested();
967
void QJSDebugClient::sendMessage(const QByteArray &msg)
969
if (state() == Enabled) {
970
QQmlDebugClient::sendMessage(msg);
972
sendBuffer.append(msg);
976
void QJSDebugClient::flushSendBuffer()
978
foreach (const QByteArray &msg, sendBuffer)
979
QQmlDebugClient::sendMessage(msg);
983
QByteArray QJSDebugClient::packMessage(const QByteArray &type, const QByteArray &message)
986
QDataStream rs(&reply, QIODevice::WriteOnly);
987
QByteArray cmd = "V8DEBUG";
988
rs << cmd << type << message;
992
void tst_QQmlDebugJS::initTestCase()
994
QQmlDataTest::initTestCase();
1001
void tst_QQmlDebugJS::cleanupTestCase()
1014
// qDebug() << "Time Elapsed:" << t.elapsed();
1017
bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode)
1019
connection = new QQmlDebugConnection();
1020
process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
1021
client = new QJSDebugClient(connection);
1024
process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile));
1026
process->start(QStringList() << QLatin1String(NORMALMODE) << testFile(qmlFile));
1028
if (!process->waitForSessionStart()) {
1032
connection->connectToHost("127.0.0.1", 3771);
1033
if (!connection->waitForConnected())
1036
return QQmlDebugTest::waitForSignal(client, SIGNAL(enabled()));
1039
void tst_QQmlDebugJS::cleanup()
1057
void tst_QQmlDebugJS::connect()
1063
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1066
void tst_QQmlDebugJS::interrupt()
1073
client->interrupt();
1074
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested())));
1077
void tst_QQmlDebugJS::breakAfterCompile()
1079
//void breakAfterCompile(bool enabled)
1082
client->breakAfterCompile(true);
1085
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(breakAfterCompileRequested())));
1086
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1089
void tst_QQmlDebugJS::getVersion()
1095
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1098
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1101
void tst_QQmlDebugJS::getVersionWhenAttaching()
1105
QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1109
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1112
void tst_QQmlDebugJS::applyV8Flags()
1114
//void v8flags(QString flags)
1119
client->v8flags(QString());
1120
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1123
void tst_QQmlDebugJS::disconnect()
1130
client->disconnect();
1131
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1134
void tst_QQmlDebugJS::gc()
1142
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1145
void tst_QQmlDebugJS::listBreakpoints()
1147
//void listBreakpoints()
1149
int sourceLine1 = 47;
1150
int sourceLine2 = 48;
1151
int sourceLine3 = 49;
1156
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1157
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1158
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1159
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1160
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_QMLFILE), sourceLine3, -1, true);
1161
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1162
client->listBreakpoints();
1163
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1165
QString jsonString(client->response);
1166
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1168
QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList();
1170
QCOMPARE(breakpoints.count(), 3);
1173
void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
1175
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1177
int sourceLine = 47;
1178
QVERIFY(init(ONCOMPLETED_QMLFILE));
1180
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1182
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1184
QString jsonString(client->response);
1185
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1187
QVariantMap body = value.value("body").toMap();
1189
QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1190
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1193
void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
1195
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1197
int sourceLine = 47;
1198
QVERIFY(init(CREATECOMPONENT_QMLFILE));
1200
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1202
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1204
QString jsonString(client->response);
1205
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1207
QVariantMap body = value.value("body").toMap();
1209
QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1210
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1213
void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
1215
int sourceLine = 48;
1216
QVERIFY(init(TIMER_QMLFILE));
1220
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine, -1, true);
1221
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1223
QString jsonString(client->response);
1224
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1226
QVariantMap body = value.value("body").toMap();
1228
QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1229
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1232
void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
1234
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1236
int sourceLine = 43;
1237
QVERIFY(init(LOADJSFILE_QMLFILE));
1240
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1241
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1243
QString jsonString(client->response);
1244
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1246
QVariantMap body = value.value("body").toMap();
1248
QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1249
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1252
void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
1254
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1256
int sourceLine = 47;
1257
int actualLine = 49;
1258
QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1261
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1262
QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1263
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
1265
QString jsonString(client->response);
1266
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1268
QVariantMap body = value.value("body").toMap();
1270
QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1271
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1274
void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
1276
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1278
int sourceLine = 48;
1279
int actualLine = 49;
1280
QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1283
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1284
QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1285
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
1287
QString jsonString(client->response);
1288
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1290
QVariantMap body = value.value("body").toMap();
1292
QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1293
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1296
void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
1298
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1300
int sourceLine = 52;
1301
QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1303
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1305
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1307
QString jsonString(client->response);
1308
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1310
QVariantMap body = value.value("body").toMap();
1312
QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1313
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1316
void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
1318
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1321
int sourceLine = 50;
1322
QVERIFY(init(CONDITION_QMLFILE));
1325
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10"));
1326
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1328
//Get the frame index
1329
QString jsonString = client->response;
1330
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1332
QVariantMap body = value.value("body").toMap();
1334
int frameIndex = body.value("index").toInt();
1336
//Verify the value of 'result'
1337
client->evaluate(QLatin1String("a"),frameIndex);
1339
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1341
jsonString = client->response;
1342
value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1344
body = value.value("body").toMap();
1346
QVERIFY(body.value("value").toInt() > out);
1349
void tst_QQmlDebugJS::setBreakpointWhenAttaching()
1351
int sourceLine = 49;
1352
QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1355
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine);
1356
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1359
//void tst_QQmlDebugJS::setBreakpointInFunction()
1361
// //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1363
// int actualLine = 31;
1365
// client->connect();
1366
// client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
1368
// QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1370
// QString jsonString(client->response);
1371
// QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1373
// QVariantMap body = value.value("body").toMap();
1375
// QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1376
// QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
1379
void tst_QQmlDebugJS::setBreakpointOnEvent()
1381
//void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1383
QVERIFY(init(TIMER_QMLFILE));
1387
client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true);
1388
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1390
QString jsonString(client->response);
1391
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1393
QVariantMap body = value.value("body").toMap();
1395
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1399
void tst_QQmlDebugJS::changeBreakpoint()
1401
//void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1403
int sourceLine1 = 50;
1404
int sourceLine2 = 51;
1405
QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1408
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1409
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1411
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1413
//Will hit 1st brakpoint, change this breakpoint enable = false
1414
QString jsonString(client->response);
1415
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1417
QVariantMap body = value.value("body").toMap();
1418
QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1420
int breakpoint = breakpointsHit.at(0).toInt();
1421
client->changeBreakpoint(breakpoint,false);
1423
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1425
//Continue with debugging
1426
client->continueDebugging(QJSDebugClient::Continue);
1427
//Hit 2nd breakpoint
1428
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1430
//Continue with debugging
1431
client->continueDebugging(QJSDebugClient::Continue);
1432
//Should stop at 2nd breakpoint
1433
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1435
jsonString = client->response;
1436
value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1438
body = value.value("body").toMap();
1440
QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1443
void tst_QQmlDebugJS::changeBreakpointOnCondition()
1445
//void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1447
int sourceLine1 = 50;
1448
int sourceLine2 = 51;
1450
QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1453
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1454
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1456
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1458
//Will hit 1st brakpoint, change this breakpoint enable = false
1459
QString jsonString(client->response);
1460
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1462
QVariantMap body = value.value("body").toMap();
1463
QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1465
int breakpoint = breakpointsHit.at(0).toInt();
1466
client->changeBreakpoint(breakpoint, false, QLatin1String("d == 0"));
1468
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1470
//Continue with debugging
1471
client->continueDebugging(QJSDebugClient::Continue);
1472
//Hit 2nd breakpoint
1473
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1475
//Continue with debugging
1476
client->continueDebugging(QJSDebugClient::Continue);
1477
//Should stop at 2nd breakpoint
1478
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1480
jsonString = client->response;
1481
value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1483
body = value.value("body").toMap();
1485
QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1489
void tst_QQmlDebugJS::clearBreakpoint()
1491
//void clearBreakpoint(int breakpoint);
1493
int sourceLine1 = 50;
1494
int sourceLine2 = 51;
1495
QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1498
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1499
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1501
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1503
//Will hit 1st brakpoint, change this breakpoint enable = false
1504
QString jsonString(client->response);
1505
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1507
QVariantMap body = value.value("body").toMap();
1508
QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1510
int breakpoint = breakpointsHit.at(0).toInt();
1511
client->clearBreakpoint(breakpoint);
1513
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1515
//Continue with debugging
1516
client->continueDebugging(QJSDebugClient::Continue);
1517
//Hit 2nd breakpoint
1518
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1520
//Continue with debugging
1521
client->continueDebugging(QJSDebugClient::Continue);
1522
//Should stop at 2nd breakpoint
1523
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1525
jsonString = client->response;
1526
value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1528
body = value.value("body").toMap();
1530
QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1533
void tst_QQmlDebugJS::setExceptionBreak()
1535
//void setExceptionBreak(QString type, bool enabled = false);
1537
QVERIFY(init(EXCEPTION_QMLFILE));
1538
client->setExceptionBreak(QJSDebugClient::All,true);
1540
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1543
void tst_QQmlDebugJS::stepNext()
1545
//void continueDebugging(StepAction stepAction, int stepCount = 1);
1547
int sourceLine = 50;
1548
QVERIFY(init(STEPACTION_QMLFILE));
1550
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1552
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1554
client->continueDebugging(QJSDebugClient::Next);
1555
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1557
QString jsonString(client->response);
1558
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1560
QVariantMap body = value.value("body").toMap();
1562
QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1);
1563
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1566
void tst_QQmlDebugJS::stepNextWithCount()
1568
//void continueDebugging(StepAction stepAction, int stepCount = 1);
1570
int sourceLine = 50;
1571
QVERIFY(init(STEPACTION_QMLFILE));
1574
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1575
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1577
client->continueDebugging(QJSDebugClient::Next, 2);
1578
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1580
QString jsonString(client->response);
1581
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1583
QVariantMap body = value.value("body").toMap();
1585
QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2);
1586
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1589
void tst_QQmlDebugJS::stepIn()
1591
//void continueDebugging(StepAction stepAction, int stepCount = 1);
1593
int sourceLine = 54;
1594
int actualLine = 50;
1595
QVERIFY(init(STEPACTION_QMLFILE));
1598
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
1599
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1601
client->continueDebugging(QJSDebugClient::In);
1602
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1604
QString jsonString(client->response);
1605
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1607
QVariantMap body = value.value("body").toMap();
1609
QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1610
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1613
void tst_QQmlDebugJS::stepOut()
1615
//void continueDebugging(StepAction stepAction, int stepCount = 1);
1617
int sourceLine = 50;
1618
int actualLine = 54;
1619
QVERIFY(init(STEPACTION_QMLFILE));
1622
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1623
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1625
client->continueDebugging(QJSDebugClient::Out);
1626
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1628
QString jsonString(client->response);
1629
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1631
QVariantMap body = value.value("body").toMap();
1633
QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1634
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1637
void tst_QQmlDebugJS::continueDebugging()
1639
//void continueDebugging(StepAction stepAction, int stepCount = 1);
1641
int sourceLine1 = 54;
1642
int sourceLine2 = 51;
1643
QVERIFY(init(STEPACTION_QMLFILE));
1646
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
1647
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
1648
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1650
client->continueDebugging(QJSDebugClient::Continue);
1651
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1653
QString jsonString(client->response);
1654
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1656
QVariantMap body = value.value("body").toMap();
1658
QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1659
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1662
void tst_QQmlDebugJS::backtrace()
1664
//void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
1666
int sourceLine = 47;
1667
QVERIFY(init(ONCOMPLETED_QMLFILE));
1669
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1671
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1673
client->backtrace();
1674
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1677
void tst_QQmlDebugJS::getFrameDetails()
1679
//void frame(int number = -1);
1681
int sourceLine = 47;
1682
QVERIFY(init(ONCOMPLETED_QMLFILE));
1684
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1686
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1689
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1692
void tst_QQmlDebugJS::getScopeDetails()
1694
//void scope(int number = -1, int frameNumber = -1);
1696
int sourceLine = 47;
1697
QVERIFY(init(ONCOMPLETED_QMLFILE));
1699
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1701
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1704
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1707
void tst_QQmlDebugJS::evaluateInGlobalScope()
1709
//void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1714
client->evaluate(QLatin1String("console.log('Hello World')"), true);
1715
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1717
//Verify the value of 'print'
1718
QString jsonString(client->response);
1719
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1721
QVariantMap body = value.value("body").toMap();
1723
QCOMPARE(body.value("text").toString(),QLatin1String("undefined"));
1726
void tst_QQmlDebugJS::evaluateInLocalScope()
1728
//void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1730
int sourceLine = 47;
1731
QVERIFY(init(ONCOMPLETED_QMLFILE));
1733
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1735
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1738
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1740
//Get the frame index
1741
QString jsonString(client->response);
1742
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1744
QVariantMap body = value.value("body").toMap();
1746
int frameIndex = body.value("index").toInt();
1748
client->evaluate(QLatin1String("root.a"), frameIndex);
1749
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1751
//Verify the value of 'timer.interval'
1752
jsonString = client->response;
1753
value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1755
body = value.value("body").toMap();
1757
QCOMPARE(body.value("value").toInt(),10);
1760
void tst_QQmlDebugJS::getScopes()
1762
//void scopes(int frameNumber = -1);
1764
int sourceLine = 47;
1765
QVERIFY(init(ONCOMPLETED_QMLFILE));
1767
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1769
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1772
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1775
void tst_QQmlDebugJS::getScripts()
1777
//void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
1780
QSKIP("QTBUG-23475 - Unreliable test on Mac OS X");
1788
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult())));
1789
QString jsonString(client->response);
1790
QVariantMap value = client->parser.call(QJSValueList()
1791
<< QJSValue(jsonString)).toVariant().toMap();
1793
QList<QVariant> scripts = value.value("body").toList();
1795
QCOMPARE(scripts.count(), 2);
1798
void tst_QQmlDebugJS::getSource()
1800
//void source(int frame = -1, int fromLine = -1, int toLine = -1);
1802
int sourceLine = 47;
1803
QVERIFY(init(ONCOMPLETED_QMLFILE));
1805
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1807
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1810
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1813
QTEST_MAIN(tst_QQmlDebugJS)
1815
#include "tst_qqmldebugjs.moc"