1 /****************************************************************************
3 ** Copyright (C) 2014 Kurt Pattyn <pattyn.kurt@gmail.com>.
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
43 #include <QNetworkProxy>
44 #include <QtWebSockets/QWebSocketServer>
45 #include <QtWebSockets/QWebSocket>
46 #include <QtWebSockets/QWebSocketCorsAuthenticator>
47 #include <QtWebSockets/qwebsocketprotocol.h>
51 Q_DECLARE_METATYPE(QWebSocketProtocol::Version)
52 Q_DECLARE_METATYPE(QWebSocketProtocol::CloseCode)
53 Q_DECLARE_METATYPE(QWebSocketServer::SslMode)
54 Q_DECLARE_METATYPE(QWebSocketCorsAuthenticator *)
55 Q_DECLARE_METATYPE(QSslError)
57 class tst_QWebSocketServer : public QObject
62 tst_QWebSocketServer();
67 void cleanupTestCase();
68 void tst_initialisation();
69 void tst_settersAndGetters();
71 void tst_connectivity();
72 void tst_maxPendingConnections();
75 tst_QWebSocketServer::tst_QWebSocketServer()
79 void tst_QWebSocketServer::init()
81 qRegisterMetaType<QWebSocketProtocol::Version>("QWebSocketProtocol::Version");
82 qRegisterMetaType<QWebSocketProtocol::CloseCode>("QWebSocketProtocol::CloseCode");
83 qRegisterMetaType<QWebSocketServer::SslMode>("QWebSocketServer::SslMode");
84 qRegisterMetaType<QWebSocketCorsAuthenticator *>("QWebSocketCorsAuthenticator *");
85 qRegisterMetaType<QSslError>("QSslError");
88 void tst_QWebSocketServer::initTestCase()
92 void tst_QWebSocketServer::cleanupTestCase()
96 void tst_QWebSocketServer::tst_initialisation()
99 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
101 QVERIFY(server.serverName().isEmpty());
102 QCOMPARE(server.secureMode(), QWebSocketServer::NonSecureMode);
103 QVERIFY(!server.isListening());
104 QCOMPARE(server.maxPendingConnections(), 30);
105 QCOMPARE(server.serverPort(), quint16(0));
106 QCOMPARE(server.serverAddress(), QHostAddress());
107 QCOMPARE(server.socketDescriptor(), -1);
108 QVERIFY(!server.hasPendingConnections());
109 QVERIFY(!server.nextPendingConnection());
110 QCOMPARE(server.error(), QWebSocketProtocol::CloseCodeNormal);
111 QVERIFY(server.errorString().isEmpty());
112 #ifndef QT_NO_NETWORKPROXY
113 QCOMPARE(server.proxy().type(), QNetworkProxy::DefaultProxy);
116 QCOMPARE(server.sslConfiguration(), QSslConfiguration::defaultConfiguration());
118 QCOMPARE(server.supportedVersions().count(), 1);
119 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::VersionLatest);
120 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::Version13);
123 //closing a server should not affect any of the parameters
124 //certainly if the server was not opened before
126 QVERIFY(server.serverName().isEmpty());
127 QCOMPARE(server.secureMode(), QWebSocketServer::NonSecureMode);
128 QVERIFY(!server.isListening());
129 QCOMPARE(server.maxPendingConnections(), 30);
130 QCOMPARE(server.serverPort(), quint16(0));
131 QCOMPARE(server.serverAddress(), QHostAddress());
132 QCOMPARE(server.socketDescriptor(), -1);
133 QVERIFY(!server.hasPendingConnections());
134 QVERIFY(!server.nextPendingConnection());
135 QCOMPARE(server.error(), QWebSocketProtocol::CloseCodeNormal);
136 QVERIFY(server.errorString().isEmpty());
137 #ifndef QT_NO_NETWORKPROXY
138 QCOMPARE(server.proxy().type(), QNetworkProxy::DefaultProxy);
141 QCOMPARE(server.sslConfiguration(), QSslConfiguration::defaultConfiguration());
143 QCOMPARE(server.supportedVersions().count(), 1);
144 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::VersionLatest);
145 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::Version13);
149 QWebSocketServer sslServer(QString(), QWebSocketServer::SecureMode);
151 QCOMPARE(sslServer.secureMode(), QWebSocketServer::SecureMode);
153 QCOMPARE(sslServer.secureMode(), QWebSocketServer::NonSecureMode);
158 void tst_QWebSocketServer::tst_settersAndGetters()
160 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
162 server.setMaxPendingConnections(23);
163 QCOMPARE(server.maxPendingConnections(), 23);
164 server.setMaxPendingConnections(INT_MIN);
165 QCOMPARE(server.maxPendingConnections(), INT_MIN);
166 server.setMaxPendingConnections(INT_MAX);
167 QCOMPARE(server.maxPendingConnections(), INT_MAX);
169 QVERIFY(!server.setSocketDescriptor(-2));
170 QCOMPARE(server.socketDescriptor(), -1);
172 server.setServerName(QStringLiteral("Qt WebSocketServer"));
173 QCOMPARE(server.serverName(), QStringLiteral("Qt WebSocketServer"));
175 #ifndef QT_NO_NETWORKPROXY
176 QNetworkProxy proxy(QNetworkProxy::Socks5Proxy);
177 server.setProxy(proxy);
178 QCOMPARE(server.proxy(), proxy);
181 //cannot set an ssl configuration on a non secure server
182 QSslConfiguration sslConfiguration = QSslConfiguration::defaultConfiguration();
183 sslConfiguration.setPeerVerifyDepth(sslConfiguration.peerVerifyDepth() + 1);
184 server.setSslConfiguration(sslConfiguration);
185 QVERIFY(server.sslConfiguration() != sslConfiguration);
186 QCOMPARE(server.sslConfiguration(), QSslConfiguration::defaultConfiguration());
188 QWebSocketServer sslServer(QString(), QWebSocketServer::SecureMode);
189 sslServer.setSslConfiguration(sslConfiguration);
190 QCOMPARE(sslServer.sslConfiguration(), sslConfiguration);
191 QVERIFY(sslServer.sslConfiguration() != QSslConfiguration::defaultConfiguration());
195 void tst_QWebSocketServer::tst_listening()
197 //These listening tests are not too extensive, as the implementation of QWebSocketServer
198 //relies on QTcpServer
200 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
202 QSignalSpy serverAcceptErrorSpy(&server, SIGNAL(acceptError(QAbstractSocket::SocketError)));
203 QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
204 QSignalSpy serverErrorSpy(&server,
205 SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
206 QSignalSpy corsAuthenticationSpy(&server,
207 SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)));
208 QSignalSpy serverClosedSpy(&server, SIGNAL(closed()));
210 QSignalSpy peerVerifyErrorSpy(&server, SIGNAL(peerVerifyError(QSslError)));
211 QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
214 QVERIFY(server.listen()); //listen on all network interface, choose an appropriate port
215 QVERIFY(server.isListening());
216 QCOMPARE(serverClosedSpy.count(), 0);
218 QVERIFY(serverClosedSpy.wait(1000));
219 QVERIFY(!server.isListening());
220 QCOMPARE(serverErrorSpy.count(), 0);
222 QVERIFY(!server.listen(QHostAddress(QStringLiteral("1.2.3.4")), 0));
223 QCOMPARE(server.error(), QWebSocketProtocol::CloseCodeAbnormalDisconnection);
224 QCOMPARE(server.errorString().toLatin1().constData(), "The address is not available");
225 QVERIFY(!server.isListening());
227 QCOMPARE(serverAcceptErrorSpy.count(), 0);
228 QCOMPARE(serverConnectionSpy.count(), 0);
229 QCOMPARE(corsAuthenticationSpy.count(), 0);
231 QCOMPARE(peerVerifyErrorSpy.count(), 0);
232 QCOMPARE(sslErrorsSpy.count(), 0);
234 QCOMPARE(serverErrorSpy.count(), 1);
235 QCOMPARE(serverClosedSpy.count(), 1);
238 void tst_QWebSocketServer::tst_connectivity()
240 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
241 QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
242 QSignalSpy serverErrorSpy(&server,
243 SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
244 QSignalSpy corsAuthenticationSpy(&server,
245 SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)));
246 QSignalSpy serverClosedSpy(&server, SIGNAL(closed()));
248 QSignalSpy peerVerifyErrorSpy(&server, SIGNAL(peerVerifyError(QSslError)));
249 QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
252 QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
254 QVERIFY(server.listen());
256 socket.open(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
257 QStringLiteral(":").append(QString::number(server.serverPort())));
259 if (socketConnectedSpy.count() == 0)
260 QVERIFY(socketConnectedSpy.wait());
261 QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
262 QCOMPARE(serverConnectionSpy.count(), 1);
263 QCOMPARE(corsAuthenticationSpy.count(), 1);
265 QCOMPARE(serverClosedSpy.count(), 0);
269 QVERIFY(serverClosedSpy.wait());
270 QCOMPARE(serverClosedSpy.count(), 1);
272 QCOMPARE(peerVerifyErrorSpy.count(), 0);
273 QCOMPARE(sslErrorsSpy.count(), 0);
275 QCOMPARE(serverErrorSpy.count(), 0);
278 void tst_QWebSocketServer::tst_maxPendingConnections()
280 //tests if maximum connections are respected
281 //also checks if there are no side-effects like signals that are unexpectedly thrown
282 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
283 server.setMaxPendingConnections(2);
284 QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
285 QSignalSpy serverErrorSpy(&server,
286 SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
287 QSignalSpy corsAuthenticationSpy(&server,
288 SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)));
289 QSignalSpy serverClosedSpy(&server, SIGNAL(closed()));
291 QSignalSpy peerVerifyErrorSpy(&server, SIGNAL(peerVerifyError(QSslError)));
292 QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
294 QSignalSpy serverAcceptErrorSpy(&server, SIGNAL(acceptError(QAbstractSocket::SocketError)));
300 QSignalSpy socket1ConnectedSpy(&socket1, SIGNAL(connected()));
301 QSignalSpy socket2ConnectedSpy(&socket2, SIGNAL(connected()));
302 QSignalSpy socket3ConnectedSpy(&socket3, SIGNAL(connected()));
304 QVERIFY(server.listen());
306 socket1.open(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
307 QStringLiteral(":").append(QString::number(server.serverPort())));
309 if (socket1ConnectedSpy.count() == 0)
310 QVERIFY(socket1ConnectedSpy.wait());
311 QCOMPARE(socket1.state(), QAbstractSocket::ConnectedState);
312 QCOMPARE(serverConnectionSpy.count(), 1);
313 QCOMPARE(corsAuthenticationSpy.count(), 1);
314 socket2.open(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
315 QStringLiteral(":").append(QString::number(server.serverPort())));
316 if (socket2ConnectedSpy.count() == 0)
317 QVERIFY(socket2ConnectedSpy.wait());
318 QCOMPARE(socket2.state(), QAbstractSocket::ConnectedState);
319 QCOMPARE(serverConnectionSpy.count(), 2);
320 QCOMPARE(corsAuthenticationSpy.count(), 2);
321 socket3.open(QStringLiteral("ws://") + server.serverAddress().toString() +
322 QStringLiteral(":").append(QString::number(server.serverPort())));
323 QVERIFY(!socket3ConnectedSpy.wait(250));
324 QCOMPARE(socket3.state(), QAbstractSocket::UnconnectedState);
325 QCOMPARE(serverConnectionSpy.count(), 2);
326 QCOMPARE(corsAuthenticationSpy.count(), 2);
328 QVERIFY(server.hasPendingConnections());
329 QWebSocket *pSocket = server.nextPendingConnection();
332 QVERIFY(server.hasPendingConnections());
333 pSocket = server.nextPendingConnection();
336 QVERIFY(!server.hasPendingConnections());
337 QVERIFY(!server.nextPendingConnection());
339 QCOMPARE(serverErrorSpy.count(), 1);
340 QCOMPARE(serverErrorSpy.at(0).at(0).value<QWebSocketProtocol::CloseCode>(),
341 QWebSocketProtocol::CloseCodeAbnormalDisconnection);
343 QCOMPARE(serverClosedSpy.count(), 0);
347 QVERIFY(serverClosedSpy.wait());
348 QCOMPARE(serverClosedSpy.count(), 1);
350 QCOMPARE(peerVerifyErrorSpy.count(), 0);
351 QCOMPARE(sslErrorsSpy.count(), 0);
353 QCOMPARE(serverAcceptErrorSpy.count(), 0);
357 QTEST_MAIN(tst_QWebSocketServer)
359 #include "tst_qwebsocketserver.moc"