packaging: devel subpackage take imports too
[contrib/qtwebsockets.git] / tests / auto / qwebsocket / tst_qwebsocket.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Kurt Pattyn <pattyn.kurt@gmail.com>.
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** In addition, as a special exception, Digia gives you certain additional
27 ** rights. These rights are described in the Digia Qt LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33 #include <QString>
34 #include <QtTest>
35 #include <QtWebSockets/QWebSocket>
36 #include <QtWebSockets/QWebSocketServer>
37 #include <QtWebSockets/qwebsocketprotocol.h>
38
39 QT_USE_NAMESPACE
40
41 Q_DECLARE_METATYPE(QWebSocketProtocol::Version)
42
43 class EchoServer : public QObject
44 {
45     Q_OBJECT
46 public:
47     explicit EchoServer(QObject *parent = Q_NULLPTR);
48     ~EchoServer();
49
50     QHostAddress hostAddress() const { return m_pWebSocketServer->serverAddress(); }
51     quint16 port() const { return m_pWebSocketServer->serverPort(); }
52
53 Q_SIGNALS:
54     void closed();
55
56 private Q_SLOTS:
57     void onNewConnection();
58     void processTextMessage(QString message);
59     void processBinaryMessage(QByteArray message);
60     void socketDisconnected();
61
62 private:
63     QWebSocketServer *m_pWebSocketServer;
64     QList<QWebSocket *> m_clients;
65 };
66
67 EchoServer::EchoServer(QObject *parent) :
68     QObject(parent),
69     m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"),
70                                             QWebSocketServer::NonSecureMode, this)),
71     m_clients()
72 {
73     if (m_pWebSocketServer->listen()) {
74         connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
75                 this, &EchoServer::onNewConnection);
76         connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed);
77     }
78 }
79
80 EchoServer::~EchoServer()
81 {
82     m_pWebSocketServer->close();
83     qDeleteAll(m_clients.begin(), m_clients.end());
84 }
85
86 void EchoServer::onNewConnection()
87 {
88     QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
89
90     connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage);
91     connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage);
92     connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected);
93
94     m_clients << pSocket;
95 }
96
97 void EchoServer::processTextMessage(QString message)
98 {
99     QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
100     if (pClient) {
101         pClient->sendTextMessage(message);
102     }
103 }
104
105 void EchoServer::processBinaryMessage(QByteArray message)
106 {
107     QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
108     if (pClient) {
109         pClient->sendBinaryMessage(message);
110     }
111 }
112
113 void EchoServer::socketDisconnected()
114 {
115     QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
116     if (pClient) {
117         m_clients.removeAll(pClient);
118         pClient->deleteLater();
119     }
120 }
121
122 class tst_QWebSocket : public QObject
123 {
124     Q_OBJECT
125
126 public:
127     tst_QWebSocket();
128
129 private Q_SLOTS:
130     void init();
131     void initTestCase();
132     void cleanupTestCase();
133     void tst_initialisation_data();
134     void tst_initialisation();
135     void tst_settersAndGetters();
136     void tst_invalidOpen_data();
137     void tst_invalidOpen();
138     void tst_invalidOrigin();
139     void tst_sendTextMessage();
140     void tst_sendBinaryMessage();
141     void tst_errorString();
142 #ifndef QT_NO_NETWORKPROXY
143     void tst_setProxy();
144 #endif
145 };
146
147 tst_QWebSocket::tst_QWebSocket()
148 {
149 }
150
151 void tst_QWebSocket::init()
152 {
153     qRegisterMetaType<QWebSocketProtocol::Version>("QWebSocketProtocol::Version");
154 }
155
156 void tst_QWebSocket::initTestCase()
157 {
158 }
159
160 void tst_QWebSocket::cleanupTestCase()
161 {
162 }
163
164 void tst_QWebSocket::tst_initialisation_data()
165 {
166     QTest::addColumn<QString>("origin");
167     QTest::addColumn<QString>("expectedOrigin");
168     QTest::addColumn<QWebSocketProtocol::Version>("version");
169     QTest::addColumn<QWebSocketProtocol::Version>("expectedVersion");
170
171     QTest::newRow("Default origin and version")
172             << QString() << QString()
173             << QWebSocketProtocol::VersionUnknown << QWebSocketProtocol::VersionLatest;
174     QTest::newRow("Specific origin and default version")
175             << QStringLiteral("qt-project.org") << QStringLiteral("qt-project.org")
176             << QWebSocketProtocol::VersionUnknown << QWebSocketProtocol::VersionLatest;
177     QTest::newRow("Specific origin and specific version")
178             << QStringLiteral("qt-project.org") << QStringLiteral("qt-project.org")
179             << QWebSocketProtocol::Version7 << QWebSocketProtocol::Version7;
180 }
181
182 void tst_QWebSocket::tst_initialisation()
183 {
184     QFETCH(QString, origin);
185     QFETCH(QString, expectedOrigin);
186     QFETCH(QWebSocketProtocol::Version, version);
187     QFETCH(QWebSocketProtocol::Version, expectedVersion);
188
189     QScopedPointer<QWebSocket> socket;
190
191     if (origin.isEmpty() && (version == QWebSocketProtocol::VersionUnknown))
192         socket.reset(new QWebSocket);
193     else if (!origin.isEmpty() && (version == QWebSocketProtocol::VersionUnknown))
194         socket.reset(new QWebSocket(origin));
195     else
196         socket.reset(new QWebSocket(origin, version));
197
198     QCOMPARE(socket->origin(), expectedOrigin);
199     QCOMPARE(socket->version(), expectedVersion);
200     QCOMPARE(socket->error(), QAbstractSocket::UnknownSocketError);
201     QVERIFY(socket->errorString().isEmpty());
202     QVERIFY(!socket->isValid());
203     QVERIFY(socket->localAddress().isNull());
204     QCOMPARE(socket->localPort(), quint16(0));
205     QCOMPARE(socket->pauseMode(), QAbstractSocket::PauseNever);
206     QVERIFY(socket->peerAddress().isNull());
207     QCOMPARE(socket->peerPort(), quint16(0));
208     QVERIFY(socket->peerName().isEmpty());
209     QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
210     QCOMPARE(socket->readBufferSize(), 0);
211     QVERIFY(socket->resourceName().isEmpty());
212     QVERIFY(!socket->requestUrl().isValid());
213     QCOMPARE(socket->closeCode(), QWebSocketProtocol::CloseCodeNormal);
214     QVERIFY(socket->closeReason().isEmpty());
215     QVERIFY(socket->flush());
216     QCOMPARE(socket->sendTextMessage(QStringLiteral("A text message")), 0);
217     QCOMPARE(socket->sendBinaryMessage(QByteArrayLiteral("A binary message")), 0);
218 }
219
220 void tst_QWebSocket::tst_settersAndGetters()
221 {
222     QWebSocket socket;
223
224     socket.setPauseMode(QAbstractSocket::PauseNever);
225     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseNever);
226     socket.setPauseMode(QAbstractSocket::PauseOnSslErrors);
227     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseOnSslErrors);
228
229     socket.setReadBufferSize(0);
230     QCOMPARE(socket.readBufferSize(), 0);
231     socket.setReadBufferSize(128);
232     QCOMPARE(socket.readBufferSize(), 128);
233     socket.setReadBufferSize(-1);
234     QCOMPARE(socket.readBufferSize(), -1);
235 }
236
237 void tst_QWebSocket::tst_invalidOpen_data()
238 {
239     QTest::addColumn<QString>("url");
240     QTest::addColumn<QString>("expectedUrl");
241     QTest::addColumn<QString>("expectedPeerName");
242     QTest::addColumn<QString>("expectedResourceName");
243     QTest::addColumn<QAbstractSocket::SocketState>("stateAfterOpenCall");
244     QTest::addColumn<int>("disconnectedCount");
245     QTest::addColumn<int>("stateChangedCount");
246
247     QTest::newRow("Illegal local address")
248             << QStringLiteral("ws://127.0.0.1:1/") << QStringLiteral("ws://127.0.0.1:1/")
249             << QStringLiteral("127.0.0.1")
250             << QStringLiteral("/") << QAbstractSocket::ConnectingState
251             << 1
252             << 2;  //going from connecting to disconnected
253     QTest::newRow("URL containing new line in the hostname")
254             << QStringLiteral("ws://myhacky\r\nserver/") << QString()
255             << QString()
256             << QString() << QAbstractSocket::UnconnectedState
257             << 0 << 0;
258     QTest::newRow("URL containing new line in the resource name")
259             << QStringLiteral("ws://127.0.0.1:1/tricky\r\npath") << QString()
260             << QString()
261             << QString()
262             << QAbstractSocket::UnconnectedState
263             << 0 << 0;
264 }
265
266 void tst_QWebSocket::tst_invalidOpen()
267 {
268     QFETCH(QString, url);
269     QFETCH(QString, expectedUrl);
270     QFETCH(QString, expectedPeerName);
271     QFETCH(QString, expectedResourceName);
272     QFETCH(QAbstractSocket::SocketState, stateAfterOpenCall);
273     QFETCH(int, disconnectedCount);
274     QFETCH(int, stateChangedCount);
275     QWebSocket socket;
276     QSignalSpy errorSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
277     QSignalSpy aboutToCloseSpy(&socket, SIGNAL(aboutToClose()));
278     QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
279     QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
280     QSignalSpy stateChangedSpy(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
281     QSignalSpy readChannelFinishedSpy(&socket, SIGNAL(readChannelFinished()));
282     QSignalSpy textFrameReceivedSpy(&socket, SIGNAL(textFrameReceived(QString,bool)));
283     QSignalSpy binaryFrameReceivedSpy(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
284     QSignalSpy textMessageReceivedSpy(&socket, SIGNAL(textMessageReceived(QString)));
285     QSignalSpy binaryMessageReceivedSpy(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
286     QSignalSpy pongSpy(&socket, SIGNAL(pong(quint64,QByteArray)));
287     QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64)));
288
289     socket.open(QUrl(url));
290
291     QVERIFY(socket.origin().isEmpty());
292     QCOMPARE(socket.version(), QWebSocketProtocol::VersionLatest);
293     //at this point the socket is in a connecting state
294     //so, there should no error at this point
295     QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
296     QVERIFY(!socket.errorString().isEmpty());
297     QVERIFY(!socket.isValid());
298     QVERIFY(socket.localAddress().isNull());
299     QCOMPARE(socket.localPort(), quint16(0));
300     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseNever);
301     QVERIFY(socket.peerAddress().isNull());
302     QCOMPARE(socket.peerPort(), quint16(0));
303     QCOMPARE(socket.peerName(), expectedPeerName);
304     QCOMPARE(socket.state(), stateAfterOpenCall);
305     QCOMPARE(socket.readBufferSize(), 0);
306     QCOMPARE(socket.resourceName(), expectedResourceName);
307     QCOMPARE(socket.requestUrl().toString(), expectedUrl);
308     QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeNormal);
309     QVERIFY(socket.closeReason().isEmpty());
310     QCOMPARE(socket.sendTextMessage(QStringLiteral("A text message")), 0);
311     QCOMPARE(socket.sendBinaryMessage(QByteArrayLiteral("A text message")), 0);
312
313     if (errorSpy.count() == 0)
314         QVERIFY(errorSpy.wait());
315     QCOMPARE(errorSpy.count(), 1);
316     QList<QVariant> arguments = errorSpy.takeFirst();
317     QAbstractSocket::SocketError socketError =
318             qvariant_cast<QAbstractSocket::SocketError>(arguments.at(0));
319     QCOMPARE(socketError, QAbstractSocket::ConnectionRefusedError);
320     QCOMPARE(aboutToCloseSpy.count(), 0);
321     QCOMPARE(connectedSpy.count(), 0);
322     QCOMPARE(disconnectedSpy.count(), disconnectedCount);
323     QCOMPARE(stateChangedSpy.count(), stateChangedCount);
324     if (stateChangedCount == 2) {
325         arguments = stateChangedSpy.takeFirst();
326         QAbstractSocket::SocketState socketState =
327                 qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
328         arguments = stateChangedSpy.takeFirst();
329         socketState = qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
330         QCOMPARE(socketState, QAbstractSocket::UnconnectedState);
331     }
332     QCOMPARE(readChannelFinishedSpy.count(), 0);
333     QCOMPARE(textFrameReceivedSpy.count(), 0);
334     QCOMPARE(binaryFrameReceivedSpy.count(), 0);
335     QCOMPARE(textMessageReceivedSpy.count(), 0);
336     QCOMPARE(binaryMessageReceivedSpy.count(), 0);
337     QCOMPARE(pongSpy.count(), 0);
338     QCOMPARE(bytesWrittenSpy.count(), 0);
339 }
340
341 void tst_QWebSocket::tst_invalidOrigin()
342 {
343     QWebSocket socket(QStringLiteral("My server\r\nin the wild."));
344
345     QSignalSpy errorSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
346     QSignalSpy aboutToCloseSpy(&socket, SIGNAL(aboutToClose()));
347     QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
348     QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
349     QSignalSpy stateChangedSpy(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
350     QSignalSpy readChannelFinishedSpy(&socket, SIGNAL(readChannelFinished()));
351     QSignalSpy textFrameReceivedSpy(&socket, SIGNAL(textFrameReceived(QString,bool)));
352     QSignalSpy binaryFrameReceivedSpy(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
353     QSignalSpy textMessageReceivedSpy(&socket, SIGNAL(textMessageReceived(QString)));
354     QSignalSpy binaryMessageReceivedSpy(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
355     QSignalSpy pongSpy(&socket, SIGNAL(pong(quint64,QByteArray)));
356     QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64)));
357
358     socket.open(QUrl(QStringLiteral("ws://127.0.0.1:1/")));
359
360     //at this point the socket is in a connecting state
361     //so, there should no error at this point
362     QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
363     QVERIFY(!socket.errorString().isEmpty());
364     QVERIFY(!socket.isValid());
365     QVERIFY(socket.localAddress().isNull());
366     QCOMPARE(socket.localPort(), quint16(0));
367     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseNever);
368     QVERIFY(socket.peerAddress().isNull());
369     QCOMPARE(socket.peerPort(), quint16(0));
370     QCOMPARE(socket.peerName(), QStringLiteral("127.0.0.1"));
371     QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
372     QCOMPARE(socket.readBufferSize(), 0);
373     QCOMPARE(socket.resourceName(), QStringLiteral("/"));
374     QCOMPARE(socket.requestUrl(), QUrl(QStringLiteral("ws://127.0.0.1:1/")));
375     QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeNormal);
376
377     QVERIFY(errorSpy.wait());
378
379     QCOMPARE(errorSpy.count(), 1);
380     QList<QVariant> arguments = errorSpy.takeFirst();
381     QAbstractSocket::SocketError socketError =
382             qvariant_cast<QAbstractSocket::SocketError>(arguments.at(0));
383     QCOMPARE(socketError, QAbstractSocket::ConnectionRefusedError);
384     QCOMPARE(aboutToCloseSpy.count(), 0);
385     QCOMPARE(connectedSpy.count(), 0);
386     QCOMPARE(disconnectedSpy.count(), 1);
387     QCOMPARE(stateChangedSpy.count(), 2);   //connectingstate, unconnectedstate
388     arguments = stateChangedSpy.takeFirst();
389     QAbstractSocket::SocketState socketState =
390             qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
391     arguments = stateChangedSpy.takeFirst();
392     socketState = qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
393     QCOMPARE(socketState, QAbstractSocket::UnconnectedState);
394     QCOMPARE(readChannelFinishedSpy.count(), 0);
395     QCOMPARE(textFrameReceivedSpy.count(), 0);
396     QCOMPARE(binaryFrameReceivedSpy.count(), 0);
397     QCOMPARE(textMessageReceivedSpy.count(), 0);
398     QCOMPARE(binaryMessageReceivedSpy.count(), 0);
399     QCOMPARE(pongSpy.count(), 0);
400     QCOMPARE(bytesWrittenSpy.count(), 0);
401 }
402
403 void tst_QWebSocket::tst_sendTextMessage()
404 {
405     //TODO: will resolve in another commit
406 #ifndef Q_OS_WIN
407     EchoServer echoServer;
408
409     QWebSocket socket;
410
411     //should return 0 because socket is not open yet
412     QCOMPARE(socket.sendTextMessage(QStringLiteral("1234")), 0);
413
414     QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
415     QSignalSpy textMessageReceived(&socket, SIGNAL(textMessageReceived(QString)));
416     QSignalSpy textFrameReceived(&socket, SIGNAL(textFrameReceived(QString,bool)));
417     QSignalSpy binaryMessageReceived(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
418     QSignalSpy binaryFrameReceived(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
419
420     socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
421                      QStringLiteral(":") + QString::number(echoServer.port())));
422
423     if (socketConnectedSpy.count() == 0)
424         QVERIFY(socketConnectedSpy.wait(500));
425     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
426
427     socket.sendTextMessage(QStringLiteral("Hello world!"));
428
429     QVERIFY(textMessageReceived.wait(500));
430     QCOMPARE(textMessageReceived.count(), 1);
431     QCOMPARE(binaryMessageReceived.count(), 0);
432     QCOMPARE(binaryFrameReceived.count(), 0);
433     QList<QVariant> arguments = textMessageReceived.takeFirst();
434     QString messageReceived = arguments.at(0).toString();
435     QCOMPARE(messageReceived, QStringLiteral("Hello world!"));
436
437     QCOMPARE(textFrameReceived.count(), 1);
438     arguments = textFrameReceived.takeFirst();
439     QString frameReceived = arguments.at(0).toString();
440     bool isLastFrame = arguments.at(1).toBool();
441     QCOMPARE(frameReceived, QStringLiteral("Hello world!"));
442     QVERIFY(isLastFrame);
443
444     socket.close();
445
446     //QTBUG-36762: QWebSocket emits multiplied signals when socket was reopened
447     socketConnectedSpy.clear();
448     textMessageReceived.clear();
449     textFrameReceived.clear();
450
451     socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
452                      QStringLiteral(":") + QString::number(echoServer.port())));
453
454     if (socketConnectedSpy.count() == 0)
455         QVERIFY(socketConnectedSpy.wait(500));
456     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
457
458     socket.sendTextMessage(QStringLiteral("Hello world!"));
459
460     QVERIFY(textMessageReceived.wait(500));
461     QCOMPARE(textMessageReceived.count(), 1);
462     QCOMPARE(binaryMessageReceived.count(), 0);
463     QCOMPARE(binaryFrameReceived.count(), 0);
464     arguments = textMessageReceived.takeFirst();
465     messageReceived = arguments.at(0).toString();
466     QCOMPARE(messageReceived, QStringLiteral("Hello world!"));
467
468     QCOMPARE(textFrameReceived.count(), 1);
469     arguments = textFrameReceived.takeFirst();
470     frameReceived = arguments.at(0).toString();
471     isLastFrame = arguments.at(1).toBool();
472     QCOMPARE(frameReceived, QStringLiteral("Hello world!"));
473     QVERIFY(isLastFrame);
474
475     QString reason = QStringLiteral("going away");
476     socket.close(QWebSocketProtocol::CloseCodeGoingAway, reason);
477     QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeGoingAway);
478     QCOMPARE(socket.closeReason(), reason);
479 #endif
480 }
481
482 void tst_QWebSocket::tst_sendBinaryMessage()
483 {
484     //TODO: will resolve in another commit
485 #ifndef Q_OS_WIN
486     EchoServer echoServer;
487
488     QWebSocket socket;
489
490     //should return 0 because socket is not open yet
491     QCOMPARE(socket.sendBinaryMessage(QByteArrayLiteral("1234")), 0);
492
493     QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
494     QSignalSpy textMessageReceived(&socket, SIGNAL(textMessageReceived(QString)));
495     QSignalSpy textFrameReceived(&socket, SIGNAL(textFrameReceived(QString,bool)));
496     QSignalSpy binaryMessageReceived(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
497     QSignalSpy binaryFrameReceived(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
498
499     socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
500                      QStringLiteral(":") + QString::number(echoServer.port())));
501
502     if (socketConnectedSpy.count() == 0)
503         QVERIFY(socketConnectedSpy.wait(500));
504     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
505
506     socket.sendBinaryMessage(QByteArrayLiteral("Hello world!"));
507
508     QVERIFY(binaryMessageReceived.wait(500));
509     QCOMPARE(textMessageReceived.count(), 0);
510     QCOMPARE(textFrameReceived.count(), 0);
511     QCOMPARE(binaryMessageReceived.count(), 1);
512     QList<QVariant> arguments = binaryMessageReceived.takeFirst();
513     QByteArray messageReceived = arguments.at(0).toByteArray();
514     QCOMPARE(messageReceived, QByteArrayLiteral("Hello world!"));
515
516     QCOMPARE(binaryFrameReceived.count(), 1);
517     arguments = binaryFrameReceived.takeFirst();
518     QByteArray frameReceived = arguments.at(0).toByteArray();
519     bool isLastFrame = arguments.at(1).toBool();
520     QCOMPARE(frameReceived, QByteArrayLiteral("Hello world!"));
521     QVERIFY(isLastFrame);
522
523     socket.close();
524
525     //QTBUG-36762: QWebSocket emits multiple signals when socket is reopened
526     socketConnectedSpy.clear();
527     binaryMessageReceived.clear();
528     binaryFrameReceived.clear();
529
530     socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
531                      QStringLiteral(":") + QString::number(echoServer.port())));
532
533     if (socketConnectedSpy.count() == 0)
534         QVERIFY(socketConnectedSpy.wait(500));
535     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
536
537     socket.sendBinaryMessage(QByteArrayLiteral("Hello world!"));
538
539     QVERIFY(binaryMessageReceived.wait(500));
540     QCOMPARE(textMessageReceived.count(), 0);
541     QCOMPARE(textFrameReceived.count(), 0);
542     QCOMPARE(binaryMessageReceived.count(), 1);
543     arguments = binaryMessageReceived.takeFirst();
544     messageReceived = arguments.at(0).toByteArray();
545     QCOMPARE(messageReceived, QByteArrayLiteral("Hello world!"));
546
547     QCOMPARE(binaryFrameReceived.count(), 1);
548     arguments = binaryFrameReceived.takeFirst();
549     frameReceived = arguments.at(0).toByteArray();
550     isLastFrame = arguments.at(1).toBool();
551     QCOMPARE(frameReceived, QByteArrayLiteral("Hello world!"));
552     QVERIFY(isLastFrame);
553 #endif
554 }
555
556 void tst_QWebSocket::tst_errorString()
557 {
558     //Check for QTBUG-37228: QWebSocket returns "Unknown Error" for known errors
559     QWebSocket socket;
560
561     //check that the default error string is empty
562     QVERIFY(socket.errorString().isEmpty());
563
564     QSignalSpy errorSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
565
566     socket.open(QUrl(QStringLiteral("ws://someserver.on.mars:9999")));
567
568     if (errorSpy.count() == 0)
569         errorSpy.wait();
570     QCOMPARE(errorSpy.count(), 1);
571     QList<QVariant> arguments = errorSpy.takeFirst();
572     QAbstractSocket::SocketError socketError =
573             qvariant_cast<QAbstractSocket::SocketError>(arguments.at(0));
574     QCOMPARE(socketError, QAbstractSocket::HostNotFoundError);
575     QCOMPARE(socket.errorString(), QStringLiteral("Host not found"));
576 }
577
578 #ifndef QT_NO_NETWORKPROXY
579 void tst_QWebSocket::tst_setProxy()
580 {
581     // check if property assignment works as expected.
582     QWebSocket socket;
583     QCOMPARE(socket.proxy(), QNetworkProxy(QNetworkProxy::DefaultProxy));
584
585     QNetworkProxy proxy;
586     proxy.setPort(123);
587     socket.setProxy(proxy);
588     QCOMPARE(socket.proxy(), proxy);
589
590     proxy.setPort(321);
591     QCOMPARE(socket.proxy().port(), quint16(123));
592     socket.setProxy(proxy);
593     QCOMPARE(socket.proxy(), proxy);
594 }
595 #endif // QT_NO_NETWORKPROXY
596
597 QTEST_MAIN(tst_QWebSocket)
598
599 #include "tst_qwebsocket.moc"