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