2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-19 11:23:05 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
|
|
**
|
2016-01-19 11:23:05 +00:00
|
|
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
2012-09-20 05:21:40 +00:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2015-01-28 11:55:39 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-19 11:23:05 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-09-20 05:21:40 +00:00
|
|
|
**
|
2016-01-19 11:23:05 +00:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2015-09-16 14:28:24 +00:00
|
|
|
#include "qqmlenginedebugclient.h"
|
|
|
|
#include "debugutil_p.h"
|
|
|
|
#include "../../../shared/util.h"
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-02-16 04:43:03 +00:00
|
|
|
#include <private/qqmlbinding_p.h>
|
|
|
|
#include <private/qqmlboundsignal_p.h>
|
|
|
|
#include <private/qqmldebugservice_p.h>
|
|
|
|
#include <private/qqmlmetatype_p.h>
|
|
|
|
#include <private/qqmlproperty_p.h>
|
2015-09-16 14:28:24 +00:00
|
|
|
#include <private/qqmldebugconnection_p.h>
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2015-09-16 14:28:24 +00:00
|
|
|
#include <QtTest/qtest.h>
|
|
|
|
#include <QtTest/qsignalspy.h>
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2015-09-16 14:28:24 +00:00
|
|
|
#include <QtQml/qqmlengine.h>
|
|
|
|
#include <QtQml/qqmlcontext.h>
|
|
|
|
#include <QtQml/qqmlcomponent.h>
|
|
|
|
#include <QtQml/qqmlexpression.h>
|
|
|
|
#include <QtQml/qqmlproperty.h>
|
2017-01-11 10:44:58 +00:00
|
|
|
#include <QtQml/qqmlincubator.h>
|
2015-09-16 14:28:24 +00:00
|
|
|
#include <QtQuick/qquickitem.h>
|
|
|
|
|
|
|
|
#include <QtNetwork/qhostaddress.h>
|
|
|
|
#include <QtCore/qtimer.h>
|
|
|
|
#include <QtCore/qdebug.h>
|
|
|
|
#include <QtCore/qthread.h>
|
|
|
|
#include <QtCore/qabstractitemmodel.h>
|
2012-03-06 16:25:58 +00:00
|
|
|
|
|
|
|
#define QVERIFYOBJECT(statement) \
|
|
|
|
do {\
|
|
|
|
if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\
|
|
|
|
return QmlDebugObjectReference();\
|
|
|
|
}\
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
class NonScriptProperty : public QObject {
|
|
|
|
Q_OBJECT
|
|
|
|
Q_PROPERTY(int nonScriptProp READ nonScriptProp WRITE setNonScriptProp NOTIFY nonScriptPropChanged SCRIPTABLE false)
|
|
|
|
public:
|
|
|
|
int nonScriptProp() const { return 0; }
|
|
|
|
void setNonScriptProp(int) {}
|
|
|
|
signals:
|
|
|
|
void nonScriptPropChanged();
|
|
|
|
};
|
|
|
|
QML_DECLARE_TYPE(NonScriptProperty)
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2014-11-06 10:43:19 +00:00
|
|
|
class CustomTypes : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
Q_PROPERTY(QModelIndex modelIndex READ modelIndex)
|
|
|
|
public:
|
|
|
|
CustomTypes(QObject *parent = 0) : QObject(parent) {}
|
|
|
|
|
|
|
|
QModelIndex modelIndex() { return QModelIndex(); }
|
|
|
|
};
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
class tst_QQmlEngineDebugService : public QObject
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
Q_OBJECT
|
2015-06-12 12:55:49 +00:00
|
|
|
public:
|
|
|
|
tst_QQmlEngineDebugService() : m_conn(0), m_dbg(0), m_engine(0), m_rootItem(0) {}
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
private:
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference findRootObject(int context = 0,
|
|
|
|
bool recursive = false);
|
|
|
|
QmlDebugPropertyReference findProperty(
|
|
|
|
const QList<QmlDebugPropertyReference> &props,
|
|
|
|
const QString &name) const;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
void recursiveObjectTest(QObject *o,
|
|
|
|
const QmlDebugObjectReference &oref,
|
|
|
|
bool recursive) const;
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2017-10-23 09:24:16 +00:00
|
|
|
void getContexts();
|
|
|
|
|
2012-02-16 04:43:03 +00:00
|
|
|
QQmlDebugConnection *m_conn;
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *m_dbg;
|
2012-02-16 04:43:03 +00:00
|
|
|
QQmlEngine *m_engine;
|
2011-10-14 08:51:42 +00:00
|
|
|
QQuickItem *m_rootItem;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QObjectList m_components;
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void initTestCase();
|
|
|
|
void cleanupTestCase();
|
|
|
|
|
|
|
|
void watch_property();
|
|
|
|
void watch_object();
|
|
|
|
void watch_expression();
|
|
|
|
void watch_expression_data();
|
|
|
|
void watch_context();
|
|
|
|
void watch_file();
|
|
|
|
|
|
|
|
void queryAvailableEngines();
|
|
|
|
void queryRootContexts();
|
|
|
|
void queryObject();
|
|
|
|
void queryObject_data();
|
2012-05-10 07:21:26 +00:00
|
|
|
void queryObjectsForLocation();
|
|
|
|
void queryObjectsForLocation_data();
|
2011-04-27 10:05:43 +00:00
|
|
|
void queryExpressionResult();
|
|
|
|
void queryExpressionResult_data();
|
2012-05-09 09:30:27 +00:00
|
|
|
void queryExpressionResultInRootContext();
|
|
|
|
void queryExpressionResultBC();
|
|
|
|
void queryExpressionResultBC_data();
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
void setBindingForObject();
|
2012-05-16 13:20:59 +00:00
|
|
|
void resetBindingForObject();
|
2011-04-27 10:05:43 +00:00
|
|
|
void setMethodBody();
|
|
|
|
void queryObjectTree();
|
|
|
|
void setBindingInStates();
|
2012-05-22 12:01:16 +00:00
|
|
|
|
|
|
|
void regression_QTCREATORBUG_7451();
|
2014-11-06 10:43:19 +00:00
|
|
|
void queryObjectWithNonStreamableTypes();
|
2017-01-11 10:44:58 +00:00
|
|
|
void asynchronousCreate();
|
2017-10-23 09:24:16 +00:00
|
|
|
void invalidContexts();
|
2011-04-27 10:05:43 +00:00
|
|
|
};
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject(
|
|
|
|
int context, bool recursive)
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
m_dbg->queryAvailableEngines(&success);
|
|
|
|
QVERIFYOBJECT(success);
|
|
|
|
QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
QVERIFYOBJECT(m_dbg->engines().count());
|
|
|
|
m_dbg->queryRootContexts(m_dbg->engines()[0].debugId, &success);
|
|
|
|
QVERIFYOBJECT(success);
|
|
|
|
QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
QVERIFYOBJECT(m_dbg->rootContext().contexts.count());
|
|
|
|
QVERIFYOBJECT(m_dbg->rootContext().contexts.last().objects.count());
|
|
|
|
int count = m_dbg->rootContext().contexts.count();
|
|
|
|
recursive ? m_dbg->queryObjectRecursive(m_dbg->rootContext().contexts[count - context - 1].objects[0],
|
|
|
|
&success) :
|
|
|
|
m_dbg->queryObject(m_dbg->rootContext().contexts[count - context - 1].objects[0], &success);
|
|
|
|
QVERIFYOBJECT(success);
|
|
|
|
QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
return m_dbg->object();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugPropertyReference tst_QQmlEngineDebugService::findProperty(
|
|
|
|
const QList<QmlDebugPropertyReference> &props, const QString &name) const
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
foreach (const QmlDebugPropertyReference &p, props) {
|
|
|
|
if (p.name == name)
|
2011-04-27 10:05:43 +00:00
|
|
|
return p;
|
|
|
|
}
|
2012-03-06 16:25:58 +00:00
|
|
|
return QmlDebugPropertyReference();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
void tst_QQmlEngineDebugService::recursiveObjectTest(
|
|
|
|
QObject *o, const QmlDebugObjectReference &oref, bool recursive) const
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
const QMetaObject *meta = o->metaObject();
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(oref.debugId, QQmlDebugService::idForObject(o));
|
|
|
|
QCOMPARE(oref.name, o->objectName());
|
2017-03-15 11:12:22 +00:00
|
|
|
QCOMPARE(oref.className, QQmlMetaType::prettyTypeName(o));
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(oref.contextDebugId, QQmlDebugService::idForObject(
|
|
|
|
qmlContext(o)));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
const QObjectList &children = o->children();
|
|
|
|
for (int i=0; i<children.count(); i++) {
|
|
|
|
QObject *child = children[i];
|
|
|
|
if (!qmlContext(child))
|
|
|
|
continue;
|
2012-02-16 04:43:03 +00:00
|
|
|
int debugId = QQmlDebugService::idForObject(child);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(debugId >= 0);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference cref;
|
|
|
|
foreach (const QmlDebugObjectReference &ref, oref.children) {
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!ref.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
if (ref.debugId == debugId) {
|
2011-04-27 10:05:43 +00:00
|
|
|
cref = ref;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(cref.debugId >= 0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
if (recursive)
|
|
|
|
recursiveObjectTest(child, cref, true);
|
|
|
|
}
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
foreach (const QmlDebugPropertyReference &p, oref.properties) {
|
|
|
|
QCOMPARE(p.objectDebugId, QQmlDebugService::idForObject(o));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-21 06:28:32 +00:00
|
|
|
// signal properties are fake - they are generated from QQmlAbstractBoundSignal children
|
2012-03-06 16:25:58 +00:00
|
|
|
if (p.name.startsWith("on") && p.name.length() > 2 && p.name[2].isUpper()) {
|
|
|
|
QString signal = p.value.toString();
|
2012-03-27 06:56:08 +00:00
|
|
|
QQmlBoundSignalExpression *expr = QQmlPropertyPrivate::signalExpression(QQmlProperty(o, p.name));
|
2012-03-22 22:22:02 +00:00
|
|
|
QVERIFY(expr && expr->expression() == signal);
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(p.valueTypeName.isEmpty());
|
|
|
|
QVERIFY(p.binding.isEmpty());
|
|
|
|
QVERIFY(!p.hasNotifySignal);
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name.toUtf8().constData()));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(p.name, QString::fromUtf8(pmeta.name()));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
if (pmeta.type() < QVariant::UserType && pmeta.userType() !=
|
|
|
|
QMetaType::QVariant) // TODO test complex types
|
|
|
|
QCOMPARE(p.value , pmeta.read(o));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
if (p.name == "parent")
|
|
|
|
QVERIFY(p.valueTypeName == "QGraphicsObject*" ||
|
|
|
|
p.valueTypeName == "QQuickItem*");
|
2011-04-27 10:05:43 +00:00
|
|
|
else
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(p.valueTypeName, QString::fromUtf8(pmeta.typeName()));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QQmlAbstractBinding *binding =
|
|
|
|
QQmlPropertyPrivate::binding(
|
|
|
|
QQmlProperty(o, p.name));
|
2011-04-27 10:05:43 +00:00
|
|
|
if (binding)
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(binding->expression(), p.binding);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(p.hasNotifySignal, pmeta.hasNotifySignal());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QVERIFY(pmeta.isValid());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-23 09:24:16 +00:00
|
|
|
void tst_QQmlEngineDebugService::getContexts()
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
m_dbg->queryAvailableEngines(&success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
QList<QmlDebugEngineReference> engines = m_dbg->engines();
|
|
|
|
QCOMPARE(engines.count(), 1);
|
|
|
|
m_dbg->queryRootContexts(engines.first().debugId, &success);
|
|
|
|
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::initTestCase()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
qmlRegisterType<NonScriptProperty>("Test", 1, 0, "NonScriptPropertyElement");
|
|
|
|
|
2012-03-08 14:15:10 +00:00
|
|
|
QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Waiting for connection on port 3768...");
|
2012-02-16 04:43:03 +00:00
|
|
|
m_engine = new QQmlEngine(this);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QList<QByteArray> qml;
|
2011-07-11 03:47:51 +00:00
|
|
|
qml << "import QtQuick 2.0\n"
|
2011-04-27 10:05:43 +00:00
|
|
|
"import Test 1.0\n"
|
|
|
|
"Item {"
|
|
|
|
"id: root\n"
|
|
|
|
"width: 10; height: 20; scale: blueRect.scale;"
|
|
|
|
"Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }"
|
2012-05-16 13:20:59 +00:00
|
|
|
"Text { font.bold: true; color: blueRect.color; }"
|
2011-04-27 10:05:43 +00:00
|
|
|
"MouseArea {"
|
|
|
|
"onEntered: { console.log('hello') }"
|
|
|
|
"}"
|
|
|
|
"property variant varObj\n"
|
|
|
|
"property variant varObjList: []\n"
|
2012-02-17 10:09:31 +00:00
|
|
|
"property variant varObjMap\n"
|
2012-05-25 08:14:53 +00:00
|
|
|
"property variant simpleVar: 10.05\n"
|
2011-04-27 10:05:43 +00:00
|
|
|
"Component.onCompleted: {\n"
|
|
|
|
"varObj = blueRect;\n"
|
|
|
|
"var list = varObjList;\n"
|
|
|
|
"list[0] = blueRect;\n"
|
|
|
|
"varObjList = list;\n"
|
2012-02-17 10:09:31 +00:00
|
|
|
"var map = new Object;\n"
|
|
|
|
"map.rect = blueRect;\n"
|
|
|
|
"varObjMap = map;\n"
|
2011-04-27 10:05:43 +00:00
|
|
|
"}\n"
|
|
|
|
"NonScriptPropertyElement {\n"
|
|
|
|
"}\n"
|
|
|
|
"}";
|
|
|
|
|
|
|
|
// add second component to test multiple root contexts
|
2011-07-11 03:47:51 +00:00
|
|
|
qml << "import QtQuick 2.0\n"
|
2011-04-27 10:05:43 +00:00
|
|
|
"Item {}";
|
|
|
|
|
|
|
|
// and a third to test methods
|
2011-07-11 03:47:51 +00:00
|
|
|
qml << "import QtQuick 2.0\n"
|
2011-04-27 10:05:43 +00:00
|
|
|
"Item {"
|
|
|
|
"function myMethodNoArgs() { return 3; }\n"
|
|
|
|
"function myMethod(a) { return a + 9; }\n"
|
|
|
|
"function myMethodIndirect() { myMethod(3); }\n"
|
|
|
|
"}";
|
|
|
|
|
|
|
|
// and a fourth to test states
|
2011-07-11 03:47:51 +00:00
|
|
|
qml << "import QtQuick 2.0\n"
|
2011-04-27 10:05:43 +00:00
|
|
|
"Rectangle {\n"
|
|
|
|
"id:rootRect\n"
|
|
|
|
"width:100\n"
|
|
|
|
"states: [\n"
|
|
|
|
"State {\n"
|
|
|
|
"name:\"state1\"\n"
|
|
|
|
"PropertyChanges {\n"
|
|
|
|
"target:rootRect\n"
|
|
|
|
"width:200\n"
|
|
|
|
"}\n"
|
|
|
|
"}\n"
|
|
|
|
"]\n"
|
|
|
|
"transitions: [\n"
|
|
|
|
"Transition {\n"
|
|
|
|
"from:\"*\"\n"
|
|
|
|
"to:\"state1\"\n"
|
|
|
|
"PropertyAnimation {\n"
|
|
|
|
"target:rootRect\n"
|
|
|
|
"property:\"width\"\n"
|
|
|
|
"duration:100\n"
|
|
|
|
"}\n"
|
|
|
|
"}\n"
|
|
|
|
"]\n"
|
|
|
|
"}\n"
|
|
|
|
;
|
|
|
|
|
2014-11-06 10:43:19 +00:00
|
|
|
// test non-streamable properties
|
|
|
|
qmlRegisterType<CustomTypes>("Backend", 1, 0, "CustomTypes");
|
|
|
|
qml << "import Backend 1.0\n"
|
|
|
|
"CustomTypes {}"
|
|
|
|
;
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
for (int i=0; i<qml.count(); i++) {
|
2012-02-16 04:43:03 +00:00
|
|
|
QQmlComponent component(m_engine);
|
2011-04-27 10:05:43 +00:00
|
|
|
component.setData(qml[i], QUrl::fromLocalFile(""));
|
2011-05-18 00:45:16 +00:00
|
|
|
QVERIFY(component.isReady()); // fails if bad syntax
|
2011-10-14 08:51:42 +00:00
|
|
|
m_components << qobject_cast<QQuickItem*>(component.create());
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2011-10-14 08:51:42 +00:00
|
|
|
m_rootItem = qobject_cast<QQuickItem*>(m_components.first());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// add an extra context to test for multiple contexts
|
2012-02-16 04:43:03 +00:00
|
|
|
QQmlContext *context = new QQmlContext(m_engine->rootContext(), this);
|
|
|
|
context->setObjectName("tst_QQmlDebug_childContext");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-02-16 04:43:03 +00:00
|
|
|
m_conn = new QQmlDebugConnection(this);
|
2011-04-27 10:05:43 +00:00
|
|
|
m_conn->connectToHost("127.0.0.1", 3768);
|
|
|
|
|
|
|
|
bool ok = m_conn->waitForConnected();
|
2011-05-18 00:45:16 +00:00
|
|
|
QVERIFY(ok);
|
2012-03-13 16:16:16 +00:00
|
|
|
m_dbg = new QQmlEngineDebugClient(m_conn);
|
2015-09-16 14:28:24 +00:00
|
|
|
QList<QQmlDebugClient *> others = QQmlDebugTest::createOtherClients(m_conn);
|
2015-07-24 13:27:58 +00:00
|
|
|
QTRY_COMPARE(m_dbg->state(), QQmlEngineDebugClient::Enabled);
|
2015-08-10 13:13:09 +00:00
|
|
|
foreach (QQmlDebugClient *other, others)
|
|
|
|
QCOMPARE(other->state(), QQmlDebugClient::Unavailable);
|
|
|
|
qDeleteAll(others);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::cleanupTestCase()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
delete m_conn;
|
|
|
|
qDeleteAll(m_components);
|
|
|
|
delete m_engine;
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::setMethodBody()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
|
|
|
QmlDebugObjectReference obj = findRootObject(2);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QObject *root = m_components.at(2);
|
|
|
|
// Without args
|
|
|
|
{
|
|
|
|
QVariant rv;
|
|
|
|
QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
|
|
|
|
Q_RETURN_ARG(QVariant, rv)));
|
2015-07-24 13:27:58 +00:00
|
|
|
QCOMPARE(rv, QVariant(qreal(3)));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethodNoArgs", "return 7",
|
|
|
|
&success));
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
|
|
|
|
Q_RETURN_ARG(QVariant, rv)));
|
2015-07-24 13:27:58 +00:00
|
|
|
QCOMPARE(rv, QVariant(qreal(7)));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// With args
|
|
|
|
{
|
|
|
|
QVariant rv;
|
|
|
|
QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
|
|
|
|
Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
|
2015-07-24 13:27:58 +00:00
|
|
|
QCOMPARE(rv, QVariant(qreal(28)));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethod", "return a + 7",
|
|
|
|
&success));
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
|
|
|
|
Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
|
2015-07-24 13:27:58 +00:00
|
|
|
QCOMPARE(rv, QVariant(qreal(26)));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::watch_property()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference obj = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugPropertyReference prop = findProperty(obj.properties, "width");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
unconnected->addWatch(prop, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->addWatch(QmlDebugPropertyReference(), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), false);
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
quint32 id = m_dbg->addWatch(prop, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
int origWidth = m_rootItem->property("width").toInt();
|
|
|
|
m_rootItem->setProperty("width", origWidth*2);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
|
2011-04-27 10:05:43 +00:00
|
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->removeWatch(id, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name.toUtf8());
|
2011-04-27 10:05:43 +00:00
|
|
|
QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2));
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::watch_object()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference obj = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
unconnected->addWatch(obj, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->addWatch(QmlDebugObjectReference(), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), false);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
quint32 id = m_dbg->addWatch(obj, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
int origWidth = m_rootItem->property("width").toInt();
|
|
|
|
int origHeight = m_rootItem->property("height").toInt();
|
|
|
|
m_rootItem->setProperty("width", origWidth*2);
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
|
2011-04-27 10:05:43 +00:00
|
|
|
m_rootItem->setProperty("height", origHeight*2);
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->removeWatch(id, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::watch_expression()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QFETCH(QString, expr);
|
|
|
|
QFETCH(int, increment);
|
|
|
|
QFETCH(int, incrementCount);
|
|
|
|
|
|
|
|
int origWidth = m_rootItem->property("width").toInt();
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference obj = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
unconnected->addWatch(obj, expr, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->addWatch(QmlDebugObjectReference(), expr, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), false);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
quint32 id = m_dbg->addWatch(obj, expr, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
int width = origWidth;
|
|
|
|
for (int i=0; i<incrementCount+1; i++) {
|
|
|
|
if (i > 0) {
|
|
|
|
width += increment;
|
|
|
|
m_rootItem->setProperty("width", width);
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->removeWatch(id, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// restore original value and verify spy doesn't get a signal since watch has been removed
|
2011-05-18 00:45:16 +00:00
|
|
|
m_rootItem->setProperty("width", origWidth);
|
2011-04-27 10:05:43 +00:00
|
|
|
QTest::qWait(100);
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(spy.count(), incrementCount);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
width = origWidth + increment;
|
|
|
|
for (int i=0; i<spy.count(); i++) {
|
|
|
|
width += increment;
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::watch_expression_data()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("expr");
|
|
|
|
QTest::addColumn<int>("increment");
|
|
|
|
QTest::addColumn<int>("incrementCount");
|
|
|
|
|
|
|
|
QTest::newRow("width") << "width" << 0 << 0;
|
|
|
|
QTest::newRow("width+10") << "width + 10" << 10 << 5;
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::watch_context()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugContextReference c;
|
|
|
|
QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebugClient::addWatch(): Not implemented");
|
|
|
|
bool success;
|
|
|
|
m_dbg->addWatch(c, QString(), &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::watch_file()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugFileReference f;
|
|
|
|
QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebugClient::addWatch(): Not implemented");
|
|
|
|
bool success;
|
|
|
|
m_dbg->addWatch(f, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryAvailableEngines()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
unconnected->queryAvailableEngines(&success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryAvailableEngines(&success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// TODO test multiple engines
|
2012-03-06 16:25:58 +00:00
|
|
|
QList<QmlDebugEngineReference> engines = m_dbg->engines();
|
2011-04-27 10:05:43 +00:00
|
|
|
QCOMPARE(engines.count(), 1);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
foreach (const QmlDebugEngineReference &e, engines) {
|
|
|
|
QCOMPARE(e.debugId, QQmlDebugService::idForObject(m_engine));
|
|
|
|
QCOMPARE(e.name, m_engine->objectName());
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryRootContexts()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
|
|
|
m_dbg->queryAvailableEngines(&success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QVERIFY(m_dbg->engines().count());
|
|
|
|
int engineId = m_dbg->engines()[0].debugId;
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
unconnected->queryRootContexts(engineId, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryRootContexts(engineId, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-02-16 04:43:03 +00:00
|
|
|
QQmlContext *actualContext = m_engine->rootContext();
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugContextReference context = m_dbg->rootContext();
|
|
|
|
QCOMPARE(context.debugId, QQmlDebugService::idForObject(actualContext));
|
|
|
|
QCOMPARE(context.name, actualContext->objectName());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// root context query sends only root object data - it doesn't fill in
|
|
|
|
// the children or property info
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(context.objects.count(), 0);
|
2014-11-06 10:43:19 +00:00
|
|
|
QCOMPARE(context.contexts.count(), 6);
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(context.contexts[0].debugId >= 0);
|
|
|
|
QCOMPARE(context.contexts[0].name, QString("tst_QQmlDebug_childContext"));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryObject()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QFETCH(bool, recursive);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
recursive ? m_dbg->queryObjectRecursive(rootObject, &success) : m_dbg->queryObject(rootObject, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference obj = m_dbg->object();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// check source as defined in main()
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugFileReference source = obj.source;
|
|
|
|
QCOMPARE(source.url, QUrl::fromLocalFile(""));
|
|
|
|
QCOMPARE(source.lineNumber, 3);
|
|
|
|
QCOMPARE(source.columnNumber, 1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// generically test all properties, children and childrens' properties
|
|
|
|
recursiveObjectTest(m_rootItem, obj, recursive);
|
|
|
|
|
|
|
|
if (recursive) {
|
2017-03-15 11:12:22 +00:00
|
|
|
foreach (const QmlDebugObjectReference &child, obj.children) {
|
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(child.properties.count() > 0);
|
2017-03-15 11:12:22 +00:00
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference rect;
|
|
|
|
QmlDebugObjectReference text;
|
|
|
|
foreach (const QmlDebugObjectReference &child, obj.children) {
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
if (child.className == "Rectangle")
|
2011-04-27 10:05:43 +00:00
|
|
|
rect = child;
|
2012-03-06 16:25:58 +00:00
|
|
|
else if (child.className == "Text")
|
2011-04-27 10:05:43 +00:00
|
|
|
text = child;
|
|
|
|
}
|
|
|
|
|
|
|
|
// test specific property values
|
2012-03-06 16:25:58 +00:00
|
|
|
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")));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue")));
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
2017-03-15 11:12:22 +00:00
|
|
|
foreach (const QmlDebugObjectReference &child, obj.children) {
|
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(child.properties.count(), 0);
|
2017-03-15 11:12:22 +00:00
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryObject_data()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QTest::addColumn<bool>("recursive");
|
|
|
|
|
|
|
|
QTest::newRow("non-recursive") << false;
|
|
|
|
QTest::newRow("recursive") << true;
|
|
|
|
}
|
|
|
|
|
2012-05-10 07:21:26 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryObjectsForLocation()
|
|
|
|
{
|
|
|
|
QFETCH(bool, recursive);
|
|
|
|
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
QmlDebugObjectReference rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-05-10 07:21:26 +00:00
|
|
|
|
|
|
|
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
|
|
|
|
int lineNumber = rootObject.source.lineNumber;
|
|
|
|
int columnNumber = rootObject.source.columnNumber;
|
|
|
|
|
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
|
|
|
recursive ? unconnected->queryObjectsForLocationRecursive(fileName, lineNumber,
|
|
|
|
columnNumber, &success)
|
|
|
|
: unconnected->queryObjectsForLocation(fileName, lineNumber,
|
|
|
|
columnNumber, &success);
|
|
|
|
QVERIFY(!success);
|
|
|
|
delete unconnected;
|
|
|
|
|
|
|
|
recursive ? m_dbg->queryObjectsForLocationRecursive(fileName, lineNumber,
|
|
|
|
columnNumber, &success)
|
|
|
|
: m_dbg->queryObjectsForLocation(fileName, lineNumber,
|
|
|
|
columnNumber, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
2015-07-24 13:27:58 +00:00
|
|
|
QCOMPARE(m_dbg->objects().count(), 1);
|
2012-05-10 07:21:26 +00:00
|
|
|
QmlDebugObjectReference obj = m_dbg->objects().first();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-05-10 07:21:26 +00:00
|
|
|
|
|
|
|
// check source as defined in main()
|
|
|
|
QmlDebugFileReference source = obj.source;
|
|
|
|
QCOMPARE(source.url, QUrl(fileName));
|
|
|
|
QCOMPARE(source.lineNumber, lineNumber);
|
|
|
|
QCOMPARE(source.columnNumber, columnNumber);
|
|
|
|
|
|
|
|
// generically test all properties, children and childrens' properties
|
|
|
|
recursiveObjectTest(m_rootItem, obj, recursive);
|
|
|
|
|
|
|
|
if (recursive) {
|
2017-03-15 11:12:22 +00:00
|
|
|
foreach (const QmlDebugObjectReference &child, obj.children) {
|
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-05-10 07:21:26 +00:00
|
|
|
QVERIFY(child.properties.count() > 0);
|
2017-03-15 11:12:22 +00:00
|
|
|
}
|
2012-05-10 07:21:26 +00:00
|
|
|
|
|
|
|
QmlDebugObjectReference rect;
|
|
|
|
QmlDebugObjectReference text;
|
|
|
|
foreach (const QmlDebugObjectReference &child, obj.children) {
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-05-10 07:21:26 +00:00
|
|
|
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 {
|
2017-03-15 11:12:22 +00:00
|
|
|
foreach (const QmlDebugObjectReference &child, obj.children) {
|
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-05-10 07:21:26 +00:00
|
|
|
QCOMPARE(child.properties.count(), 0);
|
2017-03-15 11:12:22 +00:00
|
|
|
}
|
2012-05-10 07:21:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QQmlEngineDebugService::queryObjectsForLocation_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<bool>("recursive");
|
|
|
|
|
|
|
|
QTest::newRow("non-recursive") << false;
|
|
|
|
QTest::newRow("recursive") << true;
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:01:16 +00:00
|
|
|
void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
|
|
|
|
{
|
|
|
|
QmlDebugObjectReference rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-05-22 12:01:16 +00:00
|
|
|
int contextId = rootObject.contextDebugId;
|
|
|
|
QQmlContext *context = qobject_cast<QQmlContext *>(QQmlDebugService::objectForId(contextId));
|
|
|
|
QQmlComponent component(context->engine());
|
|
|
|
QByteArray content;
|
|
|
|
content.append("import QtQuick 2.0\n"
|
|
|
|
"Text {"
|
|
|
|
"y: 10\n"
|
|
|
|
"text: \"test\"\n"
|
|
|
|
"}");
|
|
|
|
component.setData(content, rootObject.source.url);
|
|
|
|
QObject *object = component.create(context);
|
|
|
|
QVERIFY(object);
|
|
|
|
int idNew = QQmlDebugService::idForObject(object);
|
|
|
|
QVERIFY(idNew >= 0);
|
|
|
|
|
|
|
|
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
|
|
|
|
int lineNumber = rootObject.source.lineNumber;
|
|
|
|
int columnNumber = rootObject.source.columnNumber;
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
m_dbg->queryObjectsForLocation(fileName, lineNumber,
|
|
|
|
columnNumber, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
foreach (QmlDebugObjectReference child, rootObject.children) {
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-05-22 12:01:16 +00:00
|
|
|
success = false;
|
|
|
|
lineNumber = child.source.lineNumber;
|
|
|
|
columnNumber = child.source.columnNumber;
|
|
|
|
m_dbg->queryObjectsForLocation(fileName, lineNumber,
|
|
|
|
columnNumber, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
}
|
|
|
|
|
|
|
|
delete object;
|
|
|
|
QObject *deleted = QQmlDebugService::objectForId(idNew);
|
|
|
|
QVERIFY(!deleted);
|
|
|
|
|
|
|
|
lineNumber = rootObject.source.lineNumber;
|
|
|
|
columnNumber = rootObject.source.columnNumber;
|
|
|
|
success = false;
|
|
|
|
m_dbg->queryObjectsForLocation(fileName, lineNumber,
|
|
|
|
columnNumber, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
foreach (QmlDebugObjectReference child, rootObject.children) {
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!child.className.isEmpty());
|
2012-05-22 12:01:16 +00:00
|
|
|
success = false;
|
|
|
|
lineNumber = child.source.lineNumber;
|
|
|
|
columnNumber = child.source.columnNumber;
|
|
|
|
m_dbg->queryObjectsForLocation(fileName, lineNumber,
|
|
|
|
columnNumber, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-06 10:43:19 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes()
|
|
|
|
{
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
QmlDebugObjectReference rootObject = findRootObject(4, true);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2014-11-06 10:43:19 +00:00
|
|
|
|
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
|
|
|
unconnected->queryObject(rootObject, &success);
|
|
|
|
QVERIFY(!success);
|
|
|
|
delete unconnected;
|
|
|
|
|
|
|
|
m_dbg->queryObject(rootObject, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
QmlDebugObjectReference obj = m_dbg->object();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2014-11-06 10:43:19 +00:00
|
|
|
|
|
|
|
QCOMPARE(findProperty(obj.properties, "modelIndex").value, QVariant());
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:01:16 +00:00
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryExpressionResult()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QFETCH(QString, expr);
|
|
|
|
QFETCH(QVariant, result);
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
int objectId = findRootObject().debugId;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-13 16:16:16 +00:00
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
2012-03-06 16:25:58 +00:00
|
|
|
unconnected->queryExpressionResult(objectId, expr, &success);
|
|
|
|
QVERIFY(!success);
|
2011-04-27 10:05:43 +00:00
|
|
|
delete unconnected;
|
2011-05-18 00:45:16 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(objectId, expr, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(m_dbg->resultExpr(), result);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryExpressionResult_data()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("expr");
|
|
|
|
QTest::addColumn<QVariant>("result");
|
|
|
|
|
|
|
|
QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60);
|
|
|
|
QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500);
|
|
|
|
QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("<undefined>"));
|
2012-05-09 09:30:27 +00:00
|
|
|
QTest::newRow("QObject*") << "varObj" << qVariantFromValue(QString("<unnamed object>"));
|
2012-07-05 01:53:18 +00:00
|
|
|
QTest::newRow("list of QObject*") << "varObjList" << qVariantFromValue(QVariantList() << QVariant(QString("<unnamed object>")));
|
2012-05-09 09:30:27 +00:00
|
|
|
QVariantMap map;
|
|
|
|
map.insert(QLatin1String("rect"), QVariant(QLatin1String("<unnamed object>")));
|
|
|
|
QTest::newRow("varObjMap") << "varObjMap" << qVariantFromValue(map);
|
2012-05-25 08:14:53 +00:00
|
|
|
QTest::newRow("simpleVar") << "simpleVar" << qVariantFromValue(10.05);
|
2012-05-09 09:30:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QQmlEngineDebugService::queryExpressionResultInRootContext()
|
|
|
|
{
|
|
|
|
bool success;
|
|
|
|
const QString exp = QLatin1String("1");
|
|
|
|
m_dbg->queryExpressionResult(-1, exp, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
QCOMPARE(m_dbg->resultExpr().toString(), exp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QQmlEngineDebugService::queryExpressionResultBC()
|
|
|
|
{
|
|
|
|
QFETCH(QString, expr);
|
|
|
|
QFETCH(QVariant, result);
|
|
|
|
|
|
|
|
int objectId = findRootObject().debugId;
|
|
|
|
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
|
|
|
unconnected->queryExpressionResultBC(objectId, expr, &success);
|
|
|
|
QVERIFY(!success);
|
|
|
|
delete unconnected;
|
|
|
|
|
|
|
|
m_dbg->queryExpressionResultBC(objectId, expr, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
|
|
|
|
QCOMPARE(m_dbg->resultExpr(), result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QQmlEngineDebugService::queryExpressionResultBC_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("expr");
|
|
|
|
QTest::addColumn<QVariant>("result");
|
|
|
|
|
|
|
|
QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60);
|
|
|
|
QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500);
|
|
|
|
QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("<undefined>"));
|
2011-04-27 10:05:43 +00:00
|
|
|
QTest::newRow("QObject*") << "varObj" << qVariantFromValue(QString("<unnamed object>"));
|
2012-07-05 01:53:18 +00:00
|
|
|
QTest::newRow("list of QObject*") << "varObjList" << qVariantFromValue(QVariantList() << QVariant(QString("<unnamed object>")));
|
2012-02-17 10:09:31 +00:00
|
|
|
QVariantMap map;
|
|
|
|
map.insert(QLatin1String("rect"), QVariant(QLatin1String("<unnamed object>")));
|
|
|
|
QTest::newRow("varObjMap") << "varObjMap" << qVariantFromValue(map);
|
2012-05-25 08:14:53 +00:00
|
|
|
QTest::newRow("simpleVar") << "simpleVar" << qVariantFromValue(10.05);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::setBindingForObject()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(rootObject.debugId != -1);
|
|
|
|
QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(widthPropertyRef.value, QVariant(10));
|
|
|
|
QCOMPARE(widthPropertyRef.binding, QString());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
//
|
|
|
|
// set literal
|
|
|
|
//
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->setBindingForObject(rootObject.debugId, "width", "15", true,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
widthPropertyRef = findProperty(rootObject.properties, "width");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(widthPropertyRef.value, QVariant(15));
|
|
|
|
QCOMPARE(widthPropertyRef.binding, QString());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// set expression
|
|
|
|
//
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->setBindingForObject(rootObject.debugId, "width", "height", false,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
widthPropertyRef = findProperty(rootObject.properties, "width");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(widthPropertyRef.value, QVariant(20));
|
2014-03-04 03:53:52 +00:00
|
|
|
QEXPECT_FAIL("", "Cannot retrieve text for a binding (QTBUG-37273)", Continue);
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(widthPropertyRef.binding, QString("height"));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// set handler
|
|
|
|
//
|
|
|
|
rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(rootObject.children.size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement
|
|
|
|
QmlDebugObjectReference mouseAreaObject = rootObject.children.at(2);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!mouseAreaObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryObjectRecursive(mouseAreaObject, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
mouseAreaObject = m_dbg->object();
|
|
|
|
QCOMPARE(mouseAreaObject.className, QString("MouseArea"));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(onEnteredRef.name, QString("onEntered"));
|
2013-10-08 09:44:57 +00:00
|
|
|
// Sorry, can't do that anymore: QCOMPARE(onEnteredRef.value, QVariant("{ console.log('hello') }"));
|
|
|
|
QCOMPARE(onEnteredRef.value, QVariant("function() { [code] }"));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->setBindingForObject(mouseAreaObject.debugId, "onEntered",
|
|
|
|
"{console.log('hello, world') }", false,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
mouseAreaObject = rootObject.children.at(2);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!mouseAreaObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryObjectRecursive(mouseAreaObject, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
mouseAreaObject = m_dbg->object();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!mouseAreaObject.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
|
|
|
|
QCOMPARE(onEnteredRef.name, QString("onEntered"));
|
2015-05-03 16:38:29 +00:00
|
|
|
QCOMPARE(onEnteredRef.value, QVariant("function() { [code] }"));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-05-16 13:20:59 +00:00
|
|
|
void tst_QQmlEngineDebugService::resetBindingForObject()
|
|
|
|
{
|
|
|
|
QmlDebugObjectReference rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-05-16 13:20:59 +00:00
|
|
|
QVERIFY(rootObject.debugId != -1);
|
|
|
|
QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width");
|
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
m_dbg->setBindingForObject(rootObject.debugId, "width", "15", true,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
|
|
|
|
|
|
|
//
|
|
|
|
// reset
|
|
|
|
//
|
|
|
|
m_dbg->resetBindingForObject(rootObject.debugId, "width", &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
|
|
|
|
|
|
|
rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-05-16 13:20:59 +00:00
|
|
|
widthPropertyRef = findProperty(rootObject.properties, "width");
|
|
|
|
|
|
|
|
QCOMPARE(widthPropertyRef.value, QVariant(0));
|
|
|
|
QCOMPARE(widthPropertyRef.binding, QString());
|
|
|
|
|
|
|
|
//
|
|
|
|
// reset nested property
|
|
|
|
//
|
|
|
|
success = false;
|
|
|
|
m_dbg->resetBindingForObject(rootObject.debugId, "font.bold", &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
|
|
|
|
|
|
|
rootObject = findRootObject();
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!rootObject.className.isEmpty());
|
2012-05-16 13:20:59 +00:00
|
|
|
QmlDebugPropertyReference boldPropertyRef = findProperty(rootObject.properties, "font.bold");
|
|
|
|
|
|
|
|
QCOMPARE(boldPropertyRef.value.toBool(), false);
|
|
|
|
QCOMPARE(boldPropertyRef.binding, QString());
|
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::setBindingInStates()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
// Check if changing bindings of propertychanges works
|
|
|
|
|
|
|
|
const int sourceIndex = 3;
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(obj.debugId != -1);
|
|
|
|
QVERIFY(obj.children.count() >= 2);
|
|
|
|
bool success;
|
2011-04-27 10:05:43 +00:00
|
|
|
// We are going to switch state a couple of times, we need to get rid of the transition before
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(obj.debugId,QString("transitions = []"), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// check initial value of the property that is changing
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),200);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""),
|
|
|
|
&success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex, true);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// change the binding
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference state = obj.children[1];
|
|
|
|
QCOMPARE(state.className, QString("State"));
|
|
|
|
QVERIFY(state.children.count() > 0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference propertyChange = state.children[0];
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!propertyChange.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(propertyChange.debugId != -1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->setBindingForObject(propertyChange.debugId, "width",QVariant(300),true,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// check properties changed in state
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// check changing properties of base state from within a state
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->setBindingForObject(obj.debugId,"width","height*2",false,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
m_dbg->setBindingForObject(obj.debugId,"height","200",true,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// reset binding while in a state
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->resetBindingForObject(propertyChange.debugId, "width", &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// re-add binding
|
2012-03-06 16:25:58 +00:00
|
|
|
m_dbg->setBindingForObject(propertyChange.debugId, "width", "300", true,
|
|
|
|
QString(), -1, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
|
|
|
QCOMPARE(m_dbg->valid(), true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
obj = findRootObject(sourceIndex);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
void tst_QQmlEngineDebugService::queryObjectTree()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
const int sourceIndex = 3;
|
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference obj = findRootObject(sourceIndex, true);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!obj.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(obj.debugId != -1);
|
|
|
|
QVERIFY(obj.children.count() >= 2);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// check state
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference state = obj.children[1];
|
|
|
|
QCOMPARE(state.className, QString("State"));
|
|
|
|
QVERIFY(state.children.count() > 0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference propertyChange = state.children[0];
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!propertyChange.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(propertyChange.debugId != -1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties,"target");
|
|
|
|
QCOMPARE(propertyChangeTarget.objectDebugId, propertyChange.debugId);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference targetReference = qvariant_cast<QmlDebugObjectReference>(propertyChangeTarget.value);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!targetReference.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(targetReference.debugId != -1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// check transition
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference transition = obj.children[0];
|
|
|
|
QCOMPARE(transition.className, QString("Transition"));
|
|
|
|
QCOMPARE(findProperty(transition.properties,"from").value.toString(), QString("*"));
|
|
|
|
QCOMPARE(findProperty(transition.properties,"to").value, findProperty(state.properties,"name").value);
|
|
|
|
QVERIFY(transition.children.count() > 0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugObjectReference animation = transition.children[0];
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!animation.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(animation.debugId != -1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QmlDebugPropertyReference animationTarget = findProperty(animation.properties,"target");
|
|
|
|
QCOMPARE(animationTarget.objectDebugId, animation.debugId);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
targetReference = qvariant_cast<QmlDebugObjectReference>(animationTarget.value);
|
2017-03-15 11:12:22 +00:00
|
|
|
QVERIFY(!targetReference.className.isEmpty());
|
2012-03-06 16:25:58 +00:00
|
|
|
QVERIFY(targetReference.debugId != -1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-03-06 16:25:58 +00:00
|
|
|
QCOMPARE(findProperty(animation.properties,"property").value.toString(), QString("width"));
|
|
|
|
QCOMPARE(findProperty(animation.properties,"duration").value.toInt(), 100);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-01-11 10:44:58 +00:00
|
|
|
void tst_QQmlEngineDebugService::asynchronousCreate() {
|
|
|
|
QmlDebugObjectReference object;
|
|
|
|
auto connection = connect(m_dbg, &QQmlEngineDebugClient::newObject, this, [&](int objectId) {
|
|
|
|
object.debugId = objectId;
|
|
|
|
});
|
|
|
|
|
|
|
|
QByteArray asynchronousComponent = "import QtQuick 2.5\n"
|
|
|
|
"Rectangle { id: asyncRect }";
|
|
|
|
QQmlComponent component(m_engine);
|
|
|
|
component.setData(asynchronousComponent, QUrl::fromLocalFile(""));
|
|
|
|
QVERIFY(component.isReady()); // fails if bad syntax
|
|
|
|
QQmlIncubator incubator(QQmlIncubator::Asynchronous);
|
|
|
|
component.create(incubator);
|
|
|
|
|
|
|
|
QVERIFY(m_dbg->object().idString != QLatin1String("asyncRect"));
|
|
|
|
|
|
|
|
QTRY_VERIFY(object.debugId != -1);
|
|
|
|
disconnect(connection);
|
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
m_dbg->queryObject(object, &success);
|
|
|
|
QVERIFY(success);
|
|
|
|
|
|
|
|
QTRY_COMPARE(m_dbg->object().idString, QLatin1String("asyncRect"));
|
|
|
|
}
|
|
|
|
|
2017-10-23 09:24:16 +00:00
|
|
|
void tst_QQmlEngineDebugService::invalidContexts()
|
|
|
|
{
|
|
|
|
getContexts();
|
|
|
|
const int base = m_dbg->rootContext().contexts.count();
|
|
|
|
QQmlContext context(m_engine);
|
|
|
|
getContexts();
|
|
|
|
QCOMPARE(m_dbg->rootContext().contexts.count(), base + 1);
|
|
|
|
QQmlContextData *contextData = QQmlContextData::get(&context);
|
|
|
|
contextData->invalidate();
|
|
|
|
getContexts();
|
|
|
|
QCOMPARE(m_dbg->rootContext().contexts.count(), base);
|
|
|
|
QQmlContextData *rootData = QQmlContextData::get(m_engine->rootContext());
|
|
|
|
rootData->invalidate();
|
|
|
|
getContexts();
|
|
|
|
QCOMPARE(m_dbg->rootContext().contexts.count(), 0);
|
|
|
|
contextData->setParent(rootData); // makes context valid again, but not root.
|
|
|
|
getContexts();
|
|
|
|
QCOMPARE(m_dbg->rootContext().contexts.count(), 0);
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int _argc = argc + 1;
|
2016-08-02 10:49:06 +00:00
|
|
|
QScopedArrayPointer<char *>_argv(new char*[_argc]);
|
2011-04-27 10:05:43 +00:00
|
|
|
for (int i = 0; i < argc; ++i)
|
|
|
|
_argv[i] = argv[i];
|
2015-08-05 15:27:08 +00:00
|
|
|
char arg[] = "-qmljsdebugger=port:3768,services:QmlDebugger";
|
2011-08-31 07:05:00 +00:00
|
|
|
_argv[_argc - 1] = arg;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2016-08-02 10:49:06 +00:00
|
|
|
QGuiApplication app(_argc, _argv.data());
|
2012-03-06 13:59:29 +00:00
|
|
|
tst_QQmlEngineDebugService tc;
|
2016-08-02 10:49:06 +00:00
|
|
|
return QTest::qExec(&tc, _argc, _argv.data());
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 13:59:29 +00:00
|
|
|
#include "tst_qqmlenginedebugservice.moc"
|