38be0d1383
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
764 lines
26 KiB
C++
764 lines
26 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
** All rights reserved.
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
**
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** No Commercial Usage
|
|
** This file contains pre-release code and may not be distributed.
|
|
** You may use this file in accordance with the terms and conditions
|
|
** contained in the Technology Preview License Agreement accompanying
|
|
** this package.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** If you have questions regarding the use of this file, please contact
|
|
** Nokia at qt-info@nokia.com.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <QtTest/QtTest>
|
|
|
|
#ifdef Q_OS_WIN
|
|
#include <winsock2.h>
|
|
#endif
|
|
|
|
#include <qcoreapplication.h>
|
|
|
|
|
|
#include <qdatastream.h>
|
|
|
|
#include <qhostaddress.h>
|
|
#include <qdatetime.h>
|
|
|
|
#ifdef Q_OS_UNIX
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#endif
|
|
|
|
#include <stddef.h>
|
|
|
|
#ifdef Q_OS_SYMBIAN
|
|
#include <QNetworkConfigurationManager>
|
|
#include <QNetworkConfiguration>
|
|
#include <QNetworkSession>
|
|
#include <QScopedPointer>
|
|
#define PLATFORMSOCKETENGINE QSymbianSocketEngine
|
|
#define PLATFORMSOCKETENGINESTRING "QSymbianSocketEngine"
|
|
#include <private/qsymbiansocketengine_p.h>
|
|
#include <private/qcore_symbian_p.h>
|
|
#else
|
|
#define PLATFORMSOCKETENGINE QNativeSocketEngine
|
|
#define PLATFORMSOCKETENGINESTRING "QNativeSocketEngine"
|
|
#include <private/qnativesocketengine_p.h>
|
|
#endif
|
|
|
|
#include <qstringlist.h>
|
|
|
|
#include "../network-settings.h"
|
|
|
|
//TESTED_FILES=network/qnativesocketengine.cpp network/qnativesocketengine_p.h network/qnativesocketengine_unix.cpp
|
|
|
|
class tst_PlatformSocketEngine : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
tst_PlatformSocketEngine();
|
|
virtual ~tst_PlatformSocketEngine();
|
|
|
|
|
|
public slots:
|
|
void init();
|
|
void cleanup();
|
|
private slots:
|
|
void construction();
|
|
void simpleConnectToIMAP();
|
|
void udpLoopbackTest();
|
|
void udpIPv6LoopbackTest();
|
|
void broadcastTest();
|
|
void serverTest();
|
|
void udpLoopbackPerformance();
|
|
void tcpLoopbackPerformance();
|
|
void readWriteBufferSize();
|
|
void bind();
|
|
void networkError();
|
|
void setSocketDescriptor();
|
|
void invalidSend();
|
|
void receiveUrgentData();
|
|
void tooManySockets();
|
|
};
|
|
|
|
tst_PlatformSocketEngine::tst_PlatformSocketEngine()
|
|
{
|
|
Q_SET_DEFAULT_IAP
|
|
}
|
|
|
|
tst_PlatformSocketEngine::~tst_PlatformSocketEngine()
|
|
{
|
|
}
|
|
|
|
void tst_PlatformSocketEngine::init()
|
|
{
|
|
}
|
|
|
|
void tst_PlatformSocketEngine::cleanup()
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::construction()
|
|
{
|
|
PLATFORMSOCKETENGINE socketDevice;
|
|
|
|
QVERIFY(!socketDevice.isValid());
|
|
|
|
// Initialize device
|
|
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
|
|
QVERIFY(socketDevice.isValid());
|
|
QVERIFY(socketDevice.protocol() == QAbstractSocket::IPv4Protocol);
|
|
QVERIFY(socketDevice.socketType() == QAbstractSocket::TcpSocket);
|
|
QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
|
|
QVERIFY(socketDevice.socketDescriptor() != -1);
|
|
QVERIFY(socketDevice.localAddress() == QHostAddress());
|
|
QVERIFY(socketDevice.localPort() == 0);
|
|
QVERIFY(socketDevice.peerAddress() == QHostAddress());
|
|
QVERIFY(socketDevice.peerPort() == 0);
|
|
QVERIFY(socketDevice.error() == QAbstractSocket::UnknownSocketError);
|
|
|
|
QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::bytesAvailable() was called in QAbstractSocket::UnconnectedState");
|
|
QVERIFY(socketDevice.bytesAvailable() == 0);
|
|
|
|
QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState");
|
|
QVERIFY(!socketDevice.hasPendingDatagrams());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::simpleConnectToIMAP()
|
|
{
|
|
PLATFORMSOCKETENGINE socketDevice;
|
|
|
|
// Initialize device
|
|
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
|
|
QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
|
|
|
|
const bool isConnected = socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143);
|
|
if (!isConnected) {
|
|
QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState);
|
|
QVERIFY(socketDevice.waitForWrite());
|
|
QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState);
|
|
}
|
|
QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState);
|
|
QVERIFY(socketDevice.peerAddress() == QtNetworkSettings::serverIP());
|
|
|
|
// Wait for the greeting
|
|
QVERIFY(socketDevice.waitForRead());
|
|
|
|
// Read the greeting
|
|
qint64 available = socketDevice.bytesAvailable();
|
|
QVERIFY(available > 0);
|
|
QByteArray array;
|
|
array.resize(available);
|
|
QVERIFY(socketDevice.read(array.data(), array.size()) == available);
|
|
|
|
// Check that the greeting is what we expect it to be
|
|
QVERIFY2(QtNetworkSettings::compareReplyIMAP(array), array.constData());
|
|
|
|
// Write a logout message
|
|
QByteArray array2 = "ZZZ LOGOUT\r\n";
|
|
QVERIFY(socketDevice.write(array2.data(),
|
|
array2.size()) == array2.size());
|
|
|
|
// Wait for the response
|
|
QVERIFY(socketDevice.waitForRead());
|
|
|
|
available = socketDevice.bytesAvailable();
|
|
QVERIFY(available > 0);
|
|
array.resize(available);
|
|
QVERIFY(socketDevice.read(array.data(), array.size()) == available);
|
|
|
|
// Check that the greeting is what we expect it to be
|
|
QCOMPARE(array.constData(),
|
|
"* BYE LOGOUT received\r\n"
|
|
"ZZZ OK Completed\r\n");
|
|
|
|
// Wait for the response
|
|
QVERIFY(socketDevice.waitForRead());
|
|
char c;
|
|
QVERIFY(socketDevice.read(&c, sizeof(c)) == -1);
|
|
QVERIFY(socketDevice.error() == QAbstractSocket::RemoteHostClosedError);
|
|
QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::udpLoopbackTest()
|
|
{
|
|
PLATFORMSOCKETENGINE udpSocket;
|
|
|
|
// Initialize device #1
|
|
QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
|
|
QVERIFY(udpSocket.isValid());
|
|
QVERIFY(udpSocket.socketDescriptor() != -1);
|
|
QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol);
|
|
QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket);
|
|
QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState);
|
|
|
|
// Bind #1 to localhost
|
|
QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0));
|
|
QVERIFY(udpSocket.state() == QAbstractSocket::BoundState);
|
|
quint16 port = udpSocket.localPort();
|
|
QVERIFY(port != 0);
|
|
|
|
// Initialize device #2
|
|
PLATFORMSOCKETENGINE udpSocket2;
|
|
QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket));
|
|
|
|
// Connect device #2 to #1
|
|
QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port));
|
|
QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState);
|
|
|
|
// Write a message to #1
|
|
QByteArray message1 = "hei der";
|
|
QVERIFY(udpSocket2.write(message1.data(),
|
|
message1.size()) == message1.size());
|
|
|
|
// Read the message from #2
|
|
QVERIFY(udpSocket.waitForRead());
|
|
QVERIFY(udpSocket.hasPendingDatagrams());
|
|
qint64 available = udpSocket.pendingDatagramSize();
|
|
QVERIFY(available > 0);
|
|
QByteArray answer;
|
|
answer.resize(available);
|
|
QHostAddress senderAddress;
|
|
quint16 senderPort = 0;
|
|
QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(),
|
|
&senderAddress,
|
|
&senderPort) == message1.size());
|
|
QVERIFY(senderAddress == QHostAddress("127.0.0.1"));
|
|
QVERIFY(senderPort != 0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::udpIPv6LoopbackTest()
|
|
{
|
|
PLATFORMSOCKETENGINE udpSocket;
|
|
|
|
// Initialize device #1
|
|
bool init = udpSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol);
|
|
|
|
if (!init) {
|
|
QVERIFY(udpSocket.error() == QAbstractSocket::UnsupportedSocketOperationError);
|
|
} else {
|
|
QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv6Protocol);
|
|
|
|
// Bind #1 to localhost
|
|
QVERIFY(udpSocket.bind(QHostAddress("::1"), 0));
|
|
QVERIFY(udpSocket.state() == QAbstractSocket::BoundState);
|
|
quint16 port = udpSocket.localPort();
|
|
QVERIFY(port != 0);
|
|
|
|
// Initialize device #2
|
|
PLATFORMSOCKETENGINE udpSocket2;
|
|
QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol));
|
|
|
|
// Connect device #2 to #1
|
|
QVERIFY(udpSocket2.connectToHost(QHostAddress("::1"), port));
|
|
QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState);
|
|
|
|
// Write a message to #1
|
|
QByteArray message1 = "hei der";
|
|
QVERIFY(udpSocket2.write(message1.data(),
|
|
message1.size()) == message1.size());
|
|
|
|
// Read the message from #2
|
|
QVERIFY(udpSocket.waitForRead());
|
|
QVERIFY(udpSocket.hasPendingDatagrams());
|
|
qint64 available = udpSocket.pendingDatagramSize();
|
|
QVERIFY(available > 0);
|
|
QByteArray answer;
|
|
answer.resize(available);
|
|
QHostAddress senderAddress;
|
|
quint16 senderPort = 0;
|
|
QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(),
|
|
&senderAddress,
|
|
&senderPort) == message1.size());
|
|
QVERIFY(senderAddress == QHostAddress("::1"));
|
|
QVERIFY(senderPort != 0);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::broadcastTest()
|
|
{
|
|
#ifdef Q_OS_SYMBIAN
|
|
//broadcast isn't supported on loopback connections, but is on WLAN
|
|
#ifndef QT_NO_BEARERMANAGEMENT
|
|
QScopedPointer<QNetworkConfigurationManager> netConfMan(new QNetworkConfigurationManager());
|
|
QNetworkConfiguration networkConfiguration(netConfMan->defaultConfiguration());
|
|
QScopedPointer<QNetworkSession> networkSession(new QNetworkSession(networkConfiguration));
|
|
if (!networkSession->isOpen()) {
|
|
networkSession->open();
|
|
bool ok = networkSession->waitForOpened(30000);
|
|
qDebug() << networkSession->isOpen() << networkSession->error() << networkSession->errorString();
|
|
QVERIFY(ok);
|
|
}
|
|
#endif
|
|
#endif
|
|
#ifdef Q_OS_AIX
|
|
QSKIP("Broadcast does not work on darko", SkipAll);
|
|
#endif
|
|
PLATFORMSOCKETENGINE broadcastSocket;
|
|
|
|
// Initialize a regular Udp socket
|
|
QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket));
|
|
|
|
// Bind to any port on all interfaces
|
|
QVERIFY(broadcastSocket.bind(QHostAddress::Any, 0));
|
|
QVERIFY(broadcastSocket.state() == QAbstractSocket::BoundState);
|
|
quint16 port = broadcastSocket.localPort();
|
|
QVERIFY(port > 0);
|
|
|
|
// Broadcast an inappropriate troll message
|
|
QByteArray trollMessage
|
|
= "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH.";
|
|
qint64 written = broadcastSocket.writeDatagram(trollMessage.data(),
|
|
trollMessage.size(),
|
|
QHostAddress::Broadcast,
|
|
port);
|
|
|
|
#ifdef Q_OS_SYMBIAN
|
|
//On symbian, broadcasts return 0 bytes written if none of the interfaces support it.
|
|
//Notably the loopback interfaces do not. (though they do support multicast!?)
|
|
if (written == 0)
|
|
QEXPECT_FAIL("", "No active interface supports broadcast", Abort);
|
|
#endif
|
|
QCOMPARE((int)written, trollMessage.size());
|
|
|
|
// Wait until we receive it ourselves
|
|
#if defined(Q_OS_FREEBSD)
|
|
QEXPECT_FAIL("", "Broadcasting to 255.255.255.255 does not work on FreeBSD", Abort);
|
|
#endif
|
|
QVERIFY(broadcastSocket.waitForRead());
|
|
QVERIFY(broadcastSocket.hasPendingDatagrams());
|
|
|
|
qlonglong available = broadcastSocket.pendingDatagramSize();
|
|
QByteArray response;
|
|
response.resize(available);
|
|
QVERIFY(broadcastSocket.readDatagram(response.data(), response.size())
|
|
== response.size());
|
|
QCOMPARE(response, trollMessage);
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::serverTest()
|
|
{
|
|
PLATFORMSOCKETENGINE server;
|
|
|
|
// Initialize a Tcp socket
|
|
QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
// Bind to any port on all interfaces
|
|
QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
|
|
QVERIFY(server.state() == QAbstractSocket::BoundState);
|
|
quint16 port = server.localPort();
|
|
|
|
// Listen for incoming connections
|
|
QVERIFY(server.listen());
|
|
QVERIFY(server.state() == QAbstractSocket::ListeningState);
|
|
|
|
// Initialize a Tcp socket
|
|
PLATFORMSOCKETENGINE client;
|
|
QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
|
|
if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) {
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectingState);
|
|
QVERIFY(client.waitForWrite());
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectedState);
|
|
}
|
|
|
|
// The server accepts the connection
|
|
int socketDescriptor = server.accept();
|
|
QVERIFY(socketDescriptor > 0);
|
|
|
|
// A socket device is initialized on the server side, passing the
|
|
// socket descriptor from accept(). It's pre-connected.
|
|
PLATFORMSOCKETENGINE serverSocket;
|
|
QVERIFY(serverSocket.initialize(socketDescriptor));
|
|
QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState);
|
|
|
|
// The server socket sends a greeting to the clietn
|
|
QByteArray greeting = "Greetings!";
|
|
QVERIFY(serverSocket.write(greeting.data(),
|
|
greeting.size()) == greeting.size());
|
|
|
|
// The client waits for the greeting to arrive
|
|
QVERIFY(client.waitForRead());
|
|
qint64 available = client.bytesAvailable();
|
|
QVERIFY(available > 0);
|
|
|
|
// The client reads the greeting and checks that it's correct
|
|
QByteArray response;
|
|
response.resize(available);
|
|
QVERIFY(client.read(response.data(),
|
|
response.size()) == response.size());
|
|
QCOMPARE(response, greeting);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::udpLoopbackPerformance()
|
|
{
|
|
#ifdef SYMBIAN_WINSOCK_CONNECTIVITY
|
|
QSKIP("Not working on Emulator without WinPCAP", SkipAll);
|
|
#endif
|
|
PLATFORMSOCKETENGINE udpSocket;
|
|
|
|
// Initialize device #1
|
|
QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
|
|
QVERIFY(udpSocket.isValid());
|
|
QVERIFY(udpSocket.socketDescriptor() != -1);
|
|
QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol);
|
|
QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket);
|
|
QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState);
|
|
|
|
// Bind #1 to localhost
|
|
QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0));
|
|
QVERIFY(udpSocket.state() == QAbstractSocket::BoundState);
|
|
quint16 port = udpSocket.localPort();
|
|
QVERIFY(port != 0);
|
|
|
|
// Initialize device #2
|
|
PLATFORMSOCKETENGINE udpSocket2;
|
|
QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket));
|
|
|
|
// Connect device #2 to #1
|
|
QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port));
|
|
QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState);
|
|
|
|
const int messageSize = 8192;
|
|
QByteArray message1(messageSize, '@');
|
|
QByteArray answer(messageSize, '@');
|
|
|
|
QHostAddress localhost = QHostAddress::LocalHost;
|
|
|
|
qlonglong readBytes = 0;
|
|
QTime timer;
|
|
timer.start();
|
|
while (timer.elapsed() < 5000) {
|
|
udpSocket2.write(message1.data(), message1.size());
|
|
udpSocket.waitForRead();
|
|
while (udpSocket.hasPendingDatagrams()) {
|
|
readBytes += (qlonglong) udpSocket.readDatagram(answer.data(),
|
|
answer.size());
|
|
}
|
|
}
|
|
|
|
qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
|
|
readBytes / (1024.0 * 1024.0),
|
|
timer.elapsed() / 1024.0,
|
|
(readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024));
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::tcpLoopbackPerformance()
|
|
{
|
|
PLATFORMSOCKETENGINE server;
|
|
|
|
// Initialize a Tcp socket
|
|
QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
// Bind to any port on all interfaces
|
|
QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
|
|
QVERIFY(server.state() == QAbstractSocket::BoundState);
|
|
quint16 port = server.localPort();
|
|
|
|
// Listen for incoming connections
|
|
QVERIFY(server.listen());
|
|
QVERIFY(server.state() == QAbstractSocket::ListeningState);
|
|
|
|
// Initialize a Tcp socket
|
|
PLATFORMSOCKETENGINE client;
|
|
QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
// Connect to our server
|
|
if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) {
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectingState);
|
|
QVERIFY(client.waitForWrite());
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectedState);
|
|
}
|
|
|
|
// The server accepts the connection
|
|
int socketDescriptor = server.accept();
|
|
QVERIFY(socketDescriptor > 0);
|
|
|
|
// A socket device is initialized on the server side, passing the
|
|
// socket descriptor from accept(). It's pre-connected.
|
|
PLATFORMSOCKETENGINE serverSocket;
|
|
QVERIFY(serverSocket.initialize(socketDescriptor));
|
|
QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState);
|
|
|
|
#if defined (Q_OS_SYMBIAN) && defined (__WINS__)
|
|
const int messageSize = 1024 * 16;
|
|
#else
|
|
const int messageSize = 1024 * 256;
|
|
#endif
|
|
QByteArray message1(messageSize, '@');
|
|
QByteArray answer(messageSize, '@');
|
|
|
|
QTime timer;
|
|
timer.start();
|
|
qlonglong readBytes = 0;
|
|
while (timer.elapsed() < 5000) {
|
|
qlonglong written = serverSocket.write(message1.data(), message1.size());
|
|
while (written > 0) {
|
|
client.waitForRead();
|
|
if (client.bytesAvailable() > 0) {
|
|
qlonglong readNow = client.read(answer.data(), answer.size());
|
|
written -= readNow;
|
|
readBytes += readNow;
|
|
}
|
|
}
|
|
}
|
|
|
|
qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
|
|
readBytes / (1024.0 * 1024.0),
|
|
timer.elapsed() / 1024.0,
|
|
(readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024));
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::readWriteBufferSize()
|
|
{
|
|
PLATFORMSOCKETENGINE device;
|
|
|
|
QVERIFY(device.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
qint64 bufferSize = device.receiveBufferSize();
|
|
QVERIFY(bufferSize != -1);
|
|
device.setReceiveBufferSize(bufferSize + 1);
|
|
#if defined(Q_OS_WINCE)
|
|
QEXPECT_FAIL(0, "Not supported by default on WinCE", Continue);
|
|
#endif
|
|
QVERIFY(device.receiveBufferSize() > bufferSize);
|
|
|
|
bufferSize = device.sendBufferSize();
|
|
QVERIFY(bufferSize != -1);
|
|
device.setSendBufferSize(bufferSize + 1);
|
|
QVERIFY(device.sendBufferSize() > bufferSize);
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::tooManySockets()
|
|
{
|
|
#if defined Q_OS_WIN
|
|
QSKIP("Certain windows machines suffocate and spend too much time in this test.", SkipAll);
|
|
#endif
|
|
QList<PLATFORMSOCKETENGINE *> sockets;
|
|
PLATFORMSOCKETENGINE *socketLayer = 0;
|
|
for (;;) {
|
|
socketLayer = new PLATFORMSOCKETENGINE;
|
|
sockets.append(socketLayer);
|
|
|
|
if (!socketLayer->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol))
|
|
break;
|
|
}
|
|
|
|
QCOMPARE(socketLayer->error(), QAbstractSocket::SocketResourceError);
|
|
|
|
qDeleteAll(sockets);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::bind()
|
|
{
|
|
#if !defined Q_OS_WIN && !defined Q_OS_SYMBIAN
|
|
PLATFORMSOCKETENGINE binder;
|
|
QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
|
|
QVERIFY(!binder.bind(QHostAddress::Any, 82));
|
|
QVERIFY(binder.error() == QAbstractSocket::SocketAccessError);
|
|
#endif
|
|
|
|
PLATFORMSOCKETENGINE binder2;
|
|
QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
|
|
QVERIFY(binder2.bind(QHostAddress::Any, 31180));
|
|
|
|
PLATFORMSOCKETENGINE binder3;
|
|
QVERIFY(binder3.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
|
|
QVERIFY(!binder3.bind(QHostAddress::Any, 31180));
|
|
|
|
#ifdef SYMBIAN_WINSOCK_CONNECTIVITY
|
|
qDebug("On Symbian Emulator (WinSock) we get EADDRNOTAVAIL instead of EADDRINUSE");
|
|
QVERIFY(binder3.error() == QAbstractSocket::SocketAddressNotAvailableError);
|
|
#else
|
|
QVERIFY(binder3.error() == QAbstractSocket::AddressInUseError);
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::networkError()
|
|
{
|
|
PLATFORMSOCKETENGINE client;
|
|
|
|
QVERIFY(client.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
|
|
|
|
const bool isConnected = client.connectToHost(QtNetworkSettings::serverIP(), 143);
|
|
if (!isConnected) {
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectingState);
|
|
QVERIFY(client.waitForWrite());
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectedState);
|
|
}
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectedState);
|
|
|
|
// An unexpected network error!
|
|
#ifdef Q_OS_WIN
|
|
// could use shutdown to produce different errors
|
|
::closesocket(client.socketDescriptor());
|
|
#elif defined(Q_OS_SYMBIAN)
|
|
RSocket sock;
|
|
QVERIFY(QSymbianSocketManager::instance().lookupSocket(client.socketDescriptor(), sock));
|
|
TRequestStatus stat;
|
|
sock.Shutdown(RSocket::EImmediate, stat);
|
|
User::WaitForRequest(stat);
|
|
#else
|
|
::close(client.socketDescriptor());
|
|
#endif
|
|
|
|
QVERIFY(client.read(0, 0) == -1);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::setSocketDescriptor()
|
|
{
|
|
PLATFORMSOCKETENGINE socket1;
|
|
QVERIFY(socket1.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
PLATFORMSOCKETENGINE socket2;
|
|
QVERIFY(socket2.initialize(socket1.socketDescriptor()));
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::invalidSend()
|
|
{
|
|
PLATFORMSOCKETENGINE socket;
|
|
QVERIFY(socket.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::writeDatagram() was"
|
|
" called by a socket other than QAbstractSocket::UdpSocket");
|
|
QCOMPARE(socket.writeDatagram("hei", 3, QHostAddress::LocalHost, 143),
|
|
(qlonglong) -1);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void tst_PlatformSocketEngine::receiveUrgentData()
|
|
{
|
|
PLATFORMSOCKETENGINE server;
|
|
|
|
QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
// Bind to any port on all interfaces
|
|
QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
|
|
QVERIFY(server.state() == QAbstractSocket::BoundState);
|
|
quint16 port = server.localPort();
|
|
|
|
QVERIFY(server.listen());
|
|
QVERIFY(server.state() == QAbstractSocket::ListeningState);
|
|
|
|
PLATFORMSOCKETENGINE client;
|
|
QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
|
|
|
|
if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) {
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectingState);
|
|
QVERIFY(client.waitForWrite());
|
|
QVERIFY(client.state() == QAbstractSocket::ConnectedState);
|
|
}
|
|
|
|
int socketDescriptor = server.accept();
|
|
QVERIFY(socketDescriptor > 0);
|
|
|
|
PLATFORMSOCKETENGINE serverSocket;
|
|
QVERIFY(serverSocket.initialize(socketDescriptor));
|
|
QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState);
|
|
|
|
char msg;
|
|
int available;
|
|
QByteArray response;
|
|
|
|
#if defined Q_OS_HPUX
|
|
QSKIP("Native OOB data test doesn't work on HP-UX.", SkipAll);
|
|
#elif defined (Q_OS_WINCE)
|
|
QSKIP("Native OOB data test doesn't work on WinCE.", SkipAll);
|
|
#endif
|
|
|
|
// The server sends an urgent message
|
|
msg = 'Q';
|
|
#if defined(Q_OS_SYMBIAN)
|
|
RSocket sock;
|
|
QVERIFY(QSymbianSocketManager::instance().lookupSocket(socketDescriptor, sock));
|
|
TRequestStatus stat;
|
|
TSockXfrLength len;
|
|
sock.Send(TPtrC8((TUint8*)&msg,1), KSockWriteUrgent, stat, len);
|
|
User::WaitForRequest(stat);
|
|
QVERIFY(stat == KErrNone);
|
|
QCOMPARE(len(), 1);
|
|
#else
|
|
QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1);
|
|
#endif
|
|
|
|
// The client receives the urgent message
|
|
QVERIFY(client.waitForRead());
|
|
available = client.bytesAvailable();
|
|
QCOMPARE(available, 1);
|
|
response.resize(available);
|
|
QCOMPARE(client.read(response.data(), response.size()), qint64(1));
|
|
QCOMPARE(response.at(0), msg);
|
|
|
|
// The client sends an urgent message
|
|
msg = 'T';
|
|
int clientDescriptor = client.socketDescriptor();
|
|
#if defined(Q_OS_SYMBIAN)
|
|
QVERIFY(QSymbianSocketManager::instance().lookupSocket(clientDescriptor, sock));
|
|
sock.Send(TPtrC8((TUint8*)&msg,1), KSockWriteUrgent, stat, len);
|
|
User::WaitForRequest(stat);
|
|
QVERIFY(stat == KErrNone);
|
|
QCOMPARE(len(), 1);
|
|
#else
|
|
QCOMPARE(int(::send(clientDescriptor, &msg, sizeof(msg), MSG_OOB)), 1);
|
|
#endif
|
|
|
|
// The server receives the urgent message
|
|
QVERIFY(serverSocket.waitForRead());
|
|
available = serverSocket.bytesAvailable();
|
|
QCOMPARE(available, 1);
|
|
response.resize(available);
|
|
QCOMPARE(serverSocket.read(response.data(), response.size()), qint64(1));
|
|
QCOMPARE(response.at(0), msg);
|
|
|
|
}
|
|
|
|
QTEST_MAIN(tst_PlatformSocketEngine)
|
|
#include "tst_platformsocketengine.moc"
|