void tst_QDeclarativeDebug::setMethodBody() { QDeclarativeDebugObjectReference obj = findRootObject(2); QObject *root = m_components.at(2); // Without args { QVariant rv; QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection, Q_RETURN_ARG(QVariant, rv))); QVERIFY(rv == QVariant(qreal(3))); QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethodNoArgs", "return 7")); QTest::qWait(100); QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection, Q_RETURN_ARG(QVariant, rv))); QVERIFY(rv == QVariant(qreal(7))); } // With args { QVariant rv; QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection, Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19)))); QVERIFY(rv == QVariant(qreal(28))); QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethod", "return a + 7")); QTest::qWait(100); QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection, Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19)))); QVERIFY(rv == QVariant(qreal(26))); } }
void tst_QDeclarativeDebug::watch_property() { QDeclarativeDebugObjectReference obj = findRootObject(); QDeclarativeDebugPropertyReference prop = findProperty(obj.properties(), "width"); QDeclarativeDebugPropertyWatch *watch; QDeclarativeEngineDebug *unconnected = new QDeclarativeEngineDebug(0); watch = unconnected->addWatch(prop, this); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Dead); delete watch; delete unconnected; watch = m_dbg->addWatch(QDeclarativeDebugPropertyReference(), this); QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)))); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Inactive); delete watch; watch = m_dbg->addWatch(prop, this); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Waiting); QCOMPARE(watch->objectDebugId(), obj.debugId()); QCOMPARE(watch->name(), prop.name()); QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); int origWidth = m_rootItem->property("width").toInt(); m_rootItem->setProperty("width", origWidth*2); // stateChanged() is received before valueChanged() QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)))); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Active); QCOMPARE(spy.count(), 1); m_dbg->removeWatch(watch); delete watch; // restore original value and verify spy doesn't get additional 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<QByteArray>(), prop.name().toUtf8()); QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2)); }
void tst_QDeclarativeDebug::watch_expression() { QFETCH(QString, expr); QFETCH(int, increment); QFETCH(int, incrementCount); int origWidth = m_rootItem->property("width").toInt(); QDeclarativeDebugObjectReference obj = findRootObject(); QDeclarativeDebugObjectExpressionWatch *watch; QDeclarativeEngineDebug *unconnected = new QDeclarativeEngineDebug(0); watch = unconnected->addWatch(obj, expr, this); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Dead); delete watch; delete unconnected; watch = m_dbg->addWatch(QDeclarativeDebugObjectReference(), expr, this); QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)))); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Inactive); delete watch; watch = m_dbg->addWatch(obj, expr, this); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Waiting); QCOMPARE(watch->objectDebugId(), obj.debugId()); QCOMPARE(watch->expression(), expr); QSignalSpy spyState(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))); 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<incrementCount+1; i++) { if (i > 0) { width += increment; m_rootItem->setProperty("width", width); } if (!QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(valueChanged(QByteArray,QVariant)))) QFAIL("Did not receive valueChanged() for expression"); } if (spyState.count() == 0) QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)))); QCOMPARE(spyState.count(), 1); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Active); 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<spy.count(); i++) { QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width); width += increment; } }
void tst_QDeclarativeDebug::watch_object() { QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); waitForQuery(q_engines); QVERIFY(q_engines->engines().count() > 0); QDeclarativeDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); QVERIFY(q_context->rootContext().objects().count() > 0); QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); waitForQuery(q_obj); QDeclarativeDebugObjectReference obj = q_obj->object(); delete q_engines; delete q_context; delete q_obj; QDeclarativeDebugWatch *watch; QDeclarativeEngineDebug *unconnected = new QDeclarativeEngineDebug(0); watch = unconnected->addWatch(obj, this); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Dead); delete watch; delete unconnected; watch = m_dbg->addWatch(QDeclarativeDebugObjectReference(), this); QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)))); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Inactive); delete watch; watch = m_dbg->addWatch(obj, this); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Waiting); QCOMPARE(watch->objectDebugId(), obj.debugId()); QSignalSpy spy(watch, SIGNAL(valueChanged(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); // stateChanged() is received before any valueChanged() signals QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)))); QCOMPARE(watch->state(), QDeclarativeDebugWatch::Active); QVERIFY(spy.count() > 0); int newWidth = -1; int newHeight = -1; for (int i=0; i<spy.count(); i++) { const QVariantList &values = spy[i]; if (values[0].value<QByteArray>() == "width") newWidth = values[1].value<QVariant>().toInt(); else if (values[0].value<QByteArray>() == "height") newHeight = values[1].value<QVariant>().toInt(); } m_dbg->removeWatch(watch); delete watch; // since watch has been removed, restoring the original values should not trigger a valueChanged() spy.clear(); m_rootItem->setProperty("width", origWidth); m_rootItem->setProperty("height", origHeight); QTest::qWait(100); QCOMPARE(spy.count(), 0); QCOMPARE(newWidth, origWidth * 2); QCOMPARE(newHeight, origHeight * 2); }
void tst_QDeclarativeDebug::recursiveObjectTest(QObject *o, const QDeclarativeDebugObjectReference &oref, bool recursive) const { const QMetaObject *meta = o->metaObject(); QDeclarativeType *type = QDeclarativeMetaType::qmlType(meta); QString className = type ? QString(type->qmlTypeName()) : QString(meta->className()); className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); QCOMPARE(oref.debugId(), QDeclarativeDebugService::idForObject(o)); QCOMPARE(oref.name(), o->objectName()); QCOMPARE(oref.className(), className); QCOMPARE(oref.contextDebugId(), QDeclarativeDebugService::idForObject(qmlContext(o))); const QObjectList &children = o->children(); for (int i=0; i<children.count(); i++) { QObject *child = children[i]; if (!qmlContext(child)) continue; int debugId = QDeclarativeDebugService::idForObject(child); QVERIFY(debugId >= 0); QDeclarativeDebugObjectReference cref; foreach (const QDeclarativeDebugObjectReference &ref, oref.children()) { if (ref.debugId() == debugId) { cref = ref; break; } } QVERIFY(cref.debugId() >= 0); if (recursive) recursiveObjectTest(child, cref, true); } foreach (const QDeclarativeDebugPropertyReference &p, oref.properties()) { QCOMPARE(p.objectDebugId(), QDeclarativeDebugService::idForObject(o)); // signal properties are fake - they are generated from QDeclarativeBoundSignal children if (p.name().startsWith("on") && p.name().length() > 2 && p.name()[2].isUpper()) { QVERIFY(p.value().toString().startsWith('{') && p.value().toString().endsWith('}')); QVERIFY(p.valueTypeName().isEmpty()); QVERIFY(p.binding().isEmpty()); QVERIFY(!p.hasNotifySignal()); continue; } QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData())); QCOMPARE(p.name(), QString::fromUtf8(pmeta.name())); if (pmeta.type() > 0 && pmeta.type() < QVariant::UserType) // TODO test complex types QCOMPARE(p.value(), pmeta.read(o)); if (p.name() == "parent") QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QDeclarativeItem*"); else QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName())); QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::binding(QDeclarativeProperty(o, p.name())); if (binding) QCOMPARE(binding->expression(), p.binding()); QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal()); QVERIFY(pmeta.isValid()); } }