summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-06-22 08:09:56 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-06-22 08:09:56 (GMT)
commit80f14fb7b13eac4b6ae4cdf11795723254103a58 (patch)
treef1e5ba4f3d71f3ef607e1b81ba53c506963eb41e
parentd57d0037080425773eddc73d8c4e7fbb7f2de92c (diff)
parentd349c879e1d55e4cd2b7d31c08e2796c0fec4020 (diff)
downloadQt-80f14fb7b13eac4b6ae4cdf11795723254103a58.zip
Qt-80f14fb7b13eac4b6ae4cdf11795723254103a58.tar.gz
Qt-80f14fb7b13eac4b6ae4cdf11795723254103a58.tar.bz2
Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qt-qml-team
* 'master' of git://scm.dev.nokia.troll.no/qt/qt-qml-team: QDeclarativeDebug: Add code coverage information
-rw-r--r--src/declarative/debugger/qjsdebuggeragent.cpp42
-rw-r--r--src/declarative/debugger/qjsdebuggeragent_p.h12
-rw-r--r--src/declarative/debugger/qjsdebugservice.cpp53
-rw-r--r--src/declarative/debugger/qjsdebugservice_p.h24
-rw-r--r--tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp101
5 files changed, 225 insertions, 7 deletions
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp
index dff637b..683032b 100644
--- a/src/declarative/debugger/qjsdebuggeragent.cpp
+++ b/src/declarative/debugger/qjsdebuggeragent.cpp
@@ -41,6 +41,7 @@
#include "private/qjsdebuggeragent_p.h"
#include "private/qdeclarativedebughelper_p.h"
+#include "private/qjsdebugservice_p.h"
#include <QtCore/qdatetime.h>
#include <QtCore/qcoreapplication.h>
@@ -56,7 +57,7 @@ class QJSDebuggerAgentPrivate
{
public:
QJSDebuggerAgentPrivate(QJSDebuggerAgent *q)
- : q(q), state(NoState), isInitialized(false)
+ : q(q), state(NoState), isInitialized(false), coverageEnabled(false)
{}
void continueExec();
@@ -80,6 +81,7 @@ public:
QStringList watchExpressions;
QSet<qint64> knownObjectIds;
bool isInitialized;
+ bool coverageEnabled;
};
namespace {
@@ -261,6 +263,12 @@ bool QJSDebuggerAgent::isInitialized() const
return d->isInitialized;
}
+void QJSDebuggerAgent::setCoverageEnabled(bool enabled)
+{
+ d->isInitialized = true;
+ d->coverageEnabled = enabled;
+}
+
void QJSDebuggerAgent::setBreakpoints(const JSAgentBreakpoints &breakpoints)
{
d->breakpoints = breakpoints;
@@ -417,10 +425,16 @@ void QJSDebuggerAgent::setProperty(qint64 objectId,
\reimp
*/
void QJSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
- const QString &fileName, int)
+ const QString &fileName, int baseLineNumber)
{
- Q_UNUSED(program);
d->filenames.insert(id, fileName);
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageScriptLoad,
+ id, program, fileName, baseLineNumber,
+ 0, 0, QString()};
+ QJSDebugService::instance()->processMessage(rd);
+ }
}
/*!
@@ -450,8 +464,14 @@ void QJSDebuggerAgent::contextPop()
*/
void QJSDebuggerAgent::functionEntry(qint64 scriptId)
{
- Q_UNUSED(scriptId);
d->stepDepth++;
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageFuncEntry,
+ scriptId, QString(), QString(), 0, 0, 0, QString()};
+ QJSDebugService::instance()->processMessage(rd);
+ QJSDebugService::instance()->m_timer.restart();
+ }
}
/*!
@@ -459,9 +479,13 @@ void QJSDebuggerAgent::functionEntry(qint64 scriptId)
*/
void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
{
- Q_UNUSED(scriptId);
- Q_UNUSED(returnValue);
d->stepDepth--;
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageFuncExit,
+ scriptId, QString(), QString(), 0, 0, 0, returnValue.toString()};
+ QJSDebugService::instance()->processMessage(rd);
+ }
}
/*!
@@ -470,6 +494,12 @@ void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnV
void QJSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
{
d->positionChange(scriptId, lineNumber, columnNumber);
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoveragePosChange,
+ scriptId, QString(), QString(), 0, lineNumber, columnNumber, QString()};
+ QJSDebugService::instance()->processMessage(rd);
+ }
}
void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h
index 4b27fc8..e999080 100644
--- a/src/declarative/debugger/qjsdebuggeragent_p.h
+++ b/src/declarative/debugger/qjsdebuggeragent_p.h
@@ -78,6 +78,17 @@ enum JSDebuggerState
StoppedState
};
+enum JSCoverageMessage {
+ CoverageLocation,
+ CoverageScriptLoad,
+ CoveragePosChange,
+ CoverageFuncEntry,
+ CoverageFuncExit,
+ CoverageComplete,
+
+ CoverageMaximumMessage
+};
+
struct JSAgentWatchData
{
QByteArray exp;
@@ -165,6 +176,7 @@ public:
void stepInto();
void stepOut();
void continueExecution();
+ void setCoverageEnabled(bool enabled);
JSAgentWatchData executeExpression(const QString &expr);
QList<JSAgentWatchData> expandObjectById(quint64 objectId);
diff --git a/src/declarative/debugger/qjsdebugservice.cpp b/src/declarative/debugger/qjsdebugservice.cpp
index ad84f65..03d1f76 100644
--- a/src/declarative/debugger/qjsdebugservice.cpp
+++ b/src/declarative/debugger/qjsdebugservice.cpp
@@ -49,10 +49,22 @@
Q_GLOBAL_STATIC(QJSDebugService, serviceInstance)
+// convert to a QByteArray that can be sent to the debug client
+QByteArray JSAgentCoverageData::toByteArray() const
+{
+ QByteArray data;
+ //### using QDataStream is relatively expensive
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << prefix << time << messageType << scriptId << program << fileName << baseLineNumber
+ << lineNumber << columnNumber << returnValue;
+ return data;
+}
+
QJSDebugService::QJSDebugService(QObject *parent)
: QDeclarativeDebugService(QLatin1String("JSDebugger"), parent)
- , m_agent(0)
+ , m_agent(0), m_deferredSend(true)
{
+ m_timer.start();
}
QJSDebugService::~QJSDebugService()
@@ -186,6 +198,13 @@ void QJSDebugService::messageReceived(const QByteArray &message)
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("PONG") << ping;
sendMessage(reply);
+ } else if (command == "COVERAGE") {
+ bool enabled;
+ ds >> enabled;
+ m_agent->setCoverageEnabled(enabled);
+ if (!enabled) {
+ sendMessages();
+ }
} else {
qDebug() << Q_FUNC_INFO << "Unknown command" << command;
}
@@ -206,3 +225,35 @@ void QJSDebugService::executionStopped(bool becauseOfException,
<< becauseOfException << exception;
sendMessage(reply);
}
+
+/*
+ Either send the message directly, or queue up
+ a list of messages to send later (via sendMessages)
+*/
+void QJSDebugService::processMessage(const JSAgentCoverageData &message)
+{
+ if (m_deferredSend)
+ m_data.append(message);
+ else
+ sendMessage(message.toByteArray());
+}
+
+/*
+ Send the messages queued up by processMessage
+*/
+void QJSDebugService::sendMessages()
+{
+ if (m_deferredSend) {
+ //### this is a suboptimal way to send batched messages
+ for (int i = 0; i < m_data.count(); ++i)
+ sendMessage(m_data.at(i).toByteArray());
+ m_data.clear();
+
+ //indicate completion
+ QByteArray data;
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << QByteArray("COVERAGE") << (qint64)-1 << (int)CoverageComplete;
+ sendMessage(data);
+ }
+}
+
diff --git a/src/declarative/debugger/qjsdebugservice_p.h b/src/declarative/debugger/qjsdebugservice_p.h
index 7e7642e..4f99043 100644
--- a/src/declarative/debugger/qjsdebugservice_p.h
+++ b/src/declarative/debugger/qjsdebugservice_p.h
@@ -54,6 +54,7 @@
//
#include <QtCore/QPointer>
+#include <QElapsedTimer>
#include "private/qdeclarativedebugservice_p.h"
@@ -66,6 +67,23 @@ QT_MODULE(Declarative)
class QDeclarativeEngine;
class QJSDebuggerAgent;
+struct JSAgentCoverageData
+{
+ QByteArray prefix;
+ qint64 time;
+ int messageType;
+
+ qint64 scriptId;
+ QString program;
+ QString fileName;
+ int baseLineNumber;
+ int lineNumber;
+ int columnNumber;
+ QString returnValue;
+
+ QByteArray toByteArray() const;
+};
+
class QJSDebugService : public QDeclarativeDebugService
{
Q_OBJECT
@@ -78,6 +96,9 @@ public:
void addEngine(QDeclarativeEngine *);
void removeEngine(QDeclarativeEngine *);
+ void processMessage(const JSAgentCoverageData &message);
+
+ QElapsedTimer m_timer;
protected:
void statusChanged(Status status);
@@ -88,8 +109,11 @@ private Q_SLOTS:
const QString &exception);
private:
+ void sendMessages();
QList<QDeclarativeEngine *> m_engines;
QPointer<QJSDebuggerAgent> m_agent;
+ bool m_deferredSend;
+ QList<JSAgentCoverageData> m_data;
};
QT_END_NAMESPACE
diff --git a/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp b/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
index a40bcc0..1990c0d 100644
--- a/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
+++ b/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
@@ -69,6 +69,8 @@ public:
void expandObjectById(const QByteArray& objectName, quint64 objectId);
void setProperty(const QByteArray& id, qint64 objectId, const QString &property, const QString &value);
void activateFrame(int frameId);
+ void startCoverageCompleted();
+ void startCoverageRun();
// info from last exec
JSAgentWatchData exec_data;
@@ -94,6 +96,11 @@ signals:
void stopped();
void expanded();
void watchTriggered();
+ void coverageScriptLoaded();
+ void coverageFuncEntered();
+ void coverageFuncExited();
+ void coveragePosChanged();
+ void coverageCompleted();
protected:
virtual void statusChanged(Status status);
@@ -156,6 +163,9 @@ private slots:
void setProperty4();
void activateFrame2();
void verifyQMLOptimizerDisabled();
+ void testCoverageCompleted();
+ void testCoverageRun();
+
};
@@ -280,6 +290,28 @@ void QJSDebugClient::activateFrame(int frameId)
sendMessage(reply);
}
+void QJSDebugClient::startCoverageRun()
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ QByteArray cmd = "COVERAGE";
+ bool enabled = true;
+ rs << cmd
+ << enabled;
+ sendMessage(reply);
+}
+
+void QJSDebugClient::startCoverageCompleted()
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ QByteArray cmd = "COVERAGE";
+ bool enabled = false;
+ rs << cmd
+ << enabled;
+ sendMessage(reply);
+}
+
void QJSDebugClient::statusChanged(Status /*status*/)
{
emit statusHasChanged();
@@ -317,6 +349,30 @@ void QJSDebugClient::messageReceived(const QByteArray &data)
stream >> ping;
QCOMPARE(ping, m_ping);
emit pong();
+ } else if (command == "COVERAGE") {
+ qint64 time;
+ int messageType;
+ qint64 scriptId;
+ QString program;
+ QString fileName;
+ int baseLineNumber;
+ int lineNumber;
+ int columnNumber;
+ QString returnValue;
+
+ stream >> time >> messageType >> scriptId >> program >> fileName >> baseLineNumber
+ >> lineNumber >> columnNumber >> returnValue;
+ if (messageType == CoverageComplete) {
+ emit coverageCompleted();
+ } else if (messageType == CoverageScriptLoad) {
+ emit coverageScriptLoaded();
+ } else if (messageType == CoveragePosChange) {
+ emit coveragePosChanged();
+ } else if (messageType == CoverageFuncEntry) {
+ emit coverageFuncEntered();
+ } else if (messageType == CoverageFuncExit) {
+ emit coverageFuncExited();
+ }
} else {
QFAIL("Unknown message :" + command);
}
@@ -1336,6 +1392,51 @@ void tst_QDeclarativeDebugJS::verifyQMLOptimizerDisabled()
QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(stopped())));
}
+
+void tst_QDeclarativeDebugJS::testCoverageCompleted()
+{
+ QJSDebugProcess process;
+ process.start(QStringList() << "-qmljsdebugger=port:3771,block" << TEST_FILE("backtrace1.qml"));
+ QVERIFY(process.waitForStarted());
+
+ QDeclarativeDebugConnection connection;
+ connection.connectToHost("127.0.0.1", 3771);
+ QVERIFY(connection.waitForConnected());
+
+ QJSDebugClient client(&connection);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())));
+ if (client.status() == QJSDebugClient::Unavailable)
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())));
+ QCOMPARE(client.status(), QJSDebugClient::Enabled);
+
+ client.startCoverageCompleted();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(coverageCompleted())));
+}
+
+void tst_QDeclarativeDebugJS::testCoverageRun()
+{
+ QJSDebugProcess process;
+ process.start(QStringList() << "-qmljsdebugger=port:3771,block" << TEST_FILE("backtrace1.qml"));
+ QVERIFY(process.waitForStarted());
+
+ QDeclarativeDebugConnection connection;
+ connection.connectToHost("127.0.0.1", 3771);
+ QVERIFY(connection.waitForConnected());
+
+ QJSDebugClient client(&connection);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())));
+ if (client.status() == QJSDebugClient::Unavailable)
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())));
+ QCOMPARE(client.status(), QJSDebugClient::Enabled);
+
+ client.startCoverageRun();
+ client.startCoverageCompleted();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(coverageScriptLoaded())));
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(coveragePosChanged())));
+ //QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(coverageFuncEntered())));
+ //QVERIFY(QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(coverageFuncExited())));
+}
+
QTEST_MAIN(tst_QDeclarativeDebugJS)
#include "tst_qdeclarativedebugjs.moc"