Debugger: Disable breakpoint relocation in JS
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / debugger / qdeclarativedebugjs / tst_qdeclarativedebugjs.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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 <QtDeclarative/private/qdeclarativedebugclient_p.h>
50 #include <QtDeclarative/QJSEngine>
51
52 //QDeclarativeDebugTest
53 #include "../shared/debugutil_p.h"
54 #include "../../shared/util.h"
55
56 const char *SEQ = "seq";
57 const char *TYPE = "type";
58 const char *COMMAND = "command";
59 const char *ARGUMENTS = "arguments";
60 const char *STEPACTION = "stepaction";
61 const char *STEPCOUNT = "stepcount";
62 const char *EXPRESSION = "expression";
63 const char *FRAME = "frame";
64 const char *GLOBAL = "global";
65 const char *DISABLEBREAK = "disable_break";
66 const char *HANDLES = "handles";
67 const char *INCLUDESOURCE = "includeSource";
68 const char *FROMFRAME = "fromFrame";
69 const char *TOFRAME = "toFrame";
70 const char *BOTTOM = "bottom";
71 const char *NUMBER = "number";
72 const char *FRAMENUMBER = "frameNumber";
73 const char *TYPES = "types";
74 const char *IDS = "ids";
75 const char *FILTER = "filter";
76 const char *FROMLINE = "fromLine";
77 const char *TOLINE = "toLine";
78 const char *TARGET = "target";
79 const char *LINE = "line";
80 const char *COLUMN = "column";
81 const char *ENABLED = "enabled";
82 const char *CONDITION = "condition";
83 const char *IGNORECOUNT = "ignoreCount";
84 const char *BREAKPOINT = "breakpoint";
85 const char *FLAGS = "flags";
86
87 const char *CONTINEDEBUGGING = "continue";
88 const char *EVALUATE = "evaluate";
89 const char *LOOKUP = "lookup";
90 const char *BACKTRACE = "backtrace";
91 const char *SCOPE = "scope";
92 const char *SCOPES = "scopes";
93 const char *SCRIPTS = "scripts";
94 const char *SOURCE = "source";
95 const char *SETBREAKPOINT = "setbreakpoint";
96 const char *CHANGEBREAKPOINT = "changebreakpoint";
97 const char *CLEARBREAKPOINT = "clearbreakpoint";
98 const char *SETEXCEPTIONBREAK = "setexceptionbreak";
99 const char *V8FLAGS = "v8flags";
100 const char *VERSION = "version";
101 const char *DISCONNECT = "disconnect";
102 const char *LISTBREAKPOINTS = "listbreakpoints";
103 const char *GARBAGECOLLECTOR = "gc";
104 //const char *PROFILE = "profile";
105
106 const char *CONNECT = "connect";
107 const char *INTERRUPT = "interrupt";
108
109 const char *REQUEST = "request";
110 const char *IN = "in";
111 const char *NEXT = "next";
112 const char *OUT = "out";
113
114 const char *FUNCTION = "function";
115 const char *SCRIPT = "script";
116
117 const char *ALL = "all";
118 const char *UNCAUGHT = "uncaught";
119
120 //const char *PAUSE = "pause";
121 //const char *RESUME = "resume";
122
123 const char *BLOCKMODE = "-qmljsdebugger=port:3771,block";
124 const char *NORMALMODE = "-qmljsdebugger=port:3771";
125 const char *TEST_QMLFILE = "test.qml";
126 const char *TEST_JSFILE = "test.js";
127 const char *TIMER_QMLFILE = "timer.qml";
128
129 #define VARIANTMAPINIT \
130     QString obj("{}"); \
131     QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj); \
132     jsonVal.setProperty(SEQ,QJSValue(seq++)); \
133     jsonVal.setProperty(TYPE,REQUEST);
134
135
136 #undef QVERIFY
137 #define QVERIFY(statement) \
138 do {\
139     if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\
140         qDebug().nospace() << "\nDEBUGGEE OUTPUT:\n" << process->output();\
141         return;\
142     }\
143 } while (0)
144
145
146 class QJSDebugClient;
147
148 class tst_QDeclarativeDebugJS : public QObject
149 {
150     Q_OBJECT
151
152     bool init(const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true);
153
154 private slots:
155     void initTestCase();
156     void cleanupTestCase();
157
158     void cleanup();
159
160     void getVersion();
161     void getVersionWhenAttaching();
162
163     void applyV8Flags();
164
165     void disconnect();
166
167     void gc();
168
169     void listBreakpoints();
170
171     void setBreakpointInScriptOnCompleted();
172     void setBreakpointInScriptOnTimerCallback();
173     void setBreakpointInScriptInDifferentFile();
174     void setBreakpointInScriptOnComment();
175     void setBreakpointInScriptOnEmptyLine();
176     void setBreakpointInScriptWithCondition();
177     //void setBreakpointInFunction(); //NOT SUPPORTED
178     void setBreakpointWhenAttaching();
179
180     void changeBreakpoint();
181     void changeBreakpointOnCondition();
182
183     void clearBreakpoint();
184
185     void setExceptionBreak();
186
187     void stepNext();
188     void stepNextWithCount();
189     void stepIn();
190     void stepOut();
191     void continueDebugging();
192
193     void backtrace();
194
195     void getFrameDetails();
196
197     void getScopeDetails();
198
199     void evaluateInGlobalScope();
200     void evaluateInLocalScope();
201
202     void getScopes();
203
204     void getScripts();
205
206     void getSource();
207
208     //    void profile(); //NOT SUPPORTED
209
210     //    void verifyQMLOptimizerDisabled();
211
212 private:
213     QDeclarativeDebugProcess *process;
214     QJSDebugClient *client;
215     QDeclarativeDebugConnection *connection;
216 };
217
218 class QJSDebugClient : public QDeclarativeDebugClient
219 {
220     Q_OBJECT
221 public:
222     enum StepAction
223     {
224         Continue,
225         In,
226         Out,
227         Next
228     };
229
230     enum Exception
231     {
232         All,
233         Uncaught
234     };
235
236 //    enum ProfileCommand
237 //    {
238 //        Pause,
239 //        Resume
240 //    };
241
242     QJSDebugClient(QDeclarativeDebugConnection *connection)
243         : QDeclarativeDebugClient(QLatin1String("V8Debugger"), connection),
244           seq(0)
245     {
246         parser = jsEngine.evaluate(QLatin1String("JSON.parse"));
247         stringify = jsEngine.evaluate(QLatin1String("JSON.stringify"));
248     }
249
250     void startDebugging();
251     void interrupt();
252
253     void continueDebugging(StepAction stepAction, int stepCount = 1);
254     void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
255     void lookup(QList<int> handles, bool includeSource = false);
256     void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
257     void frame(int number = -1);
258     void scope(int number = -1, int frameNumber = -1);
259     void scopes(int frameNumber = -1);
260     void scripts(int types = 4, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
261     void source(int frame = -1, int fromLine = -1, int toLine = -1);
262     void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
263     void changeBreakpoint(int breakpoint, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
264     void clearBreakpoint(int breakpoint);
265     void setExceptionBreak(Exception type, bool enabled = false);
266     void v8flags(QString flags);
267     void version();
268     //void profile(ProfileCommand command); //NOT SUPPORTED
269     void disconnect();
270     void gc();
271     void listBreakpoints();
272
273 protected:
274     //inherited from QDeclarativeDebugClient
275     void statusChanged(Status status);
276     void messageReceived(const QByteArray &data);
277
278 signals:
279     void enabled();
280     void breakpointSet();
281     void result();
282     void stopped();
283
284 private:
285     void sendMessage(const QByteArray &);
286     void flushSendBuffer();
287     QByteArray packMessage(QByteArray message);
288
289 private:
290     QJSEngine jsEngine;
291     int seq;
292
293     QList<QByteArray> sendBuffer;
294
295 public:
296     QJSValue parser;
297     QJSValue stringify;
298     QByteArray response;
299
300 };
301
302 void QJSDebugClient::startDebugging()
303 {
304     //    { "seq"     : <number>,
305     //      "type"    : "request",
306     //      "command" : "connect",
307     //    }
308     VARIANTMAPINIT;
309     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONNECT)));
310
311     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
312     sendMessage(packMessage(json.toString().toUtf8()));
313 }
314
315 void QJSDebugClient::interrupt()
316 {
317     //    { "seq"     : <number>,
318     //      "type"    : "request",
319     //      "command" : "interrupt",
320     //    }
321     VARIANTMAPINIT;
322     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(INTERRUPT)));
323
324     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
325     sendMessage(packMessage(json.toString().toUtf8()));
326 }
327
328 void QJSDebugClient::continueDebugging(StepAction action, int count)
329 {
330     //    { "seq"       : <number>,
331     //      "type"      : "request",
332     //      "command"   : "continue",
333     //      "arguments" : { "stepaction" : <"in", "next" or "out">,
334     //                      "stepcount"  : <number of steps (default 1)>
335     //                    }
336     //    }
337     VARIANTMAPINIT;
338     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING)));
339
340     if (action != Continue) {
341         QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
342         switch (action) {
343         case In: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(IN)));
344             break;
345         case Out: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(OUT)));
346             break;
347         case Next: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(NEXT)));
348             break;
349         default:break;
350         }
351         if (args.isValid()) {
352             if (count != 1)
353                 args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count));
354             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
355         }
356     }
357     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
358     sendMessage(packMessage(json.toString().toUtf8()));
359 }
360
361 void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/)
362 {
363     //    { "seq"       : <number>,
364     //      "type"      : "request",
365     //      "command"   : "evaluate",
366     //      "arguments" : { "expression"    : <expression to evaluate>,
367     //                      "frame"         : <number>,
368     //                      "global"        : <boolean>,
369     //                      "disable_break" : <boolean>,
370     //                      "additional_context" : [
371     //                           { "name" : <name1>, "handle" : <handle1> },
372     //                           { "name" : <name2>, "handle" : <handle2> },
373     //                           ...
374     //                      ]
375     //                    }
376     //    }
377     VARIANTMAPINIT;
378     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE)));
379
380     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
381     args.setProperty(QLatin1String(EXPRESSION),QJSValue(expr));
382
383     if (frame != -1)
384         args.setProperty(QLatin1String(FRAME),QJSValue(frame));
385
386     if (global)
387         args.setProperty(QLatin1String(GLOBAL),QJSValue(global));
388
389     if (disableBreak)
390         args.setProperty(QLatin1String(DISABLEBREAK),QJSValue(disableBreak));
391
392     if (args.isValid()) {
393         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
394     }
395
396     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
397     sendMessage(packMessage(json.toString().toUtf8()));
398 }
399
400 void QJSDebugClient::lookup(QList<int> handles, bool includeSource)
401 {
402     //    { "seq"       : <number>,
403     //      "type"      : "request",
404     //      "command"   : "lookup",
405     //      "arguments" : { "handles"       : <array of handles>,
406     //                      "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
407     //                    }
408     //    }
409     VARIANTMAPINIT;
410     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP)));
411
412     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
413
414     QString arr("[]");
415     QJSValue array = parser.call(QJSValue(), QJSValueList() << arr);
416     int index = 0;
417     foreach (int handle, handles) {
418         array.setProperty(index++,QJSValue(handle));
419     }
420     args.setProperty(QLatin1String(HANDLES),array);
421
422     if (includeSource)
423         args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
424
425     if (args.isValid()) {
426         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
427     }
428
429     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
430     sendMessage(packMessage(json.toString().toUtf8()));
431 }
432
433 void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
434 {
435     //    { "seq"       : <number>,
436     //      "type"      : "request",
437     //      "command"   : "backtrace",
438     //      "arguments" : { "fromFrame" : <number>
439     //                      "toFrame" : <number>
440     //                      "bottom" : <boolean, set to true if the bottom of the stack is requested>
441     //                    }
442     //    }
443     VARIANTMAPINIT;
444     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE)));
445
446     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
447
448     if (fromFrame != -1)
449         args.setProperty(QLatin1String(FROMFRAME),QJSValue(fromFrame));
450
451     if (toFrame != -1)
452         args.setProperty(QLatin1String(TOFRAME),QJSValue(toFrame));
453
454     if (bottom)
455         args.setProperty(QLatin1String(BOTTOM),QJSValue(bottom));
456
457     if (args.isValid()) {
458         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
459     }
460
461     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
462     sendMessage(packMessage(json.toString().toUtf8()));
463 }
464
465 void QJSDebugClient::frame(int number)
466 {
467     //    { "seq"       : <number>,
468     //      "type"      : "request",
469     //      "command"   : "frame",
470     //      "arguments" : { "number" : <frame number>
471     //                    }
472     //    }
473     VARIANTMAPINIT;
474     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME)));
475
476     if (number != -1) {
477         QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
478         args.setProperty(QLatin1String(NUMBER),QJSValue(number));
479
480         if (args.isValid()) {
481             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
482         }
483     }
484
485     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
486     sendMessage(packMessage(json.toString().toUtf8()));
487 }
488
489 void QJSDebugClient::scope(int number, int frameNumber)
490 {
491     //    { "seq"       : <number>,
492     //      "type"      : "request",
493     //      "command"   : "scope",
494     //      "arguments" : { "number" : <scope number>
495     //                      "frameNumber" : <frame number, optional uses selected frame if missing>
496     //                    }
497     //    }
498     VARIANTMAPINIT;
499     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE)));
500
501     if (number != -1) {
502         QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
503         args.setProperty(QLatin1String(NUMBER),QJSValue(number));
504
505         if (frameNumber != -1)
506             args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
507
508         if (args.isValid()) {
509             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
510         }
511     }
512
513     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
514     sendMessage(packMessage(json.toString().toUtf8()));
515 }
516
517 void QJSDebugClient::scopes(int frameNumber)
518 {
519     //    { "seq"       : <number>,
520     //      "type"      : "request",
521     //      "command"   : "scopes",
522     //      "arguments" : { "frameNumber" : <frame number, optional uses selected frame if missing>
523     //                    }
524     //    }
525     VARIANTMAPINIT;
526     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES)));
527
528     if (frameNumber != -1) {
529         QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
530         args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
531
532         if (args.isValid()) {
533             jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
534         }
535     }
536
537     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
538     sendMessage(packMessage(json.toString().toUtf8()));
539 }
540
541 void QJSDebugClient::scripts(int types, QList<int> ids, bool includeSource, QVariant /*filter*/)
542 {
543     //    { "seq"       : <number>,
544     //      "type"      : "request",
545     //      "command"   : "scripts",
546     //      "arguments" : { "types"         : <types of scripts to retrieve
547     //                                           set bit 0 for native scripts
548     //                                           set bit 1 for extension scripts
549     //                                           set bit 2 for normal scripts
550     //                                         (default is 4 for normal scripts)>
551     //                      "ids"           : <array of id's of scripts to return. If this is not specified all scripts are requrned>
552     //                      "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
553     //                      "filter"        : <string or number: filter string or script id.
554     //                                         If a number is specified, then only the script with the same number as its script id will be retrieved.
555     //                                         If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
556     //                    }
557     //    }
558     VARIANTMAPINIT;
559     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS)));
560
561     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
562     args.setProperty(QLatin1String(TYPES),QJSValue(types));
563
564     if (ids.count()) {
565         QString arr("[]");
566         QJSValue array = parser.call(QJSValue(), QJSValueList() << arr);
567         int index = 0;
568         foreach (int id, ids) {
569             array.setProperty(index++,QJSValue(id));
570         }
571         args.setProperty(QLatin1String(IDS),array);
572     }
573
574     if (includeSource)
575         args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
576
577     if (args.isValid()) {
578         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
579     }
580
581     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
582     sendMessage(packMessage(json.toString().toUtf8()));
583 }
584
585 void QJSDebugClient::source(int frame, int fromLine, int toLine)
586 {
587     //    { "seq"       : <number>,
588     //      "type"      : "request",
589     //      "command"   : "source",
590     //      "arguments" : { "frame"    : <frame number (default selected frame)>
591     //                      "fromLine" : <from line within the source default is line 0>
592     //                      "toLine"   : <to line within the source this line is not included in
593     //                                    the result default is the number of lines in the script>
594     //                    }
595     //    }
596     VARIANTMAPINIT;
597     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE)));
598
599     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
600
601     if (frame != -1)
602         args.setProperty(QLatin1String(FRAME),QJSValue(frame));
603
604     if (fromLine != -1)
605         args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine));
606
607     if (toLine != -1)
608         args.setProperty(QLatin1String(TOLINE),QJSValue(toLine));
609
610     if (args.isValid()) {
611         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
612     }
613
614     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
615     sendMessage(packMessage(json.toString().toUtf8()));
616 }
617
618 void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount)
619 {
620     //    { "seq"       : <number>,
621     //      "type"      : "request",
622     //      "command"   : "setbreakpoint",
623     //      "arguments" : { "type"        : <"function" or "script" or "scriptId" or "scriptRegExp">
624     //                      "target"      : <function expression or script identification>
625     //                      "line"        : <line in script or function>
626     //                      "column"      : <character position within the line>
627     //                      "enabled"     : <initial enabled state. True or false, default is true>
628     //                      "condition"   : <string with break point condition>
629     //                      "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
630     //                    }
631     //    }
632     VARIANTMAPINIT;
633     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT)));
634
635     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
636
637     args.setProperty(QLatin1String(TYPE),QJSValue(type));
638     args.setProperty(QLatin1String(TARGET),QJSValue(target));
639
640     if (line != -1)
641         args.setProperty(QLatin1String(LINE),QJSValue(line));
642
643     if (column != -1)
644         args.setProperty(QLatin1String(COLUMN),QJSValue(column));
645
646     args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
647
648     if (!condition.isEmpty())
649         args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
650
651     if (ignoreCount != -1)
652         args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
653
654     if (args.isValid()) {
655         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
656     }
657
658     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
659     sendMessage(packMessage(json.toString().toUtf8()));
660 }
661
662 void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount)
663 {
664     //    { "seq"       : <number>,
665     //      "type"      : "request",
666     //      "command"   : "changebreakpoint",
667     //      "arguments" : { "breakpoint"  : <number of the break point to clear>
668     //                      "enabled"     : <initial enabled state. True or false, default is true>
669     //                      "condition"   : <string with break point condition>
670     //                      "ignoreCount" : <number specifying the number of break point hits            }
671     //    }
672     VARIANTMAPINIT;
673     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CHANGEBREAKPOINT)));
674
675     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
676
677     args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
678
679     args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
680
681     if (!condition.isEmpty())
682         args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
683
684     if (ignoreCount != -1)
685         args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
686
687     if (args.isValid()) {
688         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
689     }
690
691     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
692     sendMessage(packMessage(json.toString().toUtf8()));
693 }
694
695 void QJSDebugClient::clearBreakpoint(int breakpoint)
696 {
697     //    { "seq"       : <number>,
698     //      "type"      : "request",
699     //      "command"   : "clearbreakpoint",
700     //      "arguments" : { "breakpoint" : <number of the break point to clear>
701     //                    }
702     //    }
703     VARIANTMAPINIT;
704     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT)));
705
706     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
707
708     args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
709
710     if (args.isValid()) {
711         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
712     }
713
714     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
715     sendMessage(packMessage(json.toString().toUtf8()));
716 }
717
718 void QJSDebugClient::setExceptionBreak(Exception type, bool enabled)
719 {
720     //    { "seq"       : <number>,
721     //      "type"      : "request",
722     //      "command"   : "setexceptionbreak",
723     //      "arguments" : { "type"    : <string: "all", or "uncaught">,
724     //                      "enabled" : <optional bool: enables the break type if true>
725     //                    }
726     //    }
727     VARIANTMAPINIT;
728     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK)));
729
730     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
731
732     if (type == All)
733         args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
734     else if (type == Uncaught)
735         args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(UNCAUGHT)));
736
737     if (enabled)
738         args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
739
740     if (args.isValid()) {
741         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
742     }
743
744     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
745     sendMessage(packMessage(json.toString().toUtf8()));
746 }
747
748 void QJSDebugClient::v8flags(QString flags)
749 {
750     //    { "seq"       : <number>,
751     //      "type"      : "request",
752     //      "command"   : "v8flags",
753     //      "arguments" : { "flags" : <string: a sequence of v8 flags just like those used on the command line>
754     //                    }
755     //    }
756     VARIANTMAPINIT;
757     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS)));
758
759     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
760
761     args.setProperty(QLatin1String(FLAGS),QJSValue(flags));
762
763     if (args.isValid()) {
764         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
765     }
766
767     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
768     sendMessage(packMessage(json.toString().toUtf8()));
769 }
770
771 void QJSDebugClient::version()
772 {
773     //    { "seq"       : <number>,
774     //      "type"      : "request",
775     //      "command"   : "version",
776     //    }
777     VARIANTMAPINIT;
778     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION)));
779
780     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
781     sendMessage(packMessage(json.toString().toUtf8()));
782 }
783
784 //void QJSDebugClient::profile(ProfileCommand command)
785 //{
786 ////    { "seq"       : <number>,
787 ////      "type"      : "request",
788 ////      "command"   : "profile",
789 ////      "arguments" : { "command"  : "resume" or "pause" }
790 ////    }
791 //    VARIANTMAPINIT;
792 //    jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE)));
793
794 //    QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
795
796 //    if (command == Resume)
797 //        args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(RESUME)));
798 //    else
799 //        args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PAUSE)));
800
801 //    args.setProperty(QLatin1String("modules"),QJSValue(1));
802 //    if (args.isValid()) {
803 //        jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
804 //    }
805
806 //    QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
807 //    sendMessage(packMessage(json.toString().toUtf8()));
808 //}
809
810 void QJSDebugClient::disconnect()
811 {
812     //    { "seq"     : <number>,
813     //      "type"    : "request",
814     //      "command" : "disconnect",
815     //    }
816     VARIANTMAPINIT;
817     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT)));
818
819     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
820     sendMessage(packMessage(json.toString().toUtf8()));
821 }
822
823 void QJSDebugClient::gc()
824 {
825     //    { "seq"       : <number>,
826     //      "type"      : "request",
827     //      "command"   : "gc",
828     //      "arguments" : { "type" : <string: "all">,
829     //                    }
830     //    }
831     VARIANTMAPINIT;
832     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GARBAGECOLLECTOR)));
833
834     QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
835
836     args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
837
838     if (args.isValid()) {
839         jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
840     }
841
842     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
843     sendMessage(packMessage(json.toString().toUtf8()));
844 }
845
846 void QJSDebugClient::listBreakpoints()
847 {
848     //    { "seq"       : <number>,
849     //      "type"      : "request",
850     //      "command"   : "listbreakpoints",
851     //    }
852     VARIANTMAPINIT;
853     jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS)));
854
855     QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
856     sendMessage(packMessage(json.toString().toUtf8()));
857 }
858
859 void QJSDebugClient::statusChanged(Status status)
860 {
861     if (status == Enabled) {
862         flushSendBuffer();
863         emit enabled();
864     }
865 }
866
867 void QJSDebugClient::messageReceived(const QByteArray &data)
868 {
869     QDataStream ds(data);
870     QByteArray command;
871     ds >> command;
872
873     if (command == "V8DEBUG") {
874         ds >> response;
875         QString jsonString(response);
876         QVariantMap value = parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
877         QString type = value.value("type").toString();
878
879         if (type == "response") {
880
881             if (!value.value("success").toBool()) {
882 //                qDebug() << "Error: The test case will fail since no signal is emitted";
883                 return;
884             }
885
886             QString debugCommand(value.value("command").toString());
887             if (debugCommand == "backtrace" ||
888                     debugCommand == "lookup" ||
889                     debugCommand == "setbreakpoint" ||
890                     debugCommand == "evaluate" ||
891                     debugCommand == "listbreakpoints" ||
892                     debugCommand == "version" ||
893                     debugCommand == "v8flags" ||
894                     debugCommand == "disconnect" ||
895                     debugCommand == "gc" ||
896                     debugCommand == "changebreakpoint" ||
897                     debugCommand == "clearbreakpoint" ||
898                     debugCommand == "frame" ||
899                     debugCommand == "scope" ||
900                     debugCommand == "scopes" ||
901                     debugCommand == "scripts" ||
902                     debugCommand == "source" ||
903                     debugCommand == "setexceptionbreak" /*||
904                     debugCommand == "profile"*/) {
905                 emit result();
906
907             } else {
908                 // DO NOTHING
909             }
910
911         } else if (type == "event") {
912             QString event(value.value("event").toString());
913
914             if (event == "break" ||
915                     event == "exception") {
916                 emit stopped();
917             }
918         }
919     }
920 }
921
922 void QJSDebugClient::sendMessage(const QByteArray &msg)
923 {
924     if (status() == Enabled) {
925         QDeclarativeDebugClient::sendMessage(msg);
926     } else {
927         sendBuffer.append(msg);
928     }
929 }
930
931 void QJSDebugClient::flushSendBuffer()
932 {
933     foreach (const QByteArray &msg, sendBuffer)
934         QDeclarativeDebugClient::sendMessage(msg);
935     sendBuffer.clear();
936 }
937
938 QByteArray QJSDebugClient::packMessage(QByteArray message)
939 {
940     QByteArray reply;
941     QDataStream rs(&reply, QIODevice::WriteOnly);
942     QByteArray cmd = "V8DEBUG";
943     rs << cmd << message;
944     return reply;
945 }
946
947 void tst_QDeclarativeDebugJS::initTestCase()
948 {
949     process = 0;
950     client = 0;
951     connection = 0;
952 }
953
954 void tst_QDeclarativeDebugJS::cleanupTestCase()
955 {
956     if (process) {
957         process->stop();
958         delete process;
959     }
960
961     if (client)
962         delete client;
963
964     if (connection)
965         delete connection;
966 }
967
968 bool tst_QDeclarativeDebugJS::init(const QString &qmlFile, bool blockMode)
969 {
970     connection = new QDeclarativeDebugConnection();
971     process = new QDeclarativeDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
972     client = new QJSDebugClient(connection);
973
974     if (blockMode)
975         process->start(QStringList() << QLatin1String(BLOCKMODE) << TESTDATA(qmlFile));
976     else
977         process->start(QStringList() << QLatin1String(NORMALMODE) << TESTDATA(qmlFile));
978
979     if (!process->waitForSessionStart()) {
980         return false;
981     }
982
983     connection->connectToHost("127.0.0.1", 3771);
984     if (!connection->waitForConnected())
985         return false;
986
987     return QDeclarativeDebugTest::waitForSignal(client, SIGNAL(enabled()));
988 }
989
990 void tst_QDeclarativeDebugJS::cleanup()
991 {
992     if (process) {
993         process->stop();
994         delete process;
995     }
996
997     if (client)
998         delete client;
999
1000     if (connection)
1001         delete connection;
1002
1003     process = 0;
1004     client = 0;
1005     connection = 0;
1006 }
1007
1008 void tst_QDeclarativeDebugJS::getVersion()
1009 {
1010     //void version()
1011
1012     QVERIFY(init());
1013     client->interrupt();
1014     client->startDebugging();
1015     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1016
1017     client->version();
1018     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1019 }
1020
1021 void tst_QDeclarativeDebugJS::getVersionWhenAttaching()
1022 {
1023     //void version()
1024
1025     QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1026     client->interrupt();
1027     client->startDebugging();
1028     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1029
1030     client->version();
1031     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1032 }
1033
1034 void tst_QDeclarativeDebugJS::applyV8Flags()
1035 {
1036     //void v8flags(QString flags)
1037
1038     QVERIFY(init());
1039     client->interrupt();
1040     client->startDebugging();
1041     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1042
1043     client->v8flags(QString());
1044     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1045 }
1046
1047 void tst_QDeclarativeDebugJS::disconnect()
1048 {
1049     //void disconnect()
1050
1051     QVERIFY(init());
1052     client->interrupt();
1053     client->startDebugging();
1054     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1055
1056     client->disconnect();
1057     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1058 }
1059
1060 void tst_QDeclarativeDebugJS::gc()
1061 {
1062     //void gc()
1063
1064     QVERIFY(init());
1065     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_JSFILE), 43, -1, true);
1066     client->startDebugging();
1067     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1068
1069     client->gc();
1070     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1071 }
1072
1073 void tst_QDeclarativeDebugJS::listBreakpoints()
1074 {
1075     //void listBreakpoints()
1076
1077     int sourceLine1 = 57;
1078     int sourceLine2 = 60;
1079     int sourceLine3 = 67;
1080
1081     QVERIFY(init());
1082     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1083     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1084     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_JSFILE), sourceLine3, -1, true);
1085     client->startDebugging();
1086     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1087
1088     client->listBreakpoints();
1089     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1090
1091     QString jsonString(client->response);
1092     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1093
1094     QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList();
1095
1096     QCOMPARE(breakpoints.count(), 3);
1097 }
1098
1099 void tst_QDeclarativeDebugJS::setBreakpointInScriptOnCompleted()
1100 {
1101     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1102
1103     int sourceLine = 49;
1104     QVERIFY(init());
1105
1106     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1107     client->startDebugging();
1108     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1109
1110     QString jsonString(client->response);
1111     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1112
1113     QVariantMap body = value.value("body").toMap();
1114
1115     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1116     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1117 }
1118
1119 void tst_QDeclarativeDebugJS::setBreakpointInScriptOnTimerCallback()
1120 {
1121     int sourceLine = 49;
1122     QVERIFY(init());
1123
1124     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1125     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1126     sourceLine = 67;
1127     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1128     client->startDebugging();
1129     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1130
1131     client->evaluate("timer.running = true");
1132     client->continueDebugging(QJSDebugClient::Continue);
1133
1134     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1135
1136     QString jsonString(client->response);
1137     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1138
1139     QVariantMap body = value.value("body").toMap();
1140
1141     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1142     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1143 }
1144
1145 void tst_QDeclarativeDebugJS::setBreakpointInScriptInDifferentFile()
1146 {
1147     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1148
1149     int sourceLine = 43;
1150     QVERIFY(init());
1151
1152     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1153     client->startDebugging();
1154     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1155
1156     QString jsonString(client->response);
1157     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1158
1159     QVariantMap body = value.value("body").toMap();
1160
1161     QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
1162     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1163 }
1164
1165 void tst_QDeclarativeDebugJS::setBreakpointInScriptOnComment()
1166 {
1167     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1168
1169     int sourceLine = 48;
1170     int actualLine = 50;
1171     QVERIFY(init());
1172
1173     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1174     client->startDebugging();
1175     QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1176     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1177
1178     QString jsonString(client->response);
1179     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1180
1181     QVariantMap body = value.value("body").toMap();
1182
1183     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1184     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1185 }
1186
1187 void tst_QDeclarativeDebugJS::setBreakpointInScriptOnEmptyLine()
1188 {
1189     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1190
1191     int sourceLine = 49;
1192     int actualLine = 50;
1193     QVERIFY(init());
1194
1195     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
1196     client->startDebugging();
1197     QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
1198     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1199
1200     QString jsonString(client->response);
1201     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1202
1203     QVariantMap body = value.value("body").toMap();
1204
1205     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1206     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_JSFILE));
1207 }
1208
1209 void tst_QDeclarativeDebugJS::setBreakpointInScriptWithCondition()
1210 {
1211     //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1212
1213     int out = 10;
1214     int sourceLine = 51;
1215     QVERIFY(init());
1216
1217     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_JSFILE), sourceLine, -1, true, QLatin1String("out > 10"));
1218     client->startDebugging();
1219     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1220
1221     //Get the frame index
1222     QString jsonString = client->response;
1223     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1224
1225     QVariantMap body = value.value("body").toMap();
1226
1227     int frameIndex = body.value("index").toInt();
1228
1229     //Verify the value of 'result'
1230     client->evaluate(QLatin1String("out"),frameIndex);
1231
1232     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1233
1234     jsonString = client->response;
1235     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1236
1237     body = value.value("body").toMap();
1238
1239     QVERIFY(body.value("value").toInt() > out);
1240 }
1241
1242 void tst_QDeclarativeDebugJS::setBreakpointWhenAttaching()
1243 {
1244     int sourceLine = 49;
1245     QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
1246
1247     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TIMER_QMLFILE), sourceLine);
1248     client->startDebugging();
1249     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1250 }
1251
1252 //void tst_QDeclarativeDebugJS::setBreakpointInFunction()
1253 //{
1254 //    //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1255
1256 //    int actualLine = 31;
1257
1258 //    client->startDebugging();
1259 //    client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
1260
1261 //    QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1262
1263 //    QString jsonString(client->response);
1264 //    QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1265
1266 //    QVariantMap body = value.value("body").toMap();
1267
1268 //    QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1269 //    QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
1270 //}
1271
1272 void tst_QDeclarativeDebugJS::changeBreakpoint()
1273 {
1274     //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1275
1276     int sourceLine1 = 78;
1277     int sourceLine2 = 79;
1278     QVERIFY(init());
1279
1280     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1281     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1282     client->startDebugging();
1283     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1284
1285     //Will hit 1st brakpoint, change this breakpoint enable = false
1286     QString jsonString(client->response);
1287     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1288
1289     QVariantMap body = value.value("body").toMap();
1290     QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1291
1292     int breakpoint = breakpointsHit.at(0).toInt();
1293     client->changeBreakpoint(breakpoint,false);
1294
1295     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1296
1297     //Continue with debugging
1298     client->continueDebugging(QJSDebugClient::Continue);
1299     //Hit 2nd breakpoint
1300     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1301
1302     // start timer
1303     client->evaluate("timer.running = true");
1304
1305     //Continue with debugging
1306     client->continueDebugging(QJSDebugClient::Continue);
1307     //Should stop at 2nd breakpoint
1308     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1309
1310     jsonString = client->response;
1311     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1312
1313     body = value.value("body").toMap();
1314
1315     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1316 }
1317
1318 void tst_QDeclarativeDebugJS::changeBreakpointOnCondition()
1319 {
1320     //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
1321
1322     int sourceLine1 = 56;
1323     int sourceLine2 = 60;
1324     int result = 0;
1325     QVERIFY(init());
1326
1327     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1328     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1329     client->startDebugging();
1330     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1331
1332     //Will hit 1st brakpoint, change this breakpoint enable = false
1333     QString jsonString(client->response);
1334     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1335
1336     QVariantMap body = value.value("body").toMap();
1337     QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1338
1339     int breakpoint = breakpointsHit.at(0).toInt();
1340     client->changeBreakpoint(breakpoint,false,QLatin1String("a = 0"));
1341
1342     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1343
1344     //Continue with debugging
1345     client->continueDebugging(QJSDebugClient::Continue);
1346     //Hit 2nd breakpoint
1347     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1348     // start timer
1349     client->evaluate("timer.running = true");
1350     //Continue with debugging
1351     client->continueDebugging(QJSDebugClient::Continue);
1352     //Should stop at 2nd breakpoint
1353     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1354
1355     jsonString = client->response;
1356     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1357
1358     body = value.value("body").toMap();
1359
1360     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1361
1362     client->frame();
1363     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1364
1365     //Get the frame index
1366     jsonString = client->response;
1367     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1368
1369     body = value.value("body").toMap();
1370
1371     int frameIndex = body.value("index").toInt();
1372
1373     //Verify the value of 'result'
1374     client->evaluate(QLatin1String("root.result"),frameIndex);
1375
1376     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1377
1378     jsonString = client->response;
1379     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1380
1381     body = value.value("body").toMap();
1382
1383     QVERIFY(body.value("value").toInt() > result);
1384 }
1385
1386 void tst_QDeclarativeDebugJS::clearBreakpoint()
1387 {
1388     //void clearBreakpoint(int breakpoint);
1389
1390     int sourceLine1 = 78;
1391     int sourceLine2 = 79;
1392     QVERIFY(init());
1393
1394     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1395     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1396     client->startDebugging();
1397     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1398
1399     //Will hit 1st brakpoint, change this breakpoint enable = false
1400     QString jsonString(client->response);
1401     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1402
1403     QVariantMap body = value.value("body").toMap();
1404     QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
1405
1406     int breakpoint = breakpointsHit.at(0).toInt();
1407     client->changeBreakpoint(breakpoint,false,QLatin1String("result > 5"));
1408
1409     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1410
1411     //Continue with debugging
1412     client->continueDebugging(QJSDebugClient::Continue);
1413     //Hit 2nd breakpoint
1414     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1415     // start timer
1416     client->evaluate("timer.running = true");
1417     //Continue with debugging
1418     client->continueDebugging(QJSDebugClient::Continue);
1419     //Should stop at 2nd breakpoint
1420     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1421
1422     jsonString = client->response;
1423     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1424
1425     body = value.value("body").toMap();
1426
1427     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1428 }
1429
1430 void tst_QDeclarativeDebugJS::setExceptionBreak()
1431 {
1432     //void setExceptionBreak(QString type, bool enabled = false);
1433
1434     int sourceLine = 49;
1435     QVERIFY(init());
1436
1437     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1438     client->setExceptionBreak(QJSDebugClient::All,true);
1439     client->startDebugging();
1440     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1441     client->evaluate("root.raiseException = true");
1442     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1443     client->continueDebugging(QJSDebugClient::Continue);
1444     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
1445 }
1446
1447 void tst_QDeclarativeDebugJS::stepNext()
1448 {
1449     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1450
1451     int sourceLine = 57;
1452     QVERIFY(init());
1453
1454     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1455     client->startDebugging();
1456     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1457
1458     client->continueDebugging(QJSDebugClient::Next);
1459     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
1460
1461     QString jsonString(client->response);
1462     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1463
1464     QVariantMap body = value.value("body").toMap();
1465
1466     QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1);
1467     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1468 }
1469
1470 void tst_QDeclarativeDebugJS::stepNextWithCount()
1471 {
1472     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1473
1474     int sourceLine = 59;
1475     QVERIFY(init());
1476
1477     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1478     client->startDebugging();
1479     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1480
1481     client->continueDebugging(QJSDebugClient::Next,2);
1482     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
1483
1484     QString jsonString(client->response);
1485     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1486
1487     QVariantMap body = value.value("body").toMap();
1488
1489     QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2);
1490     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1491 }
1492
1493 void tst_QDeclarativeDebugJS::stepIn()
1494 {
1495     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1496
1497     int sourceLine = 61;
1498     int actualLine = 78;
1499     QVERIFY(init());
1500
1501     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1502     client->startDebugging();
1503     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1504
1505     client->continueDebugging(QJSDebugClient::In);
1506     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
1507
1508     QString jsonString(client->response);
1509     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1510
1511     QVariantMap body = value.value("body").toMap();
1512
1513     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1514     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1515 }
1516
1517 void tst_QDeclarativeDebugJS::stepOut()
1518 {
1519     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1520
1521     int sourceLine = 56;
1522     int actualLine = 49;
1523     QVERIFY(init());
1524
1525     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1526     client->startDebugging();
1527     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1528
1529     client->continueDebugging(QJSDebugClient::Out);
1530     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
1531
1532     QString jsonString(client->response);
1533     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1534
1535     QVariantMap body = value.value("body").toMap();
1536
1537     QCOMPARE(body.value("sourceLine").toInt(), actualLine);
1538     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1539 }
1540
1541 void tst_QDeclarativeDebugJS::continueDebugging()
1542 {
1543     //void continueDebugging(StepAction stepAction, int stepCount = 1);
1544
1545     int sourceLine1 = 56;
1546     int sourceLine2 = 60;
1547     QVERIFY(init());
1548
1549     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine1, -1, true);
1550     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine2, -1, true);
1551     client->startDebugging();
1552     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1553
1554     client->continueDebugging(QJSDebugClient::Continue);
1555     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
1556
1557     QString jsonString(client->response);
1558     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1559
1560     QVariantMap body = value.value("body").toMap();
1561
1562     QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
1563     QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TEST_QMLFILE));
1564 }
1565
1566 void tst_QDeclarativeDebugJS::backtrace()
1567 {
1568     //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
1569
1570     int sourceLine = 60;
1571     QVERIFY(init());
1572
1573     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1574     client->startDebugging();
1575     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1576
1577     client->backtrace();
1578     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1579 }
1580
1581 void tst_QDeclarativeDebugJS::getFrameDetails()
1582 {
1583     //void frame(int number = -1);
1584
1585     int sourceLine = 60;
1586     QVERIFY(init());
1587
1588     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1589     client->startDebugging();
1590     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1591
1592     client->frame();
1593     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1594 }
1595
1596 void tst_QDeclarativeDebugJS::getScopeDetails()
1597 {
1598     //void scope(int number = -1, int frameNumber = -1);
1599
1600     int sourceLine = 60;
1601     QVERIFY(init());
1602
1603     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1604     client->startDebugging();
1605     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1606
1607     client->scope();
1608     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1609 }
1610
1611 void tst_QDeclarativeDebugJS::evaluateInGlobalScope()
1612 {
1613     //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1614
1615     int sourceLine = 49;
1616     QVERIFY(init());
1617
1618     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1619     client->startDebugging();
1620     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1621
1622     client->evaluate(QLatin1String("print('Hello World')"),true);
1623     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1624
1625     //Verify the value of 'print'
1626     QString jsonString(client->response);
1627     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1628
1629     QVariantMap body = value.value("body").toMap();
1630
1631     QCOMPARE(body.value("text").toString(),QLatin1String("undefined"));
1632 }
1633
1634 void tst_QDeclarativeDebugJS::evaluateInLocalScope()
1635 {
1636     //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
1637
1638     int sourceLine = 60;
1639     QVERIFY(init());
1640
1641     client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(TEST_QMLFILE), sourceLine, -1, true);
1642     client->startDebugging();
1643     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1644
1645     client->frame();
1646     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1647
1648     //Get the frame index
1649     QString jsonString(client->response);
1650     QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1651
1652     QVariantMap body = value.value("body").toMap();
1653
1654     int frameIndex = body.value("index").toInt();
1655
1656     client->evaluate(QLatin1String("root.someValue"),frameIndex);
1657     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1658
1659     //Verify the value of 'root.someValue'
1660     jsonString = client->response;
1661     value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
1662
1663     body = value.value("body").toMap();
1664
1665     QCOMPARE(body.value("value").toInt(),10);
1666 }
1667
1668 void tst_QDeclarativeDebugJS::getScopes()
1669 {
1670     //void scopes(int frameNumber = -1);
1671
1672     QVERIFY(init());
1673
1674     client->interrupt();
1675     client->startDebugging();
1676     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1677
1678     client->scopes();
1679     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1680 }
1681
1682 void tst_QDeclarativeDebugJS::getScripts()
1683 {
1684     //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
1685
1686     QVERIFY(init(QLatin1String(TIMER_QMLFILE), true));
1687
1688     client->interrupt();
1689     client->startDebugging();
1690     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1691
1692     client->scripts();
1693     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1694     QString jsonString(client->response);
1695     QVariantMap value = client->parser.call(QJSValue(),
1696                                             QJSValueList()
1697                                             << QJSValue(jsonString)).toVariant().toMap();
1698
1699     QList<QVariant> scripts = value.value("body").toList();
1700
1701     QCOMPARE(scripts.count(), 2);
1702 }
1703
1704 void tst_QDeclarativeDebugJS::getSource()
1705 {
1706     //void source(int frame = -1, int fromLine = -1, int toLine = -1);
1707
1708     QVERIFY(init());
1709
1710     client->interrupt();
1711     client->startDebugging();
1712     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
1713
1714     client->source();
1715     QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
1716 }
1717
1718 QTEST_MAIN(tst_QDeclarativeDebugJS)
1719
1720 #include "tst_qdeclarativedebugjs.moc"
1721