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 | |
44 | class tst_QQmlEngineDebugInspectorIntegration : public QQmlDebugTest |
45 | { |
46 | Q_OBJECT |
47 | |
48 | private: |
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 | |
58 | private 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 | |
68 | QQmlEngineDebugObjectReference 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 | |
88 | QQmlDebugTest::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 | |
96 | QList<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 | |
106 | void 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 | |
113 | void tst_QQmlEngineDebugInspectorIntegration::connect() |
114 | { |
115 | QFETCH(bool, restrictMode); |
116 | QCOMPARE(init(restrictMode), ConnectSuccess); |
117 | } |
118 | |
119 | void 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 | |
145 | void 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 | |
163 | void 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 | |
190 | void 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 | |
215 | void 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 | |
238 | QTEST_MAIN(tst_QQmlEngineDebugInspectorIntegration) |
239 | |
240 | #include "tst_qqmlenginedebuginspectorintegration.moc" |
241 | |