}
exec();
+
+ // make sure events still waiting are processed
+ QEventLoop eventLoop;
+ eventLoop.processEvents(QEventLoop::AllEvents);
}
bool QDeclarativeDebugServer::hasDebuggingClient() const
QReadLocker(&d->pluginsLock);
{
foreach (QDeclarativeDebugService *service, d->plugins.values()) {
+ service->statusAboutToBeChanged(QDeclarativeDebugService::NotConnected);
service->d_func()->server = 0;
service->d_func()->status = QDeclarativeDebugService::NotConnected;
service->statusChanged(QDeclarativeDebugService::NotConnected);
if (d->thread) {
d->thread->exit();
- if (!d->thread->wait(1000))
- d->thread->terminate();
+ d->thread->wait();
delete d->thread;
}
delete d->connection;
}
{
QReadLocker(&d->pluginsLock);
- d->advertisePlugins();
QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
+ service->statusAboutToBeChanged(newStatus);
+ d->advertisePlugins();
service->d_func()->server = 0;
service->d_func()->status = newStatus;
service->statusChanged(newStatus);
return d->server->waitForMessage(this);
}
+void QDeclarativeDebugService::statusAboutToBeChanged(Status)
+{
+}
+
void QDeclarativeDebugService::statusChanged(Status)
{
}
Status registerService();
+ virtual void statusAboutToBeChanged(Status);
virtual void statusChanged(Status);
virtual void messageReceived(const QByteArray &);
QList<QByteArray> messages;
for (int i = 0; i < m_data.count(); ++i)
messages << m_data.at(i).toByteArray();
- QDeclarativeDebugService::sendMessages(messages);
m_data.clear();
//indicate completion
QByteArray data;
QDataStream ds(&data, QIODevice::WriteOnly);
ds << (qint64)-1 << (int)Complete;
- sendMessage(data);
+ messages << data;
+
+ QDeclarativeDebugService::sendMessages(messages);
+}
+
+void QDeclarativeDebugTrace::statusAboutToBeChanged(QDeclarativeDebugService::Status newStatus)
+{
+ if (status() == newStatus)
+ return;
+
+ if (status() == Enabled
+ && m_enabled) {
+ stopProfilingImpl();
+ sendMessages();
+ }
}
void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
RangeData,
RangeLocation,
RangeEnd,
- Complete,
+ Complete, // end of transmission
MaximumMessage
};
~QDeclarativeDebugTrace();
protected:
+ virtual void statusAboutToBeChanged(Status status);
virtual void messageReceived(const QByteArray &);
private:
QList<QV8ProfilerData> m_data;
bool initialized;
- bool m_enabled;
+ QList<QString> m_ongoing;
};
QV8ProfilerService::QV8ProfilerService(QObject *parent)
{
Q_D(QV8ProfilerService);
- d->m_enabled = false;
-
if (registerService() == Enabled) {
// ,block mode, client attached
while (!d->initialized)
v8ProfilerInstance();
}
+void QV8ProfilerService::statusAboutToBeChanged(QDeclarativeDebugService::Status newStatus)
+{
+ Q_D(QV8ProfilerService);
+
+ if (status() == newStatus)
+ return;
+
+ if (status() == Enabled) {
+ foreach (const QString &title, d->m_ongoing)
+ QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, title));
+ sendProfilingData();
+ }
+}
+
void QV8ProfilerService::messageReceived(const QByteArray &message)
{
Q_D(QV8ProfilerService);
if (command == "V8PROFILER") {
ds >> title;
- if (option == "start" && !d->m_enabled) {
- QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, QString::fromUtf8(title)));
- d->m_enabled = true;
- } else if (option == "stop" && d->m_enabled) {
- QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, QString::fromUtf8(title)));
+ QString titleStr = QString::fromUtf8(title);
+ if (option == "start") {
+ QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
+ } else if (option == "stop" && d->initialized) {
+ QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
QMetaObject::invokeMethod(this, "sendProfilingData", Qt::QueuedConnection);
- d->m_enabled = false;
}
d->initialized = true;
}
void QV8ProfilerService::startProfiling(const QString &title)
{
+ Q_D(QV8ProfilerService);
// Start Profiling
+
+ if (d->m_ongoing.contains(title))
+ return;
+
v8::HandleScope handle_scope;
v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
v8::CpuProfiler::StartProfiling(v8title);
{
Q_D(QV8ProfilerService);
// Stop profiling
+
+ if (!d->m_ongoing.contains(title))
+ return;
+ d->m_ongoing.removeOne(title);
+
v8::HandleScope handle_scope;
v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
void sendProfilingData();
protected:
+ void statusAboutToBeChanged(Status status);
void messageReceived(const QByteArray &);
private:
--- /dev/null
+import QtQuick 2.0
+
+Item {
+ Timer {
+ running: true
+ interval: 1
+ onTriggered: Qt.quit();
+ }
+}
QDeclarativeDebugConnection *m_connection;
QDeclarativeDebugTraceClient *m_client;
- void connect(bool block);
+ void connect(bool block, const QString &testFile);
private slots:
void cleanup();
void blockingConnectWithTraceEnabled();
void blockingConnectWithTraceDisabled();
void nonBlockingConnect();
+ void profileOnExit();
};
void QDeclarativeDebugTraceClient::messageReceived(const QByteArray &message)
}
case QDeclarativeDebugTrace::Complete: {
emit complete();
- QVERIFY(stream.atEnd());
return;
}
case QDeclarativeDebugTrace::RangeStart: {
break;
}
case QDeclarativeDebugTrace::RangeLocation: {
- stream >> data.detailType >> data.detailData >> data.line;
+ stream >> data.detailType >> data.detailData >> data.line >> data.column;
QVERIFY(data.detailType >= 0 && data.detailType < QDeclarativeDebugTrace::MaximumRangeType);
QVERIFY(data.line >= -2);
break;
traceMessages.append(data);
}
-void tst_QDeclarativeDebugTrace::connect(bool block)
+void tst_QDeclarativeDebugTrace::connect(bool block, const QString &testFile)
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
QStringList arguments;
else
arguments << QString("-qmljsdebugger=port:"STR_PORT);
- arguments << testFile("test.qml");
+ arguments << QDeclarativeDataTest::instance()->testFile(testFile);
m_process = new QDeclarativeDebugProcess(executable);
m_process->start(QStringList() << arguments);
void tst_QDeclarativeDebugTrace::blockingConnectWithTraceEnabled()
{
- connect(true);
+ connect(true, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->setTraceStatus(true);
void tst_QDeclarativeDebugTrace::blockingConnectWithTraceDisabled()
{
- connect(true);
+ connect(true, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->setTraceStatus(false);
void tst_QDeclarativeDebugTrace::nonBlockingConnect()
{
- connect(false);
+ connect(false, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->setTraceStatus(true);
QCOMPARE(m_client->traceMessages.last().detailType, (int)QDeclarativeDebugTrace::EndTrace);
}
+void tst_QDeclarativeDebugTrace::profileOnExit()
+{
+ connect(true, "exit.qml");
+ QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
+
+ m_client->setTraceStatus(true);
+
+ if (!QDeclarativeDebugTest::waitForSignal(m_client, SIGNAL(complete()))) {
+ QString failMsg
+ = QString("No trace received in time. App output: \n%1\n").arg(m_process->output());
+ QFAIL(qPrintable(failMsg));
+ }
+
+ // must start with "StartTrace"
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QDeclarativeDebugTrace::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QDeclarativeDebugTrace::StartTrace);
+
+ // must end with "EndTrace"
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QDeclarativeDebugTrace::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QDeclarativeDebugTrace::EndTrace);
+}
+
QTEST_MAIN(tst_QDeclarativeDebugTrace)
#include "tst_qdeclarativedebugtrace.moc"
--- /dev/null
+import QtQuick 2.0
+
+Item {
+ Timer {
+ running: true
+ interval: 1
+ onTriggered: {
+ Qt.quit();
+ }
+ }
+}
QDeclarativeDebugConnection *m_connection;
QV8ProfilerClient *m_client;
- void connect(bool block);
+ void connect(bool block, const QString &testFile);
private slots:
void cleanup();
void blockingConnectWithTraceDisabled();
void nonBlockingConnect();
void snapshot();
+ void profileOnExit();
};
void QV8ProfilerClient::messageReceived(const QByteArray &message)
QVERIFY(stream.atEnd());
}
-void tst_QV8ProfilerService::connect(bool block)
+void tst_QV8ProfilerService::connect(bool block, const QString &testFile)
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
QStringList arguments;
else
arguments << QString("-qmljsdebugger=port:"STR_PORT);
- arguments << QDeclarativeDataTest::instance()->testFile("test.qml");
+ arguments << QDeclarativeDataTest::instance()->testFile(testFile);
m_process = new QDeclarativeDebugProcess(executable);
m_process->start(QStringList() << arguments);
void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
{
- connect(true);
+ connect(true, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->startProfiling("");
void tst_QV8ProfilerService::blockingConnectWithTraceDisabled()
{
- connect(true);
+ connect(true, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->stopProfiling("");
void tst_QV8ProfilerService::nonBlockingConnect()
{
- connect(false);
+ connect(false, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->startProfiling("");
void tst_QV8ProfilerService::snapshot()
{
- connect(false);
+ connect(false, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
m_client->takeSnapshot();
}
}
+void tst_QV8ProfilerService::profileOnExit()
+{
+ connect(true, "exit.qml");
+ QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);
+
+ m_client->startProfiling("");
+
+ if (!QDeclarativeDebugTest::waitForSignal(m_client, SIGNAL(complete()))) {
+ QString failMsg
+ = QString("No trace received in time. App output: \n%1\n").arg(m_process->output());
+ QFAIL(qPrintable(failMsg));
+ }
+}
+
QTEST_MAIN(tst_QV8ProfilerService)
#include "tst_qv8profilerservice.moc"