1 /****************************************************************************
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
27 ****************************************************************************/
29 #include "qqmlinspectorclient.h"
30 #include "qqmlenginedebugclient.h"
31 #include "../shared/debugutil_p.h"
32 #include "../../../shared/util.h"
34 #include <private/qqmldebugconnection_p.h>
36 #include <QtTest/qtest.h>
37 #include <private/qtestresult_p.h>
38 #include <QtTest/qsignalspy.h>
39 #include <QtNetwork/qhostaddress.h>
40 #include <QtCore/qtimer.h>
41 #include <QtCore/qdebug.h>
42 #include <QtCore/qthread.h>
43 #include <QtCore/qlibraryinfo.h>
45 #define STR_PORT_FROM "3776"
46 #define STR_PORT_TO "3786"
48 class tst_QQmlEngineDebugInspectorIntegration : public QQmlDataTest
53 tst_QQmlEngineDebugInspectorIntegration()
55 , m_inspectorClient(0)
56 , m_engineDebugClient(0)
63 void init(bool restrictServices);
64 QmlDebugObjectReference findRootObject();
66 QQmlDebugProcess *m_process;
67 QQmlInspectorClient *m_inspectorClient;
68 QQmlEngineDebugClient *m_engineDebugClient;
69 QQmlInspectorResultRecipient *m_recipient;
76 void objectLocationLookup();
83 QmlDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRootObject()
86 m_engineDebugClient->queryAvailableEngines(&success);
88 if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
89 return QmlDebugObjectReference();
91 m_engineDebugClient->queryRootContexts(m_engineDebugClient->engines()[0].debugId, &success);
92 if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
93 return QmlDebugObjectReference();
95 int count = m_engineDebugClient->rootContext().contexts.count();
96 m_engineDebugClient->queryObject(
97 m_engineDebugClient->rootContext().contexts[count - 1].objects[0], &success);
98 if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
99 return QmlDebugObjectReference();
100 return m_engineDebugClient->object();
103 void tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
105 const QString argument = QString::fromLatin1("-qmljsdebugger=port:%1,%2,block%3")
106 .arg(STR_PORT_FROM).arg(STR_PORT_TO)
107 .arg(restrictServices ? QStringLiteral(",services:QmlDebugger,QmlInspector") :
110 m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
112 m_process->start(QStringList() << argument << testFile("qtquick2.qml"));
113 QVERIFY2(m_process->waitForSessionStart(),
114 "Could not launch application, or did not get 'Waiting for connection'.");
116 QQmlDebugConnection *m_connection = new QQmlDebugConnection(this);
117 m_inspectorClient = new QQmlInspectorClient(m_connection);
118 m_engineDebugClient = new QQmlEngineDebugClient(m_connection);
119 m_recipient = new QQmlInspectorResultRecipient(this);
120 QObject::connect(m_inspectorClient, &QQmlInspectorClient::responseReceived,
121 m_recipient, &QQmlInspectorResultRecipient::recordResponse);
123 QList<QQmlDebugClient *> others = QQmlDebugTest::createOtherClients(m_connection);
125 m_connection->connectToHost(QLatin1String("127.0.0.1"), m_process->debugPort());
126 QVERIFY(m_connection->waitForConnected());
127 foreach (QQmlDebugClient *other, others)
128 QCOMPARE(other->state(), restrictServices ? QQmlDebugClient::Unavailable :
129 QQmlDebugClient::Enabled);
132 QTRY_COMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
133 QTRY_COMPARE(m_engineDebugClient->state(), QQmlDebugClient::Enabled);
136 void tst_QQmlEngineDebugInspectorIntegration::cleanup()
138 if (QTest::currentTestFailed()) {
139 qDebug() << "Process State:" << m_process->state();
140 qDebug() << "Application Output:" << m_process->output();
144 delete m_engineDebugClient;
145 m_engineDebugClient = 0;
146 delete m_inspectorClient;
147 m_inspectorClient = 0;
152 void tst_QQmlEngineDebugInspectorIntegration::connect_data()
154 QTest::addColumn<bool>("restrictMode");
155 QTest::newRow("unrestricted") << false;
156 QTest::newRow("restricted") << true;
159 void tst_QQmlEngineDebugInspectorIntegration::connect()
161 QFETCH(bool, restrictMode);
165 void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
168 if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
171 bool success = false;
172 QmlDebugObjectReference rootObject = findRootObject();
173 QVERIFY(rootObject.debugId != -1);
174 const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
175 int lineNumber = rootObject.source.lineNumber;
176 int columnNumber = rootObject.source.columnNumber;
177 m_engineDebugClient->queryObjectsForLocation(fileName, lineNumber,
178 columnNumber, &success);
180 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
182 foreach (QmlDebugObjectReference child, rootObject.children) {
184 lineNumber = child.source.lineNumber;
185 columnNumber = child.source.columnNumber;
186 m_engineDebugClient->queryObjectsForLocation(fileName, lineNumber,
187 columnNumber, &success);
189 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
193 void tst_QQmlEngineDebugInspectorIntegration::select()
196 if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
199 QmlDebugObjectReference rootObject = findRootObject();
202 foreach (const QmlDebugObjectReference &child, rootObject.children) {
203 requestId = m_inspectorClient->select(QList<int>() << child.debugId);
204 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
205 QVERIFY(m_recipient->lastResult);
206 childIds << child.debugId;
208 requestId = m_inspectorClient->select(childIds);
209 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
210 QVERIFY(m_recipient->lastResult);
213 void tst_QQmlEngineDebugInspectorIntegration::createObject()
216 if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
219 QString qml = QLatin1String("Rectangle {\n"
226 QmlDebugObjectReference rootObject = findRootObject();
227 QVERIFY(rootObject.debugId != -1);
228 QCOMPARE(rootObject.children.length(), 2);
230 int requestId = m_inspectorClient->createObject(
231 qml, rootObject.debugId, QStringList() << QLatin1String("import QtQuick 2.0"),
232 QLatin1String("testcreate.qml"));
233 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
234 QVERIFY(m_recipient->lastResult);
236 rootObject = findRootObject();
237 QVERIFY(rootObject.debugId != -1);
238 QCOMPARE(rootObject.children.length(), 3);
239 QCOMPARE(rootObject.children[2].idString, QLatin1String("xxxyxxx"));
242 void tst_QQmlEngineDebugInspectorIntegration::moveObject()
245 if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
248 QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
249 QmlDebugObjectReference rootObject = findRootObject();
250 QVERIFY(rootObject.debugId != -1);
251 QCOMPARE(rootObject.children.length(), 2);
253 int childId = rootObject.children[0].debugId;
254 int requestId = m_inspectorClient->moveObject(childId, rootObject.children[1].debugId);
255 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
256 QVERIFY(m_recipient->lastResult);
258 rootObject = findRootObject();
259 QVERIFY(rootObject.debugId != -1);
260 QCOMPARE(rootObject.children.length(), 1);
261 bool success = false;
262 m_engineDebugClient->queryObject(rootObject.children[0], &success);
264 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
265 QCOMPARE(m_engineDebugClient->object().children.length(), 1);
266 QCOMPARE(m_engineDebugClient->object().children[0].debugId, childId);
269 void tst_QQmlEngineDebugInspectorIntegration::destroyObject()
272 if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
275 QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
276 QmlDebugObjectReference rootObject = findRootObject();
277 QVERIFY(rootObject.debugId != -1);
278 QCOMPARE(rootObject.children.length(), 2);
280 int requestId = m_inspectorClient->destroyObject(rootObject.children[0].debugId);
281 QTRY_COMPARE(m_recipient->lastResponseId, requestId);
282 QVERIFY(m_recipient->lastResult);
284 rootObject = findRootObject();
285 QVERIFY(rootObject.debugId != -1);
286 QCOMPARE(rootObject.children.length(), 1);
287 bool success = false;
288 m_engineDebugClient->queryObject(rootObject.children[0], &success);
290 QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
291 QCOMPARE(m_engineDebugClient->object().children.length(), 0);
294 QTEST_MAIN(tst_QQmlEngineDebugInspectorIntegration)
296 #include "tst_qqmlenginedebuginspectorintegration.moc"