Fix QIODevice::getChar optimization
[qt-netbsd.git] / tests / auto / qscriptenginedebugger / tst_qscriptenginedebugger.cpp
blobe78253b72116e565275e179878f2713f5789698a
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 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 ** 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
14 ** this package.
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.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <qscriptengine.h>
46 #include <qscriptenginedebugger.h>
47 #include <qaction.h>
48 #include <qlineedit.h>
49 #include <qmainwindow.h>
50 #include <qmenu.h>
51 #include <qplaintextedit.h>
52 #include <qtoolbar.h>
54 //TESTED_CLASS=
55 //TESTED_FILES=
57 // Will try to wait for the condition while allowing event processing
58 #define QTRY_COMPARE(__expr, __expected) \
59 do { \
60 const int __step = 50; \
61 const int __timeout = 5000; \
62 if ((__expr) != (__expected)) { \
63 QTest::qWait(0); \
64 } \
65 for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
66 QTest::qWait(__step); \
67 } \
68 QCOMPARE(__expr, __expected); \
69 } while(0)
71 // Can't use QTest::qWait() because it causes event loop to hang on some platforms
72 static void qsWait(int ms)
74 QTimer timer;
75 timer.setSingleShot(true);
76 timer.setInterval(ms);
77 timer.start();
78 QEventLoop loop;
79 QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
80 loop.exec();
81 QCoreApplication::processEvents();
84 class tst_QScriptEngineDebugger : public QObject
86 Q_OBJECT
88 public:
89 tst_QScriptEngineDebugger();
90 virtual ~tst_QScriptEngineDebugger();
92 private slots:
93 void attachAndDetach();
94 void action();
95 void widget();
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);
114 #endif
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));
136 debugger.detach();
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);
145 debugger.detach();
146 QScriptEngine engine2;
147 debugger.attachTo(&engine2);
150 QScriptEngineDebugger debugger;
151 QScriptEngine engine;
152 debugger.attachTo(&engine);
153 debugger.detach();
154 QScriptEngine engine2;
155 debugger.attachTo(&engine2);
156 debugger.detach();
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);
166 #endif
168 QScriptEngine *engine = new QScriptEngine;
169 QScriptEngineDebugger debugger;
170 debugger.attachTo(engine);
171 delete 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);
181 #endif
183 QScriptEngine engine;
184 QScriptEngineDebugger debugger;
185 debugger.attachTo(&engine);
186 QList<QScriptEngineDebugger::DebuggerAction> actions;
187 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;
203 QList<QAction*> lst;
204 for (int i = 0; i < actions.size(); ++i) {
205 QScriptEngineDebugger::DebuggerAction da = actions.at(i);
206 QAction *act = debugger.action(da);
207 QVERIFY(act != 0);
208 QCOMPARE(act, debugger.action(da));
209 QCOMPARE(act->parent(), (QObject*)&debugger);
210 QVERIFY(lst.indexOf(act) == -1);
211 lst.append(act);
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);
219 #endif
221 QScriptEngine engine;
222 QScriptEngineDebugger debugger;
223 debugger.attachTo(&engine);
224 QList<QScriptEngineDebugger::DebuggerWidget> widgets;
225 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;
235 QList<QWidget*> lst;
236 for (int i = 0; i < widgets.size(); ++i) {
237 QScriptEngineDebugger::DebuggerWidget dw = widgets.at(i);
238 QWidget *wid = debugger.widget(dw);
239 QVERIFY(wid != 0);
240 QCOMPARE(wid, debugger.widget(dw));
241 QVERIFY(lst.indexOf(wid) == -1);
242 lst.append(wid);
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);
251 #endif
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);
272 delete menu;
273 delete 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);
280 #endif
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),
290 SLOT(trigger()));
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,
301 const QString &text)
303 QString before = outputEdit->toPlainText();
304 inputEdit->setText(text);
305 QTest::keyPress(inputEdit, Qt::Key_Enter);
306 const int delay = 100;
307 qsWait(delay);
308 QString after = outputEdit->toPlainText();
309 int retryCount = 10;
310 LAgain:
311 while ((before == after) && (retryCount != 0)) {
312 qsWait(delay);
313 after = outputEdit->toPlainText();
314 --retryCount;
316 if (before != after) {
317 before = after;
318 qsWait(delay);
319 after = outputEdit->toPlainText();
320 if (before != after) {
321 retryCount = 10;
322 goto LAgain;
327 class DebuggerCommandExecutor : public QObject
329 Q_OBJECT
330 public:
331 DebuggerCommandExecutor(QLineEdit *inputEdit,
332 QPlainTextEdit *outputEdit,
333 const QString &text,
334 QObject *parent = 0)
335 : QObject(parent), m_inputEdit(inputEdit),
336 m_outputEdit(outputEdit), m_commands(text) {}
337 DebuggerCommandExecutor(QLineEdit *inputEdit,
338 QPlainTextEdit *outputEdit,
339 const QStringList &commands,
340 QObject *parent = 0)
341 : QObject(parent), m_inputEdit(inputEdit),
342 m_outputEdit(outputEdit), m_commands(commands) {}
343 public Q_SLOTS:
344 void execute() {
345 for (int i = 0; i < m_commands.size(); ++i)
346 executeConsoleCommand(m_inputEdit, m_outputEdit, m_commands.at(i));
348 private:
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."));
370 outputEdit->clear();
372 // print()
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')"));
385 outputEdit->clear();
386 executeConsoleCommand(inputEdit, outputEdit, ".info scripts");
387 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info scripts\nNo scripts loaded."));
389 outputEdit->clear();
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."));
393 outputEdit->clear();
394 executeConsoleCommand(inputEdit, outputEdit, ".break 123");
395 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .break 123\nNo script."));
397 outputEdit->clear();
398 executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
399 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
401 outputEdit->clear();
402 executeConsoleCommand(inputEdit, outputEdit, ".disable 1");
403 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .disable 1"));
405 outputEdit->clear();
406 executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
407 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tno\tfoo.qs:123"));
409 outputEdit->clear();
410 executeConsoleCommand(inputEdit, outputEdit, ".disable 1");
411 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .disable 1"));
413 outputEdit->clear();
414 executeConsoleCommand(inputEdit, outputEdit, ".disable 123");
415 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .disable 123\nNo breakpoint number 123."));
417 outputEdit->clear();
418 executeConsoleCommand(inputEdit, outputEdit, ".enable 1");
419 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .enable 1"));
421 outputEdit->clear();
422 executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
423 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
425 outputEdit->clear();
426 executeConsoleCommand(inputEdit, outputEdit, ".enable 123");
427 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .enable 123\nNo breakpoint number 123."));
429 outputEdit->clear();
430 executeConsoleCommand(inputEdit, outputEdit, ".condition 1 i > 456");
431 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .condition 1 i > 456"));
433 outputEdit->clear();
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"));
437 outputEdit->clear();
438 executeConsoleCommand(inputEdit, outputEdit, ".condition 1");
439 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .condition 1\nBreakpoint 1 now unconditional."));
441 outputEdit->clear();
442 executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
443 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
445 outputEdit->clear();
446 executeConsoleCommand(inputEdit, outputEdit, ".condition 123");
447 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .condition 123\nNo breakpoint number 123."));
449 outputEdit->clear();
450 executeConsoleCommand(inputEdit, outputEdit, ".ignore 1");
451 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .ignore 1\nMissing argument (ignore-count)."));
453 outputEdit->clear();
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)."));
457 outputEdit->clear();
458 executeConsoleCommand(inputEdit, outputEdit, ".delete 1");
459 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .delete 1"));
461 outputEdit->clear();
462 executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
463 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nNo breakpoints set."));
465 outputEdit->clear();
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."));
470 QString script;
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");
477 outputEdit->clear();
478 executeConsoleCommand(inputEdit, outputEdit, ".info scripts");
479 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info scripts\n\tfoo.qs"));
481 outputEdit->clear();
482 executeConsoleCommand(inputEdit, outputEdit, ".list foo.qs");
483 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .list foo.qs\n"
484 "1\tfunction foo(i) {\n"
485 "2\t i = i + 0;\n"
486 "3\t i = i + 1;\n"
487 "4\t i = i + 2;\n"
488 "5\t i = i + 3;\n"
489 "6\t i = i + 4;\n"
490 "7\t i = i + 5;\n"
491 "8\t i = i + 6;\n"
492 "9\t i = i + 7;\n"
493 "10\t i = i + 8;"));
494 outputEdit->clear();
495 executeConsoleCommand(inputEdit, outputEdit, ".list");
496 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .list\n"
497 "No script."));
499 outputEdit->clear();
500 executeConsoleCommand(inputEdit, outputEdit, ".backtrace");
501 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .backtrace\n#0 <global>() at -1"));
503 outputEdit->clear();
504 executeConsoleCommand(inputEdit, outputEdit, ".down");
505 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .down\nAlready at bottom (innermost) frame."));
507 outputEdit->clear();
508 executeConsoleCommand(inputEdit, outputEdit, ".up");
509 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .up\nAlready at top (outermost) frame."));
511 outputEdit->clear();
512 executeConsoleCommand(inputEdit, outputEdit, ".frame");
513 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .frame\n#0 <global>() at -1"));
515 outputEdit->clear();
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."));
519 outputEdit->clear();
520 executeConsoleCommand(inputEdit, outputEdit, ".clear foo.qs:789");
521 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .clear foo.qs:789\nDeleted breakpoint 3."));
523 outputEdit->clear();
524 executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
525 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n2\tyes\tbar.qs:456"));
527 outputEdit->clear();
528 executeConsoleCommand(inputEdit, outputEdit, ".info locals");
529 QVERIFY(outputEdit->toPlainText().startsWith("qsdb> .info locals\n"
530 "NaN : NaN\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] }"));
551 outputEdit->clear();
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);
557 outputEdit->clear();
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);
563 outputEdit->clear();
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);
570 outputEdit->clear();
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);
578 outputEdit->clear();
579 engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
580 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
581 "1\tvoid(123);\n"
582 "qsdb> .step\n"
583 "2\tvoid(456);\n"
584 "qsdb> .step"));
588 DebuggerCommandExecutor executor(inputEdit, outputEdit, ".step 2");
589 QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
590 outputEdit->clear();
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);
598 outputEdit->clear();
599 engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
600 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
601 "1\tvoid(123);\n"
602 "qsdb> .next\n"
603 "2\tvoid(456);\n"
604 "qsdb> .next"));
608 DebuggerCommandExecutor executor(inputEdit, outputEdit, ".next 2");
609 QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
610 outputEdit->clear();
611 engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
612 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
613 "1\tvoid(123);\n"
614 "qsdb> .next 2"));
618 DebuggerCommandExecutor executor(inputEdit, outputEdit, ".finish");
619 QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
620 outputEdit->clear();
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);
628 outputEdit->clear();
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);
636 outputEdit->clear();
637 engine.evaluate("void(123);\nvoid(456);\n789;", "myscript.qs");
638 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
639 "1\tvoid(123);\n"
640 "qsdb> .list\n"
641 "1\tvoid(123);\n"
642 "2\tvoid(456);\n"
643 "3\t789;\n"
644 "4\n"
645 "5\n"
646 "6\n"
647 "7\n"
648 "8\n"
649 "9\n"
650 "10\n"
651 "qsdb> .continue"));
655 QString script;
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");
663 outputEdit->clear();
664 executeConsoleCommand(inputEdit, outputEdit, ".break bar.qs:7");
667 DebuggerCommandExecutor executor(inputEdit, outputEdit, QStringList()
668 << ".list"
669 << ".up"
670 << ".list"
671 << ".frame"
672 << ".down"
673 << ".list"
674 << ".continue");
675 QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
676 outputEdit->clear();
677 engine.evaluate("bar(123);", "testscript.qs");
678 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 5 at bar.qs, line 7.\n"
679 "7\t i = i + 5;\n"
680 "qsdb> .list\n"
681 "2\t i = i + 0;\n"
682 "3\t i = i + 1;\n"
683 "4\t i = i + 2;\n"
684 "5\t i = i + 3;\n"
685 "6\t i = i + 4;\n"
686 "7\t i = i + 5;\n"
687 "8\t i = i + 6;\n"
688 "9\t i = i + 7;\n"
689 "10\t i = i + 8;\n"
690 "11\t i = i + 9;\n"
691 "qsdb> .up\n"
692 "#1 <global>()@testscript.qs:1\n"
693 "qsdb> .list\n"
694 "1\tbar(123);\n"
695 "2\n"
696 "3\n"
697 "4\n"
698 "5\n"
699 "6\n"
700 "7\n"
701 "8\n"
702 "9\n"
703 "10\n"
704 "qsdb> .frame\n"
705 "#1 <global>()@testscript.qs:1\n"
706 "qsdb> .down\n"
707 "#0 bar(123)@bar.qs:7\n"
708 "qsdb> .list\n"
709 "2\t i = i + 0;\n"
710 "3\t i = i + 1;\n"
711 "4\t i = i + 2;\n"
712 "5\t i = i + 3;\n"
713 "6\t i = i + 4;\n"
714 "7\t i = i + 5;\n"
715 "8\t i = i + 6;\n"
716 "9\t i = i + 7;\n"
717 "10\t i = i + 8;\n"
718 "11\t i = i + 9;\n"
719 "qsdb> .continue"));
723 DebuggerCommandExecutor executor(inputEdit, outputEdit, QStringList()
724 << ".list 9"
725 << ".continue");
726 QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
727 outputEdit->clear();
728 engine.evaluate("bar(123);", "testscript.qs");
729 QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 5 at bar.qs, line 7.\n"
730 "7\t i = i + 5;\n"
731 "qsdb> .list 9\n"
732 "4\t i = i + 2;\n"
733 "5\t i = i + 3;\n"
734 "6\t i = i + 4;\n"
735 "7\t i = i + 5;\n"
736 "8\t i = i + 6;\n"
737 "9\t i = i + 7;\n"
738 "10\t i = i + 8;\n"
739 "11\t i = i + 9;\n"
740 "12\t return i;\n"
741 "13\t}\n"
742 "qsdb> .continue"));
746 class ScriptEvaluator : public QObject
748 Q_OBJECT
749 public:
750 ScriptEvaluator(QObject *parent = 0)
751 : QObject(parent) {
752 m_engine = new QScriptEngine(this);
754 QScriptEngine *engine() const {
755 return m_engine;
757 public Q_SLOTS:
758 QScriptValue evaluate(const QString &program) {
759 return m_engine->evaluate(program);
761 private:
762 QScriptEngine *m_engine;
765 void tst_QScriptEngineDebugger::multithreadedDebugging()
767 #ifdef Q_OS_WINCE
768 QSKIP("This tests uses too much memory for Windows CE", SkipAll);
769 #endif
770 ScriptEvaluator eval;
771 QThread thread;
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()));
780 thread.start();
781 QTRY_COMPARE(evaluationSuspendedSpy.count(), 1);
782 QTRY_COMPARE(evaluationResumedSpy.count(), 0);
783 thread.quit();
784 QTRY_COMPARE(threadFinishedSpy.count(), 1);
787 QTEST_MAIN(tst_QScriptEngineDebugger)
788 #include "tst_qscriptenginedebugger.moc"