1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <qscriptengine.h>
46 #include <qscriptenginedebugger.h>
48 #include <qlineedit.h>
49 #include <qmainwindow.h>
51 #include <qplaintextedit.h>
57 // Will try to wait for the condition while allowing event processing
58 #define QTRY_COMPARE(__expr, __expected) \
60 const int __step = 50; \
61 const int __timeout = 5000; \
62 if ((__expr) != (__expected)) { \
65 for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
66 QTest::qWait(__step); \
68 QCOMPARE(__expr, __expected); \
71 // Can't use QTest::qWait() because it causes event loop to hang on some platforms
72 static void qsWait(int ms
)
75 timer
.setSingleShot(true);
76 timer
.setInterval(ms
);
79 QObject::connect(&timer
, SIGNAL(timeout()), &loop
, SLOT(quit()));
81 QCoreApplication::processEvents();
84 class tst_QScriptEngineDebugger
: public QObject
89 tst_QScriptEngineDebugger();
90 virtual ~tst_QScriptEngineDebugger();
93 void attachAndDetach();
96 void standardObjects();
97 void debuggerSignals();
98 void consoleCommands();
99 void multithreadedDebugging();
102 tst_QScriptEngineDebugger::tst_QScriptEngineDebugger()
106 tst_QScriptEngineDebugger::~tst_QScriptEngineDebugger()
110 void tst_QScriptEngineDebugger::attachAndDetach()
112 #if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
113 QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll
);
116 QScriptEngineDebugger debugger
;
117 QCOMPARE(debugger
.state(), QScriptEngineDebugger::SuspendedState
);
118 debugger
.attachTo(0);
119 QScriptEngine engine
;
120 debugger
.attachTo(&engine
);
121 QCOMPARE(debugger
.state(), QScriptEngineDebugger::SuspendedState
);
124 QScriptEngineDebugger debugger
;
125 QScriptEngine engine
;
126 QScriptValue oldPrint
= engine
.globalObject().property("print");
127 QVERIFY(oldPrint
.isFunction());
128 QVERIFY(!engine
.globalObject().property("__FILE__").isValid());
129 QVERIFY(!engine
.globalObject().property("__LINE__").isValid());
131 debugger
.attachTo(&engine
);
132 QVERIFY(engine
.globalObject().property("__FILE__").isUndefined());
133 QVERIFY(engine
.globalObject().property("__LINE__").isNumber());
134 QVERIFY(!engine
.globalObject().property("print").strictlyEquals(oldPrint
));
137 QVERIFY(engine
.globalObject().property("print").strictlyEquals(oldPrint
));
138 QVERIFY(!engine
.globalObject().property("__FILE__").isValid());
139 QVERIFY(!engine
.globalObject().property("__LINE__").isValid());
142 QScriptEngineDebugger debugger
;
143 QScriptEngine engine
;
144 debugger
.attachTo(&engine
);
146 QScriptEngine engine2
;
147 debugger
.attachTo(&engine2
);
150 QScriptEngineDebugger debugger
;
151 QScriptEngine engine
;
152 debugger
.attachTo(&engine
);
154 QScriptEngine engine2
;
155 debugger
.attachTo(&engine2
);
158 #ifndef Q_OS_WINCE // demands too much memory for WinCE
160 QScriptEngineDebugger debugger
;
161 QScriptEngine engine
;
162 debugger
.attachTo(&engine
);
163 QScriptEngineDebugger debugger2
;
164 debugger2
.attachTo(&engine
);
168 QScriptEngine
*engine
= new QScriptEngine
;
169 QScriptEngineDebugger debugger
;
170 debugger
.attachTo(engine
);
172 QScriptEngine engine2
;
173 debugger
.attachTo(&engine2
);
177 void tst_QScriptEngineDebugger::action()
179 #if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
180 QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll
);
183 QScriptEngine engine
;
184 QScriptEngineDebugger debugger
;
185 debugger
.attachTo(&engine
);
186 QList
<QScriptEngineDebugger::DebuggerAction
> actions
;
188 << QScriptEngineDebugger::InterruptAction
189 << QScriptEngineDebugger::ContinueAction
190 << QScriptEngineDebugger::StepIntoAction
191 << QScriptEngineDebugger::StepOverAction
192 << QScriptEngineDebugger::StepOutAction
193 << QScriptEngineDebugger::RunToCursorAction
194 << QScriptEngineDebugger::RunToNewScriptAction
195 << QScriptEngineDebugger::ToggleBreakpointAction
196 << QScriptEngineDebugger::ClearDebugOutputAction
197 << QScriptEngineDebugger::ClearErrorLogAction
198 << QScriptEngineDebugger::ClearConsoleAction
199 << QScriptEngineDebugger::FindInScriptAction
200 << QScriptEngineDebugger::FindNextInScriptAction
201 << QScriptEngineDebugger::FindPreviousInScriptAction
202 << QScriptEngineDebugger::GoToLineAction
;
204 for (int i
= 0; i
< actions
.size(); ++i
) {
205 QScriptEngineDebugger::DebuggerAction da
= actions
.at(i
);
206 QAction
*act
= debugger
.action(da
);
208 QCOMPARE(act
, debugger
.action(da
));
209 QCOMPARE(act
->parent(), (QObject
*)&debugger
);
210 QVERIFY(lst
.indexOf(act
) == -1);
215 void tst_QScriptEngineDebugger::widget()
217 #if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
218 QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll
);
221 QScriptEngine engine
;
222 QScriptEngineDebugger debugger
;
223 debugger
.attachTo(&engine
);
224 QList
<QScriptEngineDebugger::DebuggerWidget
> widgets
;
226 << QScriptEngineDebugger::ConsoleWidget
227 << QScriptEngineDebugger::StackWidget
228 << QScriptEngineDebugger::ScriptsWidget
229 << QScriptEngineDebugger::LocalsWidget
230 << QScriptEngineDebugger::CodeWidget
231 << QScriptEngineDebugger::CodeFinderWidget
232 << QScriptEngineDebugger::BreakpointsWidget
233 << QScriptEngineDebugger::DebugOutputWidget
234 << QScriptEngineDebugger::ErrorLogWidget
;
236 for (int i
= 0; i
< widgets
.size(); ++i
) {
237 QScriptEngineDebugger::DebuggerWidget dw
= widgets
.at(i
);
238 QWidget
*wid
= debugger
.widget(dw
);
240 QCOMPARE(wid
, debugger
.widget(dw
));
241 QVERIFY(lst
.indexOf(wid
) == -1);
243 QCOMPARE(static_cast<QWidget
*>(wid
->parent()), (QWidget
*)0);
247 void tst_QScriptEngineDebugger::standardObjects()
249 #if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
250 QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll
);
253 QScriptEngine engine
;
254 QScriptEngineDebugger debugger
;
255 debugger
.attachTo(&engine
);
257 QMainWindow
*win
= debugger
.standardWindow();
258 QCOMPARE(static_cast<QWidget
*>(win
->parent()), (QWidget
*)0);
260 QMenu
*menu
= debugger
.createStandardMenu();
261 QCOMPARE(static_cast<QWidget
*>(menu
->parent()), (QWidget
*)0);
262 QToolBar
*toolBar
= debugger
.createStandardToolBar();
263 QCOMPARE(static_cast<QWidget
*>(toolBar
->parent()), (QWidget
*)0);
265 QMenu
*menu2
= debugger
.createStandardMenu(win
);
266 QCOMPARE(static_cast<QWidget
*>(menu2
->parent()), (QWidget
*)win
);
267 QVERIFY(menu2
!= menu
);
268 QToolBar
*toolBar2
= debugger
.createStandardToolBar(win
);
269 QCOMPARE(static_cast<QWidget
*>(toolBar2
->parent()), (QWidget
*)win
);
270 QVERIFY(toolBar2
!= toolBar
);
276 void tst_QScriptEngineDebugger::debuggerSignals()
278 #if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
279 QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll
);
282 QScriptEngine engine
;
283 QScriptEngineDebugger debugger
;
284 debugger
.attachTo(&engine
);
285 debugger
.setAutoShowStandardWindow(false);
286 QSignalSpy
evaluationSuspendedSpy(&debugger
, SIGNAL(evaluationSuspended()));
287 QSignalSpy
evaluationResumedSpy(&debugger
, SIGNAL(evaluationResumed()));
288 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()),
289 debugger
.action(QScriptEngineDebugger::ContinueAction
),
291 engine
.evaluate("123");
292 QCOMPARE(evaluationSuspendedSpy
.count(), 0);
293 QCOMPARE(evaluationResumedSpy
.count(), 0);
294 engine
.evaluate("debugger");
295 QCoreApplication::processEvents();
296 QCOMPARE(evaluationSuspendedSpy
.count(), 1);
297 QCOMPARE(evaluationResumedSpy
.count(), 1);
300 static void executeConsoleCommand(QLineEdit
*inputEdit
, QPlainTextEdit
*outputEdit
,
303 QString before
= outputEdit
->toPlainText();
304 inputEdit
->setText(text
);
305 QTest::keyPress(inputEdit
, Qt::Key_Enter
);
306 const int delay
= 100;
308 QString after
= outputEdit
->toPlainText();
311 while ((before
== after
) && (retryCount
!= 0)) {
313 after
= outputEdit
->toPlainText();
316 if (before
!= after
) {
319 after
= outputEdit
->toPlainText();
320 if (before
!= after
) {
327 class DebuggerCommandExecutor
: public QObject
331 DebuggerCommandExecutor(QLineEdit
*inputEdit
,
332 QPlainTextEdit
*outputEdit
,
335 : QObject(parent
), m_inputEdit(inputEdit
),
336 m_outputEdit(outputEdit
), m_commands(text
) {}
337 DebuggerCommandExecutor(QLineEdit
*inputEdit
,
338 QPlainTextEdit
*outputEdit
,
339 const QStringList
&commands
,
341 : QObject(parent
), m_inputEdit(inputEdit
),
342 m_outputEdit(outputEdit
), m_commands(commands
) {}
345 for (int i
= 0; i
< m_commands
.size(); ++i
)
346 executeConsoleCommand(m_inputEdit
, m_outputEdit
, m_commands
.at(i
));
349 QLineEdit
*m_inputEdit
;
350 QPlainTextEdit
*m_outputEdit
;
351 QStringList m_commands
;
354 void tst_QScriptEngineDebugger::consoleCommands()
356 QSKIP("This test can hang / misbehave because of timing/event loop issues (task 241300)", SkipAll
);
358 QScriptEngine engine
;
359 QScriptEngineDebugger debugger
;
360 debugger
.setAutoShowStandardWindow(false);
361 debugger
.attachTo(&engine
);
363 QWidget
*consoleWidget
= debugger
.widget(QScriptEngineDebugger::ConsoleWidget
);
364 QLineEdit
*inputEdit
= qFindChild
<QLineEdit
*>(consoleWidget
);
365 QVERIFY(inputEdit
!= 0);
366 QPlainTextEdit
*outputEdit
= qFindChild
<QPlainTextEdit
*>(consoleWidget
);
367 QVERIFY(outputEdit
!= 0);
369 QVERIFY(outputEdit
->toPlainText().startsWith("Welcome to the Qt Script debugger."));
374 QWidget
*debugOutputWidget
= debugger
.widget(QScriptEngineDebugger::DebugOutputWidget
);
375 QPlainTextEdit
*debugOutputEdit
= qFindChild
<QPlainTextEdit
*>(debugOutputWidget
);
376 QVERIFY(debugOutputEdit
!= 0);
378 QVERIFY(debugOutputEdit
->toPlainText().isEmpty());
379 executeConsoleCommand(inputEdit
, outputEdit
, "print('Test of debug output')");
380 QCOMPARE(debugOutputEdit
->toPlainText(), QString::fromLatin1("Test of debug output"));
382 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> print('Test of debug output')"));
386 executeConsoleCommand(inputEdit
, outputEdit
, ".info scripts");
387 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info scripts\nNo scripts loaded."));
390 executeConsoleCommand(inputEdit
, outputEdit
, ".break foo.qs:123");
391 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .break foo.qs:123\nBreakpoint 1: foo.qs, line 123."));
394 executeConsoleCommand(inputEdit
, outputEdit
, ".break 123");
395 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .break 123\nNo script."));
398 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
399 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
402 executeConsoleCommand(inputEdit
, outputEdit
, ".disable 1");
403 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .disable 1"));
406 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
407 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tno\tfoo.qs:123"));
410 executeConsoleCommand(inputEdit
, outputEdit
, ".disable 1");
411 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .disable 1"));
414 executeConsoleCommand(inputEdit
, outputEdit
, ".disable 123");
415 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .disable 123\nNo breakpoint number 123."));
418 executeConsoleCommand(inputEdit
, outputEdit
, ".enable 1");
419 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .enable 1"));
422 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
423 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
426 executeConsoleCommand(inputEdit
, outputEdit
, ".enable 123");
427 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .enable 123\nNo breakpoint number 123."));
430 executeConsoleCommand(inputEdit
, outputEdit
, ".condition 1 i > 456");
431 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .condition 1 i > 456"));
434 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
435 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123\n\tstop only if i > 456"));
438 executeConsoleCommand(inputEdit
, outputEdit
, ".condition 1");
439 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .condition 1\nBreakpoint 1 now unconditional."));
442 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
443 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
446 executeConsoleCommand(inputEdit
, outputEdit
, ".condition 123");
447 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .condition 123\nNo breakpoint number 123."));
450 executeConsoleCommand(inputEdit
, outputEdit
, ".ignore 1");
451 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .ignore 1\nMissing argument (ignore-count)."));
454 executeConsoleCommand(inputEdit
, outputEdit
, ".ignore 1 10");
455 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .ignore 1 10\nBreakpoint 1 will be ignored the next 10 time(s)."));
458 executeConsoleCommand(inputEdit
, outputEdit
, ".delete 1");
459 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .delete 1"));
462 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
463 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nNo breakpoints set."));
466 executeConsoleCommand(inputEdit
, outputEdit
, ".tbreak bar.qs:456");
467 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .tbreak bar.qs:456\nBreakpoint 2: bar.qs, line 456."));
471 script
.append("function foo(i) {\n");
472 for (int i
= 0; i
< 100; ++i
)
473 script
.append(QString::fromLatin1(" i = i + %0;\n").arg(i
));
474 script
.append(" return i;\n}");
475 engine
.evaluate(script
, "foo.qs");
478 executeConsoleCommand(inputEdit
, outputEdit
, ".info scripts");
479 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info scripts\n\tfoo.qs"));
482 executeConsoleCommand(inputEdit
, outputEdit
, ".list foo.qs");
483 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .list foo.qs\n"
484 "1\tfunction foo(i) {\n"
495 executeConsoleCommand(inputEdit
, outputEdit
, ".list");
496 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .list\n"
500 executeConsoleCommand(inputEdit
, outputEdit
, ".backtrace");
501 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .backtrace\n#0 <global>() at -1"));
504 executeConsoleCommand(inputEdit
, outputEdit
, ".down");
505 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .down\nAlready at bottom (innermost) frame."));
508 executeConsoleCommand(inputEdit
, outputEdit
, ".up");
509 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .up\nAlready at top (outermost) frame."));
512 executeConsoleCommand(inputEdit
, outputEdit
, ".frame");
513 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .frame\n#0 <global>() at -1"));
516 executeConsoleCommand(inputEdit
, outputEdit
, ".break foo.qs:789");
517 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .break foo.qs:789\nBreakpoint 3: foo.qs, line 789."));
520 executeConsoleCommand(inputEdit
, outputEdit
, ".clear foo.qs:789");
521 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .clear foo.qs:789\nDeleted breakpoint 3."));
524 executeConsoleCommand(inputEdit
, outputEdit
, ".info breakpoints");
525 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n2\tyes\tbar.qs:456"));
528 executeConsoleCommand(inputEdit
, outputEdit
, ".info locals");
529 QVERIFY(outputEdit
->toPlainText().startsWith("qsdb> .info locals\n"
531 "Infinity : Infinity\n"
532 "undefined : undefined\n"
533 "print : function () { [native] }\n"
534 "parseInt : function () { [native] }\n"
535 "parseFloat : function () { [native] }\n"
536 "isNaN : function () { [native] }\n"
537 "isFinite : function () { [native] }\n"
538 "decodeURI : function () { [native] }\n"
539 "decodeURIComponent : function () { [native] }\n"
540 "encodeURI : function () { [native] }\n"
541 "encodeURIComponent : function () { [native] }\n"
542 "escape : function () { [native] }\n"
543 "unescape : function () { [native] }\n"
544 "version : function () { [native] }\n"
545 "gc : function () { [native] }\n"
546 "Object : function () { [native] }\n"
547 "Function : function () { [native] }\n"
548 "Number : function () { [native] }\n"
549 "Boolean : function () { [native] }"));
552 QVERIFY(!engine
.globalObject().property("a").isValid());
553 executeConsoleCommand(inputEdit
, outputEdit
, ".eval a = 123");
554 QVERIFY(engine
.globalObject().property("a").isNumber());
555 QCOMPARE(engine
.globalObject().property("a").toInt32(), 123);
558 QVERIFY(!engine
.globalObject().property("b").isValid());
559 executeConsoleCommand(inputEdit
, outputEdit
, "b = 456");
560 QVERIFY(engine
.globalObject().property("b").isNumber());
561 QCOMPARE(engine
.globalObject().property("b").toInt32(), 456);
564 executeConsoleCommand(inputEdit
, outputEdit
, ".break myscript.qs:1");
565 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("qsdb> .break myscript.qs:1\nBreakpoint 4: myscript.qs, line 1."));
568 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".continue");
569 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
571 engine
.evaluate("void(123);", "myscript.qs");
572 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .continue"));
576 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".step");
577 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
579 engine
.evaluate("void(123);\nvoid(456);", "myscript.qs");
580 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
588 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".step 2");
589 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
591 engine
.evaluate("void(123);\nvoid(456);", "myscript.qs");
592 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .step 2"));
596 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".next");
597 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
599 engine
.evaluate("void(123);\nvoid(456);", "myscript.qs");
600 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
608 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".next 2");
609 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
611 engine
.evaluate("void(123);\nvoid(456);", "myscript.qs");
612 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
618 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".finish");
619 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
621 engine
.evaluate("void(123);\nvoid(456);", "myscript.qs");
622 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .finish"));
626 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, ".return");
627 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
629 engine
.evaluate("void(123);\nvoid(456);\n789;", "myscript.qs");
630 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .return"));
634 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, QStringList() << ".list" << ".continue");
635 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
637 engine
.evaluate("void(123);\nvoid(456);\n789;", "myscript.qs");
638 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
656 script
.append("function bar(i) {\n");
657 for (int i
= 0; i
< 10; ++i
)
658 script
.append(QString::fromLatin1(" i = i + %0;\n").arg(i
));
659 script
.append(" return i;\n}");
660 engine
.evaluate(script
, "bar.qs");
664 executeConsoleCommand(inputEdit
, outputEdit
, ".break bar.qs:7");
667 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, QStringList()
675 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
677 engine
.evaluate("bar(123);", "testscript.qs");
678 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 5 at bar.qs, line 7.\n"
692 "#1 <global>()@testscript.qs:1\n"
705 "#1 <global>()@testscript.qs:1\n"
707 "#0 bar(123)@bar.qs:7\n"
723 DebuggerCommandExecutor
executor(inputEdit
, outputEdit
, QStringList()
726 QObject::connect(&debugger
, SIGNAL(evaluationSuspended()), &executor
, SLOT(execute()), Qt::QueuedConnection
);
728 engine
.evaluate("bar(123);", "testscript.qs");
729 QCOMPARE(outputEdit
->toPlainText(), QString::fromLatin1("Breakpoint 5 at bar.qs, line 7.\n"
746 class ScriptEvaluator
: public QObject
750 ScriptEvaluator(QObject
*parent
= 0)
752 m_engine
= new QScriptEngine(this);
754 QScriptEngine
*engine() const {
758 QScriptValue
evaluate(const QString
&program
) {
759 return m_engine
->evaluate(program
);
762 QScriptEngine
*m_engine
;
765 void tst_QScriptEngineDebugger::multithreadedDebugging()
768 QSKIP("This tests uses too much memory for Windows CE", SkipAll
);
770 ScriptEvaluator eval
;
772 eval
.moveToThread(&thread
);
773 eval
.engine()->moveToThread(&thread
);
774 QScriptEngineDebugger debugger
;
775 QSignalSpy
evaluationSuspendedSpy(&debugger
, SIGNAL(evaluationSuspended()));
776 QSignalSpy
evaluationResumedSpy(&debugger
, SIGNAL(evaluationResumed()));
777 debugger
.attachTo(eval
.engine());
778 QMetaObject::invokeMethod(&eval
, "evaluate", Qt::QueuedConnection
, Q_ARG(QString
, "debugger"));
779 QSignalSpy
threadFinishedSpy(&thread
, SIGNAL(finished()));
781 QTRY_COMPARE(evaluationSuspendedSpy
.count(), 1);
782 QTRY_COMPARE(evaluationResumedSpy
.count(), 0);
784 QTRY_COMPARE(threadFinishedSpy
.count(), 1);
787 QTEST_MAIN(tst_QScriptEngineDebugger
)
788 #include "tst_qscriptenginedebugger.moc"