aba9eb39ab625d29071d54fee88bb259ec44eafd
[qtdeclarative-opensource-src.git] /
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 "qqmlinspectorclient.h"
30 #include "qqmlenginedebugclient.h"
31 #include "../shared/debugutil_p.h"
32 #include "../../../shared/util.h"
33
34 #include <private/qqmldebugconnection_p.h>
35
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>
44
45 #define STR_PORT_FROM "3776"
46 #define STR_PORT_TO "3786"
47
48 class tst_QQmlEngineDebugInspectorIntegration : public QQmlDataTest
49 {
50     Q_OBJECT
51
52 public:
53     tst_QQmlEngineDebugInspectorIntegration()
54         : m_process(0)
55         , m_inspectorClient(0)
56         , m_engineDebugClient(0)
57         , m_recipient(0)
58     {
59     }
60
61
62 private:
63     void init(bool restrictServices);
64     QmlDebugObjectReference findRootObject();
65
66     QQmlDebugProcess *m_process;
67     QQmlInspectorClient *m_inspectorClient;
68     QQmlEngineDebugClient *m_engineDebugClient;
69     QQmlInspectorResultRecipient *m_recipient;
70
71 private slots:
72     void cleanup();
73
74     void connect_data();
75     void connect();
76     void objectLocationLookup();
77     void select();
78     void createObject();
79     void moveObject();
80     void destroyObject();
81 };
82
83 QmlDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRootObject()
84 {
85     bool success = false;
86     m_engineDebugClient->queryAvailableEngines(&success);
87
88     if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
89         return QmlDebugObjectReference();
90
91     m_engineDebugClient->queryRootContexts(m_engineDebugClient->engines()[0].debugId, &success);
92     if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
93         return QmlDebugObjectReference();
94
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();
101 }
102
103 void tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
104 {
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") :
108                                     QString());
109
110     m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
111                                      this);
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'.");
115
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);
122
123     QList<QQmlDebugClient *> others = QQmlDebugTest::createOtherClients(m_connection);
124
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);
130     qDeleteAll(others);
131
132     QTRY_COMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
133     QTRY_COMPARE(m_engineDebugClient->state(), QQmlDebugClient::Enabled);
134 }
135
136 void tst_QQmlEngineDebugInspectorIntegration::cleanup()
137 {
138     if (QTest::currentTestFailed()) {
139         qDebug() << "Process State:" << m_process->state();
140         qDebug() << "Application Output:" << m_process->output();
141     }
142     delete m_process;
143     m_process = 0;
144     delete m_engineDebugClient;
145     m_engineDebugClient = 0;
146     delete m_inspectorClient;
147     m_inspectorClient = 0;
148     delete m_recipient;
149     m_recipient = 0;
150 }
151
152 void tst_QQmlEngineDebugInspectorIntegration::connect_data()
153 {
154     QTest::addColumn<bool>("restrictMode");
155     QTest::newRow("unrestricted") << false;
156     QTest::newRow("restricted") << true;
157 }
158
159 void tst_QQmlEngineDebugInspectorIntegration::connect()
160 {
161     QFETCH(bool, restrictMode);
162     init(restrictMode);
163 }
164
165 void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
166 {
167     init(true);
168     if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
169         return;
170
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);
179     QVERIFY(success);
180     QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
181
182     foreach (QmlDebugObjectReference child, rootObject.children) {
183         success = false;
184         lineNumber = child.source.lineNumber;
185         columnNumber = child.source.columnNumber;
186         m_engineDebugClient->queryObjectsForLocation(fileName, lineNumber,
187                                        columnNumber, &success);
188         QVERIFY(success);
189         QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
190     }
191 }
192
193 void tst_QQmlEngineDebugInspectorIntegration::select()
194 {
195     init(true);
196     if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
197         return;
198
199     QmlDebugObjectReference rootObject = findRootObject();
200     QList<int> childIds;
201     int requestId = 0;
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;
207     }
208     requestId = m_inspectorClient->select(childIds);
209     QTRY_COMPARE(m_recipient->lastResponseId, requestId);
210     QVERIFY(m_recipient->lastResult);
211 }
212
213 void tst_QQmlEngineDebugInspectorIntegration::createObject()
214 {
215     init(true);
216     if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
217         return;
218
219     QString qml = QLatin1String("Rectangle {\n"
220                                 "  id: xxxyxxx\n"
221                                 "  width: 10\n"
222                                 "  height: 10\n"
223                                 "  color: \"blue\"\n"
224                                 "}");
225
226     QmlDebugObjectReference rootObject = findRootObject();
227     QVERIFY(rootObject.debugId != -1);
228     QCOMPARE(rootObject.children.length(), 2);
229
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);
235
236     rootObject = findRootObject();
237     QVERIFY(rootObject.debugId != -1);
238     QCOMPARE(rootObject.children.length(), 3);
239     QCOMPARE(rootObject.children[2].idString, QLatin1String("xxxyxxx"));
240 }
241
242 void tst_QQmlEngineDebugInspectorIntegration::moveObject()
243 {
244     init(true);
245     if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
246         return;
247
248     QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
249     QmlDebugObjectReference rootObject = findRootObject();
250     QVERIFY(rootObject.debugId != -1);
251     QCOMPARE(rootObject.children.length(), 2);
252
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);
257
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);
263     QVERIFY(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);
267 }
268
269 void tst_QQmlEngineDebugInspectorIntegration::destroyObject()
270 {
271     init(true);
272     if (QTest::currentTestFailed() || QTestResult::skipCurrentTest())
273         return;
274
275     QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
276     QmlDebugObjectReference rootObject = findRootObject();
277     QVERIFY(rootObject.debugId != -1);
278     QCOMPARE(rootObject.children.length(), 2);
279
280     int requestId = m_inspectorClient->destroyObject(rootObject.children[0].debugId);
281     QTRY_COMPARE(m_recipient->lastResponseId, requestId);
282     QVERIFY(m_recipient->lastResult);
283
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);
289     QVERIFY(success);
290     QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
291     QCOMPARE(m_engineDebugClient->object().children.length(), 0);
292 }
293
294 QTEST_MAIN(tst_QQmlEngineDebugInspectorIntegration)
295
296 #include "tst_qqmlenginedebuginspectorintegration.moc"