1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "../shared/debugutil_p.h"
30#include "../../../shared/util.h"
31
32#include <private/qqmldebugconnection_p.h>
33#include <private/qqmlenginedebugclient_p.h>
34#include <private/qqmlinspectorclient_p.h>
35
36#include <QtTest/qtest.h>
37#include <QtTest/qsignalspy.h>
38#include <QtNetwork/qhostaddress.h>
39#include <QtCore/qtimer.h>
40#include <QtCore/qdebug.h>
41#include <QtCore/qthread.h>
42#include <QtCore/qlibraryinfo.h>
43
44class tst_QQmlEngineDebugInspectorIntegration : public QQmlDebugTest
45{
46 Q_OBJECT
47
48private:
49 ConnectResult init(bool restrictServices);
50 QList<QQmlDebugClient *> createClients() override;
51
52 QQmlEngineDebugObjectReference findRootObject();
53
54 QPointer<QQmlInspectorClient> m_inspectorClient;
55 QPointer<QQmlEngineDebugClient> m_engineDebugClient;
56 QPointer<QQmlInspectorResultRecipient> m_recipient;
57
58private slots:
59 void connect_data();
60 void connect();
61 void objectLocationLookup();
62 void select();
63 void createObject();
64 void moveObject();
65 void destroyObject();
66};
67
68QQmlEngineDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRootObject()
69{
70 bool success = false;
71 m_engineDebugClient->queryAvailableEngines(success: &success);
72
73 if (!QQmlDebugTest::waitForSignal(receiver: m_engineDebugClient, SIGNAL(result())))
74 return QQmlEngineDebugObjectReference();
75
76 m_engineDebugClient->queryRootContexts(m_engineDebugClient->engines()[0], success: &success);
77 if (!QQmlDebugTest::waitForSignal(receiver: m_engineDebugClient, SIGNAL(result())))
78 return QQmlEngineDebugObjectReference();
79
80 int count = m_engineDebugClient->rootContext().contexts.count();
81 m_engineDebugClient->queryObject(
82 m_engineDebugClient->rootContext().contexts[count - 1].objects[0], success: &success);
83 if (!QQmlDebugTest::waitForSignal(receiver: m_engineDebugClient, SIGNAL(result())))
84 return QQmlEngineDebugObjectReference();
85 return m_engineDebugClient->object();
86}
87
88QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
89{
90 return QQmlDebugTest::connectTo(
91 executable: QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
92 services: restrictServices ? QStringLiteral("QmlDebugger,QmlInspector") : QString(),
93 extraArgs: testFile(fileName: "qtquick2.qml"), block: true);
94}
95
96QList<QQmlDebugClient *> tst_QQmlEngineDebugInspectorIntegration::createClients()
97{
98 m_inspectorClient = new QQmlInspectorClient(m_connection);
99 m_engineDebugClient = new QQmlEngineDebugClient(m_connection);
100 m_recipient = new QQmlInspectorResultRecipient(m_inspectorClient);
101 QObject::connect(sender: m_inspectorClient.data(), signal: &QQmlInspectorClient::responseReceived,
102 receiver: m_recipient.data(), slot: &QQmlInspectorResultRecipient::recordResponse);
103 return QList<QQmlDebugClient *>({m_inspectorClient, m_engineDebugClient});
104}
105
106void tst_QQmlEngineDebugInspectorIntegration::connect_data()
107{
108 QTest::addColumn<bool>(name: "restrictMode");
109 QTest::newRow(dataTag: "unrestricted") << false;
110 QTest::newRow(dataTag: "restricted") << true;
111}
112
113void tst_QQmlEngineDebugInspectorIntegration::connect()
114{
115 QFETCH(bool, restrictMode);
116 QCOMPARE(init(restrictMode), ConnectSuccess);
117}
118
119void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
120{
121 QCOMPARE(init(true), ConnectSuccess);
122
123 bool success = false;
124 QQmlEngineDebugObjectReference rootObject = findRootObject();
125 QVERIFY(rootObject.debugId != -1);
126 const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
127 int lineNumber = rootObject.source.lineNumber;
128 int columnNumber = rootObject.source.columnNumber;
129 m_engineDebugClient->queryObjectsForLocation(file: fileName, lineNumber,
130 columnNumber, success: &success);
131 QVERIFY(success);
132 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
133
134 foreach (QQmlEngineDebugObjectReference child, rootObject.children) {
135 success = false;
136 lineNumber = child.source.lineNumber;
137 columnNumber = child.source.columnNumber;
138 m_engineDebugClient->queryObjectsForLocation(file: fileName, lineNumber,
139 columnNumber, success: &success);
140 QVERIFY(success);
141 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
142 }
143}
144
145void tst_QQmlEngineDebugInspectorIntegration::select()
146{
147 QCOMPARE(init(true), ConnectSuccess);
148
149 QQmlEngineDebugObjectReference rootObject = findRootObject();
150 QList<int> childIds;
151 int requestId = 0;
152 foreach (const QQmlEngineDebugObjectReference &child, rootObject.children) {
153 requestId = m_inspectorClient->select(objectIds: QList<int>() << child.debugId);
154 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
155 QVERIFY(m_recipient->lastResult);
156 childIds << child.debugId;
157 }
158 requestId = m_inspectorClient->select(objectIds: childIds);
159 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
160 QVERIFY(m_recipient->lastResult);
161}
162
163void tst_QQmlEngineDebugInspectorIntegration::createObject()
164{
165 QCOMPARE(init(true), ConnectSuccess);
166
167 QString qml = QLatin1String("Rectangle {\n"
168 " id: xxxyxxx\n"
169 " width: 10\n"
170 " height: 10\n"
171 " color: \"blue\"\n"
172 "}");
173
174 QQmlEngineDebugObjectReference rootObject = findRootObject();
175 QVERIFY(rootObject.debugId != -1);
176 QCOMPARE(rootObject.children.length(), 2);
177
178 int requestId = m_inspectorClient->createObject(
179 qml, parentId: rootObject.debugId, imports: QStringList() << QLatin1String("import QtQuick 2.0"),
180 filename: QLatin1String("testcreate.qml"));
181 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
182 QVERIFY(m_recipient->lastResult);
183
184 rootObject = findRootObject();
185 QVERIFY(rootObject.debugId != -1);
186 QCOMPARE(rootObject.children.length(), 3);
187 QCOMPARE(rootObject.children[2].idString, QLatin1String("xxxyxxx"));
188}
189
190void tst_QQmlEngineDebugInspectorIntegration::moveObject()
191{
192 QCOMPARE(init(true), ConnectSuccess);
193
194 QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
195 QQmlEngineDebugObjectReference rootObject = findRootObject();
196 QVERIFY(rootObject.debugId != -1);
197 QCOMPARE(rootObject.children.length(), 2);
198
199 int childId = rootObject.children[0].debugId;
200 int requestId = m_inspectorClient->moveObject(childId, newParentId: rootObject.children[1].debugId);
201 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
202 QVERIFY(m_recipient->lastResult);
203
204 rootObject = findRootObject();
205 QVERIFY(rootObject.debugId != -1);
206 QCOMPARE(rootObject.children.length(), 1);
207 bool success = false;
208 m_engineDebugClient->queryObject(rootObject.children[0], success: &success);
209 QVERIFY(success);
210 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
211 QCOMPARE(m_engineDebugClient->object().children.length(), 1);
212 QCOMPARE(m_engineDebugClient->object().children[0].debugId, childId);
213}
214
215void tst_QQmlEngineDebugInspectorIntegration::destroyObject()
216{
217 QCOMPARE(init(true), ConnectSuccess);
218
219 QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
220 QQmlEngineDebugObjectReference rootObject = findRootObject();
221 QVERIFY(rootObject.debugId != -1);
222 QCOMPARE(rootObject.children.length(), 2);
223
224 int requestId = m_inspectorClient->destroyObject(objectId: rootObject.children[0].debugId);
225 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
226 QVERIFY(m_recipient->lastResult);
227
228 rootObject = findRootObject();
229 QVERIFY(rootObject.debugId != -1);
230 QCOMPARE(rootObject.children.length(), 1);
231 bool success = false;
232 m_engineDebugClient->queryObject(rootObject.children[0], success: &success);
233 QVERIFY(success);
234 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
235 QCOMPARE(m_engineDebugClient->object().children.length(), 0);
236}
237
238QTEST_MAIN(tst_QQmlEngineDebugInspectorIntegration)
239
240#include "tst_qqmlenginedebuginspectorintegration.moc"
241

source code of qtdeclarative/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp