Fix unit tests
[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 };
151
152 tst_QWebSocket::tst_QWebSocket()
153 {
154 }
155
156 void tst_QWebSocket::init()
157 {
158     qRegisterMetaType<QWebSocketProtocol::Version>("QWebSocketProtocol::Version");
159 }
160
161 void tst_QWebSocket::initTestCase()
162 {
163 }
164
165 void tst_QWebSocket::cleanupTestCase()
166 {
167 }
168
169 void tst_QWebSocket::tst_initialisation_data()
170 {
171     QTest::addColumn<QString>("origin");
172     QTest::addColumn<QString>("expectedOrigin");
173     QTest::addColumn<QWebSocketProtocol::Version>("version");
174     QTest::addColumn<QWebSocketProtocol::Version>("expectedVersion");
175
176     QTest::newRow("Default origin and version")
177             << QString() << QString()
178             << QWebSocketProtocol::VersionUnknown << QWebSocketProtocol::VersionLatest;
179     QTest::newRow("Specific origin and default version")
180             << QStringLiteral("qt-project.org") << QStringLiteral("qt-project.org")
181             << QWebSocketProtocol::VersionUnknown << QWebSocketProtocol::VersionLatest;
182     QTest::newRow("Specific origin and specific version")
183             << QStringLiteral("qt-project.org") << QStringLiteral("qt-project.org")
184             << QWebSocketProtocol::Version7 << QWebSocketProtocol::Version7;
185 }
186
187 void tst_QWebSocket::tst_initialisation()
188 {
189     QFETCH(QString, origin);
190     QFETCH(QString, expectedOrigin);
191     QFETCH(QWebSocketProtocol::Version, version);
192     QFETCH(QWebSocketProtocol::Version, expectedVersion);
193
194     QScopedPointer<QWebSocket> socket;
195
196     if (origin.isEmpty() && (version == QWebSocketProtocol::VersionUnknown))
197         socket.reset(new QWebSocket);
198     else if (!origin.isEmpty() && (version == QWebSocketProtocol::VersionUnknown))
199         socket.reset(new QWebSocket(origin));
200     else
201         socket.reset(new QWebSocket(origin, version));
202
203     QCOMPARE(socket->origin(), expectedOrigin);
204     QCOMPARE(socket->version(), expectedVersion);
205     QCOMPARE(socket->error(), QAbstractSocket::UnknownSocketError);
206     QVERIFY(socket->errorString().isEmpty());
207     QVERIFY(!socket->isValid());
208     QVERIFY(socket->localAddress().isNull());
209     QCOMPARE(socket->localPort(), quint16(0));
210     QCOMPARE(socket->pauseMode(), QAbstractSocket::PauseNever);
211     QVERIFY(socket->peerAddress().isNull());
212     QCOMPARE(socket->peerPort(), quint16(0));
213     QVERIFY(socket->peerName().isEmpty());
214     QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
215     QCOMPARE(socket->readBufferSize(), 0);
216     QVERIFY(socket->resourceName().isEmpty());
217     QVERIFY(!socket->requestUrl().isValid());
218     QCOMPARE(socket->closeCode(), QWebSocketProtocol::CloseCodeNormal);
219     QVERIFY(socket->closeReason().isEmpty());
220     QVERIFY(socket->flush());
221     QCOMPARE(socket->sendTextMessage(QStringLiteral("A text message")), 0);
222     QCOMPARE(socket->sendBinaryMessage(QByteArrayLiteral("A binary message")), 0);
223 }
224
225 void tst_QWebSocket::tst_settersAndGetters()
226 {
227     QWebSocket socket;
228
229     socket.setPauseMode(QAbstractSocket::PauseNever);
230     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseNever);
231     socket.setPauseMode(QAbstractSocket::PauseOnSslErrors);
232     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseOnSslErrors);
233
234     socket.setReadBufferSize(0);
235     QCOMPARE(socket.readBufferSize(), 0);
236     socket.setReadBufferSize(128);
237     QCOMPARE(socket.readBufferSize(), 128);
238     socket.setReadBufferSize(-1);
239     QCOMPARE(socket.readBufferSize(), -1);
240 }
241
242 void tst_QWebSocket::tst_invalidOpen_data()
243 {
244     QTest::addColumn<QString>("url");
245     QTest::addColumn<QString>("expectedUrl");
246     QTest::addColumn<QString>("expectedPeerName");
247     QTest::addColumn<QString>("expectedResourceName");
248     QTest::addColumn<QAbstractSocket::SocketState>("stateAfterOpenCall");
249     QTest::addColumn<int>("disconnectedCount");
250     QTest::addColumn<int>("stateChangedCount");
251
252     QTest::newRow("Illegal local address")
253             << QStringLiteral("ws://127.0.0.1:1/") << QStringLiteral("ws://127.0.0.1:1/")
254             << QStringLiteral("127.0.0.1")
255             << QStringLiteral("/") << QAbstractSocket::ConnectingState
256             << 1
257             << 2;  //going from connecting to disconnected
258     QTest::newRow("URL containing new line in the hostname")
259             << QStringLiteral("ws://myhacky\r\nserver/") << QString()
260             << QString()
261             << QString() << QAbstractSocket::UnconnectedState
262             << 0 << 0;
263     QTest::newRow("URL containing new line in the resource name")
264             << QStringLiteral("ws://127.0.0.1:1/tricky\r\npath") << QString()
265             << QString()
266             << QString()
267             << QAbstractSocket::UnconnectedState
268             << 0 << 0;
269 }
270
271 void tst_QWebSocket::tst_invalidOpen()
272 {
273     QFETCH(QString, url);
274     QFETCH(QString, expectedUrl);
275     QFETCH(QString, expectedPeerName);
276     QFETCH(QString, expectedResourceName);
277     QFETCH(QAbstractSocket::SocketState, stateAfterOpenCall);
278     QFETCH(int, disconnectedCount);
279     QFETCH(int, stateChangedCount);
280     QWebSocket socket;
281     QSignalSpy errorSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
282     QSignalSpy aboutToCloseSpy(&socket, SIGNAL(aboutToClose()));
283     QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
284     QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
285     QSignalSpy stateChangedSpy(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
286     QSignalSpy readChannelFinishedSpy(&socket, SIGNAL(readChannelFinished()));
287     QSignalSpy textFrameReceivedSpy(&socket, SIGNAL(textFrameReceived(QString,bool)));
288     QSignalSpy binaryFrameReceivedSpy(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
289     QSignalSpy textMessageReceivedSpy(&socket, SIGNAL(textMessageReceived(QString)));
290     QSignalSpy binaryMessageReceivedSpy(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
291     QSignalSpy pongSpy(&socket, SIGNAL(pong(quint64,QByteArray)));
292     QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64)));
293
294     socket.open(QUrl(url));
295
296     QVERIFY(socket.origin().isEmpty());
297     QCOMPARE(socket.version(), QWebSocketProtocol::VersionLatest);
298     //at this point the socket is in a connecting state
299     //so, there should no error at this point
300     QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
301     QVERIFY(!socket.errorString().isEmpty());
302     QVERIFY(!socket.isValid());
303     QVERIFY(socket.localAddress().isNull());
304     QCOMPARE(socket.localPort(), quint16(0));
305     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseNever);
306     QVERIFY(socket.peerAddress().isNull());
307     QCOMPARE(socket.peerPort(), quint16(0));
308     QCOMPARE(socket.peerName(), expectedPeerName);
309     QCOMPARE(socket.state(), stateAfterOpenCall);
310     QCOMPARE(socket.readBufferSize(), 0);
311     QCOMPARE(socket.resourceName(), expectedResourceName);
312     QCOMPARE(socket.requestUrl().toString(), expectedUrl);
313     QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeNormal);
314     QVERIFY(socket.closeReason().isEmpty());
315     QCOMPARE(socket.sendTextMessage(QStringLiteral("A text message")), 0);
316     QCOMPARE(socket.sendBinaryMessage(QByteArrayLiteral("A text message")), 0);
317
318     if (errorSpy.count() == 0)
319         QVERIFY(errorSpy.wait());
320     QCOMPARE(errorSpy.count(), 1);
321     QList<QVariant> arguments = errorSpy.takeFirst();
322     QAbstractSocket::SocketError socketError =
323             qvariant_cast<QAbstractSocket::SocketError>(arguments.at(0));
324     QCOMPARE(socketError, QAbstractSocket::ConnectionRefusedError);
325     QCOMPARE(aboutToCloseSpy.count(), 0);
326     QCOMPARE(connectedSpy.count(), 0);
327     QCOMPARE(disconnectedSpy.count(), disconnectedCount);
328     QCOMPARE(stateChangedSpy.count(), stateChangedCount);
329     if (stateChangedCount == 2) {
330         arguments = stateChangedSpy.takeFirst();
331         QAbstractSocket::SocketState socketState =
332                 qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
333         arguments = stateChangedSpy.takeFirst();
334         socketState = qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
335         QCOMPARE(socketState, QAbstractSocket::UnconnectedState);
336     }
337     QCOMPARE(readChannelFinishedSpy.count(), 0);
338     QCOMPARE(textFrameReceivedSpy.count(), 0);
339     QCOMPARE(binaryFrameReceivedSpy.count(), 0);
340     QCOMPARE(textMessageReceivedSpy.count(), 0);
341     QCOMPARE(binaryMessageReceivedSpy.count(), 0);
342     QCOMPARE(pongSpy.count(), 0);
343     QCOMPARE(bytesWrittenSpy.count(), 0);
344 }
345
346 void tst_QWebSocket::tst_invalidOrigin()
347 {
348     QWebSocket socket(QStringLiteral("My server\r\nin the wild."));
349
350     QSignalSpy errorSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
351     QSignalSpy aboutToCloseSpy(&socket, SIGNAL(aboutToClose()));
352     QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
353     QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
354     QSignalSpy stateChangedSpy(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
355     QSignalSpy readChannelFinishedSpy(&socket, SIGNAL(readChannelFinished()));
356     QSignalSpy textFrameReceivedSpy(&socket, SIGNAL(textFrameReceived(QString,bool)));
357     QSignalSpy binaryFrameReceivedSpy(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
358     QSignalSpy textMessageReceivedSpy(&socket, SIGNAL(textMessageReceived(QString)));
359     QSignalSpy binaryMessageReceivedSpy(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
360     QSignalSpy pongSpy(&socket, SIGNAL(pong(quint64,QByteArray)));
361     QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64)));
362
363     socket.open(QUrl(QStringLiteral("ws://127.0.0.1:1/")));
364
365     //at this point the socket is in a connecting state
366     //so, there should no error at this point
367     QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
368     QVERIFY(!socket.errorString().isEmpty());
369     QVERIFY(!socket.isValid());
370     QVERIFY(socket.localAddress().isNull());
371     QCOMPARE(socket.localPort(), quint16(0));
372     QCOMPARE(socket.pauseMode(), QAbstractSocket::PauseNever);
373     QVERIFY(socket.peerAddress().isNull());
374     QCOMPARE(socket.peerPort(), quint16(0));
375     QCOMPARE(socket.peerName(), QStringLiteral("127.0.0.1"));
376     QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
377     QCOMPARE(socket.readBufferSize(), 0);
378     QCOMPARE(socket.resourceName(), QStringLiteral("/"));
379     QCOMPARE(socket.requestUrl(), QUrl(QStringLiteral("ws://127.0.0.1:1/")));
380     QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeNormal);
381
382     QVERIFY(errorSpy.wait());
383
384     QCOMPARE(errorSpy.count(), 1);
385     QList<QVariant> arguments = errorSpy.takeFirst();
386     QAbstractSocket::SocketError socketError =
387             qvariant_cast<QAbstractSocket::SocketError>(arguments.at(0));
388     QCOMPARE(socketError, QAbstractSocket::ConnectionRefusedError);
389     QCOMPARE(aboutToCloseSpy.count(), 0);
390     QCOMPARE(connectedSpy.count(), 0);
391     QCOMPARE(disconnectedSpy.count(), 1);
392     QCOMPARE(stateChangedSpy.count(), 2);   //connectingstate, unconnectedstate
393     arguments = stateChangedSpy.takeFirst();
394     QAbstractSocket::SocketState socketState =
395             qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
396     arguments = stateChangedSpy.takeFirst();
397     socketState = qvariant_cast<QAbstractSocket::SocketState>(arguments.at(0));
398     QCOMPARE(socketState, QAbstractSocket::UnconnectedState);
399     QCOMPARE(readChannelFinishedSpy.count(), 0);
400     QCOMPARE(textFrameReceivedSpy.count(), 0);
401     QCOMPARE(binaryFrameReceivedSpy.count(), 0);
402     QCOMPARE(textMessageReceivedSpy.count(), 0);
403     QCOMPARE(binaryMessageReceivedSpy.count(), 0);
404     QCOMPARE(pongSpy.count(), 0);
405     QCOMPARE(bytesWrittenSpy.count(), 0);
406 }
407
408 void tst_QWebSocket::tst_sendTextMessage()
409 {
410     //TODO: will resolve in another commit
411 #ifndef Q_OS_WIN
412     EchoServer echoServer;
413
414     QWebSocket socket;
415
416     //should return 0 because socket is not open yet
417     QCOMPARE(socket.sendTextMessage(QStringLiteral("1234")), 0);
418
419     QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
420     QSignalSpy textMessageReceived(&socket, SIGNAL(textMessageReceived(QString)));
421     QSignalSpy textFrameReceived(&socket, SIGNAL(textFrameReceived(QString,bool)));
422     QSignalSpy binaryMessageReceived(&socket, SIGNAL(binaryMessageReceived(QByteArray)));
423     QSignalSpy binaryFrameReceived(&socket, SIGNAL(binaryFrameReceived(QByteArray,bool)));
424
425     socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
426                      QStringLiteral(":") + QString::number(echoServer.port())));
427
428     if (socketConnectedSpy.count() == 0)
429         QVERIFY(socketConnectedSpy.wait(500));
430     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
431
432     socket.sendTextMessage(QStringLiteral("Hello world!"));
433
434     QVERIFY(textMessageReceived.wait(500));
435     QCOMPARE(textMessageReceived.count(), 1);
436     QCOMPARE(binaryMessageReceived.count(), 0);
437     QCOMPARE(binaryFrameReceived.count(), 0);
438     QList<QVariant> arguments = textMessageReceived.takeFirst();
439     QString messageReceived = arguments.at(0).toString();
440     QCOMPARE(messageReceived, QStringLiteral("Hello world!"));
441
442     QCOMPARE(textFrameReceived.count(), 1);
443     arguments = textFrameReceived.takeFirst();
444     QString frameReceived = arguments.at(0).toString();
445     bool isLastFrame = arguments.at(1).toBool();
446     QCOMPARE(frameReceived, QStringLiteral("Hello world!"));
447     QVERIFY(isLastFrame);
448
449     socket.close();
450
451     //QTBUG-36762: QWebSocket emits multiplied signals when socket was reopened
452     socketConnectedSpy.clear();
453     textMessageReceived.clear();
454     textFrameReceived.clear();
455
456     socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
457                      QStringLiteral(":") + QString::number(echoServer.port())));
458
459     if (socketConnectedSpy.count() == 0)
460         QVERIFY(socketConnectedSpy.wait(500));
461     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
462
463     socket.sendTextMessage(QStringLiteral("Hello world!"));
464
465     QVERIFY(textMessageReceived.wait(500));
466     QCOMPARE(textMessageReceived.count(), 1);
467     QCOMPARE(binaryMessageReceived.count(), 0);
468     QCOMPARE(binaryFrameReceived.count(), 0);
469     arguments = textMessageReceived.takeFirst();
470     messageReceived = arguments.at(0).toString();
471     QCOMPARE(messageReceived, QStringLiteral("Hello world!"));
472
473     QCOMPARE(textFrameReceived.count(), 1);
474     arguments = textFrameReceived.takeFirst();
475     frameReceived = arguments.at(0).toString();
476     isLastFrame = arguments.at(1).toBool();
477     QCOMPARE(frameReceived, QStringLiteral("Hello world!"));
478     QVERIFY(isLastFrame);
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 QTEST_MAIN(tst_QWebSocket)
579
580 #include "tst_qwebsocket.moc"