From 0910a577f4d12eea4a099c989bd58f1dee6c88db Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 16 Oct 2013 12:29:47 +0200 Subject: Debugging with V4 Currently missing, but coming in subsequent patches: - evaluating expressions - evaluating breakpoint conditions Change-Id: Ib43f2a3aaa252741ea7ce857a274480feb8741aa Reviewed-by: Simon Hausmann --- tests/auto/qml/debugger/debugger.pro | 2 +- .../qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp | 284 ++------------------- tests/auto/qml/qv4debugger/tst_qv4debugger.cpp | 210 ++++++++++----- 3 files changed, 177 insertions(+), 319 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro index 15abbcc7ab..aa3ad6a3a3 100644 --- a/tests/auto/qml/debugger/debugger.pro +++ b/tests/auto/qml/debugger/debugger.pro @@ -2,7 +2,7 @@ TEMPLATE = subdirs PUBLICTESTS += \ qqmlenginedebugservice \ -# qqmldebugjs \ + qqmldebugjs \ qpacketprotocol \ # qv8profilerservice \ # qdebugmessageservice \ diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 28b7775fc6..fb6b4eee65 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -100,7 +100,6 @@ const char *SCOPES = "scopes"; const char *SCRIPTS = "scripts"; const char *SOURCE = "source"; const char *SETBREAKPOINT = "setbreakpoint"; -const char *CHANGEBREAKPOINT = "changebreakpoint"; const char *CLEARBREAKPOINT = "clearbreakpoint"; const char *SETEXCEPTIONBREAK = "setexceptionbreak"; const char *VERSION = "version"; @@ -127,7 +126,6 @@ const char *UNCAUGHT = "uncaught"; //const char *PAUSE = "pause"; //const char *RESUME = "resume"; -const char *ENABLE_DEBUG= "-enable-debugger";//flag needed for debugger with qml binary const char *BLOCKMODE = "-qmljsdebugger=port:3771,3800,block"; const char *NORMALMODE = "-qmljsdebugger=port:3771,3800"; const char *TEST_QMLFILE = "test.qml"; @@ -189,21 +187,17 @@ private slots: void setBreakpointInScriptOnComment(); void setBreakpointInScriptOnEmptyLine(); void setBreakpointInScriptOnOptimizedBinding(); - void setBreakpointInScriptWithCondition(); +// void setBreakpointInScriptWithCondition(); // Not supported yet. void setBreakpointInScriptThatQuits(); //void setBreakpointInFunction(); //NOT SUPPORTED - void setBreakpointOnEvent(); +// void setBreakpointOnEvent(); // void setBreakpointWhenAttaching(); - void changeBreakpoint(); - void changeBreakpointOnCondition(); - void clearBreakpoint(); void setExceptionBreak(); void stepNext(); - void stepNextWithCount(); void stepIn(); void stepOut(); void continueDebugging(); @@ -214,15 +208,11 @@ private slots: void getScopeDetails(); - void evaluateInGlobalScope(); - void evaluateInLocalScope(); - - void getScopes(); +// void evaluateInGlobalScope(); // Not supported yet. +// void evaluateInLocalScope(); // Not supported yet. void getScripts(); - void getSource(); - // void profile(); //NOT SUPPORTED // void verifyQMLOptimizerDisabled(); @@ -269,17 +259,14 @@ public: void connect(); void interrupt(); - void continueDebugging(StepAction stepAction, int stepCount = 1); + void continueDebugging(StepAction stepAction); void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); void lookup(QList handles, bool includeSource = false); void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); void frame(int number = -1); void scope(int number = -1, int frameNumber = -1); - void scopes(int frameNumber = -1); void scripts(int types = 4, QList ids = QList(), bool includeSource = false, QVariant filter = QVariant()); - void source(int frame = -1, int fromLine = -1, int toLine = -1); void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = true, QString condition = QString(), int ignoreCount = -1); - void changeBreakpoint(int breakpoint, bool enabled = true, QString condition = QString(), int ignoreCount = -1); void clearBreakpoint(int breakpoint); void setExceptionBreak(Exception type, bool enabled = false); void version(); @@ -327,7 +314,7 @@ void QJSDebugClient::interrupt() sendMessage(packMessage(INTERRUPT)); } -void QJSDebugClient::continueDebugging(StepAction action, int count) +void QJSDebugClient::continueDebugging(StepAction action) { // { "seq" : , // "type" : "request", @@ -351,8 +338,6 @@ void QJSDebugClient::continueDebugging(StepAction action, int count) default:break; } if (!args.isUndefined()) { - if (count != 1) - args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count)); jsonVal.setProperty(QLatin1String(ARGUMENTS),args); } } @@ -516,30 +501,6 @@ void QJSDebugClient::scope(int number, int frameNumber) sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); } -void QJSDebugClient::scopes(int frameNumber) -{ - // { "seq" : , - // "type" : "request", - // "command" : "scopes", - // "arguments" : { "frameNumber" : - // } - // } - VARIANTMAPINIT; - jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES))); - - if (frameNumber != -1) { - QJSValue args = parser.call(QJSValueList() << obj); - args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber)); - - if (!args.isUndefined()) { - jsonVal.setProperty(QLatin1String(ARGUMENTS),args); - } - } - - QJSValue json = stringify.call(QJSValueList() << jsonVal); - sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); -} - void QJSDebugClient::scripts(int types, QList ids, bool includeSource, QVariant /*filter*/) { // { "seq" : , @@ -584,39 +545,6 @@ void QJSDebugClient::scripts(int types, QList ids, bool includeSource, QVar sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); } -void QJSDebugClient::source(int frame, int fromLine, int toLine) -{ - // { "seq" : , - // "type" : "request", - // "command" : "source", - // "arguments" : { "frame" : - // "fromLine" : - // "toLine" : - // } - // } - VARIANTMAPINIT; - jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE))); - - QJSValue args = parser.call(QJSValueList() << obj); - - if (frame != -1) - args.setProperty(QLatin1String(FRAME),QJSValue(frame)); - - if (fromLine != -1) - args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine)); - - if (toLine != -1) - args.setProperty(QLatin1String(TOLINE),QJSValue(toLine)); - - if (!args.isUndefined()) { - jsonVal.setProperty(QLatin1String(ARGUMENTS),args); - } - - QJSValue json = stringify.call(QJSValueList() << jsonVal); - sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); -} - void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount) { // { "seq" : , @@ -670,39 +598,6 @@ void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int c } } -void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount) -{ - // { "seq" : , - // "type" : "request", - // "command" : "changebreakpoint", - // "arguments" : { "breakpoint" : - // "enabled" : - // "condition" : - // "ignoreCount" : , @@ -938,13 +833,13 @@ void tst_QQmlDebugJS::cleanupTestCase() bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode) { connection = new QQmlDebugConnection(); - process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", this); + process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this); client = new QJSDebugClient(connection); if (blockMode) - process->start(QStringList() << QLatin1String(ENABLE_DEBUG) << QLatin1String(BLOCKMODE) << testFile(qmlFile)); + process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile)); else - process->start(QStringList() << QLatin1String(ENABLE_DEBUG) << QLatin1String(NORMALMODE) << testFile(qmlFile)); + process->start(QStringList() << QLatin1String(NORMALMODE) << testFile(qmlFile)); if (!process->waitForSessionStart()) { qDebug() << "could not launch application, or did not get 'Waiting for connection'."; @@ -1186,8 +1081,11 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding() QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE)); } +#if 0 void tst_QQmlDebugJS::setBreakpointInScriptWithCondition() { + QFAIL("conditional breakpoints are not yet supported"); + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) int out = 10; @@ -1218,6 +1116,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition() QVERIFY(body.value("value").toInt() > out); } +#endif void tst_QQmlDebugJS::setBreakpointInScriptThatQuits() { @@ -1274,8 +1173,11 @@ void tst_QQmlDebugJS::setBreakpointWhenAttaching() // QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE)); //} +#if 0 void tst_QQmlDebugJS::setBreakpointOnEvent() { + QFAIL("Not implemented in V4."); + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QVERIFY(init(TIMER_QMLFILE)); @@ -1292,97 +1194,7 @@ void tst_QQmlDebugJS::setBreakpointOnEvent() QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(TIMER_QMLFILE)); } - - -void tst_QQmlDebugJS::changeBreakpoint() -{ - //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1) - - int sourceLine1 = 50; - int sourceLine2 = 51; - QVERIFY(init(CHANGEBREAKPOINT_QMLFILE)); - - client->connect(); - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true); - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true); - - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - //Will hit 1st brakpoint, change this breakpoint enable = false - QString jsonString(client->response); - QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); - - QVariantMap body = value.value("body").toMap(); - QList breakpointsHit = body.value("breakpoints").toList(); - - int breakpoint = breakpointsHit.at(0).toInt(); - client->changeBreakpoint(breakpoint,false); - - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); - - //Continue with debugging - client->continueDebugging(QJSDebugClient::Continue); - //Hit 2nd breakpoint - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - //Continue with debugging - client->continueDebugging(QJSDebugClient::Continue); - //Should stop at 2nd breakpoint - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - jsonString = client->response; - value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); - - body = value.value("body").toMap(); - - QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); -} - -void tst_QQmlDebugJS::changeBreakpointOnCondition() -{ - //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1) - - int sourceLine1 = 50; - int sourceLine2 = 51; - - QVERIFY(init(CHANGEBREAKPOINT_QMLFILE)); - - client->connect(); - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true); - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true); - - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - //Will hit 1st brakpoint, change this breakpoint enable = false - QString jsonString(client->response); - QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); - - QVariantMap body = value.value("body").toMap(); - QList breakpointsHit = body.value("breakpoints").toList(); - - int breakpoint = breakpointsHit.at(0).toInt(); - client->changeBreakpoint(breakpoint, false, QLatin1String("d == 0")); - - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); - - //Continue with debugging - client->continueDebugging(QJSDebugClient::Continue); - //Hit 2nd breakpoint - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - //Continue with debugging - client->continueDebugging(QJSDebugClient::Continue); - //Should stop at 2nd breakpoint - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - jsonString = client->response; - value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); - - body = value.value("body").toMap(); - - QCOMPARE(body.value("sourceLine").toInt(), sourceLine2); - -} +#endif void tst_QQmlDebugJS::clearBreakpoint() { @@ -1461,29 +1273,6 @@ void tst_QQmlDebugJS::stepNext() QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); } -void tst_QQmlDebugJS::stepNextWithCount() -{ - //void continueDebugging(StepAction stepAction, int stepCount = 1); - - int sourceLine = 50; - QVERIFY(init(STEPACTION_QMLFILE)); - - client->connect(); - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - client->continueDebugging(QJSDebugClient::Next, 2); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - QString jsonString(client->response); - QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); - - QVariantMap body = value.value("body").toMap(); - - QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2); - QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(STEPACTION_QMLFILE)); -} - void tst_QQmlDebugJS::stepIn() { //void continueDebugging(StepAction stepAction, int stepCount = 1); @@ -1602,6 +1391,7 @@ void tst_QQmlDebugJS::getScopeDetails() QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); } +#if 0 void tst_QQmlDebugJS::evaluateInGlobalScope() { //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); @@ -1620,7 +1410,9 @@ void tst_QQmlDebugJS::evaluateInGlobalScope() QCOMPARE(body.value("text").toString(),QLatin1String("undefined")); } +#endif +#if 0 void tst_QQmlDebugJS::evaluateInLocalScope() { //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); @@ -1654,21 +1446,7 @@ void tst_QQmlDebugJS::evaluateInLocalScope() QCOMPARE(body.value("value").toInt(),10); } - -void tst_QQmlDebugJS::getScopes() -{ - //void scopes(int frameNumber = -1); - - int sourceLine = 47; - QVERIFY(init(ONCOMPLETED_QMLFILE)); - - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - client->scopes(); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); -} +#endif void tst_QQmlDebugJS::getScripts() { @@ -1677,6 +1455,8 @@ void tst_QQmlDebugJS::getScripts() QVERIFY(init()); client->connect(); + client->interrupt(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested()))); client->scripts(); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult()))); @@ -1686,22 +1466,8 @@ void tst_QQmlDebugJS::getScripts() QList scripts = value.value("body").toList(); - QCOMPARE(scripts.count(), 3); -} - -void tst_QQmlDebugJS::getSource() -{ - //void source(int frame = -1, int fromLine = -1, int toLine = -1); - - int sourceLine = 47; - QVERIFY(init(ONCOMPLETED_QMLFILE)); - - client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); - - client->source(); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + QCOMPARE(scripts.count(), 1); + QVERIFY(scripts.first().toMap()[QStringLiteral("name")].toString().endsWith(QStringLiteral("data/test.qml"))); } QTEST_MAIN(tst_QQmlDebugJS) diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp index 56df3a469a..15a6acc272 100644 --- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp @@ -45,6 +45,9 @@ #include #include +using namespace QV4; +using namespace QV4::Debugging; + static bool waitForSignal(QObject* obj, const char* signal, int timeout = 10000) { QEventLoop loop; @@ -95,32 +98,109 @@ signals: Q_DECLARE_METATYPE(TestEngine::InjectedFunction) +namespace { +class TestCollector: public QV4::Debugging::Debugger::Collector +{ +public: + TestCollector(QV4::ExecutionEngine *engine) + : Collector(engine) + , destination(0) + {} + + virtual ~TestCollector() {} + + void setDestination(QVariantMap *dest) + { destination = dest; } + +protected: + virtual void addUndefined(const QString &name) + { + destination->insert(name, QStringLiteral("undefined")); // TODO: add a user-defined type for this + } + + virtual void addNull(const QString &name) + { + destination->insert(name, QStringLiteral("null")); // TODO: add a user-defined type for this + } + + virtual void addBoolean(const QString &name, bool value) + { + destination->insert(name, value); + } + + virtual void addString(const QString &name, const QString &value) + { + destination->insert(name, value); + } + + virtual void addObject(const QString &name, QV4::ValueRef value) + { + QV4::Scope scope(engine()); + QV4::ScopedObject obj(scope, value->asObject()); + + QVariantMap props, *prev = &props; + qSwap(destination, prev); + collect(obj); + qSwap(destination, prev); + + destination->insert(name, props); + } + + virtual void addInteger(const QString &name, int value) + { + destination->insert(name, QVariant::fromValue(static_cast(value))); + } + + virtual void addDouble(const QString &name, double value) + { + destination->insert(name, QVariant::fromValue(value)); + } + +private: + QVariantMap *destination; +}; +} + class TestAgent : public QV4::Debugging::DebuggerAgent { Q_OBJECT public: - typedef QV4::Debugging::Debugger Debugger; - TestAgent() : m_wasPaused(false) , m_captureContextInfo(false) { } - virtual void debuggerPaused(Debugger *debugger) + virtual void debuggerPaused(Debugger *debugger, PauseReason reason) { Q_ASSERT(m_debuggers.count() == 1 && m_debuggers.first() == debugger); m_wasPaused = true; + m_pauseReason = reason; m_statesWhenPaused << debugger->currentExecutionState(); + TestCollector collector(debugger->engine()); + QVariantMap tmp; + collector.setDestination(&tmp); + debugger->collectThrownValue(&collector); + m_thrownValue = tmp["exception"]; + foreach (const TestBreakPoint &bp, m_breakPointsToAddWhenPaused) debugger->addBreakPoint(bp.fileName, bp.lineNumber); m_breakPointsToAddWhenPaused.clear(); + m_stackTrace = debugger->stackTrace(); + if (m_captureContextInfo) captureContextInfo(debugger); - debugger->resume(); + debugger->resume(Debugger::FullThrottle); + } + + virtual void sourcesCollected(Debugger *debugger, QStringList sources, int requestSequenceNr) + { + Q_UNUSED(debugger); + Q_UNUSED(sources); + Q_UNUSED(requestSequenceNr); } int debuggerCount() const { return m_debuggers.count(); } @@ -136,25 +216,30 @@ public: void captureContextInfo(Debugger *debugger) { - m_stackTrace = debugger->stackTrace(); + TestCollector collector(debugger->engine()); + for (int i = 0, ei = m_stackTrace.size(); i != ei; ++i) { - m_capturedArguments.append(debugger->retrieveArgumentsFromContext(QStringList(), i)); - m_capturedLocals.append(debugger->retrieveLocalsFromContext(QStringList(), i)); + QVariantMap args; + collector.setDestination(&args); + debugger->collectArgumentsInContext(&collector, i); + m_capturedArguments.append(args); + + QVariantMap locals; + collector.setDestination(&locals); + debugger->collectLocalsInContext(&collector, i); + m_capturedLocals.append(locals); } - - foreach (const QStringList &path, m_localPathsToRead) - m_localPathResults += debugger->retrieveLocalsFromContext(path); } bool m_wasPaused; + PauseReason m_pauseReason; bool m_captureContextInfo; - QList m_statesWhenPaused; + QList m_statesWhenPaused; QList m_breakPointsToAddWhenPaused; QVector m_stackTrace; - QList > m_capturedArguments; - QList > m_capturedLocals; - QList m_localPathsToRead; - QList > m_localPathResults; + QList m_capturedArguments; + QList m_capturedLocals; + QVariant m_thrownValue; // Utility methods: void dumpStackTrace() const @@ -170,8 +255,6 @@ class tst_qv4debugger : public QObject { Q_OBJECT - typedef QV4::Debugging::Debugger::VarInfo VarInfo; - private slots: void init(); void cleanup(); @@ -190,6 +273,9 @@ private slots: void readObject(); void readContextInAllFrames(); + // exceptions: + void pauseOnThrow(); + private: void evaluateJavaScript(const QString &script, const QString &fileName, int lineNumber = 1) { @@ -278,8 +364,8 @@ void tst_qv4debugger::removePendingBreakPoint() "var i = 42;\n" "var j = i + 1\n" "var k = i\n"; - m_debuggerAgent->addBreakPoint("removePendingBreakPoint", 2); - m_debuggerAgent->removeBreakPoint("removePendingBreakPoint", 2); + int id = m_debuggerAgent->addBreakPoint("removePendingBreakPoint", 2); + m_debuggerAgent->removeBreakPoint(id); evaluateJavaScript(script, "removePendingBreakPoint"); QVERIFY(!m_debuggerAgent->m_wasPaused); } @@ -339,16 +425,12 @@ void tst_qv4debugger::readArguments() evaluateJavaScript(script, "readArguments"); QVERIFY(m_debuggerAgent->m_wasPaused); QCOMPARE(m_debuggerAgent->m_capturedArguments[0].size(), 4); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][0].name, QString("a")); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][0].type, VarInfo::Number); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][0].value.toDouble(), 1.0); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][1].name, QString("b")); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][1].type, VarInfo::String); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][1].value.toString(), QLatin1String("two")); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][2].name, QString("c")); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][2].type, VarInfo::Null); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][3].name, QString("d")); - QCOMPARE(m_debuggerAgent->m_capturedArguments[0][3].type, VarInfo::Undefined); + QVERIFY(m_debuggerAgent->m_capturedArguments[0].contains(QStringLiteral("a"))); + QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["a"].type(), QVariant::Double); + QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["a"].toDouble(), 1.0); + QVERIFY(m_debuggerAgent->m_capturedArguments[0].contains("b")); + QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["b"].type(), QVariant::String); + QCOMPARE(m_debuggerAgent->m_capturedArguments[0]["b"].toString(), QLatin1String("two")); } void tst_qv4debugger::readLocals() @@ -365,11 +447,11 @@ void tst_qv4debugger::readLocals() evaluateJavaScript(script, "readLocals"); QVERIFY(m_debuggerAgent->m_wasPaused); QCOMPARE(m_debuggerAgent->m_capturedLocals[0].size(), 2); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][0].name, QString("c")); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][0].type, VarInfo::Number); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][0].value.toDouble(), 3.0); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][1].name, QString("d")); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][1].type, VarInfo::Undefined); + QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains("c")); + QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["c"].type(), QVariant::Double); + QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["c"].toDouble(), 3.0); + QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains("d")); + QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["d"].toString(), QString("undefined")); } void tst_qv4debugger::readObject() @@ -382,31 +464,25 @@ void tst_qv4debugger::readObject() "}\n" "f({head: 1, tail: { head: 'asdf', tail: null }});\n"; m_debuggerAgent->addBreakPoint("readObject", 3); - m_debuggerAgent->m_localPathsToRead.append(QStringList() << QLatin1String("b")); - m_debuggerAgent->m_localPathsToRead.append(QStringList() << QLatin1String("b") << QLatin1String("tail")); evaluateJavaScript(script, "readObject"); QVERIFY(m_debuggerAgent->m_wasPaused); QCOMPARE(m_debuggerAgent->m_capturedLocals[0].size(), 1); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][0].name, QString("b")); - QCOMPARE(m_debuggerAgent->m_capturedLocals[0][0].type, VarInfo::Object); - - QCOMPARE(m_debuggerAgent->m_localPathResults.size(), 2); + QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains("b")); + QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["b"].type(), QVariant::Map); - QList b = m_debuggerAgent->m_localPathResults[0]; + QVariantMap b = m_debuggerAgent->m_capturedLocals[0]["b"].toMap(); QCOMPARE(b.size(), 2); - QCOMPARE(b[0].name, QLatin1String("head")); - QCOMPARE(b[0].type, VarInfo::Number); - QCOMPARE(b[0].value.toDouble(), 1.0); - QCOMPARE(b[1].name, QLatin1String("tail")); - QCOMPARE(b[1].type, VarInfo::Object); + QVERIFY(b.contains("head")); + QCOMPARE(b["head"].type(), QVariant::Double); + QCOMPARE(b["head"].toDouble(), 1.0); + QVERIFY(b.contains("tail")); + QCOMPARE(b["tail"].type(), QVariant::Map); - QList b_tail = m_debuggerAgent->m_localPathResults[1]; + QVariantMap b_tail = b["tail"].toMap(); QCOMPARE(b_tail.size(), 2); - QCOMPARE(b_tail[0].name, QLatin1String("head")); - QCOMPARE(b_tail[0].type, VarInfo::String); - QCOMPARE(b_tail[0].value.toString(), QLatin1String("asdf")); - QCOMPARE(b_tail[1].name, QLatin1String("tail")); - QCOMPARE(b_tail[1].type, VarInfo::Null); + QVERIFY(b_tail.contains("head")); + QCOMPARE(b_tail["head"].type(), QVariant::String); + QCOMPARE(b_tail["head"].toString(), QString("asdf")); } void tst_qv4debugger::readContextInAllFrames() @@ -431,23 +507,39 @@ void tst_qv4debugger::readContextInAllFrames() for (int i = 0; i < 12; ++i) { QCOMPARE(m_debuggerAgent->m_capturedArguments[i].size(), 1); - QCOMPARE(m_debuggerAgent->m_capturedArguments[i][0].name, QString("n")); - QCOMPARE(m_debuggerAgent->m_capturedArguments[i][0].type, VarInfo::Number); - QCOMPARE(m_debuggerAgent->m_capturedArguments[i][0].value.toInt(), i + 1); + QVERIFY(m_debuggerAgent->m_capturedArguments[i].contains("n")); + QCOMPARE(m_debuggerAgent->m_capturedArguments[i]["n"].type(), QVariant::Double); + QCOMPARE(m_debuggerAgent->m_capturedArguments[i]["n"].toDouble(), i + 1.0); QCOMPARE(m_debuggerAgent->m_capturedLocals[i].size(), 1); - QCOMPARE(m_debuggerAgent->m_capturedLocals[i][0].name, QString("n_1")); + QVERIFY(m_debuggerAgent->m_capturedLocals[i].contains("n_1")); if (i == 0) { - QCOMPARE(m_debuggerAgent->m_capturedLocals[i][0].type, VarInfo::Undefined); + QCOMPARE(m_debuggerAgent->m_capturedLocals[i]["n_1"].toString(), QString("undefined")); } else { - QCOMPARE(m_debuggerAgent->m_capturedLocals[i][0].type, VarInfo::Number); - QCOMPARE(m_debuggerAgent->m_capturedLocals[i][0].value.toInt(), i); + QCOMPARE(m_debuggerAgent->m_capturedLocals[i]["n_1"].type(), QVariant::Double); + QCOMPARE(m_debuggerAgent->m_capturedLocals[i]["n_1"].toInt(), i); } } QCOMPARE(m_debuggerAgent->m_capturedArguments[12].size(), 0); QCOMPARE(m_debuggerAgent->m_capturedLocals[12].size(), 0); } +void tst_qv4debugger::pauseOnThrow() +{ + QString script = + "function die(n) {\n" + " throw n\n" + "}\n" + "die('hard');\n"; + m_debuggerAgent->setBreakOnThrow(true); + evaluateJavaScript(script, "pauseOnThrow"); + QVERIFY(m_debuggerAgent->m_wasPaused); + QCOMPARE(m_debuggerAgent->m_pauseReason, Throwing); + QCOMPARE(m_debuggerAgent->m_stackTrace.size(), 2); + QCOMPARE(m_debuggerAgent->m_thrownValue.type(), QVariant::String); + QCOMPARE(m_debuggerAgent->m_thrownValue.toString(), QString("hard")); +} + QTEST_MAIN(tst_qv4debugger) #include "tst_qv4debugger.moc" -- cgit v1.2.3