940f89e936eb26ac31f3cbe79002caccabc3099b
[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 <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 #define STR_PORT_FROM "3776"
45 #define STR_PORT_TO "3786"
46
47 class tst_QQmlEngineDebugInspectorIntegration : public QQmlDataTest
48 {
49     Q_OBJECT
50
51 public:
52     tst_QQmlEngineDebugInspectorIntegration()
53         : m_process(0)
54         , m_inspectorClient(0)
55         , m_engineDebugClient(0)
56         , m_recipient(0)
57     {
58     }
59
60
61 private:
62     void init(bool restrictServices);
63     QmlDebugObjectReference findRootObject();
64
65     QQmlDebugProcess *m_process;
66     QQmlInspectorClient *m_inspectorClient;
67     QQmlEngineDebugClient *m_engineDebugClient;
68     QQmlInspectorResultRecipient *m_recipient;
69
70 private slots:
71     void cleanup();
72
73     void connect_data();
74     void connect();
75     void objectLocationLookup();
76     void select();
77     void createObject();
78     void moveObject();
79     void destroyObject();
80 };
81
82 QmlDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRootObject()
83 {
84     bool success = false;
85     m_engineDebugClient->queryAvailableEngines(&success);
86
87     if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
88         return QmlDebugObjectReference();
89
90     m_engineDebugClient->queryRootContexts(m_engineDebugClient->engines()[0].debugId, &success);
91     if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
92         return QmlDebugObjectReference();
93
94     int count = m_engineDebugClient->rootContext().contexts.count();
95     m_engineDebugClient->queryObject(
96                 m_engineDebugClient->rootContext().contexts[count - 1].objects[0], &success);
97     if (!QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())))
98         return QmlDebugObjectReference();
99     return m_engineDebugClient->object();
100 }
101
102 void tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
103 {
104     const QString argument = QString::fromLatin1("-qmljsdebugger=port:%1,%2,block%3")
105             .arg(STR_PORT_FROM).arg(STR_PORT_TO)
106             .arg(restrictServices ? QStringLiteral(",services:QmlDebugger,QmlInspector") :
107                                     QString());
108
109     m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
110                                      this);
111     m_process->start(QStringList() << argument << testFile("qtquick2.qml"));
112     QVERIFY2(m_process->waitForSessionStart(),
113              "Could not launch application, or did not get 'Waiting for connection'.");
114
115     QQmlDebugConnection *m_connection = new QQmlDebugConnection(this);
116     m_inspectorClient = new QQmlInspectorClient(m_connection);
117     m_engineDebugClient = new QQmlEngineDebugClient(m_connection);
118     m_recipient = new QQmlInspectorResultRecipient(this);
119     QObject::connect(m_inspectorClient, &QQmlInspectorClient::responseReceived,
120                      m_recipient, &QQmlInspectorResultRecipient::recordResponse);
121
122     QList<QQmlDebugClient *> others = QQmlDebugTest::createOtherClients(m_connection);
123
124     m_connection->connectToHost(QLatin1String("127.0.0.1"), m_process->debugPort());
125     QVERIFY(m_connection->waitForConnected());
126     foreach (QQmlDebugClient *other, others)
127         QCOMPARE(other->state(), restrictServices ? QQmlDebugClient::Unavailable :
128                                                     QQmlDebugClient::Enabled);
129     qDeleteAll(others);
130
131     QTRY_COMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
132     QTRY_COMPARE(m_engineDebugClient->state(), QQmlDebugClient::Enabled);
133 }
134
135 void tst_QQmlEngineDebugInspectorIntegration::cleanup()
136 {
137     if (QTest::currentTestFailed()) {
138         qDebug() << "Process State:" << m_process->state();
139         qDebug() << "Application Output:" << m_process->output();
140     }
141     delete m_process;
142     m_process = 0;
143     delete m_engineDebugClient;
144     m_engineDebugClient = 0;
145     delete m_inspectorClient;
146     m_inspectorClient = 0;
147     delete m_recipient;
148     m_recipient = 0;
149 }
150
151 void tst_QQmlEngineDebugInspectorIntegration::connect_data()
152 {
153     QTest::addColumn<bool>("restrictMode");
154     QTest::newRow("unrestricted") << false;
155     QTest::newRow("restricted") << true;
156 }
157
158 void tst_QQmlEngineDebugInspectorIntegration::connect()
159 {
160     QFETCH(bool, restrictMode);
161     init(restrictMode);
162 }
163
164 void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
165 {
166     init(true);
167
168     bool success = false;
169     QmlDebugObjectReference rootObject = findRootObject();
170     QVERIFY(rootObject.debugId != -1);
171     const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
172     int lineNumber = rootObject.source.lineNumber;
173     int columnNumber = rootObject.source.columnNumber;
174     m_engineDebugClient->queryObjectsForLocation(fileName, lineNumber,
175                                         columnNumber, &success);
176     QVERIFY(success);
177     QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
178
179     foreach (QmlDebugObjectReference child, rootObject.children) {
180         success = false;
181         lineNumber = child.source.lineNumber;
182         columnNumber = child.source.columnNumber;
183         m_engineDebugClient->queryObjectsForLocation(fileName, lineNumber,
184                                        columnNumber, &success);
185         QVERIFY(success);
186         QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
187     }
188 }
189
190 void tst_QQmlEngineDebugInspectorIntegration::select()
191 {
192     init(true);
193     QmlDebugObjectReference rootObject = findRootObject();
194     QList<int> childIds;
195     int requestId = 0;
196     foreach (const QmlDebugObjectReference &child, rootObject.children) {
197         requestId = m_inspectorClient->select(QList<int>() << child.debugId);
198         QTRY_COMPARE(m_recipient->lastResponseId, requestId);
199         QVERIFY(m_recipient->lastResult);
200         childIds << child.debugId;
201     }
202     requestId = m_inspectorClient->select(childIds);
203     QTRY_COMPARE(m_recipient->lastResponseId, requestId);
204     QVERIFY(m_recipient->lastResult);
205 }
206
207 void tst_QQmlEngineDebugInspectorIntegration::createObject()
208 {
209     init(true);
210
211     QString qml = QLatin1String("Rectangle {\n"
212                                 "  id: xxxyxxx\n"
213                                 "  width: 10\n"
214                                 "  height: 10\n"
215                                 "  color: \"blue\"\n"
216                                 "}");
217
218     QmlDebugObjectReference rootObject = findRootObject();
219     QVERIFY(rootObject.debugId != -1);
220     QCOMPARE(rootObject.children.length(), 2);
221
222     int requestId = m_inspectorClient->createObject(
223                 qml, rootObject.debugId, QStringList() << QLatin1String("import QtQuick 2.0"),
224                 QLatin1String("testcreate.qml"));
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(), 3);
231     QCOMPARE(rootObject.children[2].idString, QLatin1String("xxxyxxx"));
232 }
233
234 void tst_QQmlEngineDebugInspectorIntegration::moveObject()
235 {
236     init(true);
237     QmlDebugObjectReference rootObject = findRootObject();
238     QVERIFY(rootObject.debugId != -1);
239     QCOMPARE(rootObject.children.length(), 2);
240
241     int childId = rootObject.children[0].debugId;
242     int requestId = m_inspectorClient->moveObject(childId, rootObject.children[1].debugId);
243     QTRY_COMPARE(m_recipient->lastResponseId, requestId);
244     QVERIFY(m_recipient->lastResult);
245
246     rootObject = findRootObject();
247     QVERIFY(rootObject.debugId != -1);
248     QCOMPARE(rootObject.children.length(), 1);
249     bool success = false;
250     m_engineDebugClient->queryObject(rootObject.children[0], &success);
251     QVERIFY(success);
252     QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
253     QCOMPARE(m_engineDebugClient->object().children.length(), 1);
254     QCOMPARE(m_engineDebugClient->object().children[0].debugId, childId);
255 }
256
257 void tst_QQmlEngineDebugInspectorIntegration::destroyObject()
258 {
259     init(true);
260     QmlDebugObjectReference rootObject = findRootObject();
261     QVERIFY(rootObject.debugId != -1);
262     QCOMPARE(rootObject.children.length(), 2);
263
264     int requestId = m_inspectorClient->destroyObject(rootObject.children[0].debugId);
265     QTRY_COMPARE(m_recipient->lastResponseId, requestId);
266     QVERIFY(m_recipient->lastResult);
267
268     rootObject = findRootObject();
269     QVERIFY(rootObject.debugId != -1);
270     QCOMPARE(rootObject.children.length(), 1);
271     bool success = false;
272     m_engineDebugClient->queryObject(rootObject.children[0], &success);
273     QVERIFY(success);
274     QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
275     QCOMPARE(m_engineDebugClient->object().children.length(), 0);
276 }
277
278 QTEST_MAIN(tst_QQmlEngineDebugInspectorIntegration)
279
280 #include "tst_qqmlenginedebuginspectorintegration.moc"