1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the test suite of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:GPL-EXCEPT$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU
20** General Public License version 3 as published by the Free Software
21** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <QtTest/QTest>
31
32#include <qcoreapplication.h>
33#include <qdatastream.h>
34#include <qhostaddress.h>
35#include <qelapsedtimer.h>
36
37#ifdef Q_OS_UNIX
38#include <unistd.h>
39#include <sys/types.h>
40#include <sys/socket.h>
41#endif
42
43#ifdef Q_OS_VXWORKS
44#include <sockLib.h>
45#endif
46
47#include <stddef.h>
48
49#define PLATFORMSOCKETENGINE QNativeSocketEngine
50#define PLATFORMSOCKETENGINESTRING "QNativeSocketEngine"
51#ifndef Q_OS_WINRT
52# include <private/qnativesocketengine_p.h>
53#else
54# include <private/qnativesocketengine_winrt_p.h>
55#endif
56
57#include <qstringlist.h>
58
59#include "../../../network-settings.h"
60
61class tst_PlatformSocketEngine : public QObject
62{
63 Q_OBJECT
64
65private slots:
66 void initTestCase();
67 void construction();
68 void simpleConnectToIMAP();
69 void udpLoopbackTest();
70 void udpIPv6LoopbackTest();
71 void broadcastTest();
72 void serverTest();
73 void udpLoopbackPerformance();
74 void tcpLoopbackPerformance();
75#if 0
76 void readWriteBufferSize();
77#endif
78 void bind();
79 void networkError();
80 void setSocketDescriptor();
81 void invalidSend();
82#ifndef Q_OS_WINRT
83 void receiveUrgentData();
84#endif
85 void tooManySockets();
86};
87
88void tst_PlatformSocketEngine::initTestCase()
89{
90 if (!QtNetworkSettings::verifyTestNetworkSettings())
91 QSKIP("No network test server available");
92}
93
94//---------------------------------------------------------------------------
95void tst_PlatformSocketEngine::construction()
96{
97 PLATFORMSOCKETENGINE socketDevice;
98
99 QVERIFY(!socketDevice.isValid());
100
101 // Initialize device
102 QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
103 QVERIFY(socketDevice.isValid());
104 QCOMPARE(socketDevice.protocol(), QAbstractSocket::IPv4Protocol);
105 QCOMPARE(socketDevice.socketType(), QAbstractSocket::TcpSocket);
106 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
107 QVERIFY(socketDevice.socketDescriptor() != -1);
108 QCOMPARE(socketDevice.localAddress(), QHostAddress());
109 QCOMPARE(socketDevice.localPort(), quint16(0));
110 QCOMPARE(socketDevice.peerAddress(), QHostAddress());
111 QCOMPARE(socketDevice.peerPort(), quint16(0));
112 QCOMPARE(socketDevice.error(), QAbstractSocket::UnknownSocketError);
113 QCOMPARE(socketDevice.option(QNativeSocketEngine::NonBlockingSocketOption), -1);
114
115 QTest::ignoreMessage(type: QtWarningMsg, PLATFORMSOCKETENGINESTRING "::bytesAvailable() was called in QAbstractSocket::UnconnectedState");
116 QCOMPARE(socketDevice.bytesAvailable(), -1);
117
118 QTest::ignoreMessage(type: QtWarningMsg, PLATFORMSOCKETENGINESTRING "::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState");
119 QVERIFY(!socketDevice.hasPendingDatagrams());
120}
121
122//---------------------------------------------------------------------------
123void tst_PlatformSocketEngine::simpleConnectToIMAP()
124{
125 PLATFORMSOCKETENGINE socketDevice;
126
127 // Initialize device
128 QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
129 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
130
131 const bool isConnected = socketDevice.connectToHost(address: QtNetworkSettings::serverIP(), port: 143);
132 if (!isConnected) {
133 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
134 QVERIFY(socketDevice.waitForWrite());
135 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
136 }
137 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
138 QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
139
140 // Wait for the greeting
141 QVERIFY(socketDevice.waitForRead());
142
143 // Read the greeting
144 qint64 available = socketDevice.bytesAvailable();
145 QVERIFY(available > 0);
146 QByteArray array;
147 array.resize(size: available);
148 QVERIFY(socketDevice.read(array.data(), array.size()) == available);
149
150 // Check that the greeting is what we expect it to be
151 QVERIFY2(QtNetworkSettings::compareReplyIMAP(array), array.constData());
152
153 // Write a logout message
154 QByteArray array2 = "ZZZ LOGOUT\r\n";
155 QVERIFY(socketDevice.write(array2.data(),
156 array2.size()) == array2.size());
157
158 // Wait for the response
159 QVERIFY(socketDevice.waitForRead());
160
161 available = socketDevice.bytesAvailable();
162 QVERIFY(available > 0);
163 array.resize(size: available);
164 QVERIFY(socketDevice.read(array.data(), array.size()) == available);
165
166 // Check that the greeting is what we expect it to be
167 QCOMPARE(array.constData(),
168 "* BYE LOGOUT received\r\n"
169 "ZZZ OK Completed\r\n");
170
171 // Wait for the response
172 QVERIFY(socketDevice.waitForRead());
173 char c;
174 QVERIFY(socketDevice.read(&c, sizeof(c)) == -1);
175 QCOMPARE(socketDevice.error(), QAbstractSocket::RemoteHostClosedError);
176 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
177}
178
179//---------------------------------------------------------------------------
180void tst_PlatformSocketEngine::udpLoopbackTest()
181{
182 PLATFORMSOCKETENGINE udpSocket;
183
184 // Initialize device #1
185 QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
186 QVERIFY(udpSocket.isValid());
187 QVERIFY(udpSocket.socketDescriptor() != -1);
188 QCOMPARE(udpSocket.protocol(), QAbstractSocket::IPv4Protocol);
189 QCOMPARE(udpSocket.socketType(), QAbstractSocket::UdpSocket);
190 QCOMPARE(udpSocket.state(), QAbstractSocket::UnconnectedState);
191
192 // Bind #1 to localhost
193 QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0));
194 QCOMPARE(udpSocket.state(), QAbstractSocket::BoundState);
195 quint16 port = udpSocket.localPort();
196 QVERIFY(port != 0);
197
198 // Initialize device #2
199 PLATFORMSOCKETENGINE udpSocket2;
200 QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket));
201
202 // Connect device #2 to #1
203 QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port));
204 QCOMPARE(udpSocket2.state(), QAbstractSocket::ConnectedState);
205
206 // Write a message to #1
207 QByteArray message1 = "hei der";
208 QVERIFY(udpSocket2.write(message1.data(),
209 message1.size()) == message1.size());
210
211 // Read the message from #2
212 QVERIFY(udpSocket.waitForRead());
213 QVERIFY(udpSocket.hasPendingDatagrams());
214 qint64 available = udpSocket.pendingDatagramSize();
215 QVERIFY(available > 0);
216 QByteArray answer;
217 answer.resize(size: available);
218 QIpPacketHeader header;
219 QCOMPARE(udpSocket.readDatagram(answer.data(), answer.size(),
220 &header, QAbstractSocketEngine::WantDatagramSender),
221 qint64(message1.size()));
222 QVERIFY(header.senderAddress == QHostAddress("127.0.0.1"));
223 QCOMPARE(header.senderAddress, QHostAddress("127.0.0.1"));
224 QVERIFY(header.senderPort != 0);
225}
226
227//---------------------------------------------------------------------------
228void tst_PlatformSocketEngine::udpIPv6LoopbackTest()
229{
230 PLATFORMSOCKETENGINE udpSocket;
231
232 // Initialize device #1
233 bool init = udpSocket.initialize(type: QAbstractSocket::UdpSocket, protocol: QAbstractSocket::IPv6Protocol);
234
235 if (!init) {
236 QCOMPARE(udpSocket.error(), QAbstractSocket::UnsupportedSocketOperationError);
237 } else {
238 QCOMPARE(udpSocket.protocol(), QAbstractSocket::IPv6Protocol);
239
240 // Bind #1 to localhost
241 QVERIFY(udpSocket.bind(QHostAddress("::1"), 0));
242 QCOMPARE(udpSocket.state(), QAbstractSocket::BoundState);
243 quint16 port = udpSocket.localPort();
244 QVERIFY(port != 0);
245
246 // Initialize device #2
247 PLATFORMSOCKETENGINE udpSocket2;
248 QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol));
249
250 // Connect device #2 to #1
251 QVERIFY(udpSocket2.connectToHost(QHostAddress("::1"), port));
252 QCOMPARE(udpSocket2.state(), QAbstractSocket::ConnectedState);
253
254 // Write a message to #1
255 QByteArray message1 = "hei der";
256 QVERIFY(udpSocket2.write(message1.data(),
257 message1.size()) == message1.size());
258
259 // Read the message from #2
260 QVERIFY(udpSocket.waitForRead());
261 QVERIFY(udpSocket.hasPendingDatagrams());
262 qint64 available = udpSocket.pendingDatagramSize();
263 QVERIFY(available > 0);
264 QByteArray answer;
265 answer.resize(size: available);
266 QIpPacketHeader header;
267 QCOMPARE(udpSocket.readDatagram(answer.data(), answer.size(),
268 &header, QAbstractSocketEngine::WantDatagramSender),
269 qint64(message1.size()));
270 QVERIFY(header.senderAddress == QHostAddress("::1"));
271 QCOMPARE(header.senderAddress, QHostAddress("::1"));
272 QVERIFY(header.senderPort != 0);
273 }
274}
275
276//---------------------------------------------------------------------------
277void tst_PlatformSocketEngine::broadcastTest()
278{
279#ifdef Q_OS_AIX
280 QSKIP("Broadcast does not work on darko");
281#endif
282 PLATFORMSOCKETENGINE broadcastSocket;
283
284 // Initialize a regular Udp socket
285 QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::AnyIPProtocol));
286
287 // Bind to any port on all interfaces
288 QVERIFY(broadcastSocket.bind(QHostAddress::Any, 0));
289 QCOMPARE(broadcastSocket.state(), QAbstractSocket::BoundState);
290 quint16 port = broadcastSocket.localPort();
291 QVERIFY(port > 0);
292
293 // Broadcast an inappropriate troll message
294 QByteArray trollMessage
295 = "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH.";
296 qint64 written = broadcastSocket.writeDatagram(data: trollMessage.data(),
297 len: trollMessage.size(),
298 QIpPacketHeader(QHostAddress::Broadcast, port));
299
300 QVERIFY2(written != -1, qt_error_string().toLocal8Bit());
301 QCOMPARE((int)written, trollMessage.size());
302
303 // Wait until we receive it ourselves
304#if defined(Q_OS_FREEBSD)
305 QEXPECT_FAIL("", "Broadcasting to 255.255.255.255 does not work on FreeBSD", Abort);
306#endif
307 QVERIFY(broadcastSocket.waitForRead());
308 QVERIFY(broadcastSocket.hasPendingDatagrams());
309
310 qlonglong available = broadcastSocket.pendingDatagramSize();
311 QByteArray response;
312 response.resize(size: available);
313 QVERIFY(broadcastSocket.readDatagram(response.data(), response.size())
314 == response.size());
315 QCOMPARE(response, trollMessage);
316
317}
318
319//---------------------------------------------------------------------------
320void tst_PlatformSocketEngine::serverTest()
321{
322 PLATFORMSOCKETENGINE server;
323
324 // Initialize a Tcp socket
325 QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
326
327 // Bind to any port on all interfaces
328 QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
329 QCOMPARE(server.state(), QAbstractSocket::BoundState);
330 quint16 port = server.localPort();
331
332 // Listen for incoming connections
333 QVERIFY(server.listen());
334 QCOMPARE(server.state(), QAbstractSocket::ListeningState);
335
336 // Initialize a Tcp socket
337 PLATFORMSOCKETENGINE client;
338 QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
339 if (!client.connectToHost(address: QHostAddress("127.0.0.1"), port)) {
340 QCOMPARE(client.state(), QAbstractSocket::ConnectingState);
341 QVERIFY(client.waitForWrite());
342 QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
343 }
344
345 // The server accepts the connection
346 int socketDescriptor = server.accept();
347 QVERIFY(socketDescriptor > 0);
348
349 // A socket device is initialized on the server side, passing the
350 // socket descriptor from accept(). It's pre-connected.
351 PLATFORMSOCKETENGINE serverSocket;
352 QVERIFY(serverSocket.initialize(socketDescriptor));
353 QCOMPARE(serverSocket.state(), QAbstractSocket::ConnectedState);
354
355 // The server socket sends a greeting to the clietn
356 QByteArray greeting = "Greetings!";
357 QVERIFY(serverSocket.write(greeting.data(),
358 greeting.size()) == greeting.size());
359
360 // The client waits for the greeting to arrive
361 QVERIFY(client.waitForRead());
362 qint64 available = client.bytesAvailable();
363 QVERIFY(available > 0);
364
365 // The client reads the greeting and checks that it's correct
366 QByteArray response;
367 response.resize(size: available);
368 QVERIFY(client.read(response.data(),
369 response.size()) == response.size());
370 QCOMPARE(response, greeting);
371}
372
373//---------------------------------------------------------------------------
374void tst_PlatformSocketEngine::udpLoopbackPerformance()
375{
376 PLATFORMSOCKETENGINE udpSocket;
377
378 // Initialize device #1
379 QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
380 QVERIFY(udpSocket.isValid());
381 QVERIFY(udpSocket.socketDescriptor() != -1);
382 QCOMPARE(udpSocket.protocol(), QAbstractSocket::IPv4Protocol);
383 QCOMPARE(udpSocket.socketType(), QAbstractSocket::UdpSocket);
384 QCOMPARE(udpSocket.state(), QAbstractSocket::UnconnectedState);
385
386 // Bind #1 to localhost
387 QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0));
388 QCOMPARE(udpSocket.state(), QAbstractSocket::BoundState);
389 quint16 port = udpSocket.localPort();
390 QVERIFY(port != 0);
391
392 // Initialize device #2
393 PLATFORMSOCKETENGINE udpSocket2;
394 QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket));
395
396 // Connect device #2 to #1
397 QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port));
398 QCOMPARE(udpSocket2.state(), QAbstractSocket::ConnectedState);
399
400 const int messageSize = 8192;
401 QByteArray message1(messageSize, '@');
402 QByteArray answer(messageSize, '@');
403
404 QHostAddress localhost = QHostAddress::LocalHost;
405
406 qlonglong readBytes = 0;
407 QElapsedTimer timer;
408 timer.start();
409 while (timer.elapsed() < 5000) {
410 udpSocket2.write(data: message1.data(), len: message1.size());
411 udpSocket.waitForRead();
412 while (udpSocket.hasPendingDatagrams()) {
413 readBytes += (qlonglong) udpSocket.readDatagram(data: answer.data(),
414 maxlen: answer.size());
415 }
416 }
417
418 qDebug(msg: "\t\t%.1fMB/%.1fs: %.1fMB/s",
419 readBytes / (1024.0 * 1024.0),
420 timer.elapsed() / 1024.0,
421 (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024));
422}
423
424//---------------------------------------------------------------------------
425void tst_PlatformSocketEngine::tcpLoopbackPerformance()
426{
427 PLATFORMSOCKETENGINE server;
428
429 // Initialize a Tcp socket
430 QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
431
432 // Bind to any port on all interfaces
433 QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
434 QCOMPARE(server.state(), QAbstractSocket::BoundState);
435 quint16 port = server.localPort();
436
437 // Listen for incoming connections
438 QVERIFY(server.listen());
439 QCOMPARE(server.state(), QAbstractSocket::ListeningState);
440
441 // Initialize a Tcp socket
442 PLATFORMSOCKETENGINE client;
443 QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
444
445 // Connect to our server
446 if (!client.connectToHost(address: QHostAddress("127.0.0.1"), port)) {
447 QCOMPARE(client.state(), QAbstractSocket::ConnectingState);
448 QVERIFY(client.waitForWrite());
449 QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
450 }
451
452 // The server accepts the connection
453 int socketDescriptor = server.accept();
454 QVERIFY(socketDescriptor > 0);
455
456 // A socket device is initialized on the server side, passing the
457 // socket descriptor from accept(). It's pre-connected.
458 PLATFORMSOCKETENGINE serverSocket;
459 QVERIFY(serverSocket.initialize(socketDescriptor));
460 QCOMPARE(serverSocket.state(), QAbstractSocket::ConnectedState);
461
462 const int messageSize = 1024 * 256;
463 QByteArray message1(messageSize, '@');
464 QByteArray answer(messageSize, '@');
465
466 QElapsedTimer timer;
467 timer.start();
468 qlonglong readBytes = 0;
469 while (timer.elapsed() < 5000) {
470 qlonglong written = serverSocket.write(data: message1.data(), len: message1.size());
471 while (written > 0) {
472 client.waitForRead();
473 if (client.bytesAvailable() > 0) {
474 qlonglong readNow = client.read(data: answer.data(), maxlen: answer.size());
475 written -= readNow;
476 readBytes += readNow;
477 }
478 }
479 }
480
481 qDebug(msg: "\t\t%.1fMB/%.1fs: %.1fMB/s",
482 readBytes / (1024.0 * 1024.0),
483 timer.elapsed() / 1024.0,
484 (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024));
485}
486
487#if 0 // unused
488//---------------------------------------------------------------------------
489void tst_PlatformSocketEngine::readWriteBufferSize()
490{
491 PLATFORMSOCKETENGINE device;
492
493 QVERIFY(device.initialize(QAbstractSocket::TcpSocket));
494
495 qint64 bufferSize = device.receiveBufferSize();
496 QVERIFY(bufferSize != -1);
497 device.setReceiveBufferSize(bufferSize + 1);
498 QVERIFY(device.receiveBufferSize() > bufferSize);
499
500 bufferSize = device.sendBufferSize();
501 QVERIFY(bufferSize != -1);
502 device.setSendBufferSize(bufferSize + 1);
503 QVERIFY(device.sendBufferSize() > bufferSize);
504
505}
506#endif
507
508//---------------------------------------------------------------------------
509void tst_PlatformSocketEngine::tooManySockets()
510{
511#if defined Q_OS_WIN
512 QSKIP("Certain windows machines suffocate and spend too much time in this test.");
513#endif
514 QList<PLATFORMSOCKETENGINE *> sockets;
515 PLATFORMSOCKETENGINE *socketLayer = 0;
516 for (;;) {
517 socketLayer = new PLATFORMSOCKETENGINE;
518 sockets.append(t: socketLayer);
519
520 if (!socketLayer->initialize(type: QAbstractSocket::TcpSocket, protocol: QAbstractSocket::IPv4Protocol))
521 break;
522 }
523
524 QCOMPARE(socketLayer->error(), QAbstractSocket::SocketResourceError);
525
526 qDeleteAll(c: sockets);
527}
528
529//---------------------------------------------------------------------------
530void tst_PlatformSocketEngine::bind()
531{
532 PLATFORMSOCKETENGINE binder;
533 QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
534 QCOMPARE(binder.bind(QHostAddress::AnyIPv4, 82), QtNetworkSettings::canBindToLowPorts());
535 if (!QtNetworkSettings::canBindToLowPorts())
536 QCOMPARE(binder.error(), QAbstractSocket::SocketAccessError);
537
538 PLATFORMSOCKETENGINE binder2;
539 QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
540 QVERIFY(binder2.bind(QHostAddress::AnyIPv4, 31180));
541
542 PLATFORMSOCKETENGINE binder3;
543 QVERIFY(binder3.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
544 QVERIFY(!binder3.bind(QHostAddress::AnyIPv4, 31180));
545 QCOMPARE(binder3.error(), QAbstractSocket::AddressInUseError);
546
547 if (QtNetworkSettings::hasIPv6()) {
548 PLATFORMSOCKETENGINE binder;
549 QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv6Protocol));
550 QCOMPARE(binder.bind(QHostAddress::AnyIPv6, 82), QtNetworkSettings::canBindToLowPorts());
551 if (!QtNetworkSettings::canBindToLowPorts())
552 QCOMPARE(binder.error(), QAbstractSocket::SocketAccessError);
553
554 PLATFORMSOCKETENGINE binder4;
555 QVERIFY(binder4.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv6Protocol));
556 QVERIFY(binder4.bind(QHostAddress::AnyIPv6, 31180));
557
558 PLATFORMSOCKETENGINE binder5;
559 QVERIFY(binder5.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv6Protocol));
560 QVERIFY(!binder5.bind(QHostAddress::AnyIPv6, 31180));
561 QCOMPARE(binder5.error(), QAbstractSocket::AddressInUseError);
562 }
563
564 PLATFORMSOCKETENGINE binder6;
565 QVERIFY(binder6.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::AnyIPProtocol));
566 QVERIFY(binder6.bind(QHostAddress::Any, 31181));
567}
568
569//---------------------------------------------------------------------------
570void tst_PlatformSocketEngine::networkError()
571{
572 PLATFORMSOCKETENGINE client;
573
574 QVERIFY(client.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
575
576 const bool isConnected = client.connectToHost(address: QtNetworkSettings::serverIP(), port: 143);
577 if (!isConnected) {
578 QCOMPARE(client.state(), QAbstractSocket::ConnectingState);
579 QVERIFY(client.waitForWrite());
580 QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
581 }
582 QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
583
584 // An unexpected network error!
585#ifdef Q_OS_WINRT
586 client.close();
587#elif defined(Q_OS_WIN)
588 // could use shutdown to produce different errors
589 ::closesocket(client.socketDescriptor());
590#else
591 ::close(fd: client.socketDescriptor());
592#endif
593
594 QVERIFY(client.read(0, 0) == -1);
595}
596
597//---------------------------------------------------------------------------
598void tst_PlatformSocketEngine::setSocketDescriptor()
599{
600 PLATFORMSOCKETENGINE socket1;
601 QVERIFY(socket1.initialize(QAbstractSocket::TcpSocket));
602
603 PLATFORMSOCKETENGINE socket2;
604 QVERIFY(socket2.initialize(socket1.socketDescriptor()));
605}
606
607//---------------------------------------------------------------------------
608void tst_PlatformSocketEngine::invalidSend()
609{
610 PLATFORMSOCKETENGINE socket;
611 QVERIFY(socket.initialize(QAbstractSocket::TcpSocket));
612
613 QTest::ignoreMessage(type: QtWarningMsg, PLATFORMSOCKETENGINESTRING "::writeDatagram() was called"
614 " not in QAbstractSocket::BoundState or QAbstractSocket::ConnectedState");
615 QCOMPARE(socket.writeDatagram("hei", 3, QIpPacketHeader(QHostAddress::LocalHost, 143)),
616 (qlonglong) -1);
617}
618
619//---------------------------------------------------------------------------
620#ifndef Q_OS_WINRT
621void tst_PlatformSocketEngine::receiveUrgentData()
622{
623 PLATFORMSOCKETENGINE server;
624
625 QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
626
627 // Bind to any port on all interfaces
628 QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
629 QCOMPARE(server.state(), QAbstractSocket::BoundState);
630 quint16 port = server.localPort();
631
632 QVERIFY(server.listen());
633 QCOMPARE(server.state(), QAbstractSocket::ListeningState);
634
635 PLATFORMSOCKETENGINE client;
636 QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
637
638 if (!client.connectToHost(address: QHostAddress("127.0.0.1"), port)) {
639 QCOMPARE(client.state(), QAbstractSocket::ConnectingState);
640 QVERIFY(client.waitForWrite());
641 QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
642 }
643
644 int socketDescriptor = server.accept();
645 QVERIFY(socketDescriptor > 0);
646
647 PLATFORMSOCKETENGINE serverSocket;
648 QVERIFY(serverSocket.initialize(socketDescriptor));
649 QCOMPARE(serverSocket.state(), QAbstractSocket::ConnectedState);
650
651 char msg;
652 int available;
653 QByteArray response;
654
655 // Native OOB data test doesn't work on HP-UX or WinCE
656#if !defined(Q_OS_HPUX)
657 // The server sends an urgent message
658 msg = 'Q';
659 QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1);
660
661 // The client receives the urgent message
662 QVERIFY(client.waitForRead());
663 available = client.bytesAvailable();
664 QCOMPARE(available, 1);
665 response.resize(size: available);
666 QCOMPARE(client.read(response.data(), response.size()), qint64(1));
667 QCOMPARE(response.at(0), msg);
668
669 // The client sends an urgent message
670 msg = 'T';
671 int clientDescriptor = client.socketDescriptor();
672 QCOMPARE(int(::send(clientDescriptor, &msg, sizeof(msg), MSG_OOB)), 1);
673
674 // The server receives the urgent message
675 QVERIFY(serverSocket.waitForRead());
676 available = serverSocket.bytesAvailable();
677 QCOMPARE(available, 1);
678 response.resize(size: available);
679 QCOMPARE(serverSocket.read(response.data(), response.size()), qint64(1));
680 QCOMPARE(response.at(0), msg);
681#endif
682}
683#endif // !Q_OS_WINRT
684
685QTEST_MAIN(tst_PlatformSocketEngine)
686#include "tst_platformsocketengine.moc"
687

source code of qtbase/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp