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