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 *)
56 Q_DECLARE_METATYPE(QSslError)
59 class tst_QWebSocketServer : public QObject
64 tst_QWebSocketServer();
69 void cleanupTestCase();
70 void tst_initialisation();
71 void tst_settersAndGetters();
73 void tst_connectivity();
74 void tst_maxPendingConnections();
77 tst_QWebSocketServer::tst_QWebSocketServer()
81 void tst_QWebSocketServer::init()
83 qRegisterMetaType<QWebSocketProtocol::Version>("QWebSocketProtocol::Version");
84 qRegisterMetaType<QWebSocketProtocol::CloseCode>("QWebSocketProtocol::CloseCode");
85 qRegisterMetaType<QWebSocketServer::SslMode>("QWebSocketServer::SslMode");
86 qRegisterMetaType<QWebSocketCorsAuthenticator *>("QWebSocketCorsAuthenticator *");
88 qRegisterMetaType<QSslError>("QSslError");
92 void tst_QWebSocketServer::initTestCase()
96 void tst_QWebSocketServer::cleanupTestCase()
100 void tst_QWebSocketServer::tst_initialisation()
103 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
105 QVERIFY(server.serverName().isEmpty());
106 QCOMPARE(server.secureMode(), QWebSocketServer::NonSecureMode);
107 QVERIFY(!server.isListening());
108 QCOMPARE(server.maxPendingConnections(), 30);
109 QCOMPARE(server.serverPort(), quint16(0));
110 QCOMPARE(server.serverAddress(), QHostAddress());
111 QCOMPARE(server.socketDescriptor(), -1);
112 QVERIFY(!server.hasPendingConnections());
113 QVERIFY(!server.nextPendingConnection());
114 QCOMPARE(server.error(), QWebSocketProtocol::CloseCodeNormal);
115 QVERIFY(server.errorString().isEmpty());
116 #ifndef QT_NO_NETWORKPROXY
117 QCOMPARE(server.proxy().type(), QNetworkProxy::DefaultProxy);
120 QCOMPARE(server.sslConfiguration(), QSslConfiguration::defaultConfiguration());
122 QCOMPARE(server.supportedVersions().count(), 1);
123 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::VersionLatest);
124 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::Version13);
127 //closing a server should not affect any of the parameters
128 //certainly if the server was not opened before
130 QVERIFY(server.serverName().isEmpty());
131 QCOMPARE(server.secureMode(), QWebSocketServer::NonSecureMode);
132 QVERIFY(!server.isListening());
133 QCOMPARE(server.maxPendingConnections(), 30);
134 QCOMPARE(server.serverPort(), quint16(0));
135 QCOMPARE(server.serverAddress(), QHostAddress());
136 QCOMPARE(server.socketDescriptor(), -1);
137 QVERIFY(!server.hasPendingConnections());
138 QVERIFY(!server.nextPendingConnection());
139 QCOMPARE(server.error(), QWebSocketProtocol::CloseCodeNormal);
140 QVERIFY(server.errorString().isEmpty());
141 #ifndef QT_NO_NETWORKPROXY
142 QCOMPARE(server.proxy().type(), QNetworkProxy::DefaultProxy);
145 QCOMPARE(server.sslConfiguration(), QSslConfiguration::defaultConfiguration());
147 QCOMPARE(server.supportedVersions().count(), 1);
148 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::VersionLatest);
149 QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::Version13);
150 QCOMPARE(server.serverUrl(), QUrl());
155 QWebSocketServer sslServer(QString(), QWebSocketServer::SecureMode);
156 QCOMPARE(sslServer.secureMode(), QWebSocketServer::SecureMode);
161 void tst_QWebSocketServer::tst_settersAndGetters()
163 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
165 server.setMaxPendingConnections(23);
166 QCOMPARE(server.maxPendingConnections(), 23);
167 server.setMaxPendingConnections(INT_MIN);
168 QCOMPARE(server.maxPendingConnections(), INT_MIN);
169 server.setMaxPendingConnections(INT_MAX);
170 QCOMPARE(server.maxPendingConnections(), INT_MAX);
172 QVERIFY(!server.setSocketDescriptor(-2));
173 QCOMPARE(server.socketDescriptor(), -1);
175 server.setServerName(QStringLiteral("Qt WebSocketServer"));
176 QCOMPARE(server.serverName(), QStringLiteral("Qt WebSocketServer"));
178 #ifndef QT_NO_NETWORKPROXY
179 QNetworkProxy proxy(QNetworkProxy::Socks5Proxy);
180 server.setProxy(proxy);
181 QCOMPARE(server.proxy(), proxy);
184 //cannot set an ssl configuration on a non secure server
185 QSslConfiguration sslConfiguration = QSslConfiguration::defaultConfiguration();
186 sslConfiguration.setPeerVerifyDepth(sslConfiguration.peerVerifyDepth() + 1);
187 server.setSslConfiguration(sslConfiguration);
188 QVERIFY(server.sslConfiguration() != sslConfiguration);
189 QCOMPARE(server.sslConfiguration(), QSslConfiguration::defaultConfiguration());
191 QWebSocketServer sslServer(QString(), QWebSocketServer::SecureMode);
192 sslServer.setSslConfiguration(sslConfiguration);
193 QCOMPARE(sslServer.sslConfiguration(), sslConfiguration);
194 QVERIFY(sslServer.sslConfiguration() != QSslConfiguration::defaultConfiguration());
198 void tst_QWebSocketServer::tst_listening()
200 //These listening tests are not too extensive, as the implementation of QWebSocketServer
201 //relies on QTcpServer
203 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
205 QSignalSpy serverAcceptErrorSpy(&server, SIGNAL(acceptError(QAbstractSocket::SocketError)));
206 QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
207 QSignalSpy serverErrorSpy(&server,
208 SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
209 QSignalSpy corsAuthenticationSpy(&server,
210 SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)));
211 QSignalSpy serverClosedSpy(&server, SIGNAL(closed()));
213 QSignalSpy peerVerifyErrorSpy(&server, SIGNAL(peerVerifyError(QSslError)));
214 QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
217 QVERIFY(server.listen()); //listen on all network interface, choose an appropriate port
218 QVERIFY(server.isListening());
219 QCOMPARE(serverClosedSpy.count(), 0);
221 QVERIFY(serverClosedSpy.wait(1000));
222 QVERIFY(!server.isListening());
223 QCOMPARE(serverErrorSpy.count(), 0);
225 QVERIFY(!server.listen(QHostAddress(QStringLiteral("1.2.3.4")), 0));
226 QCOMPARE(server.error(), QWebSocketProtocol::CloseCodeAbnormalDisconnection);
227 QCOMPARE(server.errorString().toLatin1().constData(), "The address is not available");
228 QVERIFY(!server.isListening());
230 QCOMPARE(serverAcceptErrorSpy.count(), 0);
231 QCOMPARE(serverConnectionSpy.count(), 0);
232 QCOMPARE(corsAuthenticationSpy.count(), 0);
234 QCOMPARE(peerVerifyErrorSpy.count(), 0);
235 QCOMPARE(sslErrorsSpy.count(), 0);
237 QCOMPARE(serverErrorSpy.count(), 1);
238 QCOMPARE(serverClosedSpy.count(), 1);
241 void tst_QWebSocketServer::tst_connectivity()
243 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
244 QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
245 QSignalSpy serverErrorSpy(&server,
246 SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
247 QSignalSpy corsAuthenticationSpy(&server,
248 SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)));
249 QSignalSpy serverClosedSpy(&server, SIGNAL(closed()));
251 QSignalSpy peerVerifyErrorSpy(&server, SIGNAL(peerVerifyError(QSslError)));
252 QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
255 QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
257 QVERIFY(server.listen());
258 QCOMPARE(server.serverAddress(), QHostAddress(QHostAddress::Any));
259 QCOMPARE(server.serverUrl(), QUrl(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
260 QStringLiteral(":").append(QString::number(server.serverPort()))));
262 socket.open(server.serverUrl().toString());
264 if (socketConnectedSpy.count() == 0)
265 QVERIFY(socketConnectedSpy.wait());
266 QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
267 QCOMPARE(serverConnectionSpy.count(), 1);
268 QCOMPARE(corsAuthenticationSpy.count(), 1);
270 QCOMPARE(serverClosedSpy.count(), 0);
274 QVERIFY(serverClosedSpy.wait());
275 QCOMPARE(serverClosedSpy.count(), 1);
277 QCOMPARE(peerVerifyErrorSpy.count(), 0);
278 QCOMPARE(sslErrorsSpy.count(), 0);
280 QCOMPARE(serverErrorSpy.count(), 0);
283 void tst_QWebSocketServer::tst_maxPendingConnections()
285 //tests if maximum connections are respected
286 //also checks if there are no side-effects like signals that are unexpectedly thrown
287 QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
288 server.setMaxPendingConnections(2);
289 QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
290 QSignalSpy serverErrorSpy(&server,
291 SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
292 QSignalSpy corsAuthenticationSpy(&server,
293 SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*)));
294 QSignalSpy serverClosedSpy(&server, SIGNAL(closed()));
296 QSignalSpy peerVerifyErrorSpy(&server, SIGNAL(peerVerifyError(QSslError)));
297 QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
299 QSignalSpy serverAcceptErrorSpy(&server, SIGNAL(acceptError(QAbstractSocket::SocketError)));
305 QSignalSpy socket1ConnectedSpy(&socket1, SIGNAL(connected()));
306 QSignalSpy socket2ConnectedSpy(&socket2, SIGNAL(connected()));
307 QSignalSpy socket3ConnectedSpy(&socket3, SIGNAL(connected()));
309 QVERIFY(server.listen());
311 socket1.open(server.serverUrl().toString());
313 if (socket1ConnectedSpy.count() == 0)
314 QVERIFY(socket1ConnectedSpy.wait());
315 QCOMPARE(socket1.state(), QAbstractSocket::ConnectedState);
316 QCOMPARE(serverConnectionSpy.count(), 1);
317 QCOMPARE(corsAuthenticationSpy.count(), 1);
318 socket2.open(server.serverUrl().toString());
319 if (socket2ConnectedSpy.count() == 0)
320 QVERIFY(socket2ConnectedSpy.wait());
321 QCOMPARE(socket2.state(), QAbstractSocket::ConnectedState);
322 QCOMPARE(serverConnectionSpy.count(), 2);
323 QCOMPARE(corsAuthenticationSpy.count(), 2);
324 socket3.open(server.serverUrl().toString());
325 if (socket3ConnectedSpy.count() == 0)
326 QVERIFY(!socket3ConnectedSpy.wait(250));
327 QCOMPARE(socket3.state(), QAbstractSocket::UnconnectedState);
328 QCOMPARE(serverConnectionSpy.count(), 2);
329 QCOMPARE(corsAuthenticationSpy.count(), 2);
331 QVERIFY(server.hasPendingConnections());
332 QWebSocket *pSocket = server.nextPendingConnection();
335 QVERIFY(server.hasPendingConnections());
336 pSocket = server.nextPendingConnection();
339 QVERIFY(!server.hasPendingConnections());
340 QVERIFY(!server.nextPendingConnection());
342 //will resolve in another commit
344 QCOMPARE(serverErrorSpy.count(), 1);
345 QCOMPARE(serverErrorSpy.at(0).at(0).value<QWebSocketProtocol::CloseCode>(),
346 QWebSocketProtocol::CloseCodeAbnormalDisconnection);
348 QCOMPARE(serverClosedSpy.count(), 0);
352 QVERIFY(serverClosedSpy.wait());
353 QCOMPARE(serverClosedSpy.count(), 1);
355 QCOMPARE(peerVerifyErrorSpy.count(), 0);
356 QCOMPARE(sslErrorsSpy.count(), 0);
358 QCOMPARE(serverAcceptErrorSpy.count(), 0);
362 QTEST_MAIN(tst_QWebSocketServer)
364 #include "tst_qwebsocketserver.moc"