b93be16e0e844b59fdda2ac76ab2d0606ae4d97a
[profile/ivi/qtdeclarative.git] / tests / auto / qml / debugger / qqmldebugjs / tst_qqmldebugjs.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qtest.h>
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>
50
51 //QQmlDebugTest
52 #include "debugutil_p.h"
53 #include "qqmldebugclient.h"
54 #include "../../../shared/util.h"
55
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";
88
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";
107
108 const char *CONNECT = "connect";
109 const char *INTERRUPT = "interrupt";
110
111 const char *REQUEST = "request";
112 const char *IN = "in";
113 const char *NEXT = "next";
114 const char *OUT = "out";
115
116 const char *FUNCTION = "function";
117 const char *SCRIPT = "script";
118 const char *SCRIPTREGEXP = "scriptRegExp";
119 const char *EVENT = "event";
120
121 const char *ALL = "all";
122 const char *UNCAUGHT = "uncaught";
123
124 //const char *PAUSE = "pause";
125 //const char *RESUME = "resume";
126
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";
140
141 #define VARIANTMAPINIT \
142     QString obj("{}"); \
143     QJSValue jsonVal = parser.call(QJSValueList() << obj); \
144     jsonVal.setProperty(SEQ,QJSValue(seq++)); \
145     jsonVal.setProperty(TYPE,REQUEST);
146
147
148 #undef QVERIFY
149 #define QVERIFY(statement) \
150 do {\
151     if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\
152         if (QTest::currentTestFailed()) \
153           qDebug().nospace() << "\nDEBUGGEE OUTPUT:\n" << process->output();\
154         return;\
155     }\
156 } while (0)
157
158
159 class QJSDebugClient;
160
161 class tst_QQmlDebugJS : public QQmlDataTest
162 {
163     Q_OBJECT
164
165     bool init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true);
166
167 private slots:
168     void initTestCase();
169     void cleanupTestCase();
170
171     void cleanup();
172
173     void connect();
174     void interrupt();
175     void getVersion();
176     void getVersionWhenAttaching();
177
178     void applyV8Flags();
179
180     void disconnect();
181
182     void gc();
183
184     void listBreakpoints();
185
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();
197
198     void changeBreakpoint();
199     void changeBreakpointOnCondition();
200
201     void clearBreakpoint();
202
203     void setExceptionBreak();
204
205     void stepNext();
206     void stepNextWithCount();
207     void stepIn();
208     void stepOut();
209     void continueDebugging();
210
211     void backtrace();
212
213     void getFrameDetails();
214
215     void getScopeDetails();
216
217     void evaluateInGlobalScope();
218     void evaluateInLocalScope();
219
220     void getScopes();
221
222     void getScripts();
223
224     void getSource();
225
226     //    void profile(); //NOT SUPPORTED
227
228     //    void verifyQMLOptimizerDisabled();
229
230 private:
231     QQmlDebugProcess *process;
232     QJSDebugClient *client;
233     QQmlDebugConnection *connection;
234     QTime t;
235 };
236
237 class QJSDebugClient : public QQmlDebugClient
238 {
239     Q_OBJECT
240 public:
241     enum StepAction
242     {
243         Continue,
244         In,
245         Out,
246         Next
247     };
248
249     enum Exception
250     {
251         All,
252         Uncaught
253     };
254
255 //    enum ProfileCommand
256 //    {
257 //        Pause,
258 //        Resume
259 //    };
260
261     QJSDebugClient(QQmlDebugConnection *connection)
262         : QQmlDebugClient(QLatin1String("V8Debugger"), connection),
263           seq(0)
264     {
265         parser = jsEngine.evaluate(QLatin1String("JSON.parse"));
266         stringify = jsEngine.evaluate(QLatin1String("JSON.stringify"));
267     }
268
269     void connect();
270     void interrupt();
271
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);
286     void version();
287     //void profile(ProfileCommand command); //NOT SUPPORTED
288     void disconnect();
289     void gc();
290     void listBreakpoints();
291
292 protected:
293     //inherited from QQmlDebugClient
294     void stateChanged(State state);
295     void messageReceived(const QByteArray &data);
296
297 signals:
298     void enabled();
299     void connected();
300     void interruptRequested();
301     void result();
302     void stopped();
303     void scriptsResult();
304     void evaluateResult();
305
306 private:
307     void sendMessage(const QByteArray &);
308     void flushSendBuffer();
309     QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
310
311 private:
312     QJSEngine jsEngine;
313     int seq;
314
315     QList<QByteArray> sendBuffer;
316 public:
317     QJSValue parser;
318     QJSValue stringify;
319     QByteArray response;
320
321 };
322
323 void QJSDebugClient::connect()
324 {
325     sendMessage(packMessage(CONNECT));
326 }
327
328 void QJSDebugClient::interrupt()
329 {
330     sendMessage(packMessage(INTERRUPT));
331 }
332
333 void QJSDebugClient::continueDebugging(StepAction action, int count)
334 {
335     //    { "seq"       : <number>,
336     //      "type"      : "request",
337     //      "command"   : "continue",
338     //      "arguments" : { "stepaction" : <"in", "next" or "out">,
339     //                      "stepcount"  : <number of steps (default 1)>
340     //                    }
341     //    }
342     VARIANTMAPINIT;
343     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING)));
344
345     if (action != Continue) {
346         QJSValue args = parser.call(QJSValueList() << obj);
347         switch (action) {
348         case In: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(IN)));
349             break;
350         case Out: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(OUT)));
351             break;
352         case Next: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(NEXT)));
353             break;
354         default:break;
355         }
356         if (!args.isUndefined()) {
357             if (count != 1)
358                 args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count));
359             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
360         }
361     }
362     QJSValue json = stringify.call(QJSValueList() << jsonVal);
363     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
364 }
365
366 void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/)
367 {
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> },
378     //                           ...
379     //                      ]
380     //                    }
381     //    }
382     VARIANTMAPINIT;
383     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE)));
384
385     QJSValue args = parser.call(QJSValueList() << obj);
386     args.setProperty(QLatin1String(EXPRESSION),QJSValue(expr));
387
388     if (frame != -1)
389         args.setProperty(QLatin1String(FRAME),QJSValue(frame));
390
391     if (global)
392         args.setProperty(QLatin1String(GLOBAL),QJSValue(global));
393
394     if (disableBreak)
395         args.setProperty(QLatin1String(DISABLEBREAK),QJSValue(disableBreak));
396
397     if (!args.isUndefined()) {
398         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
399     }
400
401     QJSValue json = stringify.call(QJSValueList() << jsonVal);
402     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
403 }
404
405 void QJSDebugClient::lookup(QList<int> handles, bool includeSource)
406 {
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>,
412     //                    }
413     //    }
414     VARIANTMAPINIT;
415     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP)));
416
417     QJSValue args = parser.call(QJSValueList() << obj);
418
419     QString arr("[]");
420     QJSValue array = parser.call(QJSValueList() << arr);
421     int index = 0;
422     foreach (int handle, handles) {
423         array.setProperty(index++,QJSValue(handle));
424     }
425     args.setProperty(QLatin1String(HANDLES),array);
426
427     if (includeSource)
428         args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
429
430     if (!args.isUndefined()) {
431         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
432     }
433
434     QJSValue json = stringify.call(QJSValueList() << jsonVal);
435     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
436 }
437
438 void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
439 {
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>
446     //                    }
447     //    }
448     VARIANTMAPINIT;
449     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE)));
450
451     QJSValue args = parser.call(QJSValueList() << obj);
452
453     if (fromFrame != -1)
454         args.setProperty(QLatin1String(FROMFRAME),QJSValue(fromFrame));
455
456     if (toFrame != -1)
457         args.setProperty(QLatin1String(TOFRAME),QJSValue(toFrame));
458
459     if (bottom)
460         args.setProperty(QLatin1String(BOTTOM),QJSValue(bottom));
461
462     if (!args.isUndefined()) {
463         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
464     }
465
466     QJSValue json = stringify.call(QJSValueList() << jsonVal);
467     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
468 }
469
470 void QJSDebugClient::frame(int number)
471 {
472     //    { "seq"       : <number>,
473     //      "type"      : "request",
474     //      "command"   : "frame",
475     //      "arguments" : { "number" : <frame number>
476     //                    }
477     //    }
478     VARIANTMAPINIT;
479     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME)));
480
481     if (number != -1) {
482         QJSValue args = parser.call(QJSValueList() << obj);
483         args.setProperty(QLatin1String(NUMBER),QJSValue(number));
484
485         if (!args.isUndefined()) {
486             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
487         }
488     }
489
490     QJSValue json = stringify.call(QJSValueList() << jsonVal);
491     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
492 }
493
494 void QJSDebugClient::scope(int number, int frameNumber)
495 {
496     //    { "seq"       : <number>,
497     //      "type"      : "request",
498     //      "command"   : "scope",
499     //      "arguments" : { "number" : <scope number>
500     //                      "frameNumber" : <frame number, optional uses selected frame if missing>
501     //                    }
502     //    }
503     VARIANTMAPINIT;
504     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE)));
505
506     if (number != -1) {
507         QJSValue args = parser.call(QJSValueList() << obj);
508         args.setProperty(QLatin1String(NUMBER),QJSValue(number));
509
510         if (frameNumber != -1)
511             args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
512
513         if (!args.isUndefined()) {
514             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
515         }
516     }
517
518     QJSValue json = stringify.call(QJSValueList() << jsonVal);
519     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
520 }
521
522 void QJSDebugClient::scopes(int frameNumber)
523 {
524     //    { "seq"       : <number>,
525     //      "type"      : "request",
526     //      "command"   : "scopes",
527     //      "arguments" : { "frameNumber" : <frame number, optional uses selected frame if missing>
528     //                    }
529     //    }
530     VARIANTMAPINIT;
531     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES)));
532
533     if (frameNumber != -1) {
534         QJSValue args = parser.call(QJSValueList() << obj);
535         args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
536
537         if (!args.isUndefined()) {
538             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
539         }
540     }
541
542     QJSValue json = stringify.call(QJSValueList() << jsonVal);
543     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
544 }
545
546 void QJSDebugClient::scripts(int types, QList<int> ids, bool includeSource, QVariant /*filter*/)
547 {
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.>
561     //                    }
562     //    }
563     VARIANTMAPINIT;
564     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS)));
565
566     QJSValue args = parser.call(QJSValueList() << obj);
567     args.setProperty(QLatin1String(TYPES),QJSValue(types));
568
569     if (ids.count()) {
570         QString arr("[]");
571         QJSValue array = parser.call(QJSValueList() << arr);
572         int index = 0;
573         foreach (int id, ids) {
574             array.setProperty(index++,QJSValue(id));
575         }
576         args.setProperty(QLatin1String(IDS),array);
577     }
578
579     if (includeSource)
580         args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
581
582     if (!args.isUndefined()) {
583         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
584     }
585
586     QJSValue json = stringify.call(QJSValueList() << jsonVal);
587     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
588 }
589
590 void QJSDebugClient::source(int frame, int fromLine, int toLine)
591 {
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>
599     //                    }
600     //    }
601     VARIANTMAPINIT;
602     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE)));
603
604     QJSValue args = parser.call(QJSValueList() << obj);
605
606     if (frame != -1)
607         args.setProperty(QLatin1String(FRAME),QJSValue(frame));
608
609     if (fromLine != -1)
610         args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine));
611
612     if (toLine != -1)
613         args.setProperty(QLatin1String(TOLINE),QJSValue(toLine));
614
615     if (!args.isUndefined()) {
616         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
617     }
618
619     QJSValue json = stringify.call(QJSValueList() << jsonVal);
620     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
621 }
622
623 void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount)
624 {
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>
635     //                    }
636     //    }
637
638     if (type == QLatin1String(EVENT)) {
639         QByteArray reply;
640         QDataStream rs(&reply, QIODevice::WriteOnly);
641         rs <<  target.toUtf8() << enabled;
642         sendMessage(packMessage(QByteArray("breakonsignal"), reply));
643
644     } else {
645         VARIANTMAPINIT;
646         jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT)));
647
648         QJSValue args = parser.call(QJSValueList() << obj);
649
650         args.setProperty(QLatin1String(TYPE),QJSValue(type));
651         args.setProperty(QLatin1String(TARGET),QJSValue(target));
652
653         if (line != -1)
654             args.setProperty(QLatin1String(LINE),QJSValue(line));
655
656         if (column != -1)
657             args.setProperty(QLatin1String(COLUMN),QJSValue(column));
658
659         args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
660
661         if (!condition.isEmpty())
662             args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
663
664         if (ignoreCount != -1)
665             args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
666
667         if (!args.isUndefined()) {
668             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
669         }
670
671         QJSValue json = stringify.call(QJSValueList() << jsonVal);
672         sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
673     }
674 }
675
676 void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount)
677 {
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            }
685     //    }
686     VARIANTMAPINIT;
687     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CHANGEBREAKPOINT)));
688
689     QJSValue args = parser.call(QJSValueList() << obj);
690
691     args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
692
693     args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
694
695     if (!condition.isEmpty())
696         args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
697
698     if (ignoreCount != -1)
699         args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
700
701     if (!args.isUndefined()) {
702         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
703     }
704
705     QJSValue json = stringify.call(QJSValueList() << jsonVal);
706     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
707 }
708
709 void QJSDebugClient::clearBreakpoint(int breakpoint)
710 {
711     //    { "seq"       : <number>,
712     //      "type"      : "request",
713     //      "command"   : "clearbreakpoint",
714     //      "arguments" : { "breakpoint" : <number of the break point to clear>
715     //                    }
716     //    }
717     VARIANTMAPINIT;
718     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT)));
719
720     QJSValue args = parser.call(QJSValueList() << obj);
721
722     args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
723
724     if (!args.isUndefined()) {
725         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
726     }
727
728     QJSValue json = stringify.call(QJSValueList() << jsonVal);
729     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
730 }
731
732 void QJSDebugClient::setExceptionBreak(Exception type, bool enabled)
733 {
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>
739     //                    }
740     //    }
741     VARIANTMAPINIT;
742     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK)));
743
744     QJSValue args = parser.call(QJSValueList() << obj);
745
746     if (type == All)
747         args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
748     else if (type == Uncaught)
749         args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(UNCAUGHT)));
750
751     if (enabled)
752         args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
753
754     if (!args.isUndefined()) {
755         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
756     }
757
758     QJSValue json = stringify.call(QJSValueList() << jsonVal);
759     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
760 }
761
762 void QJSDebugClient::v8flags(QString flags)
763 {
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>
768     //                    }
769     //    }
770     VARIANTMAPINIT;
771     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS)));
772
773     QJSValue args = parser.call(QJSValueList() << obj);
774
775     args.setProperty(QLatin1String(FLAGS),QJSValue(flags));
776
777     if (!args.isUndefined()) {
778         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
779     }
780
781     QJSValue json = stringify.call(QJSValueList() << jsonVal);
782     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
783 }
784
785 void QJSDebugClient::version()
786 {
787     //    { "seq"       : <number>,
788     //      "type"      : "request",
789     //      "command"   : "version",
790     //    }
791     VARIANTMAPINIT;
792     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION)));
793
794     QJSValue json = stringify.call(QJSValueList() << jsonVal);
795     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
796 }
797
798 //void QJSDebugClient::profile(ProfileCommand command)
799 //{
800 ////    { "seq"       : <number>,
801 ////      "type"      : "request",
802 ////      "command"   : "profile",
803 ////      "arguments" : { "command"  : "resume" or "pause" }
804 ////    }
805 //    VARIANTMAPINIT;
806 //    jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE)));
807
808 //    QJSValue args = parser.call(QJSValueList() << obj);
809
810 //    if (command == Resume)
811 //        args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(RESUME)));
812 //    else
813 //        args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PAUSE)));
814
815 //    args.setProperty(QLatin1String("modules"),QJSValue(1));
816 //    if (!args.isUndefined()) {
817 //        jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
818 //    }
819
820 //    QJSValue json = stringify.call(QJSValueList() << jsonVal);
821 //    sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
822 //}
823
824 void QJSDebugClient::disconnect()
825 {
826     //    { "seq"     : <number>,
827     //      "type"    : "request",
828     //      "command" : "disconnect",
829     //    }
830     VARIANTMAPINIT;
831     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT)));
832
833     QJSValue json = stringify.call(QJSValueList() << jsonVal);
834     sendMessage(packMessage(DISCONNECT, json.toString().toUtf8()));
835 }
836
837 void QJSDebugClient::gc()
838 {
839     //    { "seq"       : <number>,
840     //      "type"      : "request",
841     //      "command"   : "gc",
842     //      "arguments" : { "type" : <string: "all">,
843     //                    }
844     //    }
845     VARIANTMAPINIT;
846     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GARBAGECOLLECTOR)));
847
848     QJSValue args = parser.call(QJSValueList() << obj);
849
850     args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
851
852     if (!args.isUndefined()) {
853         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
854     }
855
856     QJSValue json = stringify.call(QJSValueList() << jsonVal);
857     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
858 }
859
860 void QJSDebugClient::listBreakpoints()
861 {
862     //    { "seq"       : <number>,
863     //      "type"      : "request",
864     //      "command"   : "listbreakpoints",
865     //    }
866     VARIANTMAPINIT;
867     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS)));
868
869     QJSValue json = stringify.call(QJSValueList() << jsonVal);
870     sendMessage(packMessage(V8REQUEST, json.toString().toUtf8()));
871 }
872
873 void QJSDebugClient::stateChanged(State state)
874 {
875     if (state == Enabled) {
876         flushSendBuffer();
877         emit enabled();
878     }
879 }
880
881 void QJSDebugClient::messageReceived(const QByteArray &data)
882 {
883     QDataStream ds(data);
884     QByteArray command;
885     ds >> command;
886
887     if (command == "V8DEBUG") {
888         QByteArray type;
889         ds >> type >> response;
890
891         if (type == CONNECT) {
892             emit connected();
893
894         } else if (type == INTERRUPT) {
895             emit interruptRequested();
896
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();
901
902             if (type == "response") {
903
904                 if (!value.value("success").toBool()) {
905 //                    qDebug() << "Error: The test case will fail since no signal is emitted";
906                     return;
907                 }
908
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"*/) {
928                     emit result();
929
930                 } else {
931                     // DO NOTHING
932                 }
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();
939
940             } else if (type == QLatin1String(EVENT)) {
941                 QString event(value.value(QLatin1String(EVENT)).toString());
942
943                 if (event == "break" ||
944                         event == "exception")
945                     emit stopped();
946                 }
947
948         }
949     }
950 }
951
952 void QJSDebugClient::sendMessage(const QByteArray &msg)
953 {
954     if (state() == Enabled) {
955         QQmlDebugClient::sendMessage(msg);
956     } else {
957         sendBuffer.append(msg);
958     }
959 }
960
961 void QJSDebugClient::flushSendBuffer()
962 {
963     foreach (const QByteArray &msg, sendBuffer)
964         QQmlDebugClient::sendMessage(msg);
965     sendBuffer.clear();
966 }
967
968 QByteArray QJSDebugClient::packMessage(const QByteArray &type, const QByteArray &message)
969 {
970     QByteArray reply;
971     QDataStream rs(&reply, QIODevice::WriteOnly);
972     QByteArray cmd = "V8DEBUG";
973     rs << cmd << type << message;
974     return reply;
975 }
976
977 void tst_QQmlDebugJS::initTestCase()
978 {
979     QQmlDataTest::initTestCase();
980     t.start();
981     process = 0;
982     client = 0;
983     connection = 0;
984 }
985
986 void tst_QQmlDebugJS::cleanupTestCase()
987 {
988     if (process) {
989         process->stop();
990         delete process;
991     }
992
993     if (client)
994         delete client;
995
996     if (connection)
997         delete connection;
998
999 //    qDebug() << "Time Elapsed:" << t.elapsed();
1000 }
1001
1002 bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode)
1003 {
1004     connection = new QQmlDebugConnection();
1005     process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
1006     client = new QJSDebugClient(connection);
1007
1008     if (blockMode)
1009         process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile));
1010     else
1011         process->start(QStringList() << QLatin1String(NORMALMODE) << testFile(qmlFile));
1012
1013     if (!process->waitForSessionStart()) {
1014         return false;
1015     }
1016
1017     connection->connectToHost("127.0.0.1", 3771);
1018     if (!connection->waitForConnected())
1019         return false;
1020
1021     return QQmlDebugTest::waitForSignal(client, SIGNAL(enabled()));
1022 }
1023
1024 void tst_QQmlDebugJS::cleanup()
1025 {
1026     if (process) {
1027         process->stop();
1028         delete process;
1029     }
1030
1031     if (client)
1032         delete client;
1033
1034     if (connection)
1035         delete connection;
1036
1037     process = 0;
1038     client = 0;
1039     connection = 0;
1040 }
1041
1042 void tst_QQmlDebugJS::connect()
1043 {
1044     //void connect()
1045
1046     QVERIFY(init());
1047     client->connect();
1048     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1049 }
1050
1051 void tst_QQmlDebugJS::interrupt()
1052 {
1053     //void connect()
1054
1055     QVERIFY(init());
1056     client->connect();
1057
1058     client->interrupt();
1059     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested())));
1060 }
1061
1062 void tst_QQmlDebugJS::getVersion()
1063 {
1064     //void version()
1065
1066     QVERIFY(init());
1067     client->connect();
1068     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected())));
1069
1070     client->version();
1071     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1072 }
1073
1074 void tst_QQmlDebugJS::getVersionWhenAttaching()
1075 {
1076     //void version()
1077
1078     QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1079     client->connect();
1080
1081     client->version();
1082     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1083 }
1084
1085 void tst_QQmlDebugJS::applyV8Flags()
1086 {
1087     //void v8flags(QString flags)
1088
1089     QVERIFY(init());
1090     client->connect();
1091
1092     client->v8flags(QString());
1093     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1094 }
1095
1096 void tst_QQmlDebugJS::disconnect()
1097 {
1098     //void disconnect()
1099
1100     QVERIFY(init());
1101     client->connect();
1102
1103     client->disconnect();
1104     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1105 }
1106
1107 void tst_QQmlDebugJS::gc()
1108 {
1109     //void gc()
1110
1111     QVERIFY(init());
1112     client->connect();
1113
1114     client->gc();
1115     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1116 }
1117
1118 void tst_QQmlDebugJS::listBreakpoints()
1119 {
1120     //void listBreakpoints()
1121
1122     int sourceLine1 = 53;
1123     int sourceLine2 = 54;
1124     int sourceLine3 = 55;
1125
1126     QVERIFY(init());
1127     client->connect();
1128
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())));
1137
1138     QString jsonString(client->response);
1139     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1140
1141     QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList();
1142
1143     QCOMPARE(breakpoints.count(), 3);
1144 }
1145
1146 void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
1147 {
1148     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1149
1150     int sourceLine = 47;
1151     QVERIFY(init(ONCOMPLETED_QMLFILE));
1152
1153     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1154     client->connect();
1155     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1156
1157     QString jsonString(client->response);
1158     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1159
1160     QVariantMap body = value.value("body").toMap();
1161
1162     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1163     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1164 }
1165
1166 void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
1167 {
1168     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1169
1170     int sourceLine = 47;
1171     QVERIFY(init(CREATECOMPONENT_QMLFILE));
1172
1173     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1174     client->connect();
1175     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1176
1177     QString jsonString(client->response);
1178     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1179
1180     QVariantMap body = value.value("body").toMap();
1181
1182     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1183     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(ONCOMPLETED_QMLFILE));
1184 }
1185
1186 void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
1187 {
1188     int sourceLine = 48;
1189     QVERIFY(init(TIMER_QMLFILE));
1190
1191     client->connect();
1192
1193     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine, -1, true);
1194     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1195
1196     QString jsonString(client->response);
1197     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1198
1199     QVariantMap body = value.value("body").toMap();
1200
1201     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1202     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1203 }
1204
1205 void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
1206 {
1207     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1208
1209     int sourceLine = 43;
1210     QVERIFY(init(LOADJSFILE_QMLFILE));
1211
1212     client->connect();
1213     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1214     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1215
1216     QString jsonString(client->response);
1217     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1218
1219     QVariantMap body = value.value("body").toMap();
1220
1221     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1222     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1223 }
1224
1225 void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
1226 {
1227     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1228
1229     int sourceLine = 47;
1230     int actualLine = 49;
1231     QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1232
1233     client->connect();
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));
1237
1238     QString jsonString(client->response);
1239     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1240
1241     QVariantMap body = value.value("body").toMap();
1242
1243     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1244     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1245 }
1246
1247 void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
1248 {
1249     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1250
1251     int sourceLine = 48;
1252     int actualLine = 49;
1253     QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1254
1255     client->connect();
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));
1259
1260     QString jsonString(client->response);
1261     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1262
1263     QVariantMap body = value.value("body").toMap();
1264
1265     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1266     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1267 }
1268
1269 void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
1270 {
1271     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1272
1273     int sourceLine = 52;
1274     QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
1275
1276     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
1277     client->connect();
1278     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1279
1280     QString jsonString(client->response);
1281     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1282
1283     QVariantMap body = value.value("body").toMap();
1284
1285     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1286     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
1287 }
1288
1289 void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
1290 {
1291     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1292
1293     int out = 10;
1294     int sourceLine = 50;
1295     QVERIFY(init(CONDITION_QMLFILE));
1296
1297     client->connect();
1298     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10"));
1299     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1300
1301     //Get the frame index
1302     QString jsonString = client->response;
1303     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1304
1305     QVariantMap body = value.value("body").toMap();
1306
1307     int frameIndex = body.value("index").toInt();
1308
1309     //Verify the value of 'result'
1310     client->evaluate(QLatin1String("a"),frameIndex);
1311
1312     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1313
1314     jsonString = client->response;
1315     value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1316
1317     body = value.value("body").toMap();
1318
1319     QVERIFY(body.value("value").toInt() > out);
1320 }
1321
1322 void tst_QQmlDebugJS::setBreakpointWhenAttaching()
1323 {
1324     int sourceLine = 49;
1325     QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1326
1327     client->connect();
1328     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine);
1329     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1330 }
1331
1332 //void tst_QQmlDebugJS::setBreakpointInFunction()
1333 //{
1334 //    //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1335
1336 //    int actualLine = 31;
1337
1338 //    client->connect();
1339 //    client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
1340
1341 //    QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1342
1343 //    QString jsonString(client->response);
1344 //    QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1345
1346 //    QVariantMap body = value.value("body").toMap();
1347
1348 //    QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1349 //    QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
1350 //}
1351
1352 void tst_QQmlDebugJS::setBreakpointOnEvent()
1353 {
1354     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1355
1356     QVERIFY(init(TIMER_QMLFILE));
1357
1358     client->connect();
1359
1360     client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true);
1361     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1362
1363     QString jsonString(client->response);
1364     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1365
1366     QVariantMap body = value.value("body").toMap();
1367
1368     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE));
1369 }
1370
1371
1372 void tst_QQmlDebugJS::changeBreakpoint()
1373 {
1374     //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1375
1376     int sourceLine1 = 50;
1377     int sourceLine2 = 51;
1378     QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1379
1380     client->connect();
1381     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1382     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1383
1384     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1385
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();
1389
1390     QVariantMap body = value.value("body").toMap();
1391     QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1392
1393     int breakpoint = breakpointsHit.at(0).toInt();
1394     client->changeBreakpoint(breakpoint,false);
1395
1396     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1397
1398     //Continue with debugging
1399     client->continueDebugging(QJSDebugClient::Continue);
1400     //Hit 2nd breakpoint
1401     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1402
1403     //Continue with debugging
1404     client->continueDebugging(QJSDebugClient::Continue);
1405     //Should stop at 2nd breakpoint
1406     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1407
1408     jsonString = client->response;
1409     value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1410
1411     body = value.value("body").toMap();
1412
1413     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1414 }
1415
1416 void tst_QQmlDebugJS::changeBreakpointOnCondition()
1417 {
1418     //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1419
1420     int sourceLine1 = 50;
1421     int sourceLine2 = 51;
1422
1423     QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1424
1425     client->connect();
1426     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1427     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1428
1429     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1430
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();
1434
1435     QVariantMap body = value.value("body").toMap();
1436     QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1437
1438     int breakpoint = breakpointsHit.at(0).toInt();
1439     client->changeBreakpoint(breakpoint, false, QLatin1String("d == 0"));
1440
1441     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1442
1443     //Continue with debugging
1444     client->continueDebugging(QJSDebugClient::Continue);
1445     //Hit 2nd breakpoint
1446     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1447
1448     //Continue with debugging
1449     client->continueDebugging(QJSDebugClient::Continue);
1450     //Should stop at 2nd breakpoint
1451     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1452
1453     jsonString = client->response;
1454     value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1455
1456     body = value.value("body").toMap();
1457
1458     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1459
1460 }
1461
1462 void tst_QQmlDebugJS::clearBreakpoint()
1463 {
1464     //void clearBreakpoint(int breakpoint);
1465
1466     int sourceLine1 = 50;
1467     int sourceLine2 = 51;
1468     QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
1469
1470     client->connect();
1471     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
1472     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
1473
1474     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1475
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();
1479
1480     QVariantMap body = value.value("body").toMap();
1481     QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1482
1483     int breakpoint = breakpointsHit.at(0).toInt();
1484     client->clearBreakpoint(breakpoint);
1485
1486     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1487
1488     //Continue with debugging
1489     client->continueDebugging(QJSDebugClient::Continue);
1490     //Hit 2nd breakpoint
1491     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1492
1493     //Continue with debugging
1494     client->continueDebugging(QJSDebugClient::Continue);
1495     //Should stop at 2nd breakpoint
1496     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1497
1498     jsonString = client->response;
1499     value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1500
1501     body = value.value("body").toMap();
1502
1503     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1504 }
1505
1506 void tst_QQmlDebugJS::setExceptionBreak()
1507 {
1508     //void setExceptionBreak(QString type, bool enabled = false);
1509
1510     QVERIFY(init(EXCEPTION_QMLFILE));
1511     client->setExceptionBreak(QJSDebugClient::All,true);
1512     client->connect();
1513     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1514 }
1515
1516 void tst_QQmlDebugJS::stepNext()
1517 {
1518     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1519
1520     int sourceLine = 50;
1521     QVERIFY(init(STEPACTION_QMLFILE));
1522
1523     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1524     client->connect();
1525     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1526
1527     client->continueDebugging(QJSDebugClient::Next);
1528     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1529
1530     QString jsonString(client->response);
1531     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1532
1533     QVariantMap body = value.value("body").toMap();
1534
1535     QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1);
1536     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1537 }
1538
1539 void tst_QQmlDebugJS::stepNextWithCount()
1540 {
1541     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1542
1543     int sourceLine = 50;
1544     QVERIFY(init(STEPACTION_QMLFILE));
1545
1546     client->connect();
1547     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1548     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1549
1550     client->continueDebugging(QJSDebugClient::Next, 2);
1551     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1552
1553     QString jsonString(client->response);
1554     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1555
1556     QVariantMap body = value.value("body").toMap();
1557
1558     QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2);
1559     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1560 }
1561
1562 void tst_QQmlDebugJS::stepIn()
1563 {
1564     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1565
1566     int sourceLine = 54;
1567     int actualLine = 50;
1568     QVERIFY(init(STEPACTION_QMLFILE));
1569
1570     client->connect();
1571     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
1572     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1573
1574     client->continueDebugging(QJSDebugClient::In);
1575     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1576
1577     QString jsonString(client->response);
1578     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1579
1580     QVariantMap body = value.value("body").toMap();
1581
1582     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1583     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1584 }
1585
1586 void tst_QQmlDebugJS::stepOut()
1587 {
1588     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1589
1590     int sourceLine = 50;
1591     int actualLine = 54;
1592     QVERIFY(init(STEPACTION_QMLFILE));
1593
1594     client->connect();
1595     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
1596     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1597
1598     client->continueDebugging(QJSDebugClient::Out);
1599     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1600
1601     QString jsonString(client->response);
1602     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1603
1604     QVariantMap body = value.value("body").toMap();
1605
1606     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1607     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1608 }
1609
1610 void tst_QQmlDebugJS::continueDebugging()
1611 {
1612     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1613
1614     int sourceLine1 = 54;
1615     int sourceLine2 = 51;
1616     QVERIFY(init(STEPACTION_QMLFILE));
1617
1618     client->connect();
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())));
1622
1623     client->continueDebugging(QJSDebugClient::Continue);
1624     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1625
1626     QString jsonString(client->response);
1627     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1628
1629     QVariantMap body = value.value("body").toMap();
1630
1631     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1632     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE));
1633 }
1634
1635 void tst_QQmlDebugJS::backtrace()
1636 {
1637     //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
1638
1639     int sourceLine = 47;
1640     QVERIFY(init(ONCOMPLETED_QMLFILE));
1641
1642     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1643     client->connect();
1644     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1645
1646     client->backtrace();
1647     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1648 }
1649
1650 void tst_QQmlDebugJS::getFrameDetails()
1651 {
1652     //void frame(int number = -1);
1653
1654     int sourceLine = 47;
1655     QVERIFY(init(ONCOMPLETED_QMLFILE));
1656
1657     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1658     client->connect();
1659     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1660
1661     client->frame();
1662     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1663 }
1664
1665 void tst_QQmlDebugJS::getScopeDetails()
1666 {
1667     //void scope(int number = -1, int frameNumber = -1);
1668
1669     int sourceLine = 47;
1670     QVERIFY(init(ONCOMPLETED_QMLFILE));
1671
1672     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1673     client->connect();
1674     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1675
1676     client->scope();
1677     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1678 }
1679
1680 void tst_QQmlDebugJS::evaluateInGlobalScope()
1681 {
1682     //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1683
1684     QVERIFY(init());
1685
1686     client->connect();
1687     client->evaluate(QLatin1String("console.log('Hello World')"), true);
1688     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1689
1690     //Verify the value of 'print'
1691     QString jsonString(client->response);
1692     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1693
1694     QVariantMap body = value.value("body").toMap();
1695
1696     QCOMPARE(body.value("text").toString(),QLatin1String("undefined"));
1697 }
1698
1699 void tst_QQmlDebugJS::evaluateInLocalScope()
1700 {
1701     //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1702
1703     int sourceLine = 47;
1704     QVERIFY(init(ONCOMPLETED_QMLFILE));
1705
1706     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1707     client->connect();
1708     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1709
1710     client->frame();
1711     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1712
1713     //Get the frame index
1714     QString jsonString(client->response);
1715     QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1716
1717     QVariantMap body = value.value("body").toMap();
1718
1719     int frameIndex = body.value("index").toInt();
1720
1721     client->evaluate(QLatin1String("root.a"), frameIndex);
1722     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult())));
1723
1724     //Verify the value of 'timer.interval'
1725     jsonString = client->response;
1726     value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1727
1728     body = value.value("body").toMap();
1729
1730     QCOMPARE(body.value("value").toInt(),10);
1731 }
1732
1733 void tst_QQmlDebugJS::getScopes()
1734 {
1735     //void scopes(int frameNumber = -1);
1736
1737     int sourceLine = 47;
1738     QVERIFY(init(ONCOMPLETED_QMLFILE));
1739
1740     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1741     client->connect();
1742     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1743
1744     client->scopes();
1745     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1746 }
1747
1748 void tst_QQmlDebugJS::getScripts()
1749 {
1750     //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
1751
1752 #ifdef Q_OS_MAC
1753     QSKIP("QTBUG-23475 - Unreliable test on Mac OS X");
1754 #endif
1755
1756     QVERIFY(init());
1757
1758     client->connect();
1759
1760     client->scripts();
1761     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult())));
1762     QString jsonString(client->response);
1763     QVariantMap value = client->parser.call(QJSValueList()
1764                                             << QJSValue(jsonString)).toVariant().toMap();
1765
1766     QList<QVariant> scripts = value.value("body").toList();
1767
1768     QCOMPARE(scripts.count(), 2);
1769 }
1770
1771 void tst_QQmlDebugJS::getSource()
1772 {
1773     //void source(int frame = -1, int fromLine = -1, int toLine = -1);
1774
1775     int sourceLine = 47;
1776     QVERIFY(init(ONCOMPLETED_QMLFILE));
1777
1778     client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
1779     client->connect();
1780     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
1781
1782     client->source();
1783     QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
1784 }
1785
1786 QTEST_MAIN(tst_QQmlDebugJS)
1787
1788 #include "tst_qqmldebugjs.moc"
1789