summaryrefslogtreecommitdiffstats
path: root/tests/auto/declarative/qmldebug/tst_qmldebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/declarative/qmldebug/tst_qmldebug.cpp')
-rw-r--r--tests/auto/declarative/qmldebug/tst_qmldebug.cpp346
1 files changed, 171 insertions, 175 deletions
diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp
index a7573da..0890557 100644
--- a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp
+++ b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp
@@ -51,12 +51,18 @@
#include <QtDeclarative/qmlcontext.h>
#include <QtDeclarative/qmlcomponent.h>
#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlbinding.h>
#include <private/qmldebug_p.h>
+#include <private/qmlenginedebug_p.h>
#include <private/qmldebugclient_p.h>
#include <private/qmldebugservice_p.h>
#include <private/qmlgraphicsrectangle_p.h>
#include <private/qmlgraphicstext_p.h>
+#include <private/qmldeclarativedata_p.h>
class tst_QmlDebug : public QObject
@@ -74,101 +80,18 @@ protected slots:
}
private:
+ QmlDebugObjectReference findRootObject();
+ QmlDebugPropertyReference findProperty(const QList<QmlDebugPropertyReference> &props, const QString &name);
+ QObject *findObjectWithId(const QObjectList &objects, int id);
+ void waitForQuery(QmlDebugQuery *query);
+ void recursiveObjectTest(QObject *o, const QmlDebugObjectReference &oref, bool recursive);
+
QmlDebugConnection *m_conn;
QmlEngineDebug *m_dbg;
QmlEngine *m_engine;
QmlGraphicsItem *m_rootItem;
-
QHash<QByteArray, QVariant> m_savedValueChanges;
- void waitForQuery(QmlDebugQuery *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 verifyRootObject(const QmlDebugObjectReference &obj)
- {
- // verifies object according to component definition in main()
-
- QCOMPARE(obj.debugId(), QmlDebugService::idForObject(m_rootItem));
- QCOMPARE(obj.className(), QLatin1String("Item"));
- QCOMPARE(obj.name(), m_rootItem->objectName());
- QCOMPARE(obj.contextDebugId(), QmlDebugService::idForObject(qmlContext(m_rootItem)));
-
- QmlDebugFileReference source = obj.source();
- QCOMPARE(source.url(), QUrl("file://"));
- QCOMPARE(source.lineNumber(), 3);
- QCOMPARE(source.columnNumber(), 3);
-
- QList<QmlDebugPropertyReference> props = obj.properties();
- QHash<QString, QVariant> expected;
-
- expected["width"] = 10;
- expected["height"] = 20;
- verifyProperties(props, expected);
- }
-
- void verifyProperties(const QList<QmlDebugPropertyReference> &actual, const QHash<QString, QVariant> &expected)
- {
- foreach(const QmlDebugPropertyReference &p, actual) {
- if (expected.contains(p.name()))
- QCOMPARE(p.value(), expected[p.name()]);
- }
- }
-
- QmlDebugObjectReference 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 findProperty(const QList<QmlDebugPropertyReference> &props, const QString &name)
- {
- foreach(const QmlDebugPropertyReference &p, props) {
- if (p.name() == name)
- return p;
- }
- return QmlDebugPropertyReference();
- }
-
- int countNotifiableProperties(const QObject *obj)
- {
- int count = 0;
- for (int i=0; i<obj->metaObject()->propertyCount(); i++) {
- QMetaProperty p = obj->metaObject()->property(i);
- if (p.hasNotifySignal())
- count++;
- }
- return count;
- }
-
private slots:
void initTestCase();
@@ -180,11 +103,115 @@ private slots:
void queryAvailableEngines();
void queryRootContexts();
void queryObject();
- void queryObjectRecursive();
+ void queryObject_data();
void queryExpressionResult();
void queryExpressionResult_data();
};
+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<QmlDebugPropertyReference> &props, const QString &name)
+{
+ foreach(const QmlDebugPropertyReference &p, props) {
+ if (p.name() == name)
+ return p;
+ }
+ return QmlDebugPropertyReference();
+}
+
+QObject *tst_QmlDebug::findObjectWithId(const QObjectList &objects, int id)
+{
+ 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 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::initTestCase()
{
m_dbg = new QmlEngineDebug(m_conn, this);
@@ -219,7 +246,7 @@ void tst_QmlDebug::watch_property()
// restore original value and verify spy doesn't get a signal since watch has been removed
m_rootItem->setProperty("width", origWidth);
- QTest::qWait(500);
+ QTest::qWait(100);
QCOMPARE(spy.count(), 1);
QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name().toUtf8());
@@ -274,7 +301,7 @@ void tst_QmlDebug::watch_object()
m_savedValueChanges.clear();
m_rootItem->setProperty("width", origWidth);
m_rootItem->setProperty("height", origHeight);
- QTest::qWait(500);
+ QTest::qWait(100);
QCOMPARE(m_savedValueChanges.count(), 0);
if (newWidth.isNull() || newHeight.isNull()) {
@@ -326,8 +353,8 @@ void tst_QmlDebug::watch_expression()
delete watch;
// restore original value and verify spy doesn't get a signal since watch has been removed
- m_rootItem->setProperty("width", origWidth); // may increase spy count before QCOMPARE()
- QTest::qWait(500);
+ m_rootItem->setProperty("width", origWidth);
+ QTest::qWait(100);
QCOMPARE(spy.count(), expectedSpyCount);
width = origWidth + increment;
@@ -352,7 +379,7 @@ void tst_QmlDebug::queryAvailableEngines()
QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
waitForQuery(q_engines);
- // TODO have multiple engines
+ // TODO test multiple engines
QList<QmlDebugEngineReference> engines = q_engines->engines();
QCOMPARE(engines.count(), 1);
@@ -377,7 +404,7 @@ void tst_QmlDebug::queryRootContexts()
QCOMPARE(context.debugId(), QmlDebugService::idForObject(actualContext));
QCOMPARE(context.name(), actualContext->objectName());
- QCOMPARE(context.objects().count(), 1);
+ 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
@@ -393,104 +420,70 @@ void tst_QmlDebug::queryRootContexts()
void tst_QmlDebug::queryObject()
{
- 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();
- verifyRootObject(obj);
+ QFETCH(bool, recursive);
- QVERIFY(obj.children().count() >= 2);
-
- // non-recursive query, children data not available
- foreach(const QmlDebugObjectReference &child, obj.children())
- QCOMPARE(child.properties().count(), 0);
-
- delete q_engines;
- delete q_context;
- delete q_obj;
-}
-
-void tst_QmlDebug::queryObjectRecursive()
-{
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->queryObjectRecursive(q_context->rootContext().objects()[0], this);
+ 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);
waitForQuery(q_obj);
QmlDebugObjectReference obj = q_obj->object();
- verifyRootObject(obj);
delete q_engines;
delete q_context;
delete q_obj;
- QList<QmlDebugObjectReference> children = obj.children();
- QVERIFY(children.count() >= 2); // there may be additional properties e.g. StateGroup
-
- QList<QmlDebugPropertyReference> props;
- QHash<QString, QVariant> expected;
-
- QmlDebugObjectReference rectRef;
- QmlDebugObjectReference textRef;
- foreach (const QmlDebugObjectReference &child, children) {
- if (child.className() == "Rectangle") {
- props = child.properties();
- QVERIFY(props.count() > 0);
- expected.clear();
- expected["width"] = 500;
- expected["height"] = 600;
- expected["color"] = "blue";
- verifyProperties(props, expected);
- rectRef = child;
- } else if (child.className() == "Text") {
- props = child.properties();
- QVERIFY(props.count() > 0);
- expected.clear();
- expected["color"] = "red";
- verifyProperties(props, expected);
- textRef = child;
+ // 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;
}
- }
- QVERIFY(!rectRef.className().isEmpty());
- QVERIFY(!textRef.className().isEmpty());
+ // 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")));
- QObject *rectObj = 0;
- QObject *textObj = 0;
- foreach (QObject *o, m_rootItem->children()) {
- if (o->metaObject()->className() == QmlGraphicsRectangle::staticMetaObject.className())
- rectObj = o;
- else if (o->metaObject()->className() == QmlGraphicsText::staticMetaObject.className())
- textObj = o;
- }
+ QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue")));
- QVERIFY(rectObj);
- QVERIFY(textObj);
-
- for (int i=0; i<rectObj->metaObject()->propertyCount(); i++) {
- QMetaProperty p = rectObj->metaObject()->property(i);
- QmlDebugPropertyReference pd = findProperty(rectRef.properties(), p.name());
- if (!pd.name().isEmpty()) {
- QCOMPARE(pd.name(), QString::fromUtf8(p.name()));
- if (p.type() < QVariant::UserType)
- QCOMPARE(pd.value(), p.read(rectObj));
- if (pd.name() != "parent")
- QCOMPARE(pd.valueTypeName(), QString::fromUtf8(p.typeName()));
- QCOMPARE(pd.hasNotifySignal(), p.hasNotifySignal());
- }
+ } else {
+ foreach(const QmlDebugObjectReference &child, obj.children())
+ QCOMPARE(child.properties().count(), 0);
}
}
+void tst_QmlDebug::queryObject_data()
+{
+ QTest::addColumn<bool>("recursive");
+
+ QTest::newRow("non-recursive") << false;
+ QTest::newRow("recursive") << true;
+}
+
void tst_QmlDebug::queryExpressionResult()
{
QFETCH(QString, expr);
@@ -570,17 +563,20 @@ int main(int argc, char *argv[])
QmlComponent component(&engine,
"import Qt 4.6\n"
- "\n" // don't remove, line number is tested
- " Item {\n" // don't remove spaces, column number is tested
+ "Item {\n"
"width: 10; height: 20;\n"
"Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }"
- "Text { color: \"red\"; }"
+ "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<QmlGraphicsItem*>(o);