summaryrefslogtreecommitdiff
path: root/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commitc4af45c2914381172e1bd7ee528481edaa2fff1a (patch)
tree01265e109316fda93845e1c96c5e566d870f51d0 /tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp
downloadqtscript-c4af45c2914381172e1bd7ee528481edaa2fff1a.tar.gz
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp')
-rw-r--r--tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp854
1 files changed, 854 insertions, 0 deletions
diff --git a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp
new file mode 100644
index 0000000..70adb58
--- /dev/null
+++ b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp
@@ -0,0 +1,854 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qscriptengine.h>
+#include <qscriptenginedebugger.h>
+#include <qaction.h>
+#include <qlineedit.h>
+#include <qmainwindow.h>
+#include <qmenu.h>
+#include <qplaintextedit.h>
+#include <qtoolbar.h>
+#include "../../shared/util.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+// Can't use QTest::qWait() because it causes event loop to hang on some platforms
+static void qsWait(int ms)
+{
+ QTimer timer;
+ timer.setSingleShot(true);
+ timer.setInterval(ms);
+ timer.start();
+ QEventLoop loop;
+ QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+ loop.exec();
+ QCoreApplication::processEvents();
+}
+
+class tst_QScriptEngineDebugger : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QScriptEngineDebugger();
+ virtual ~tst_QScriptEngineDebugger();
+
+protected slots:
+ void recordDebuggerStateAndContinue();
+
+private slots:
+ void attachAndDetach();
+ void action();
+ void widget();
+ void standardObjects();
+ void debuggerSignals();
+ void consoleCommands();
+ void multithreadedDebugging();
+ void autoShowStandardWindow();
+ void standardWindowOwnership();
+
+private:
+ QScriptEngineDebugger::DebuggerState m_recordedDebuggerState;
+};
+
+tst_QScriptEngineDebugger::tst_QScriptEngineDebugger()
+{
+}
+
+tst_QScriptEngineDebugger::~tst_QScriptEngineDebugger()
+{
+}
+
+void tst_QScriptEngineDebugger::recordDebuggerStateAndContinue()
+{
+ QScriptEngineDebugger *debugger = qobject_cast<QScriptEngineDebugger*>(sender());
+ Q_ASSERT(debugger != 0);
+ m_recordedDebuggerState = debugger->state();
+ debugger->action(QScriptEngineDebugger::ContinueAction)->trigger();
+}
+
+void tst_QScriptEngineDebugger::attachAndDetach()
+{
+#if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
+ QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll);
+#endif
+ {
+ QScriptEngineDebugger debugger;
+ QCOMPARE(debugger.state(), QScriptEngineDebugger::SuspendedState);
+ debugger.attachTo(0);
+ QScriptEngine engine;
+ debugger.attachTo(&engine);
+ QCOMPARE(debugger.state(), QScriptEngineDebugger::SuspendedState);
+ }
+ {
+ QScriptEngineDebugger debugger;
+ QScriptEngine engine;
+ QScriptValue oldPrint = engine.globalObject().property("print");
+ QVERIFY(oldPrint.isFunction());
+ QVERIFY(!engine.globalObject().property("__FILE__").isValid());
+ QVERIFY(!engine.globalObject().property("__LINE__").isValid());
+
+ debugger.attachTo(&engine);
+ QVERIFY(engine.globalObject().property("__FILE__").isUndefined());
+ QVERIFY(engine.globalObject().property("__LINE__").isNumber());
+ QVERIFY(!engine.globalObject().property("print").strictlyEquals(oldPrint));
+
+ debugger.detach();
+ QVERIFY(engine.globalObject().property("print").strictlyEquals(oldPrint));
+ QVERIFY(!engine.globalObject().property("__FILE__").isValid());
+ QVERIFY(!engine.globalObject().property("__LINE__").isValid());
+ }
+ {
+ QScriptEngineDebugger debugger;
+ QScriptEngine engine;
+ debugger.attachTo(&engine);
+ debugger.detach();
+ QScriptEngine engine2;
+ debugger.attachTo(&engine2);
+ }
+ {
+ QScriptEngineDebugger debugger;
+ QScriptEngine engine;
+ debugger.attachTo(&engine);
+ debugger.detach();
+ QScriptEngine engine2;
+ debugger.attachTo(&engine2);
+ debugger.detach();
+ }
+#ifndef Q_OS_WINCE // demands too much memory for WinCE
+ {
+ QScriptEngineDebugger debugger;
+ QScriptEngine engine;
+ debugger.attachTo(&engine);
+ QScriptEngineDebugger debugger2;
+ debugger2.attachTo(&engine);
+ }
+#endif
+ {
+ QScriptEngine *engine = new QScriptEngine;
+ QScriptEngineDebugger debugger;
+ debugger.attachTo(engine);
+ delete engine;
+ QScriptEngine engine2;
+ debugger.attachTo(&engine2);
+ }
+}
+
+void tst_QScriptEngineDebugger::action()
+{
+#if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
+ QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll);
+#endif
+
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ debugger.attachTo(&engine);
+ QList<QScriptEngineDebugger::DebuggerAction> actions;
+ actions
+ << QScriptEngineDebugger::InterruptAction
+ << QScriptEngineDebugger::ContinueAction
+ << QScriptEngineDebugger::StepIntoAction
+ << QScriptEngineDebugger::StepOverAction
+ << QScriptEngineDebugger::StepOutAction
+ << QScriptEngineDebugger::RunToCursorAction
+ << QScriptEngineDebugger::RunToNewScriptAction
+ << QScriptEngineDebugger::ToggleBreakpointAction
+ << QScriptEngineDebugger::ClearDebugOutputAction
+ << QScriptEngineDebugger::ClearErrorLogAction
+ << QScriptEngineDebugger::ClearConsoleAction
+ << QScriptEngineDebugger::FindInScriptAction
+ << QScriptEngineDebugger::FindNextInScriptAction
+ << QScriptEngineDebugger::FindPreviousInScriptAction
+ << QScriptEngineDebugger::GoToLineAction;
+ QList<QAction*> lst;
+ for (int i = 0; i < actions.size(); ++i) {
+ QScriptEngineDebugger::DebuggerAction da = actions.at(i);
+ QAction *act = debugger.action(da);
+ QVERIFY(act != 0);
+ QCOMPARE(act, debugger.action(da));
+ QCOMPARE(act->parent(), (QObject*)&debugger);
+ QVERIFY(lst.indexOf(act) == -1);
+ lst.append(act);
+ }
+}
+
+void tst_QScriptEngineDebugger::widget()
+{
+#if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
+ QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll);
+#endif
+
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ debugger.attachTo(&engine);
+ QList<QScriptEngineDebugger::DebuggerWidget> widgets;
+ widgets
+ << QScriptEngineDebugger::ConsoleWidget
+ << QScriptEngineDebugger::StackWidget
+ << QScriptEngineDebugger::ScriptsWidget
+ << QScriptEngineDebugger::LocalsWidget
+ << QScriptEngineDebugger::CodeWidget
+ << QScriptEngineDebugger::CodeFinderWidget
+ << QScriptEngineDebugger::BreakpointsWidget
+ << QScriptEngineDebugger::DebugOutputWidget
+ << QScriptEngineDebugger::ErrorLogWidget;
+ QList<QWidget*> lst;
+ for (int i = 0; i < widgets.size(); ++i) {
+ QScriptEngineDebugger::DebuggerWidget dw = widgets.at(i);
+ QWidget *wid = debugger.widget(dw);
+ QVERIFY(wid != 0);
+ QCOMPARE(wid, debugger.widget(dw));
+ QVERIFY(lst.indexOf(wid) == -1);
+ lst.append(wid);
+ QCOMPARE(static_cast<QWidget *>(wid->parent()), (QWidget*)0);
+ }
+}
+
+void tst_QScriptEngineDebugger::standardObjects()
+{
+#if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
+ QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll);
+#endif
+
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ debugger.attachTo(&engine);
+
+ QMainWindow *win = debugger.standardWindow();
+ QCOMPARE(static_cast<QWidget *>(win->parent()), (QWidget*)0);
+
+ QMenu *menu = debugger.createStandardMenu();
+ QCOMPARE(static_cast<QWidget *>(menu->parent()), (QWidget*)0);
+ QToolBar *toolBar = debugger.createStandardToolBar();
+ QCOMPARE(static_cast<QWidget *>(toolBar->parent()), (QWidget*)0);
+
+ QMenu *menu2 = debugger.createStandardMenu(win);
+ QCOMPARE(static_cast<QWidget *>(menu2->parent()), (QWidget*)win);
+ QVERIFY(menu2 != menu);
+ QToolBar *toolBar2 = debugger.createStandardToolBar(win);
+ QCOMPARE(static_cast<QWidget *>(toolBar2->parent()), (QWidget*)win);
+ QVERIFY(toolBar2 != toolBar);
+
+ delete menu;
+ delete toolBar;
+}
+
+void tst_QScriptEngineDebugger::debuggerSignals()
+{
+#if defined(Q_OS_WINCE) && _WIN32_WCE < 0x600
+ QSKIP("skipped due to high mem usage until task 261062 is fixed", SkipAll);
+#endif
+
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ debugger.attachTo(&engine);
+ debugger.setAutoShowStandardWindow(false);
+ QSignalSpy evaluationSuspendedSpy(&debugger, SIGNAL(evaluationSuspended()));
+ QSignalSpy evaluationResumedSpy(&debugger, SIGNAL(evaluationResumed()));
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()),
+ debugger.action(QScriptEngineDebugger::ContinueAction),
+ SLOT(trigger()));
+ engine.evaluate("123");
+ QCOMPARE(evaluationSuspendedSpy.count(), 0);
+ QCOMPARE(evaluationResumedSpy.count(), 0);
+ engine.evaluate("debugger");
+ QCoreApplication::processEvents();
+ QCOMPARE(evaluationSuspendedSpy.count(), 1);
+ QCOMPARE(evaluationResumedSpy.count(), 1);
+}
+
+static void executeConsoleCommand(QLineEdit *inputEdit, QPlainTextEdit *outputEdit,
+ const QString &text)
+{
+ QString before = outputEdit->toPlainText();
+ inputEdit->setText(text);
+ QTest::keyPress(inputEdit, Qt::Key_Enter);
+ const int delay = 100;
+ qsWait(delay);
+ QString after = outputEdit->toPlainText();
+ int retryCount = 10;
+LAgain:
+ while ((before == after) && (retryCount != 0)) {
+ qsWait(delay);
+ after = outputEdit->toPlainText();
+ --retryCount;
+ }
+ if (before != after) {
+ before = after;
+ qsWait(delay);
+ after = outputEdit->toPlainText();
+ if (before != after) {
+ retryCount = 10;
+ goto LAgain;
+ }
+ }
+}
+
+class DebuggerCommandExecutor : public QObject
+{
+ Q_OBJECT
+public:
+ DebuggerCommandExecutor(QLineEdit *inputEdit,
+ QPlainTextEdit *outputEdit,
+ const QString &text,
+ QObject *parent = 0)
+ : QObject(parent), m_inputEdit(inputEdit),
+ m_outputEdit(outputEdit), m_commands(text) {}
+ DebuggerCommandExecutor(QLineEdit *inputEdit,
+ QPlainTextEdit *outputEdit,
+ const QStringList &commands,
+ QObject *parent = 0)
+ : QObject(parent), m_inputEdit(inputEdit),
+ m_outputEdit(outputEdit), m_commands(commands) {}
+public Q_SLOTS:
+ void execute() {
+ for (int i = 0; i < m_commands.size(); ++i)
+ executeConsoleCommand(m_inputEdit, m_outputEdit, m_commands.at(i));
+ }
+private:
+ QLineEdit *m_inputEdit;
+ QPlainTextEdit *m_outputEdit;
+ QStringList m_commands;
+};
+
+void tst_QScriptEngineDebugger::consoleCommands()
+{
+ QSKIP("This test can hang / misbehave because of timing/event loop issues (task 241300)", SkipAll);
+
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ debugger.setAutoShowStandardWindow(false);
+ debugger.attachTo(&engine);
+
+ QWidget *consoleWidget = debugger.widget(QScriptEngineDebugger::ConsoleWidget);
+ QLineEdit *inputEdit = qFindChild<QLineEdit*>(consoleWidget);
+ QVERIFY(inputEdit != 0);
+ QPlainTextEdit *outputEdit = qFindChild<QPlainTextEdit*>(consoleWidget);
+ QVERIFY(outputEdit != 0);
+
+ QVERIFY(outputEdit->toPlainText().startsWith("Welcome to the Qt Script debugger."));
+ outputEdit->clear();
+
+ // print()
+ {
+ QWidget *debugOutputWidget = debugger.widget(QScriptEngineDebugger::DebugOutputWidget);
+ QPlainTextEdit *debugOutputEdit = qFindChild<QPlainTextEdit*>(debugOutputWidget);
+ QVERIFY(debugOutputEdit != 0);
+
+ QVERIFY(debugOutputEdit->toPlainText().isEmpty());
+ executeConsoleCommand(inputEdit, outputEdit, "print('Test of debug output')");
+ QCOMPARE(debugOutputEdit->toPlainText(), QString::fromLatin1("Test of debug output"));
+
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> print('Test of debug output')"));
+ }
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info scripts");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info scripts\nNo scripts loaded."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".break foo.qs:123");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .break foo.qs:123\nBreakpoint 1: foo.qs, line 123."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".break 123");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .break 123\nNo script."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".disable 1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .disable 1"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tno\tfoo.qs:123"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".disable 1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .disable 1"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".disable 123");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .disable 123\nNo breakpoint number 123."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".enable 1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .enable 1"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".enable 123");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .enable 123\nNo breakpoint number 123."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".condition 1 i > 456");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .condition 1 i > 456"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123\n\tstop only if i > 456"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".condition 1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .condition 1\nBreakpoint 1 now unconditional."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n1\tyes\tfoo.qs:123"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".condition 123");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .condition 123\nNo breakpoint number 123."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".ignore 1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .ignore 1\nMissing argument (ignore-count)."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".ignore 1 10");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .ignore 1 10\nBreakpoint 1 will be ignored the next 10 time(s)."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".delete 1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .delete 1"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nNo breakpoints set."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".tbreak bar.qs:456");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .tbreak bar.qs:456\nBreakpoint 2: bar.qs, line 456."));
+
+ {
+ QString script;
+ script.append("function foo(i) {\n");
+ for (int i = 0; i < 100; ++i)
+ script.append(QString::fromLatin1(" i = i + %0;\n").arg(i));
+ script.append(" return i;\n}");
+ engine.evaluate(script, "foo.qs");
+ }
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info scripts");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info scripts\n\tfoo.qs"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".list foo.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .list foo.qs\n"
+ "1\tfunction foo(i) {\n"
+ "2\t i = i + 0;\n"
+ "3\t i = i + 1;\n"
+ "4\t i = i + 2;\n"
+ "5\t i = i + 3;\n"
+ "6\t i = i + 4;\n"
+ "7\t i = i + 5;\n"
+ "8\t i = i + 6;\n"
+ "9\t i = i + 7;\n"
+ "10\t i = i + 8;"));
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".list");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .list\n"
+ "No script."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".backtrace");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .backtrace\n#0 <global>() at -1"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".down");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .down\nAlready at bottom (innermost) frame."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".up");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .up\nAlready at top (outermost) frame."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".frame");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .frame\n#0 <global>() at -1"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".break foo.qs:789");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .break foo.qs:789\nBreakpoint 3: foo.qs, line 789."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".clear foo.qs:789");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .clear foo.qs:789\nDeleted breakpoint 3."));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info breakpoints");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .info breakpoints\nId\tEnabled\tWhere\n2\tyes\tbar.qs:456"));
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".info locals");
+ QVERIFY(outputEdit->toPlainText().startsWith("qsdb> .info locals\n"
+ "NaN : NaN\n"
+ "Infinity : Infinity\n"
+ "undefined : undefined\n"
+ "print : function () { [native] }\n"
+ "parseInt : function () { [native] }\n"
+ "parseFloat : function () { [native] }\n"
+ "isNaN : function () { [native] }\n"
+ "isFinite : function () { [native] }\n"
+ "decodeURI : function () { [native] }\n"
+ "decodeURIComponent : function () { [native] }\n"
+ "encodeURI : function () { [native] }\n"
+ "encodeURIComponent : function () { [native] }\n"
+ "escape : function () { [native] }\n"
+ "unescape : function () { [native] }\n"
+ "version : function () { [native] }\n"
+ "gc : function () { [native] }\n"
+ "Object : function () { [native] }\n"
+ "Function : function () { [native] }\n"
+ "Number : function () { [native] }\n"
+ "Boolean : function () { [native] }"));
+
+ outputEdit->clear();
+ QVERIFY(!engine.globalObject().property("a").isValid());
+ executeConsoleCommand(inputEdit, outputEdit, ".eval a = 123");
+ QVERIFY(engine.globalObject().property("a").isNumber());
+ QCOMPARE(engine.globalObject().property("a").toInt32(), 123);
+
+ outputEdit->clear();
+ QVERIFY(!engine.globalObject().property("b").isValid());
+ executeConsoleCommand(inputEdit, outputEdit, "b = 456");
+ QVERIFY(engine.globalObject().property("b").isNumber());
+ QCOMPARE(engine.globalObject().property("b").toInt32(), 456);
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".break myscript.qs:1");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("qsdb> .break myscript.qs:1\nBreakpoint 4: myscript.qs, line 1."));
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".continue");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .continue"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".step");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
+ "1\tvoid(123);\n"
+ "qsdb> .step\n"
+ "2\tvoid(456);\n"
+ "qsdb> .step"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".step 2");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .step 2"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".next");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
+ "1\tvoid(123);\n"
+ "qsdb> .next\n"
+ "2\tvoid(456);\n"
+ "qsdb> .next"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".next 2");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
+ "1\tvoid(123);\n"
+ "qsdb> .next 2"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".finish");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .finish"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, ".return");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);\n789;", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n1\tvoid(123);\nqsdb> .return"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, QStringList() << ".list" << ".continue");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("void(123);\nvoid(456);\n789;", "myscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 4 at myscript.qs, line 1.\n"
+ "1\tvoid(123);\n"
+ "qsdb> .list\n"
+ "1\tvoid(123);\n"
+ "2\tvoid(456);\n"
+ "3\t789;\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "8\n"
+ "9\n"
+ "10\n"
+ "qsdb> .continue"));
+ }
+
+ {
+ QString script;
+ script.append("function bar(i) {\n");
+ for (int i = 0; i < 10; ++i)
+ script.append(QString::fromLatin1(" i = i + %0;\n").arg(i));
+ script.append(" return i;\n}");
+ engine.evaluate(script, "bar.qs");
+ }
+
+ outputEdit->clear();
+ executeConsoleCommand(inputEdit, outputEdit, ".break bar.qs:7");
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, QStringList()
+ << ".list"
+ << ".up"
+ << ".list"
+ << ".frame"
+ << ".down"
+ << ".list"
+ << ".continue");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("bar(123);", "testscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 5 at bar.qs, line 7.\n"
+ "7\t i = i + 5;\n"
+ "qsdb> .list\n"
+ "2\t i = i + 0;\n"
+ "3\t i = i + 1;\n"
+ "4\t i = i + 2;\n"
+ "5\t i = i + 3;\n"
+ "6\t i = i + 4;\n"
+ "7\t i = i + 5;\n"
+ "8\t i = i + 6;\n"
+ "9\t i = i + 7;\n"
+ "10\t i = i + 8;\n"
+ "11\t i = i + 9;\n"
+ "qsdb> .up\n"
+ "#1 <global>()@testscript.qs:1\n"
+ "qsdb> .list\n"
+ "1\tbar(123);\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "8\n"
+ "9\n"
+ "10\n"
+ "qsdb> .frame\n"
+ "#1 <global>()@testscript.qs:1\n"
+ "qsdb> .down\n"
+ "#0 bar(123)@bar.qs:7\n"
+ "qsdb> .list\n"
+ "2\t i = i + 0;\n"
+ "3\t i = i + 1;\n"
+ "4\t i = i + 2;\n"
+ "5\t i = i + 3;\n"
+ "6\t i = i + 4;\n"
+ "7\t i = i + 5;\n"
+ "8\t i = i + 6;\n"
+ "9\t i = i + 7;\n"
+ "10\t i = i + 8;\n"
+ "11\t i = i + 9;\n"
+ "qsdb> .continue"));
+ }
+
+ {
+ DebuggerCommandExecutor executor(inputEdit, outputEdit, QStringList()
+ << ".list 9"
+ << ".continue");
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()), &executor, SLOT(execute()), Qt::QueuedConnection);
+ outputEdit->clear();
+ engine.evaluate("bar(123);", "testscript.qs");
+ QCOMPARE(outputEdit->toPlainText(), QString::fromLatin1("Breakpoint 5 at bar.qs, line 7.\n"
+ "7\t i = i + 5;\n"
+ "qsdb> .list 9\n"
+ "4\t i = i + 2;\n"
+ "5\t i = i + 3;\n"
+ "6\t i = i + 4;\n"
+ "7\t i = i + 5;\n"
+ "8\t i = i + 6;\n"
+ "9\t i = i + 7;\n"
+ "10\t i = i + 8;\n"
+ "11\t i = i + 9;\n"
+ "12\t return i;\n"
+ "13\t}\n"
+ "qsdb> .continue"));
+ }
+}
+
+class ScriptEvaluator : public QObject
+{
+ Q_OBJECT
+public:
+ ScriptEvaluator(QObject *parent = 0)
+ : QObject(parent) {
+ m_engine = new QScriptEngine(this);
+ }
+ QScriptEngine *engine() const {
+ return m_engine;
+ }
+public Q_SLOTS:
+ QScriptValue evaluate(const QString &program) {
+ return m_engine->evaluate(program);
+ }
+private:
+ QScriptEngine *m_engine;
+};
+
+void tst_QScriptEngineDebugger::multithreadedDebugging()
+{
+#ifdef Q_OS_WINCE
+ QSKIP("This tests uses too much memory for Windows CE", SkipAll);
+#endif
+ ScriptEvaluator eval;
+ QThread thread;
+ eval.moveToThread(&thread);
+ eval.engine()->moveToThread(&thread);
+ QScriptEngineDebugger debugger;
+ QSignalSpy evaluationSuspendedSpy(&debugger, SIGNAL(evaluationSuspended()));
+ QSignalSpy evaluationResumedSpy(&debugger, SIGNAL(evaluationResumed()));
+ debugger.attachTo(eval.engine());
+ QMetaObject::invokeMethod(&eval, "evaluate", Qt::QueuedConnection, Q_ARG(QString, "debugger"));
+ QSignalSpy threadFinishedSpy(&thread, SIGNAL(finished()));
+ thread.start();
+ QTRY_COMPARE(evaluationSuspendedSpy.count(), 1);
+ QTRY_COMPARE(evaluationResumedSpy.count(), 0);
+ thread.quit();
+ QTRY_COMPARE(threadFinishedSpy.count(), 1);
+}
+
+void tst_QScriptEngineDebugger::autoShowStandardWindow()
+{
+ {
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ QCOMPARE(debugger.autoShowStandardWindow(), true);
+ debugger.attachTo(&engine);
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()),
+ debugger.action(QScriptEngineDebugger::ContinueAction),
+ SLOT(trigger()));
+ engine.evaluate("debugger");
+ QTRY_VERIFY(debugger.standardWindow()->isVisible());
+
+ debugger.setAutoShowStandardWindow(true);
+ QCOMPARE(debugger.autoShowStandardWindow(), true);
+
+ debugger.setAutoShowStandardWindow(false);
+ QCOMPARE(debugger.autoShowStandardWindow(), false);
+
+ debugger.setAutoShowStandardWindow(true);
+ QCOMPARE(debugger.autoShowStandardWindow(), true);
+
+ debugger.standardWindow()->hide();
+
+ engine.evaluate("debugger");
+ QTRY_VERIFY(debugger.standardWindow()->isVisible());
+ }
+
+ {
+ QScriptEngine engine;
+ QScriptEngineDebugger debugger;
+ debugger.setAutoShowStandardWindow(false);
+ debugger.attachTo(&engine);
+ QObject::connect(&debugger, SIGNAL(evaluationSuspended()),
+ debugger.action(QScriptEngineDebugger::ContinueAction),
+ SLOT(trigger()));
+ QSignalSpy evaluationResumedSpy(&debugger, SIGNAL(evaluationResumed()));
+ engine.evaluate("debugger");
+ QTRY_COMPARE(evaluationResumedSpy.count(), 1);
+ QVERIFY(!debugger.standardWindow()->isVisible());
+ }
+}
+
+void tst_QScriptEngineDebugger::standardWindowOwnership()
+{
+ QScriptEngine engine;
+ QPointer<QMainWindow> win;
+ {
+ QScriptEngineDebugger debugger;
+ win = debugger.standardWindow();
+ }
+ QVERIFY(win == 0);
+
+ // Reparent the window.
+ QWidget widget;
+ {
+ QScriptEngineDebugger debugger;
+ win = debugger.standardWindow();
+ win->setParent(&widget);
+ }
+ QVERIFY(win != 0);
+}
+
+QTEST_MAIN(tst_QScriptEngineDebugger)
+#include "tst_qscriptenginedebugger.moc"