From 3b37a6463c7598adb009bd3fe2e20587a19425ae Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 10 Nov 2009 12:40:09 +1000 Subject: Fix crash bug where socket is 0. --- src/declarative/debugger/qmldebugclient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/debugger/qmldebugclient.cpp b/src/declarative/debugger/qmldebugclient.cpp index 4888758..2cd1301 100644 --- a/src/declarative/debugger/qmldebugclient.cpp +++ b/src/declarative/debugger/qmldebugclient.cpp @@ -178,6 +178,8 @@ bool QmlDebugClient::isConnected() const { Q_D(const QmlDebugClient); + if (!d->client) + return false; return d->client->isConnected(); } -- cgit v0.12 From ae9b78bff688decf9de4ead0343d8e50d40150ba Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 10 Nov 2009 12:41:21 +1000 Subject: Minor improvements, additional pointer checks. --- src/declarative/debugger/qmldebug.cpp | 26 +++++++++++++++++--------- src/declarative/qml/qmlenginedebug.cpp | 1 - 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp index 1403ffa..f24b456 100644 --- a/src/declarative/debugger/qmldebug.cpp +++ b/src/declarative/debugger/qmldebug.cpp @@ -107,31 +107,35 @@ int QmlEngineDebugPrivate::getId() void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugEnginesQuery *q) { - QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); - if (p && q) + if (c && q) { + QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); p->enginesQuery.remove(q->m_queryId); + } } void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugRootContextQuery *q) { - QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); - if (p && q) + if (c && q) { + QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); p->rootContextQuery.remove(q->m_queryId); + } } void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugObjectQuery *q) { - QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); - if (p && q) + if (c && q) { + QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); p->objectQuery.remove(q->m_queryId); + } } void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugExpressionQuery *q) { - QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); - if (p && q) + if (c && q) { + QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c); p->expressionQuery.remove(q->m_queryId); + } } @@ -424,6 +428,9 @@ void QmlEngineDebug::removeWatch(QmlDebugWatch *watch) { Q_D(QmlEngineDebug); + if (!watch || watch->state() == QmlDebugWatch::Inactive || watch->state() == QmlDebugWatch::Dead) + return; + watch->setState(QmlDebugWatch::Inactive); d->watched.remove(watch->queryId()); @@ -555,7 +562,8 @@ QmlDebugWatch::QmlDebugWatch(QObject *parent) QmlDebugWatch::~QmlDebugWatch() { - m_client->removeWatch(this); + if (m_client) + m_client->removeWatch(this); } int QmlDebugWatch::queryId() const diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 20d6fc1..3813d20 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -99,7 +99,6 @@ QmlEngineDebugServer::QmlObjectProperty QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) { QmlObjectProperty rv; -; QMetaProperty prop = obj->metaObject()->property(propIdx); -- cgit v0.12 From df16b6e5fc6458884483f6da83dbb2424ed6e66f Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 10 Nov 2009 12:42:37 +1000 Subject: Additional tests --- tests/auto/declarative/qmldebug/tst_qmldebug.cpp | 240 +++++++++++++++++++++-- 1 file changed, 226 insertions(+), 14 deletions(-) diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp index 0890557..a721dc5 100644 --- a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp +++ b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp @@ -81,10 +81,15 @@ protected slots: private: QmlDebugObjectReference findRootObject(); - QmlDebugPropertyReference findProperty(const QList &props, const QString &name); - QObject *findObjectWithId(const QObjectList &objects, int id); + QmlDebugPropertyReference findProperty(const QList &props, const QString &name) const; + QObject *findObjectWithId(const QObjectList &objects, int id) const; void waitForQuery(QmlDebugQuery *query); - void recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive); + + void recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive) const; + + void recursiveCompareObjects(const QmlDebugObjectReference &a, const QmlDebugObjectReference &b) const; + void recursiveCompareContexts(const QmlDebugContextReference &a, const QmlDebugContextReference &b) const; + void compareProperties(const QmlDebugPropertyReference &a, const QmlDebugPropertyReference &b) const; QmlDebugConnection *m_conn; QmlEngineDebug *m_dbg; @@ -106,6 +111,12 @@ private slots: void queryObject_data(); void queryExpressionResult(); void queryExpressionResult_data(); + + void tst_QmlDebugFileReference(); + void tst_QmlDebugEngineReference(); + void tst_QmlDebugObjectReference(); + void tst_QmlDebugContextReference(); + void tst_QmlDebugPropertyReference(); }; QmlDebugObjectReference tst_QmlDebug::findRootObject() @@ -132,7 +143,7 @@ QmlDebugObjectReference tst_QmlDebug::findRootObject() return result; } -QmlDebugPropertyReference tst_QmlDebug::findProperty(const QList &props, const QString &name) +QmlDebugPropertyReference tst_QmlDebug::findProperty(const QList &props, const QString &name) const { foreach(const QmlDebugPropertyReference &p, props) { if (p.name() == name) @@ -141,7 +152,7 @@ QmlDebugPropertyReference tst_QmlDebug::findProperty(const QListmetaObject(); @@ -212,6 +223,54 @@ void tst_QmlDebug::recursiveObjectTest(QObject *o, const QmlDebugObjectReference } } +void tst_QmlDebug::recursiveCompareObjects(const QmlDebugObjectReference &a, const QmlDebugObjectReference &b) const +{ + QCOMPARE(a.debugId(), b.debugId()); + QCOMPARE(a.className(), b.className()); + QCOMPARE(a.name(), b.name()); + QCOMPARE(a.contextDebugId(), b.contextDebugId()); + + QCOMPARE(a.source().url(), b.source().url()); + QCOMPARE(a.source().lineNumber(), b.source().lineNumber()); + QCOMPARE(a.source().columnNumber(), b.source().columnNumber()); + + QCOMPARE(a.properties().count(), b.properties().count()); + QCOMPARE(a.children().count(), b.children().count()); + + QList aprops = a.properties(); + QList bprops = b.properties(); + + for (int i=0; iproperty("width").toInt(); QmlDebugObjectReference obj = findRootObject(); - QmlDebugPropertyReference prop; QmlDebugObjectExpressionWatch *watch = m_dbg->addWatch(obj, expr, this); QCOMPARE(watch->state(), QmlDebugWatch::Waiting); @@ -376,7 +434,18 @@ void tst_QmlDebug::watch_expression_data() void tst_QmlDebug::queryAvailableEngines() { - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + QmlDebugEnginesQuery *q_engines; + + QmlEngineDebug unconnected(0); + q_engines = unconnected.queryAvailableEngines(0); + QCOMPARE(q_engines->state(), QmlDebugQuery::Error); + delete q_engines; + + q_engines = m_dbg->queryAvailableEngines(this); + delete q_engines; + + q_engines = m_dbg->queryAvailableEngines(this); + QVERIFY(q_engines->engines().isEmpty()); waitForQuery(q_engines); // TODO test multiple engines @@ -395,8 +464,19 @@ void tst_QmlDebug::queryRootContexts() { QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); waitForQuery(q_engines); + int engineId = q_engines->engines()[0].debugId(); + + QmlDebugRootContextQuery *q_context; - QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + QmlEngineDebug unconnected(0); + q_context = unconnected.queryRootContexts(engineId, this); + QCOMPARE(q_context->state(), QmlDebugQuery::Error); + delete q_context; + + q_context = m_dbg->queryRootContexts(engineId, this); + delete q_context; + + q_context = m_dbg->queryRootContexts(engineId, this); waitForQuery(q_context); QmlContext *actualContext = m_engine->rootContext(); @@ -427,12 +507,19 @@ void tst_QmlDebug::queryObject() QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); + QmlDebugObjectReference rootObject = q_context->rootContext().objects()[0]; QmlDebugObjectQuery *q_obj = 0; - if (recursive) - q_obj = m_dbg->queryObjectRecursive(q_context->rootContext().objects()[0], this); - else - q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); + + QmlEngineDebug unconnected(0); + q_obj = recursive ? unconnected.queryObjectRecursive(rootObject, this) : unconnected.queryObject(rootObject, this); + QCOMPARE(q_obj->state(), QmlDebugQuery::Error); + delete q_obj; + + q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); + delete q_obj; + + q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); waitForQuery(q_obj); QmlDebugObjectReference obj = q_obj->object(); @@ -494,8 +581,19 @@ void tst_QmlDebug::queryExpressionResult() QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); + int objectId = q_context->rootContext().objects()[0].debugId(); - QmlDebugExpressionQuery *q_expr = m_dbg->queryExpressionResult(q_context->rootContext().objects()[0].debugId(), expr, this); + QmlDebugExpressionQuery *q_expr; + + QmlEngineDebug unconnected(0); + q_expr = unconnected.queryExpressionResult(objectId, expr, this); + QCOMPARE(q_expr->state(), QmlDebugQuery::Error); + delete q_expr; + + q_expr = m_dbg->queryExpressionResult(objectId, expr, this); + delete q_expr; + + q_expr = m_dbg->queryExpressionResult(objectId, expr, this); QCOMPARE(q_expr->expression(), expr); waitForQuery(q_expr); @@ -516,6 +614,120 @@ void tst_QmlDebug::queryExpressionResult_data() QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("")); } +void tst_QmlDebug::tst_QmlDebugFileReference() +{ + QmlDebugFileReference ref; + QVERIFY(ref.url().isEmpty()); + QCOMPARE(ref.lineNumber(), -1); + QCOMPARE(ref.columnNumber(), -1); + + ref.setUrl(QUrl("http://test")); + QCOMPARE(ref.url(), QUrl("http://test")); + ref.setLineNumber(1); + QCOMPARE(ref.lineNumber(), 1); + ref.setColumnNumber(1); + QCOMPARE(ref.columnNumber(), 1); + + QmlDebugFileReference copy(ref); + QmlDebugFileReference copyAssign; + copyAssign = ref; + foreach (const QmlDebugFileReference &r, (QList() << copy << copyAssign)) { + QCOMPARE(r.url(), ref.url()); + QCOMPARE(r.lineNumber(), ref.lineNumber()); + QCOMPARE(r.columnNumber(), ref.columnNumber()); + } +} + +void tst_QmlDebug::tst_QmlDebugEngineReference() +{ + QmlDebugEngineReference ref; + QCOMPARE(ref.debugId(), -1); + QVERIFY(ref.name().isEmpty()); + + ref = QmlDebugEngineReference(1); + QCOMPARE(ref.debugId(), 1); + QVERIFY(ref.name().isEmpty()); + + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + ref = q_engines->engines()[0]; + delete q_engines; + + QmlDebugEngineReference copy(ref); + QmlDebugEngineReference copyAssign; + copyAssign = ref; + foreach (const QmlDebugEngineReference &r, (QList() << copy << copyAssign)) { + QCOMPARE(r.debugId(), ref.debugId()); + QCOMPARE(r.name(), ref.name()); + } +} + +void tst_QmlDebug::tst_QmlDebugObjectReference() +{ + QmlDebugObjectReference ref; + QCOMPARE(ref.debugId(), -1); + QCOMPARE(ref.className(), QString()); + QCOMPARE(ref.name(), QString()); + QCOMPARE(ref.contextDebugId(), -1); + QVERIFY(ref.properties().isEmpty()); + QVERIFY(ref.children().isEmpty()); + + QmlDebugFileReference source = ref.source(); + QVERIFY(source.url().isEmpty()); + QVERIFY(source.lineNumber() < 0); + QVERIFY(source.columnNumber() < 0); + + ref = QmlDebugObjectReference(1); + QCOMPARE(ref.debugId(), 1); + + QmlDebugObjectReference rootObject = findRootObject(); + QmlDebugObjectQuery *query = m_dbg->queryObjectRecursive(rootObject, this); + waitForQuery(query); + ref = query->object(); + delete query; + + QVERIFY(ref.debugId() >= 0); + + QmlDebugObjectReference copy(ref); + QmlDebugObjectReference copyAssign; + copyAssign = ref; + foreach (const QmlDebugObjectReference &r, (QList() << copy << copyAssign)) + recursiveCompareObjects(r, ref); +} + +void tst_QmlDebug::tst_QmlDebugContextReference() +{ + QmlDebugContextReference ref; + QCOMPARE(ref.debugId(), -1); + QVERIFY(ref.name().isEmpty()); + QVERIFY(ref.objects().isEmpty()); + QVERIFY(ref.contexts().isEmpty()); + + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + ref = q_context->rootContext(); + delete q_engines; + delete q_context; + QVERIFY(ref.debugId() >= 0); + + QmlDebugContextReference copy(ref); + QmlDebugContextReference copyAssign; + copyAssign = ref; + foreach (const QmlDebugContextReference &r, (QList() << copy << copyAssign)) + recursiveCompareContexts(r, ref); +} + +void tst_QmlDebug::tst_QmlDebugPropertyReference() +{ + QmlDebugObjectReference rootObject = findRootObject(); + QmlDebugObjectQuery *query = m_dbg->queryObject(rootObject, this); + waitForQuery(query); + QmlDebugObjectReference obj = query->object(); + delete query; +} class TestRunnerThread : public QThread { -- cgit v0.12 From 223618527a4d59bce1c373b1cae5a0627884efc0 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 10 Nov 2009 13:09:19 +1000 Subject: Additional tests --- tests/auto/declarative/qmldebug/tst_qmldebug.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp index a721dc5..7c52a19 100644 --- a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp +++ b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp @@ -44,8 +44,6 @@ #include #include #include -#include -#include #include #include @@ -53,7 +51,6 @@ #include #include #include -#include #include #include @@ -61,8 +58,6 @@ #include #include #include -#include -#include class tst_QmlDebug : public QObject -- cgit v0.12 From c411c39557d31b94efb5813be9e9ef43c05a9093 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 10 Nov 2009 16:36:43 +1000 Subject: Add QmlDebugClient and QmlDebugService tests and move debugger-related tests to debugger subdir. --- tests/auto/declarative/debugger/debugger.pro | 4 + tests/auto/declarative/debugger/debuggerutil.cpp | 102 +++ tests/auto/declarative/debugger/debuggerutil_p.h | 84 +++ .../debugger/qmldebugclient/qmldebugclient.pro | 7 + .../debugger/qmldebugclient/tst_qmldebugclient.cpp | 190 +++++ .../debugger/qmldebugservice/qmldebugservice.pro | 7 + .../qmldebugservice/tst_qmldebugservice.cpp | 222 ++++++ tests/auto/declarative/declarative.pro | 2 +- tests/auto/declarative/qmldebug/qmldebug.pro | 5 - tests/auto/declarative/qmldebug/tst_qmldebug.cpp | 797 --------------------- 10 files changed, 617 insertions(+), 803 deletions(-) create mode 100644 tests/auto/declarative/debugger/debugger.pro create mode 100644 tests/auto/declarative/debugger/debuggerutil.cpp create mode 100644 tests/auto/declarative/debugger/debuggerutil_p.h create mode 100644 tests/auto/declarative/debugger/qmldebugclient/qmldebugclient.pro create mode 100644 tests/auto/declarative/debugger/qmldebugclient/tst_qmldebugclient.cpp create mode 100644 tests/auto/declarative/debugger/qmldebugservice/qmldebugservice.pro create mode 100644 tests/auto/declarative/debugger/qmldebugservice/tst_qmldebugservice.cpp delete mode 100644 tests/auto/declarative/qmldebug/qmldebug.pro delete mode 100644 tests/auto/declarative/qmldebug/tst_qmldebug.cpp diff --git a/tests/auto/declarative/debugger/debugger.pro b/tests/auto/declarative/debugger/debugger.pro new file mode 100644 index 0000000..f4a4476 --- /dev/null +++ b/tests/auto/declarative/debugger/debugger.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS += qmldebug \ + qmldebugclient \ + qmldebugservice diff --git a/tests/auto/declarative/debugger/debuggerutil.cpp b/tests/auto/declarative/debugger/debuggerutil.cpp new file mode 100644 index 0000000..8e93407 --- /dev/null +++ b/tests/auto/declarative/debugger/debuggerutil.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 +#include +#include + +#include +#include + +#include "debuggerutil_p.h" + +namespace QmlDebuggerTest { + + void waitForSignal(QObject *receiver, const char *member) { + QEventLoop loop; + QTimer timer; + QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + QObject::connect(receiver, member, &loop, SLOT(quit())); + timer.start(5000); + loop.exec(); + } + +} + + +EchoService::EchoService(const QString &s, QObject *parent) + : QmlDebugService(s, parent), enabled(false) +{ +} + +void EchoService::messageReceived(const QByteArray &ba) +{ + sendMessage(ba); +} + +void EchoService::enabledChanged(bool e) +{ + emit enabledStateChanged(); + enabled = e; +} + + +MyQmlDebugClient::MyQmlDebugClient(const QString &s, QmlDebugConnection *c) + : QmlDebugClient(s, c) +{ +} + +QByteArray MyQmlDebugClient::waitForResponse() +{ + QSignalSpy spy(this, SIGNAL(serverMessage(QByteArray))); + QmlDebuggerTest::waitForSignal(this, SIGNAL(serverMessage(QByteArray))); + if (spy.count() == 0) { + qWarning() << "tst_QmlDebugClient: no response from server!"; + return QByteArray(); + } + return spy.at(0).at(0).value(); +} + +void MyQmlDebugClient::messageReceived(const QByteArray &ba) +{ + emit serverMessage(ba); +} + + diff --git a/tests/auto/declarative/debugger/debuggerutil_p.h b/tests/auto/declarative/debugger/debuggerutil_p.h new file mode 100644 index 0000000..155d550 --- /dev/null +++ b/tests/auto/declarative/debugger/debuggerutil_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 +#include +#include + +#include +#include + +namespace QmlDebuggerTest { + + void waitForSignal(QObject *receiver, const char *member); +} + +class EchoService : public QmlDebugService +{ + Q_OBJECT +public: + EchoService(const QString &s, QObject *parent = 0); + bool enabled; + +signals: + void enabledStateChanged(); + +protected: + virtual void messageReceived(const QByteArray &ba); + + virtual void enabledChanged(bool e); +}; + +class MyQmlDebugClient : public QmlDebugClient +{ + Q_OBJECT +public: + MyQmlDebugClient(const QString &s, QmlDebugConnection *c); + + QByteArray waitForResponse(); + +signals: + void serverMessage(const QByteArray &); + +protected: + virtual void messageReceived(const QByteArray &ba); +}; + + diff --git a/tests/auto/declarative/debugger/qmldebugclient/qmldebugclient.pro b/tests/auto/declarative/debugger/qmldebugclient/qmldebugclient.pro new file mode 100644 index 0000000..6e68cd5 --- /dev/null +++ b/tests/auto/declarative/debugger/qmldebugclient/qmldebugclient.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += network declarative +macx:CONFIG -= app_bundle + +HEADERS += ../debuggerutil_p.h +SOURCES += tst_qmldebugclient.cpp \ + ../debuggerutil.cpp diff --git a/tests/auto/declarative/debugger/qmldebugclient/tst_qmldebugclient.cpp b/tests/auto/declarative/debugger/qmldebugclient/tst_qmldebugclient.cpp new file mode 100644 index 0000000..db33061 --- /dev/null +++ b/tests/auto/declarative/debugger/qmldebugclient/tst_qmldebugclient.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "../debuggerutil_p.h" + +class tst_QmlDebugClient : public QObject +{ + Q_OBJECT + +public: + tst_QmlDebugClient(QmlDebugConnection *conn, QmlEngine *engine) + : m_conn(conn), m_engine(engine) {} + + QmlDebugConnection *m_conn; + QmlEngine *m_engine; + +private slots: + void name(); + void isEnabled(); + void setEnabled(); + void isConnected(); + void sendMessage(); +}; + +void tst_QmlDebugClient::name() +{ + QString name = "tst_QmlDebugClient::name()"; + + QmlDebugClient client(name, m_conn); + QCOMPARE(client.name(), name); +} + +void tst_QmlDebugClient::isEnabled() +{ + QmlDebugClient client("tst_QmlDebugClient::isEnabled()", m_conn); + QCOMPARE(client.isEnabled(), false); +} + +void tst_QmlDebugClient::setEnabled() +{ + EchoService service("tst_QmlDebugClient::setEnabled()"); + MyQmlDebugClient client("tst_QmlDebugClient::setEnabled()", m_conn); + + QCOMPARE(service.isEnabled(), false); + + client.setEnabled(true); + QCOMPARE(client.isEnabled(), true); + QmlDebuggerTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); + QCOMPARE(service.isEnabled(), true); + + client.setEnabled(false); + QCOMPARE(client.isEnabled(), false); + QmlDebuggerTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); + QCOMPARE(service.isEnabled(), false); +} + +void tst_QmlDebugClient::isConnected() +{ + QmlDebugClient client1("tst_QmlDebugClient::isConnected() A", m_conn); + QCOMPARE(client1.isConnected(), true); + + QmlDebugConnection conn; + QmlDebugClient client2("tst_QmlDebugClient::isConnected() B", &conn); + QCOMPARE(client2.isConnected(), false); + + QmlDebugClient client3("tst_QmlDebugClient::isConnected() C", 0); + QCOMPARE(client3.isConnected(), false); + + // duplicate plugin name + QTest::ignoreMessage(QtWarningMsg, "QmlDebugClient: Conflicting plugin name \"tst_QmlDebugClient::isConnected() A\" "); + QmlDebugClient client4("tst_QmlDebugClient::isConnected() A", m_conn); + QCOMPARE(client4.isConnected(), false); +} + +void tst_QmlDebugClient::sendMessage() +{ + EchoService service("tst_QmlDebugClient::sendMessage()"); + MyQmlDebugClient client("tst_QmlDebugClient::sendMessage()", m_conn); + + QByteArray msg = "hello!"; + + client.sendMessage(msg); + QByteArray resp = client.waitForResponse(); + QCOMPARE(resp, msg); +} + + + +class tst_QmlDebugClient_Thread : public QThread +{ + Q_OBJECT +public: + void run() { + QTest::qWait(1000); + connectToEngine(); + } + + QPointer m_engine; + +signals: + void testsFinished(); + +public slots: + + void connectToEngine() + { + QmlDebugConnection conn; + conn.connectToHost("127.0.0.1", 3768); + bool ok = conn.waitForConnected(5000); + Q_ASSERT(ok); + while (!m_engine) + QTest::qWait(50); + + tst_QmlDebugClient test(&conn, m_engine); + QTest::qExec(&test); + emit testsFinished(); + } +}; + + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + qputenv("QML_DEBUG_SERVER_PORT", "3768"); + + tst_QmlDebugClient_Thread thread; + QObject::connect(&thread, SIGNAL(testsFinished()), qApp, SLOT(quit())); + thread.start(); + + QmlEngine engine; // blocks until client connects + + // start the test + thread.m_engine = &engine; + + return app.exec(); + +} + +#include "tst_qmldebugclient.moc" diff --git a/tests/auto/declarative/debugger/qmldebugservice/qmldebugservice.pro b/tests/auto/declarative/debugger/qmldebugservice/qmldebugservice.pro new file mode 100644 index 0000000..1b6762c --- /dev/null +++ b/tests/auto/declarative/debugger/qmldebugservice/qmldebugservice.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += network declarative +macx:CONFIG -= app_bundle + +HEADERS += ../debuggerutil_p.h +SOURCES += tst_qmldebugservice.cpp \ + ../debuggerutil.cpp diff --git a/tests/auto/declarative/debugger/qmldebugservice/tst_qmldebugservice.cpp b/tests/auto/declarative/debugger/qmldebugservice/tst_qmldebugservice.cpp new file mode 100644 index 0000000..224e7e1 --- /dev/null +++ b/tests/auto/declarative/debugger/qmldebugservice/tst_qmldebugservice.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "../debuggerutil_p.h" + +class tst_QmlDebugService : public QObject +{ + Q_OBJECT + +public: + tst_QmlDebugService(QmlDebugConnection *conn, QmlEngine *engine) + : m_conn(conn), m_engine(engine) {} + + QmlDebugConnection *m_conn; + QmlEngine *m_engine; + +private slots: + void name(); + void isEnabled(); + void enabledChanged(); + void sendMessage(); + void idForObject(); + void objectForId(); + void objectToString(); +}; + +void tst_QmlDebugService::name() +{ + QString name = "tst_QmlDebugService::name()"; + + QmlDebugService service(name); + QCOMPARE(service.name(), name); +} + +void tst_QmlDebugService::isEnabled() +{ + EchoService service("tst_QmlDebugService::isEnabled()", m_conn); + QCOMPARE(service.isEnabled(), false); + + MyQmlDebugClient client("tst_QmlDebugService::isEnabled()", m_conn); + client.setEnabled(true); + QmlDebuggerTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); + QCOMPARE(service.isEnabled(), true); + + QTest::ignoreMessage(QtWarningMsg, "QmlDebugService: Conflicting plugin name \"tst_QmlDebugService::isEnabled()\" "); + QmlDebugService duplicate("tst_QmlDebugService::isEnabled()", m_conn); + QCOMPARE(duplicate.isEnabled(), false); +} + +void tst_QmlDebugService::enabledChanged() +{ + EchoService service("tst_QmlDebugService::enabledChanged()"); + MyQmlDebugClient client("tst_QmlDebugService::enabledChanged()", m_conn); + + QCOMPARE(service.enabled, false); + + client.setEnabled(true); + QmlDebuggerTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); + QCOMPARE(service.enabled, true); +} + +void tst_QmlDebugService::sendMessage() +{ + EchoService service("tst_QmlDebugService::sendMessage()"); + MyQmlDebugClient client("tst_QmlDebugService::sendMessage()", m_conn); + + QByteArray msg = "hello!"; + + client.sendMessage(msg); + QByteArray resp = client.waitForResponse(); + QCOMPARE(resp, msg); +} + +void tst_QmlDebugService::idForObject() +{ + QCOMPARE(QmlDebugService::idForObject(0), -1); + + QObject *objA = new QObject; + + int idA = QmlDebugService::idForObject(objA); + QVERIFY(idA >= 0); + QCOMPARE(QmlDebugService::objectForId(idA), objA); + + int idAA = QmlDebugService::idForObject(objA); + QCOMPARE(idAA, idA); + + QObject *objB = new QObject; + int idB = QmlDebugService::idForObject(objB); + QVERIFY(idB != idA); + QCOMPARE(QmlDebugService::objectForId(idB), objB); + + delete objA; + delete objB; +} + +void tst_QmlDebugService::objectForId() +{ + QCOMPARE(QmlDebugService::objectForId(-1), static_cast(0)); + QCOMPARE(QmlDebugService::objectForId(1), static_cast(0)); + + QObject *obj = new QObject; + int id = QmlDebugService::idForObject(obj); + QCOMPARE(QmlDebugService::objectForId(id), obj); + + delete obj; + QCOMPARE(QmlDebugService::objectForId(id), static_cast(0)); +} + +void tst_QmlDebugService::objectToString() +{ + QCOMPARE(QmlDebugService::objectToString(0), QString("NULL")); + + QObject *obj = new QObject; + QCOMPARE(QmlDebugService::objectToString(obj), QString("QObject: ")); + + obj->setObjectName("Hello"); + QCOMPARE(QmlDebugService::objectToString(obj), QString("QObject: Hello")); +} + + +class tst_QmlDebugService_Thread : public QThread +{ + Q_OBJECT +public: + void run() { + QTest::qWait(1000); + connectToEngine(); + } + + QPointer m_engine; + +signals: + void testsFinished(); + +public slots: + + void connectToEngine() + { + QmlDebugConnection conn; + conn.connectToHost("127.0.0.1", 3768); + bool ok = conn.waitForConnected(5000); + Q_ASSERT(ok); + while (!m_engine) + QTest::qWait(50); + + tst_QmlDebugService test(&conn, m_engine); + QTest::qExec(&test); + emit testsFinished(); + } +}; + + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + qputenv("QML_DEBUG_SERVER_PORT", "3768"); + + tst_QmlDebugService_Thread thread; + QObject::connect(&thread, SIGNAL(testsFinished()), qApp, SLOT(quit())); + thread.start(); + + QmlEngine engine; // blocks until client connects + + // start the test + thread.m_engine = &engine; + + return app.exec(); + +} + +#include "tst_qmldebugservice.moc" diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index 134ae1b..6a939e0 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -5,6 +5,7 @@ SUBDIRS += \ animations \ # Cover behaviors \ # Cover datetimeformatter \ # Cover + debugger \ # Cover examples \ layouts \ # Cover qmlgraphicslistview \ # Cover @@ -17,7 +18,6 @@ SUBDIRS += \ qmlbinding \ # Cover qmlconnection \ # Cover qmlcontext \ # Cover - qmldebug \ # Cover qmldom \ # Cover qmlecmascript \ # Cover qmlerror \ # Cover diff --git a/tests/auto/declarative/qmldebug/qmldebug.pro b/tests/auto/declarative/qmldebug/qmldebug.pro deleted file mode 100644 index 61f821e..0000000 --- a/tests/auto/declarative/qmldebug/qmldebug.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -contains(QT_CONFIG,declarative): QT += network declarative -macx:CONFIG -= app_bundle - -SOURCES += tst_qmldebug.cpp diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp deleted file mode 100644 index 7c52a19..0000000 --- a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp +++ /dev/null @@ -1,797 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -class tst_QmlDebug : public QObject -{ - Q_OBJECT - -public: - tst_QmlDebug(QmlDebugConnection *conn, QmlEngine *engine, QmlGraphicsItem *rootItem) - : m_conn(conn), m_dbg(0), m_engine(engine), m_rootItem(rootItem) {} - -protected slots: - void saveValueChange(const QByteArray &ba, const QVariant &v) - { - m_savedValueChanges[ba] = v; - } - -private: - QmlDebugObjectReference findRootObject(); - QmlDebugPropertyReference findProperty(const QList &props, const QString &name) const; - QObject *findObjectWithId(const QObjectList &objects, int id) const; - void waitForQuery(QmlDebugQuery *query); - - void recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive) const; - - void recursiveCompareObjects(const QmlDebugObjectReference &a, const QmlDebugObjectReference &b) const; - void recursiveCompareContexts(const QmlDebugContextReference &a, const QmlDebugContextReference &b) const; - void compareProperties(const QmlDebugPropertyReference &a, const QmlDebugPropertyReference &b) const; - - QmlDebugConnection *m_conn; - QmlEngineDebug *m_dbg; - QmlEngine *m_engine; - QmlGraphicsItem *m_rootItem; - QHash m_savedValueChanges; - -private slots: - void initTestCase(); - - void watch_property(); - void watch_object(); - void watch_expression(); - void watch_expression_data(); - - void queryAvailableEngines(); - void queryRootContexts(); - void queryObject(); - void queryObject_data(); - void queryExpressionResult(); - void queryExpressionResult_data(); - - void tst_QmlDebugFileReference(); - void tst_QmlDebugEngineReference(); - void tst_QmlDebugObjectReference(); - void tst_QmlDebugContextReference(); - void tst_QmlDebugPropertyReference(); -}; - -QmlDebugObjectReference tst_QmlDebug::findRootObject() -{ - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - if (q_engines->engines().count() == 0) - return QmlDebugObjectReference(); - QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - if (q_context->rootContext().objects().count() == 0) - return QmlDebugObjectReference(); - QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); - waitForQuery(q_obj); - - QmlDebugObjectReference result = q_obj->object(); - - delete q_engines; - delete q_context; - delete q_obj; - - return result; -} - -QmlDebugPropertyReference tst_QmlDebug::findProperty(const QList &props, const QString &name) const -{ - foreach(const QmlDebugPropertyReference &p, props) { - if (p.name() == name) - return p; - } - return QmlDebugPropertyReference(); -} - -QObject *tst_QmlDebug::findObjectWithId(const QObjectList &objects, int id) const -{ - foreach (QObject *o, objects) { - if (id == QmlDebugService::idForObject(o)) - return o; - } - return 0; -} - -void tst_QmlDebug::waitForQuery(QmlDebugQuery *query) -{ - QVERIFY(query); - QCOMPARE(query->parent(), this); - QEventLoop loop; - QTimer timer; - QVERIFY(query->state() == QmlDebugQuery::Waiting); - connect(query, SIGNAL(stateChanged(State)), &loop, SLOT(quit())); - connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - timer.start(5000); - loop.exec(); - if (!timer.isActive()) - QFAIL("query timed out"); -} - -void tst_QmlDebug::recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive) const -{ - const QMetaObject *meta = o->metaObject(); - - QmlType *type = QmlMetaType::qmlType(o->metaObject()); - QString className = type ? type->qmlTypeName() : QString(); - className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); - - QCOMPARE(oref.debugId(), QmlDebugService::idForObject(o)); - QCOMPARE(oref.name(), o->objectName()); - QCOMPARE(oref.className(), className); - QCOMPARE(oref.contextDebugId(), QmlDebugService::idForObject(qmlContext(o))); - - foreach (const QmlDebugObjectReference &cref, oref.children()) { - // ignore children with no context - if (cref.contextDebugId() < 0) - continue; - - QObject *childObject = findObjectWithId(o->children(), cref.debugId()); - QVERIFY2(childObject, qPrintable(QString("Can't find QObject* for %1").arg(cref.className()))); - - if (recursive) - recursiveObjectTest(childObject, cref, true); - } - - foreach (const QmlDebugPropertyReference &p, oref.properties()) { - QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData())); - QVERIFY(pmeta.isValid()); - - QCOMPARE(p.name(), QString::fromUtf8(pmeta.name())); - - if (pmeta.type() < QVariant::UserType) // TODO test complex types - QCOMPARE(p.value(), pmeta.read(o)); - - if (p.name() == "parent") - QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QmlGraphicsItem*"); - else - QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName())); - - QmlAbstractBinding *binding = QmlMetaProperty(o, p.name()).binding(); - if (binding) - QCOMPARE(binding->expression(), p.binding()); - - QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal()); - } -} - -void tst_QmlDebug::recursiveCompareObjects(const QmlDebugObjectReference &a, const QmlDebugObjectReference &b) const -{ - QCOMPARE(a.debugId(), b.debugId()); - QCOMPARE(a.className(), b.className()); - QCOMPARE(a.name(), b.name()); - QCOMPARE(a.contextDebugId(), b.contextDebugId()); - - QCOMPARE(a.source().url(), b.source().url()); - QCOMPARE(a.source().lineNumber(), b.source().lineNumber()); - QCOMPARE(a.source().columnNumber(), b.source().columnNumber()); - - QCOMPARE(a.properties().count(), b.properties().count()); - QCOMPARE(a.children().count(), b.children().count()); - - QList aprops = a.properties(); - QList bprops = b.properties(); - - for (int i=0; iaddWatch(prop, this); - QCOMPARE(watch->state(), QmlDebugWatch::Waiting); - QCOMPARE(watch->objectDebugId(), obj.debugId()); - QCOMPARE(watch->name(), prop.name()); - - QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); - QEventLoop loop; - QTimer timer; - connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), &loop, SLOT(quit())); - connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - - int origWidth = m_rootItem->property("width").toInt(); - timer.start(5000); - m_rootItem->setProperty("width", origWidth*2); - loop.exec(); - - if (!timer.isActive()) - QFAIL("Did not receive valueChanged() for property"); - - m_dbg->removeWatch(watch); - delete watch; - - // restore original value and verify spy doesn't get a signal since watch has been removed - m_rootItem->setProperty("width", origWidth); - QTest::qWait(100); - QCOMPARE(spy.count(), 1); - - QCOMPARE(spy.at(0).at(0).value(), prop.name().toUtf8()); - QCOMPARE(spy.at(0).at(1).value(), qVariantFromValue(origWidth*2)); -} - -void tst_QmlDebug::watch_object() -{ - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); - waitForQuery(q_obj); - - QmlDebugObjectReference obj = q_obj->object(); - - delete q_engines; - delete q_context; - delete q_obj; - - QmlDebugWatch *watch = m_dbg->addWatch(obj, this); - QCOMPARE(watch->state(), QmlDebugWatch::Waiting); - QCOMPARE(watch->objectDebugId(), obj.debugId()); - - m_savedValueChanges.clear(); - connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), - SLOT(saveValueChange(QByteArray,QVariant))); - - int origWidth = m_rootItem->property("width").toInt(); - int origHeight = m_rootItem->property("height").toInt(); - m_rootItem->setProperty("width", origWidth*2); - m_rootItem->setProperty("height", origHeight*2); - - QEventLoop loop; - QTimer timer; - timer.start(5000); - while (timer.isActive() && - (!m_savedValueChanges.contains("width") || !m_savedValueChanges.contains("height"))) { - loop.processEvents(QEventLoop::AllEvents, 50); - } - - QVariant newWidth = m_savedValueChanges["width"]; - QVariant newHeight = m_savedValueChanges["height"]; - - m_dbg->removeWatch(watch); - delete watch; - - // since watch has been removed, restoring the original values should not trigger a valueChanged() - m_savedValueChanges.clear(); - m_rootItem->setProperty("width", origWidth); - m_rootItem->setProperty("height", origHeight); - QTest::qWait(100); - QCOMPARE(m_savedValueChanges.count(), 0); - - if (newWidth.isNull() || newHeight.isNull()) { - QString s = QString("Did not receive both width and height changes (width=%1, height=%2)") - .arg(newWidth.toString()).arg(newHeight.toString()); - QFAIL(qPrintable(s)); - } - - QCOMPARE(newWidth, qVariantFromValue(origWidth*2)); - QCOMPARE(newHeight, qVariantFromValue(origHeight*2)); -} - -void tst_QmlDebug::watch_expression() -{ - QFETCH(QString, expr); - QFETCH(int, increment); - QFETCH(int, incrementCount); - - int origWidth = m_rootItem->property("width").toInt(); - - QmlDebugObjectReference obj = findRootObject(); - - QmlDebugObjectExpressionWatch *watch = m_dbg->addWatch(obj, expr, this); - QCOMPARE(watch->state(), QmlDebugWatch::Waiting); - QCOMPARE(watch->objectDebugId(), obj.debugId()); - QCOMPARE(watch->expression(), expr); - - QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); - int expectedSpyCount = incrementCount + 1; // should also get signal with expression's initial value - - int width = origWidth; - for (int i=0; i 0) { - width += increment; - m_rootItem->setProperty("width", width); - } - QEventLoop loop; - connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), &loop, SLOT(quit())); - loop.exec(); - if (!timer.isActive()) - QFAIL("Did not receive valueChanged() signal for expression"); - } - - m_dbg->removeWatch(watch); - delete watch; - - // restore original value and verify spy doesn't get a signal since watch has been removed - m_rootItem->setProperty("width", origWidth); - QTest::qWait(100); - QCOMPARE(spy.count(), expectedSpyCount); - - width = origWidth + increment; - for (int i=0; i().toInt(), width); - width += increment; - } -} - -void tst_QmlDebug::watch_expression_data() -{ - QTest::addColumn("expr"); - QTest::addColumn("increment"); - QTest::addColumn("incrementCount"); - - QTest::newRow("width") << "width" << 0 << 0; - QTest::newRow("width+10") << "width + 10" << 10 << 5; -} - -void tst_QmlDebug::queryAvailableEngines() -{ - QmlDebugEnginesQuery *q_engines; - - QmlEngineDebug unconnected(0); - q_engines = unconnected.queryAvailableEngines(0); - QCOMPARE(q_engines->state(), QmlDebugQuery::Error); - delete q_engines; - - q_engines = m_dbg->queryAvailableEngines(this); - delete q_engines; - - q_engines = m_dbg->queryAvailableEngines(this); - QVERIFY(q_engines->engines().isEmpty()); - waitForQuery(q_engines); - - // TODO test multiple engines - QList engines = q_engines->engines(); - QCOMPARE(engines.count(), 1); - - foreach(const QmlDebugEngineReference &e, engines) { - QCOMPARE(e.debugId(), QmlDebugService::idForObject(m_engine)); - QCOMPARE(e.name(), m_engine->objectName()); - } - - delete q_engines; -} - -void tst_QmlDebug::queryRootContexts() -{ - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - int engineId = q_engines->engines()[0].debugId(); - - QmlDebugRootContextQuery *q_context; - - QmlEngineDebug unconnected(0); - q_context = unconnected.queryRootContexts(engineId, this); - QCOMPARE(q_context->state(), QmlDebugQuery::Error); - delete q_context; - - q_context = m_dbg->queryRootContexts(engineId, this); - delete q_context; - - q_context = m_dbg->queryRootContexts(engineId, this); - waitForQuery(q_context); - - QmlContext *actualContext = m_engine->rootContext(); - QmlDebugContextReference context = q_context->rootContext(); - QCOMPARE(context.debugId(), QmlDebugService::idForObject(actualContext)); - QCOMPARE(context.name(), actualContext->objectName()); - - QCOMPARE(context.objects().count(), 2); // 2 objects created for engine in main() - - // root context query sends only root object data - it doesn't fill in - // the children or property info - QCOMPARE(context.objects()[0].properties().count(), 0); - QCOMPARE(context.objects()[0].children().count(), 0); - - // TODO have multiple contexts - QCOMPARE(context.contexts().count(), 0); - - delete q_engines; - delete q_context; -} - -void tst_QmlDebug::queryObject() -{ - QFETCH(bool, recursive); - - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - QmlDebugObjectReference rootObject = q_context->rootContext().objects()[0]; - - QmlDebugObjectQuery *q_obj = 0; - - QmlEngineDebug unconnected(0); - q_obj = recursive ? unconnected.queryObjectRecursive(rootObject, this) : unconnected.queryObject(rootObject, this); - QCOMPARE(q_obj->state(), QmlDebugQuery::Error); - delete q_obj; - - q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); - delete q_obj; - - q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); - waitForQuery(q_obj); - - QmlDebugObjectReference obj = q_obj->object(); - - delete q_engines; - delete q_context; - delete q_obj; - - // check source as defined in main() - QmlDebugFileReference source = obj.source(); - QCOMPARE(source.url(), QUrl("file://")); - QCOMPARE(source.lineNumber(), 2); - QCOMPARE(source.columnNumber(), 1); - - // generically test all properties, children and childrens' properties - recursiveObjectTest(m_rootItem, obj, recursive); - - if (recursive) { - foreach(const QmlDebugObjectReference &child, obj.children()) - QVERIFY(child.properties().count() > 0); - - QmlDebugObjectReference rect; - QmlDebugObjectReference text; - foreach (const QmlDebugObjectReference &child, obj.children()) { - if (child.className() == "Rectangle") - rect = child; - else if (child.className() == "Text") - text = child; - } - - // test specific property values - QCOMPARE(findProperty(rect.properties(), "width").value(), qVariantFromValue(500)); - QCOMPARE(findProperty(rect.properties(), "height").value(), qVariantFromValue(600)); - QCOMPARE(findProperty(rect.properties(), "color").value(), qVariantFromValue(QColor("blue"))); - - QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue"))); - - } else { - foreach(const QmlDebugObjectReference &child, obj.children()) - QCOMPARE(child.properties().count(), 0); - } -} - -void tst_QmlDebug::queryObject_data() -{ - QTest::addColumn("recursive"); - - QTest::newRow("non-recursive") << false; - QTest::newRow("recursive") << true; -} - -void tst_QmlDebug::queryExpressionResult() -{ - QFETCH(QString, expr); - QFETCH(QVariant, result); - - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - int objectId = q_context->rootContext().objects()[0].debugId(); - - QmlDebugExpressionQuery *q_expr; - - QmlEngineDebug unconnected(0); - q_expr = unconnected.queryExpressionResult(objectId, expr, this); - QCOMPARE(q_expr->state(), QmlDebugQuery::Error); - delete q_expr; - - q_expr = m_dbg->queryExpressionResult(objectId, expr, this); - delete q_expr; - - q_expr = m_dbg->queryExpressionResult(objectId, expr, this); - QCOMPARE(q_expr->expression(), expr); - waitForQuery(q_expr); - - QCOMPARE(q_expr->result(), result); - - delete q_engines; - delete q_context; - delete q_expr; -} - -void tst_QmlDebug::queryExpressionResult_data() -{ - QTest::addColumn("expr"); - QTest::addColumn("result"); - - QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60); - QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500); - QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("")); -} - -void tst_QmlDebug::tst_QmlDebugFileReference() -{ - QmlDebugFileReference ref; - QVERIFY(ref.url().isEmpty()); - QCOMPARE(ref.lineNumber(), -1); - QCOMPARE(ref.columnNumber(), -1); - - ref.setUrl(QUrl("http://test")); - QCOMPARE(ref.url(), QUrl("http://test")); - ref.setLineNumber(1); - QCOMPARE(ref.lineNumber(), 1); - ref.setColumnNumber(1); - QCOMPARE(ref.columnNumber(), 1); - - QmlDebugFileReference copy(ref); - QmlDebugFileReference copyAssign; - copyAssign = ref; - foreach (const QmlDebugFileReference &r, (QList() << copy << copyAssign)) { - QCOMPARE(r.url(), ref.url()); - QCOMPARE(r.lineNumber(), ref.lineNumber()); - QCOMPARE(r.columnNumber(), ref.columnNumber()); - } -} - -void tst_QmlDebug::tst_QmlDebugEngineReference() -{ - QmlDebugEngineReference ref; - QCOMPARE(ref.debugId(), -1); - QVERIFY(ref.name().isEmpty()); - - ref = QmlDebugEngineReference(1); - QCOMPARE(ref.debugId(), 1); - QVERIFY(ref.name().isEmpty()); - - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - ref = q_engines->engines()[0]; - delete q_engines; - - QmlDebugEngineReference copy(ref); - QmlDebugEngineReference copyAssign; - copyAssign = ref; - foreach (const QmlDebugEngineReference &r, (QList() << copy << copyAssign)) { - QCOMPARE(r.debugId(), ref.debugId()); - QCOMPARE(r.name(), ref.name()); - } -} - -void tst_QmlDebug::tst_QmlDebugObjectReference() -{ - QmlDebugObjectReference ref; - QCOMPARE(ref.debugId(), -1); - QCOMPARE(ref.className(), QString()); - QCOMPARE(ref.name(), QString()); - QCOMPARE(ref.contextDebugId(), -1); - QVERIFY(ref.properties().isEmpty()); - QVERIFY(ref.children().isEmpty()); - - QmlDebugFileReference source = ref.source(); - QVERIFY(source.url().isEmpty()); - QVERIFY(source.lineNumber() < 0); - QVERIFY(source.columnNumber() < 0); - - ref = QmlDebugObjectReference(1); - QCOMPARE(ref.debugId(), 1); - - QmlDebugObjectReference rootObject = findRootObject(); - QmlDebugObjectQuery *query = m_dbg->queryObjectRecursive(rootObject, this); - waitForQuery(query); - ref = query->object(); - delete query; - - QVERIFY(ref.debugId() >= 0); - - QmlDebugObjectReference copy(ref); - QmlDebugObjectReference copyAssign; - copyAssign = ref; - foreach (const QmlDebugObjectReference &r, (QList() << copy << copyAssign)) - recursiveCompareObjects(r, ref); -} - -void tst_QmlDebug::tst_QmlDebugContextReference() -{ - QmlDebugContextReference ref; - QCOMPARE(ref.debugId(), -1); - QVERIFY(ref.name().isEmpty()); - QVERIFY(ref.objects().isEmpty()); - QVERIFY(ref.contexts().isEmpty()); - - QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - ref = q_context->rootContext(); - delete q_engines; - delete q_context; - QVERIFY(ref.debugId() >= 0); - - QmlDebugContextReference copy(ref); - QmlDebugContextReference copyAssign; - copyAssign = ref; - foreach (const QmlDebugContextReference &r, (QList() << copy << copyAssign)) - recursiveCompareContexts(r, ref); -} - -void tst_QmlDebug::tst_QmlDebugPropertyReference() -{ - QmlDebugObjectReference rootObject = findRootObject(); - QmlDebugObjectQuery *query = m_dbg->queryObject(rootObject, this); - waitForQuery(query); - QmlDebugObjectReference obj = query->object(); - delete query; -} - -class TestRunnerThread : public QThread -{ - Q_OBJECT -public: - void run() { - QTest::qWait(1000); - connectToEngine(); - } - - QPointer m_engine; - QPointer m_item; - -signals: - void testsFinished(); - -public slots: - - void connectToEngine() - { - QmlDebugConnection conn; - conn.connectToHost("127.0.0.1", 3768); - bool ok = conn.waitForConnected(5000); - Q_ASSERT(ok); - while (!m_engine && !m_item) - QTest::qWait(50); - - tst_QmlDebug test(&conn, m_engine, m_item); - QTest::qExec(&test); - emit testsFinished(); - } -}; - - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - qputenv("QML_DEBUG_SERVER_PORT", "3768"); - - TestRunnerThread thread; - QObject::connect(&thread, SIGNAL(testsFinished()), qApp, SLOT(quit())); - thread.start(); - - QmlEngine engine; // blocks until client connects - - QmlComponent component(&engine, - "import Qt 4.6\n" - "Item {\n" - "width: 10; height: 20;\n" - "Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }" - "Text { color: blueRect.color; }" - "}\n", - QUrl("file://")); - Q_ASSERT(component.isReady()); - QObject *o = component.create(); - QObject::connect(&thread, SIGNAL(testsFinished()), o, SLOT(deleteLater())); - - // allows us to test that multiple contexts can be detected - QObject *o2 = component.create(); - QObject::connect(&thread, SIGNAL(testsFinished()), o2, SLOT(deleteLater())); - - // start the test - thread.m_engine = &engine; - thread.m_item = qobject_cast(o); - - return app.exec(); - -} - -//QTEST_MAIN(tst_QmlDebug) - -#include "tst_qmldebug.moc" -- cgit v0.12