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 | |
30 | #include "qqmldebugtestservice.h" |
31 | #include "debugutil_p.h" |
32 | #include "qqmldebugprocess_p.h" |
33 | #include "../../../shared/util.h" |
34 | |
35 | #include <private/qqmldebugclient_p.h> |
36 | #include <private/qqmldebugconnection_p.h> |
37 | #include <private/qqmldebugconnector_p.h> |
38 | |
39 | #include <QtTest/qtest.h> |
40 | #include <QtTest/qsignalspy.h> |
41 | #include <QtNetwork/qhostaddress.h> |
42 | #include <QtQml/qqmlengine.h> |
43 | #include <QtCore/qtimer.h> |
44 | #include <QtCore/qdebug.h> |
45 | #include <QtCore/qthread.h> |
46 | #include <QtCore/qlibraryinfo.h> |
47 | |
48 | #define PORT 3769 |
49 | #define STR_PORT "3769" |
50 | |
51 | class tst_QQmlDebugService : public QQmlDataTest |
52 | { |
53 | Q_OBJECT |
54 | private: |
55 | QQmlDebugConnection *m_conn; |
56 | QQmlDebugTestService *m_service; |
57 | |
58 | private slots: |
59 | |
60 | void initTestCase(); |
61 | void checkPortRange(); |
62 | void name(); |
63 | void version(); |
64 | void state(); |
65 | void sendMessage(); |
66 | void idForObject(); |
67 | void objectForId(); |
68 | void checkSupportForDataStreamVersion(); |
69 | void checkSupportForOldDataStreamVersion(); |
70 | }; |
71 | |
72 | void tst_QQmlDebugService::initTestCase() |
73 | { |
74 | QQmlDataTest::initTestCase(); |
75 | QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer" )); |
76 | QQmlDebugConnector::setServices(QStringList() |
77 | << QStringLiteral("tst_QQmlDebugService" )); |
78 | m_service = new QQmlDebugTestService("tst_QQmlDebugService" , 2); |
79 | |
80 | foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices()) |
81 | QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr); |
82 | foreach (const QString &service, QQmlDebuggingEnabler::inspectorServices()) |
83 | QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr); |
84 | foreach (const QString &service, QQmlDebuggingEnabler::profilerServices()) |
85 | QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr); |
86 | |
87 | const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1..." ).arg(PORT); |
88 | QTest::ignoreMessage(type: QtDebugMsg, message: waitingMsg.toLatin1().constData()); |
89 | QQmlDebuggingEnabler::startTcpDebugServer(PORT); |
90 | |
91 | new QQmlEngine(this); |
92 | |
93 | m_conn = new QQmlDebugConnection(this); |
94 | |
95 | for (int i = 0; i < 50; ++i) { |
96 | // try for 5 seconds ... |
97 | m_conn->connectToHost(hostName: "127.0.0.1" , PORT); |
98 | if (m_conn->waitForConnected()) |
99 | break; |
100 | QTest::qSleep(ms: 100); |
101 | } |
102 | QVERIFY(m_conn->isConnected()); |
103 | } |
104 | |
105 | void tst_QQmlDebugService::checkPortRange() |
106 | { |
107 | QScopedPointer<QQmlDebugConnection> connection1(new QQmlDebugConnection()); |
108 | QScopedPointer<QQmlDebugProcess> process1( |
109 | new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) |
110 | + "/qmlscene" , this)); |
111 | |
112 | process1->start(arguments: QStringList() << QLatin1String("-qmljsdebugger=port:3782,3792" ) |
113 | << testFile(fileName: "test.qml" )); |
114 | |
115 | if (!process1->waitForSessionStart()) |
116 | QFAIL("could not launch application, or did not get 'Waiting for connection'." ); |
117 | |
118 | const int port1 = process1->debugPort(); |
119 | connection1->connectToHost(hostName: "127.0.0.1" , port: port1); |
120 | if (!connection1->waitForConnected()) |
121 | QFAIL("could not connect to host!" ); |
122 | |
123 | // Second instance |
124 | QScopedPointer<QQmlDebugConnection> connection2(new QQmlDebugConnection()); |
125 | QScopedPointer<QQmlDebugProcess> process2( |
126 | new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) |
127 | + "/qmlscene" , this)); |
128 | |
129 | process2->start(arguments: QStringList() << QLatin1String("-qmljsdebugger=port:3782,3792" ) |
130 | << testFile(fileName: "test.qml" )); |
131 | |
132 | if (!process2->waitForSessionStart()) |
133 | QFAIL("could not launch application, or did not get 'Waiting for connection'." ); |
134 | |
135 | const int port2 = process2->debugPort(); |
136 | connection2->connectToHost(hostName: "127.0.0.1" , port: port2); |
137 | if (!connection2->waitForConnected()) |
138 | QFAIL("could not connect to host!" ); |
139 | } |
140 | |
141 | void tst_QQmlDebugService::name() |
142 | { |
143 | QCOMPARE(m_service->name(), QLatin1String("tst_QQmlDebugService" )); |
144 | } |
145 | |
146 | void tst_QQmlDebugService::version() |
147 | { |
148 | QCOMPARE(m_service->version(), 2.0f); |
149 | } |
150 | |
151 | void tst_QQmlDebugService::state() |
152 | { |
153 | QCOMPARE(m_service->state(), QQmlDebugService::Unavailable); |
154 | |
155 | { |
156 | QQmlDebugTestClient client("tst_QQmlDebugService" , m_conn); |
157 | QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled); |
158 | QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled); |
159 | } |
160 | |
161 | QTRY_COMPARE(m_service->state(), QQmlDebugService::Unavailable); |
162 | |
163 | // We can do this because it will never addService() |
164 | QTest::ignoreMessage(type: QtWarningMsg, |
165 | message: "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService\"" ); |
166 | QQmlDebugTestService duplicate("tst_QQmlDebugService" ); |
167 | QCOMPARE(duplicate.state(), QQmlDebugService::NotConnected); |
168 | QTest::ignoreMessage(type: QtWarningMsg, |
169 | message: "QQmlDebugService: Plugin \"tst_QQmlDebugService\" is not registered." ); |
170 | } |
171 | |
172 | void tst_QQmlDebugService::sendMessage() |
173 | { |
174 | QQmlDebugTestClient client("tst_QQmlDebugService" , m_conn); |
175 | |
176 | QByteArray msg = "hello!" ; |
177 | |
178 | QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled); |
179 | QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled); |
180 | |
181 | client.sendMessage(message: msg); |
182 | QByteArray resp = client.waitForResponse(); |
183 | QCOMPARE(resp, msg); |
184 | |
185 | QTest::ignoreMessage(type: QtWarningMsg, |
186 | message: "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService\"" ); |
187 | QQmlDebugTestService duplicate("tst_QQmlDebugService" ); |
188 | emit duplicate.messageToClient(name: duplicate.name(), message: "msg" ); |
189 | QTest::ignoreMessage(type: QtWarningMsg, |
190 | message: "QQmlDebugService: Plugin \"tst_QQmlDebugService\" is not registered." ); |
191 | } |
192 | |
193 | void tst_QQmlDebugService::checkSupportForDataStreamVersion() |
194 | { |
195 | QQmlDebugTestClient client("tst_QQmlDebugService" , m_conn); |
196 | |
197 | QByteArray msg = "hello!" ; |
198 | |
199 | QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled); |
200 | QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled); |
201 | |
202 | client.sendMessage(message: msg); |
203 | QByteArray resp = client.waitForResponse(); |
204 | QCOMPARE(resp, msg); |
205 | QCOMPARE(m_conn->currentDataStreamVersion(), int(QDataStream::Qt_DefaultCompiledVersion)); |
206 | } |
207 | |
208 | void tst_QQmlDebugService::idForObject() |
209 | { |
210 | QCOMPARE(QQmlDebugService::idForObject(nullptr), -1); |
211 | |
212 | QObject *objA = new QObject; |
213 | |
214 | int idA = QQmlDebugService::idForObject(objA); |
215 | QVERIFY(idA >= 0); |
216 | QCOMPARE(QQmlDebugService::objectForId(idA), objA); |
217 | |
218 | int idAA = QQmlDebugService::idForObject(objA); |
219 | QCOMPARE(idAA, idA); |
220 | |
221 | QObject *objB = new QObject; |
222 | int idB = QQmlDebugService::idForObject(objB); |
223 | QVERIFY(idB != idA); |
224 | QCOMPARE(QQmlDebugService::objectForId(idB), objB); |
225 | |
226 | delete objA; |
227 | delete objB; |
228 | } |
229 | |
230 | void tst_QQmlDebugService::objectForId() |
231 | { |
232 | QCOMPARE(QQmlDebugService::objectForId(-1), static_cast<QObject*>(nullptr)); |
233 | QCOMPARE(QQmlDebugService::objectForId(1), static_cast<QObject*>(nullptr)); |
234 | |
235 | QObject *obj = new QObject; |
236 | int id = QQmlDebugService::idForObject(obj); |
237 | QCOMPARE(QQmlDebugService::objectForId(id), obj); |
238 | |
239 | delete obj; |
240 | QCOMPARE(QQmlDebugService::objectForId(id), static_cast<QObject*>(nullptr)); |
241 | } |
242 | |
243 | void tst_QQmlDebugService::checkSupportForOldDataStreamVersion() |
244 | { |
245 | //create a new connection; |
246 | delete m_conn; |
247 | m_conn = new QQmlDebugConnection(this); |
248 | m_conn->setMaximumDataStreamVersion(QDataStream::Qt_5_0); |
249 | for (int i = 0; i < 50; ++i) { |
250 | // try for 5 seconds ... |
251 | m_conn->connectToHost(hostName: "127.0.0.1" , PORT); |
252 | if (m_conn->waitForConnected()) |
253 | break; |
254 | QTest::qSleep(ms: 100); |
255 | } |
256 | QVERIFY(m_conn->isConnected()); |
257 | |
258 | QQmlDebugTestClient client("tst_QQmlDebugService" , m_conn); |
259 | |
260 | QByteArray msg = "hello!" ; |
261 | |
262 | QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled); |
263 | QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled); |
264 | |
265 | client.sendMessage(message: msg); |
266 | QByteArray resp = client.waitForResponse(); |
267 | QCOMPARE(resp, msg); |
268 | QCOMPARE(m_conn->currentDataStreamVersion(), int(QDataStream::Qt_5_0)); |
269 | } |
270 | |
271 | QTEST_MAIN(tst_QQmlDebugService) |
272 | |
273 | #include "tst_qqmldebugservice.moc" |
274 | |