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