~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
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
 
 
42
#include <qglobal.h>
 
43
 
 
44
// To prevent windows system header files from re-defining min/max
 
45
#define NOMINMAX 1
 
46
#if defined(_WIN32)
 
47
#include <winsock2.h>
 
48
#else
 
49
#include <sys/types.h>
 
50
#include <sys/socket.h>
 
51
#include <fcntl.h>
 
52
#include <unistd.h>
 
53
#define SOCKET int
 
54
#define INVALID_SOCKET -1
 
55
#endif
 
56
 
 
57
#include <qplatformdefs.h>
 
58
 
 
59
#include <QtTest/QtTest>
 
60
 
 
61
#include <QAuthenticator>
 
62
#include <QCoreApplication>
 
63
#include <QEventLoop>
 
64
#include <QFile>
 
65
#include <QHostAddress>
 
66
#include <QHostInfo>
 
67
#include <QMap>
 
68
#include <QPointer>
 
69
#include <QProcess>
 
70
#include <QStringList>
 
71
#include <QTcpServer>
 
72
#include <QTcpSocket>
 
73
#ifndef QT_NO_SSL
 
74
#include <QSslSocket>
 
75
#endif
 
76
#include <QTextStream>
 
77
#include <QThread>
 
78
#include <QTime>
 
79
#include <QTimer>
 
80
#include <QDebug>
 
81
// RVCT compiles also unused inline methods
 
82
# include <QNetworkProxy>
 
83
 
 
84
#ifdef Q_OS_LINUX
 
85
#include <stdio.h>
 
86
#include <stdlib.h>
 
87
#include <sys/stat.h>
 
88
#include <unistd.h>
 
89
#endif
 
90
 
 
91
#include "private/qhostinfo_p.h"
 
92
 
 
93
#include "../../../network-settings.h"
 
94
 
 
95
QT_FORWARD_DECLARE_CLASS(QTcpSocket)
 
96
class SocketPair;
 
97
 
 
98
class tst_QTcpSocket : public QObject
 
99
{
 
100
    Q_OBJECT
 
101
 
 
102
public:
 
103
    tst_QTcpSocket();
 
104
    virtual ~tst_QTcpSocket();
 
105
 
 
106
    static void enterLoop(int secs)
 
107
    {
 
108
        ++loopLevel;
 
109
        QTestEventLoop::instance().enterLoop(secs);
 
110
        --loopLevel;
 
111
    }
 
112
    static void exitLoop()
 
113
    {
 
114
        // Safe exit - if we aren't in an event loop, don't
 
115
        // exit one.
 
116
        if (loopLevel > 0)
 
117
            QTestEventLoop::instance().exitLoop();
 
118
    }
 
119
    static bool timeout()
 
120
    {
 
121
        return QTestEventLoop::instance().timeout();
 
122
    }
 
123
 
 
124
public slots:
 
125
    void initTestCase_data();
 
126
    void initTestCase();
 
127
    void init();
 
128
    void cleanup();
 
129
private slots:
 
130
    void socketsConstructedBeforeEventLoop();
 
131
    void constructing();
 
132
    void bind_data();
 
133
    void bind();
 
134
    void setInvalidSocketDescriptor();
 
135
    void setSocketDescriptor();
 
136
    void socketDescriptor();
 
137
    void blockingIMAP();
 
138
    void nonBlockingIMAP();
 
139
    void hostNotFound();
 
140
    void timeoutConnect_data();
 
141
    void timeoutConnect();
 
142
    void delayedClose();
 
143
    void partialRead();
 
144
    void unget();
 
145
    void readAllAfterClose();
 
146
    void openCloseOpenClose();
 
147
    void connectDisconnectConnectDisconnect();
 
148
    void disconnectWhileConnecting_data();
 
149
    void disconnectWhileConnecting();
 
150
    void disconnectWhileConnectingNoEventLoop_data();
 
151
    void disconnectWhileConnectingNoEventLoop();
 
152
    void disconnectWhileLookingUp_data();
 
153
    void disconnectWhileLookingUp();
 
154
    void downloadBigFile();
 
155
    void readLine();
 
156
    void readLineString();
 
157
    void readChunks();
 
158
    void waitForBytesWritten();
 
159
    void waitForBytesWrittenMinusOne();
 
160
    void waitForReadyRead();
 
161
    void waitForReadyReadMinusOne();
 
162
    void flush();
 
163
    void synchronousApi();
 
164
    void dontCloseOnTimeout();
 
165
    void recursiveReadyRead();
 
166
    void atEnd();
 
167
    void socketInAThread();
 
168
    void socketsInThreads();
 
169
    void waitForReadyReadInASlot();
 
170
    void remoteCloseError();
 
171
    void nestedEventLoopInErrorSlot();
 
172
#ifndef Q_OS_WIN
 
173
    void connectToLocalHostNoService();
 
174
#endif
 
175
    void waitForConnectedInHostLookupSlot();
 
176
    void waitForConnectedInHostLookupSlot2();
 
177
    void readyReadSignalsAfterWaitForReadyRead();
 
178
#ifdef Q_OS_LINUX
 
179
    void linuxKernelBugLocalSocket();
 
180
#endif
 
181
    void abortiveClose();
 
182
    void localAddressEmptyOnBSD();
 
183
    void zeroAndMinusOneReturns();
 
184
    void connectionRefused();
 
185
    void suddenRemoteDisconnect_data();
 
186
    void suddenRemoteDisconnect();
 
187
    void connectToMultiIP();
 
188
    void moveToThread0();
 
189
    void increaseReadBufferSize();
 
190
    void taskQtBug5799ConnectionErrorWaitForConnected();
 
191
    void taskQtBug5799ConnectionErrorEventLoop();
 
192
    void taskQtBug7054TimeoutErrorResetting();
 
193
 
 
194
    void invalidProxy_data();
 
195
    void invalidProxy();
 
196
    void proxyFactory_data();
 
197
    void proxyFactory();
 
198
 
 
199
    void qtbug14268_peek();
 
200
 
 
201
    void setSocketOption();
 
202
 
 
203
 
 
204
protected slots:
 
205
    void nonBlockingIMAP_hostFound();
 
206
    void nonBlockingIMAP_connected();
 
207
    void nonBlockingIMAP_closed();
 
208
    void nonBlockingIMAP_readyRead();
 
209
    void nonBlockingIMAP_bytesWritten(qint64);
 
210
    void readRegularFile_readyRead();
 
211
    void exitLoopSlot();
 
212
    void downloadBigFileSlot();
 
213
    void recursiveReadyReadSlot();
 
214
    void waitForReadyReadInASlotSlot();
 
215
    void enterLoopSlot();
 
216
    void hostLookupSlot();
 
217
    void abortiveClose_abortSlot();
 
218
    void remoteCloseErrorSlot();
 
219
    void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
 
220
    void earlySocketBytesSent(qint64 bytes);
 
221
    void earlySocketReadyRead();
 
222
 
 
223
private:
 
224
    QByteArray expectedReplyIMAP();
 
225
    void fetchExpectedReplyIMAP();
 
226
    QTcpSocket *newSocket() const;
 
227
    QTcpSocket *nonBlockingIMAP_socket;
 
228
    QStringList nonBlockingIMAP_data;
 
229
    qint64 nonBlockingIMAP_totalWritten;
 
230
 
 
231
    QTcpSocket *tmpSocket;
 
232
    qint64 bytesAvailable;
 
233
    qint64 expectedLength;
 
234
    bool readingBody;
 
235
    QTime timer;
 
236
 
 
237
    QByteArray expectedReplyIMAP_cached;
 
238
 
 
239
    mutable int proxyAuthCalled;
 
240
 
 
241
    bool gotClosedSignal;
 
242
    int numConnections;
 
243
    static int loopLevel;
 
244
 
 
245
    SocketPair *earlyConstructedSockets;
 
246
    int earlyBytesWrittenCount;
 
247
    int earlyReadyReadCount;
 
248
    QString stressTestDir;
 
249
};
 
250
 
 
251
enum ProxyTests {
 
252
    NoProxy = 0x00,
 
253
    Socks5Proxy = 0x01,
 
254
    HttpProxy = 0x02,
 
255
    TypeMask = 0x0f,
 
256
 
 
257
    NoAuth = 0x00,
 
258
    AuthBasic = 0x10,
 
259
    AuthNtlm = 0x20,
 
260
    AuthMask = 0xf0
 
261
};
 
262
 
 
263
int tst_QTcpSocket::loopLevel = 0;
 
264
 
 
265
class SocketPair: public QObject
 
266
{
 
267
    Q_OBJECT
 
268
public:
 
269
    QTcpSocket *endPoints[2];
 
270
 
 
271
    SocketPair(QObject *parent = 0)
 
272
        : QObject(parent)
 
273
    {
 
274
        endPoints[0] = endPoints[1] = 0;
 
275
    }
 
276
 
 
277
    bool create()
 
278
    {
 
279
        QTcpServer server;
 
280
        server.listen();
 
281
 
 
282
        QTcpSocket *active = new QTcpSocket(this);
 
283
        active->connectToHost("127.0.0.1", server.serverPort());
 
284
 
 
285
        if (!active->waitForConnected(1000))
 
286
            return false;
 
287
 
 
288
        if (!server.waitForNewConnection(1000))
 
289
            return false;
 
290
 
 
291
        QTcpSocket *passive = server.nextPendingConnection();
 
292
        passive->setParent(this);
 
293
 
 
294
        endPoints[0] = active;
 
295
        endPoints[1] = passive;
 
296
        return true;
 
297
    }
 
298
};
 
299
 
 
300
tst_QTcpSocket::tst_QTcpSocket()
 
301
{
 
302
    tmpSocket = 0;
 
303
 
 
304
    //This code relates to the socketsConstructedBeforeEventLoop test case
 
305
    earlyConstructedSockets = new SocketPair;
 
306
    QVERIFY(earlyConstructedSockets->create());
 
307
    earlyBytesWrittenCount = 0;
 
308
    earlyReadyReadCount = 0;
 
309
    connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead()));
 
310
    connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64)));
 
311
    earlyConstructedSockets->endPoints[1]->write("hello work");
 
312
}
 
313
 
 
314
tst_QTcpSocket::~tst_QTcpSocket()
 
315
{
 
316
 
 
317
}
 
318
 
 
319
void tst_QTcpSocket::initTestCase_data()
 
320
{
 
321
    QTest::addColumn<bool>("setProxy");
 
322
    QTest::addColumn<int>("proxyType");
 
323
    QTest::addColumn<bool>("ssl");
 
324
 
 
325
    qDebug() << QtNetworkSettings::serverName();
 
326
    QTest::newRow("WithoutProxy") << false << 0 << false;
 
327
    QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false;
 
328
    QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false;
 
329
 
 
330
    QTest::newRow("WithHttpProxy") << true << int(HttpProxy) << false;
 
331
    QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic) << false;
 
332
//    QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm) << false;
 
333
 
 
334
#ifndef QT_NO_SSL
 
335
    QTest::newRow("WithoutProxy SSL") << false << 0 << true;
 
336
    QTest::newRow("WithSocks5Proxy SSL") << true << int(Socks5Proxy) << true;
 
337
    QTest::newRow("WithSocks5AuthProxy SSL") << true << int(Socks5Proxy | AuthBasic) << true;
 
338
 
 
339
    QTest::newRow("WithHttpProxy SSL") << true << int(HttpProxy) << true;
 
340
    QTest::newRow("WithHttpProxyBasicAuth SSL") << true << int(HttpProxy | AuthBasic) << true;
 
341
//    QTest::newRow("WithHttpProxyNtlmAuth SSL") << true << int(HttpProxy | AuthNtlm) << true;
 
342
#endif
 
343
 
 
344
    stressTestDir = QFINDTESTDATA("stressTest");
 
345
    QVERIFY2(!stressTestDir.isEmpty(), qPrintable(
 
346
        QString::fromLatin1("Couldn't find stressTest dir starting from %1.").arg(QDir::currentPath())));
 
347
}
 
348
 
 
349
void tst_QTcpSocket::initTestCase()
 
350
{
 
351
    QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
 
352
}
 
353
 
 
354
void tst_QTcpSocket::init()
 
355
{
 
356
    QFETCH_GLOBAL(bool, setProxy);
 
357
    if (setProxy) {
 
358
        QFETCH_GLOBAL(int, proxyType);
 
359
        QList<QHostAddress> addresses = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses();
 
360
        QVERIFY2(addresses.count() > 0, "failed to get ip address for test server");
 
361
        QString fluke = addresses.first().toString();
 
362
        QNetworkProxy proxy;
 
363
 
 
364
        switch (proxyType) {
 
365
        case Socks5Proxy:
 
366
            proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
 
367
            break;
 
368
 
 
369
        case Socks5Proxy | AuthBasic:
 
370
            proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
 
371
            break;
 
372
 
 
373
        case HttpProxy | NoAuth:
 
374
            proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
 
375
            break;
 
376
 
 
377
        case HttpProxy | AuthBasic:
 
378
            proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
 
379
            break;
 
380
 
 
381
        case HttpProxy | AuthNtlm:
 
382
            proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
 
383
            break;
 
384
        }
 
385
        QNetworkProxy::setApplicationProxy(proxy);
 
386
    }
 
387
 
 
388
    qt_qhostinfo_clear_cache();
 
389
}
 
390
 
 
391
QTcpSocket *tst_QTcpSocket::newSocket() const
 
392
{
 
393
    QTcpSocket *socket;
 
394
#ifndef QT_NO_SSL
 
395
    QFETCH_GLOBAL(bool, ssl);
 
396
    socket = ssl ? new QSslSocket : new QTcpSocket;
 
397
#else
 
398
    socket = new QTcpSocket;
 
399
#endif
 
400
 
 
401
    proxyAuthCalled = 0;
 
402
    connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
403
            SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
404
            Qt::DirectConnection);
 
405
    return socket;
 
406
}
 
407
 
 
408
void tst_QTcpSocket::cleanup()
 
409
{
 
410
    QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
 
411
}
 
412
 
 
413
void tst_QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
 
414
{
 
415
    ++proxyAuthCalled;
 
416
    auth->setUser("qsockstest");
 
417
    auth->setPassword("password");
 
418
}
 
419
 
 
420
//----------------------------------------------------------------------------------
 
421
 
 
422
void tst_QTcpSocket::socketsConstructedBeforeEventLoop()
 
423
{
 
424
    QFETCH_GLOBAL(bool, setProxy);
 
425
    QFETCH_GLOBAL(bool, ssl);
 
426
    if (setProxy || ssl)
 
427
        return;
 
428
    //This test checks that sockets constructed before QCoreApplication::exec() still emit signals
 
429
    //see construction code in the tst_QTcpSocket constructor
 
430
    enterLoop(3);
 
431
    QCOMPARE(earlyBytesWrittenCount, 1);
 
432
    QCOMPARE(earlyReadyReadCount, 1);
 
433
    earlyConstructedSockets->endPoints[0]->close();
 
434
    earlyConstructedSockets->endPoints[1]->close();
 
435
}
 
436
 
 
437
void tst_QTcpSocket::earlySocketBytesSent(qint64 /* bytes */)
 
438
{
 
439
    earlyBytesWrittenCount++;
 
440
}
 
441
 
 
442
void tst_QTcpSocket::earlySocketReadyRead()
 
443
{
 
444
    earlyReadyReadCount++;
 
445
}
 
446
 
 
447
//----------------------------------------------------------------------------------
 
448
 
 
449
void tst_QTcpSocket::constructing()
 
450
{
 
451
    QTcpSocket *socket = newSocket();
 
452
 
 
453
    // Check the initial state of the QTcpSocket.
 
454
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
455
    QVERIFY(socket->isSequential());
 
456
    QVERIFY(!socket->isOpen());
 
457
    QVERIFY(!socket->isValid());
 
458
    QCOMPARE(socket->socketType(), QTcpSocket::TcpSocket);
 
459
 
 
460
    char c;
 
461
    QCOMPARE(socket->getChar(&c), false);
 
462
    QCOMPARE((int) socket->bytesAvailable(), 0);
 
463
    QCOMPARE(socket->canReadLine(), false);
 
464
    QCOMPARE(socket->readLine(), QByteArray());
 
465
    QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
 
466
    QCOMPARE((int) socket->localPort(), 0);
 
467
    QVERIFY(socket->localAddress() == QHostAddress());
 
468
    QCOMPARE((int) socket->peerPort(), 0);
 
469
    QVERIFY(socket->peerAddress() == QHostAddress());
 
470
    QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
 
471
    QCOMPARE(socket->errorString(), QString("Unknown error"));
 
472
 
 
473
    // Check the state of the socket layer?
 
474
    delete socket;
 
475
}
 
476
 
 
477
//----------------------------------------------------------------------------------
 
478
 
 
479
void tst_QTcpSocket::bind_data()
 
480
{
 
481
    QTest::addColumn<QString>("stringAddr");
 
482
    QTest::addColumn<bool>("successExpected");
 
483
    QTest::addColumn<QString>("stringExpectedLocalAddress");
 
484
 
 
485
    // iterate all interfaces, add all addresses on them as test data
 
486
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
 
487
    foreach (const QNetworkInterface &interface, interfaces) {
 
488
        if (!interface.isValid())
 
489
            continue;
 
490
 
 
491
        foreach (const QNetworkAddressEntry &entry, interface.addressEntries()) {
 
492
            if (entry.ip().isInSubnet(QHostAddress::parseSubnet("fe80::/10"))
 
493
                || entry.ip().isInSubnet(QHostAddress::parseSubnet("169.254/16")))
 
494
                continue; // link-local bind will fail, at least on Linux, so skip it.
 
495
 
 
496
            QString ip(entry.ip().toString());
 
497
            QTest::newRow(ip.toLatin1().constData()) << ip << true << ip;
 
498
        }
 
499
    }
 
500
 
 
501
    // additionally, try bind to known-bad addresses, and make sure this doesn't work
 
502
    // these ranges are guaranteed to be reserved for 'documentation purposes',
 
503
    // and thus, should be unused in the real world. Not that I'm assuming the
 
504
    // world is full of competent administrators, or anything.
 
505
    QStringList knownBad;
 
506
    knownBad << "198.51.100.1";
 
507
    knownBad << "2001:0DB8::1";
 
508
    foreach (const QString &badAddress, knownBad) {
 
509
        QTest::newRow(badAddress.toLatin1().constData()) << badAddress << false << QString();
 
510
    }
 
511
}
 
512
 
 
513
void tst_QTcpSocket::bind()
 
514
{
 
515
    QFETCH_GLOBAL(bool, setProxy);
 
516
    if (setProxy)
 
517
        QSKIP("QTBUG-22964");
 
518
    QFETCH(QString, stringAddr);
 
519
    QFETCH(bool, successExpected);
 
520
    QFETCH(QString, stringExpectedLocalAddress);
 
521
 
 
522
    QHostAddress addr(stringAddr);
 
523
    QHostAddress expectedLocalAddress(stringExpectedLocalAddress);
 
524
 
 
525
    QTcpSocket *socket = newSocket();
 
526
    qDebug() << "Binding " << addr;
 
527
 
 
528
    if (successExpected) {
 
529
        QVERIFY2(socket->bind(addr), qPrintable(socket->errorString()));
 
530
    } else {
 
531
        QVERIFY(!socket->bind(addr));
 
532
    }
 
533
 
 
534
    QCOMPARE(socket->localAddress(), expectedLocalAddress);
 
535
 
 
536
    delete socket;
 
537
}
 
538
 
 
539
//----------------------------------------------------------------------------------
 
540
 
 
541
 
 
542
void tst_QTcpSocket::setInvalidSocketDescriptor()
 
543
{
 
544
    QTcpSocket *socket = newSocket();
 
545
    QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
 
546
    QVERIFY(!socket->setSocketDescriptor(-5, QTcpSocket::UnconnectedState));
 
547
    QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
 
548
 
 
549
    QCOMPARE(socket->error(), QTcpSocket::UnsupportedSocketOperationError);
 
550
 
 
551
    delete socket;
 
552
}
 
553
 
 
554
//----------------------------------------------------------------------------------
 
555
 
 
556
void tst_QTcpSocket::setSocketDescriptor()
 
557
{
 
558
    QFETCH_GLOBAL(bool, setProxy);
 
559
    if (setProxy)
 
560
        return;                 // this test doesn't make sense with proxies
 
561
 
 
562
#ifdef Q_OS_WIN
 
563
    // need the dummy to ensure winsock is started
 
564
    QTcpSocket *dummy = newSocket();
 
565
    dummy->connectToHost(QtNetworkSettings::serverName(), 143);
 
566
    QVERIFY(dummy->waitForConnected());
 
567
 
 
568
    SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
569
    if (sock == INVALID_SOCKET) {
 
570
        qErrnoWarning(WSAGetLastError(), "INVALID_SOCKET");
 
571
    }
 
572
#else
 
573
    SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0);
 
574
 
 
575
    // artificially increase the value of sock
 
576
    SOCKET sock2 = ::fcntl(sock, F_DUPFD, sock + 50);
 
577
    ::close(sock);
 
578
    sock = sock2;
 
579
#endif
 
580
 
 
581
    QVERIFY(sock != INVALID_SOCKET);
 
582
    QTcpSocket *socket = newSocket();
 
583
    QVERIFY(socket->setSocketDescriptor(sock, QTcpSocket::UnconnectedState));
 
584
    QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
 
585
 
 
586
    qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test.
 
587
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
588
    QCOMPARE(socket->state(), QTcpSocket::HostLookupState);
 
589
    QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
 
590
    QVERIFY(socket->waitForConnected(10000));
 
591
    // skip this, it has been broken for years, see task 260735
 
592
    // if somebody complains, consider fixing it, but it might break existing applications.
 
593
    QEXPECT_FAIL("", "bug has been around for years, will not fix without need", Continue);
 
594
    QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
 
595
    delete socket;
 
596
#ifdef Q_OS_WIN
 
597
    delete dummy;
 
598
#endif
 
599
}
 
600
 
 
601
//----------------------------------------------------------------------------------
 
602
 
 
603
void tst_QTcpSocket::socketDescriptor()
 
604
{
 
605
    QTcpSocket *socket = newSocket();
 
606
 
 
607
    QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
 
608
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
609
    QVERIFY((socket->state() == QAbstractSocket::HostLookupState && socket->socketDescriptor() == -1) ||
 
610
            (socket->state() == QAbstractSocket::ConnectingState && socket->socketDescriptor() != -1));
 
611
    QVERIFY(socket->waitForConnected(10000));
 
612
    QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
 
613
    QVERIFY(socket->socketDescriptor() != -1);
 
614
 
 
615
    delete socket;
 
616
}
 
617
 
 
618
//----------------------------------------------------------------------------------
 
619
 
 
620
void tst_QTcpSocket::blockingIMAP()
 
621
{
 
622
    QTcpSocket *socket = newSocket();
 
623
 
 
624
    // Connect
 
625
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
626
    QVERIFY(socket->waitForConnected(10000));
 
627
    QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
 
628
    QVERIFY(socket->isValid());
 
629
 
 
630
    // Read greeting
 
631
    QVERIFY(socket->waitForReadyRead(5000));
 
632
    QString s = socket->readLine();
 
633
    // only test if an OK was returned, to make the test compatible between different
 
634
    // IMAP server versions
 
635
    QCOMPARE(s.left(4).toLatin1().constData(), "* OK");
 
636
 
 
637
    // Write NOOP
 
638
    QCOMPARE((int) socket->write("1 NOOP\r\n", 8), 8);
 
639
    QCOMPARE((int) socket->write("2 NOOP\r\n", 8), 8);
 
640
 
 
641
    if (!socket->canReadLine())
 
642
        QVERIFY(socket->waitForReadyRead(5000));
 
643
 
 
644
    // Read response
 
645
    s = socket->readLine();
 
646
    QCOMPARE(s.toLatin1().constData(), "1 OK Completed\r\n");
 
647
 
 
648
    // Write a third NOOP to verify that write doesn't clear the read buffer
 
649
    QCOMPARE((int) socket->write("3 NOOP\r\n", 8), 8);
 
650
 
 
651
    // Read second response
 
652
    if (!socket->canReadLine())
 
653
        QVERIFY(socket->waitForReadyRead(5000));
 
654
    s = socket->readLine();
 
655
    QCOMPARE(s.toLatin1().constData(), "2 OK Completed\r\n");
 
656
 
 
657
    // Read third response
 
658
    if (!socket->canReadLine())
 
659
        QVERIFY(socket->waitForReadyRead(5000));
 
660
    s = socket->readLine();
 
661
    QCOMPARE(s.toLatin1().constData(), "3 OK Completed\r\n");
 
662
 
 
663
 
 
664
    // Write LOGOUT
 
665
    QCOMPARE((int) socket->write("4 LOGOUT\r\n", 10), 10);
 
666
 
 
667
    if (!socket->canReadLine())
 
668
        QVERIFY(socket->waitForReadyRead(5000));
 
669
 
 
670
    // Read two lines of respose
 
671
    s = socket->readLine();
 
672
    QCOMPARE(s.toLatin1().constData(), "* BYE LOGOUT received\r\n");
 
673
 
 
674
    if (!socket->canReadLine())
 
675
        QVERIFY(socket->waitForReadyRead(5000));
 
676
 
 
677
    s = socket->readLine();
 
678
    QCOMPARE(s.toLatin1().constData(), "4 OK Completed\r\n");
 
679
 
 
680
    // Close the socket
 
681
    socket->close();
 
682
 
 
683
    // Check that it's closed
 
684
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
685
 
 
686
    delete socket;
 
687
}
 
688
 
 
689
//----------------------------------------------------------------------------------
 
690
 
 
691
void tst_QTcpSocket::hostNotFound()
 
692
{
 
693
    QTcpSocket *socket = newSocket();
 
694
 
 
695
    socket->connectToHost("nosuchserver.qt-project.org", 80);
 
696
    QVERIFY(!socket->waitForConnected());
 
697
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
698
    QCOMPARE(int(socket->error()), int(QTcpSocket::HostNotFoundError));
 
699
 
 
700
    delete socket;
 
701
}
 
702
 
 
703
//----------------------------------------------------------------------------------
 
704
void tst_QTcpSocket::timeoutConnect_data()
 
705
{
 
706
    QTest::addColumn<QString>("address");
 
707
    QTest::newRow("host") << QtNetworkSettings::serverName();
 
708
    QTest::newRow("ip") << QtNetworkSettings::serverIP().toString();
 
709
}
 
710
 
 
711
void tst_QTcpSocket::timeoutConnect()
 
712
{
 
713
    QFETCH(QString, address);
 
714
    QTcpSocket *socket = newSocket();
 
715
 
 
716
    QElapsedTimer timer;
 
717
    timer.start();
 
718
 
 
719
    // Port 1357 is configured to drop packets on the test server
 
720
    socket->connectToHost(address, 1357);
 
721
    QVERIFY(timer.elapsed() < 150);
 
722
    QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication
 
723
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
724
    QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError));
 
725
 
 
726
    timer.start();
 
727
    socket->connectToHost(address, 1357);
 
728
    QVERIFY(timer.elapsed() < 150);
 
729
    QTimer::singleShot(50, &QTestEventLoop::instance(), SLOT(exitLoop()));
 
730
    QTestEventLoop::instance().enterLoop(5);
 
731
    QVERIFY(!QTestEventLoop::instance().timeout());
 
732
    QVERIFY(socket->state() == QTcpSocket::ConnectingState
 
733
            || socket->state() == QTcpSocket::HostLookupState);
 
734
    socket->abort();
 
735
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
736
    QCOMPARE(socket->openMode(), QIODevice::NotOpen);
 
737
 
 
738
    delete socket;
 
739
}
 
740
 
 
741
//----------------------------------------------------------------------------------
 
742
 
 
743
void tst_QTcpSocket::nonBlockingIMAP()
 
744
{
 
745
    QTcpSocket *socket = newSocket();
 
746
    connect(socket, SIGNAL(hostFound()), SLOT(nonBlockingIMAP_hostFound()));
 
747
    connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
 
748
    connect(socket, SIGNAL(disconnected()), SLOT(nonBlockingIMAP_closed()));
 
749
    connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(nonBlockingIMAP_bytesWritten(qint64)));
 
750
    connect(socket, SIGNAL(readyRead()), SLOT(nonBlockingIMAP_readyRead()));
 
751
    nonBlockingIMAP_socket = socket;
 
752
 
 
753
    // Connect
 
754
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
755
    QVERIFY(socket->state() == QTcpSocket::HostLookupState ||
 
756
            socket->state() == QTcpSocket::ConnectingState);
 
757
 
 
758
    enterLoop(30);
 
759
    if (timeout()) {
 
760
        QFAIL("Timed out");
 
761
    }
 
762
 
 
763
    if (socket->state() == QTcpSocket::ConnectingState) {
 
764
        enterLoop(30);
 
765
        if (timeout()) {
 
766
            QFAIL("Timed out");
 
767
        }
 
768
    }
 
769
 
 
770
    QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
 
771
 
 
772
    enterLoop(30);
 
773
    if (timeout()) {
 
774
        QFAIL("Timed out");
 
775
    }
 
776
 
 
777
    // Read greeting
 
778
    QVERIFY(!nonBlockingIMAP_data.isEmpty());
 
779
    QCOMPARE(nonBlockingIMAP_data.at(0).left(4).toLatin1().constData(), "* OK");
 
780
    nonBlockingIMAP_data.clear();
 
781
 
 
782
    nonBlockingIMAP_totalWritten = 0;
 
783
 
 
784
    // Write NOOP
 
785
    QCOMPARE((int) socket->write("1 NOOP\r\n", 8), 8);
 
786
 
 
787
 
 
788
    enterLoop(30);
 
789
    if (timeout()) {
 
790
        QFAIL("Timed out");
 
791
    }
 
792
 
 
793
    QVERIFY(nonBlockingIMAP_totalWritten == 8);
 
794
 
 
795
 
 
796
    enterLoop(30);
 
797
    if (timeout()) {
 
798
        QFAIL("Timed out");
 
799
    }
 
800
 
 
801
 
 
802
    // Read response
 
803
    QVERIFY(!nonBlockingIMAP_data.isEmpty());
 
804
    QCOMPARE(nonBlockingIMAP_data.at(0).toLatin1().constData(), "1 OK Completed\r\n");
 
805
    nonBlockingIMAP_data.clear();
 
806
 
 
807
 
 
808
    nonBlockingIMAP_totalWritten = 0;
 
809
 
 
810
    // Write LOGOUT
 
811
    QCOMPARE((int) socket->write("2 LOGOUT\r\n", 10), 10);
 
812
 
 
813
    enterLoop(30);
 
814
    if (timeout()) {
 
815
        QFAIL("Timed out");
 
816
    }
 
817
 
 
818
    QVERIFY(nonBlockingIMAP_totalWritten == 10);
 
819
 
 
820
    // Wait for greeting
 
821
    enterLoop(30);
 
822
    if (timeout()) {
 
823
        QFAIL("Timed out");
 
824
    }
 
825
 
 
826
    // Read two lines of respose
 
827
    QCOMPARE(nonBlockingIMAP_data.at(0).toLatin1().constData(), "* BYE LOGOUT received\r\n");
 
828
    QCOMPARE(nonBlockingIMAP_data.at(1).toLatin1().constData(), "2 OK Completed\r\n");
 
829
    nonBlockingIMAP_data.clear();
 
830
 
 
831
    // Close the socket
 
832
    socket->close();
 
833
 
 
834
    // Check that it's closed
 
835
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
836
 
 
837
    delete socket;
 
838
}
 
839
 
 
840
void tst_QTcpSocket::nonBlockingIMAP_hostFound()
 
841
{
 
842
    exitLoop();
 
843
}
 
844
 
 
845
void tst_QTcpSocket::nonBlockingIMAP_connected()
 
846
{
 
847
    exitLoop();
 
848
}
 
849
 
 
850
void tst_QTcpSocket::nonBlockingIMAP_readyRead()
 
851
{
 
852
    while (nonBlockingIMAP_socket->canReadLine())
 
853
        nonBlockingIMAP_data.append(nonBlockingIMAP_socket->readLine());
 
854
 
 
855
    exitLoop();
 
856
}
 
857
 
 
858
void tst_QTcpSocket::nonBlockingIMAP_bytesWritten(qint64 written)
 
859
{
 
860
    nonBlockingIMAP_totalWritten += written;
 
861
    exitLoop();
 
862
}
 
863
 
 
864
void tst_QTcpSocket::nonBlockingIMAP_closed()
 
865
{
 
866
}
 
867
 
 
868
//----------------------------------------------------------------------------------
 
869
 
 
870
void tst_QTcpSocket::delayedClose()
 
871
{
 
872
    QTcpSocket *socket = newSocket();
 
873
    connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
 
874
    connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
 
875
 
 
876
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
877
 
 
878
    enterLoop(30);
 
879
    if (timeout())
 
880
        QFAIL("Timed out");
 
881
 
 
882
    QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
 
883
 
 
884
    QCOMPARE((int) socket->write("1 LOGOUT\r\n", 10), 10);
 
885
 
 
886
    // Add a huge bulk of data to be written after the logout
 
887
    // command. The server will shut down after receiving the LOGOUT,
 
888
    // so this data will not be read. But our close call should
 
889
    // schedule a delayed close because all the data can not be
 
890
    // written in one go.
 
891
    QCOMPARE((int) socket->write(QByteArray(100000, '\n'), 100000), 100000);
 
892
 
 
893
    socket->close();
 
894
 
 
895
    QCOMPARE((int) socket->state(), (int) QTcpSocket::ClosingState);
 
896
 
 
897
    enterLoop(10);
 
898
    if (timeout())
 
899
        QFAIL("Timed out");
 
900
 
 
901
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
902
 
 
903
    delete socket;
 
904
}
 
905
 
 
906
 
 
907
//----------------------------------------------------------------------------------
 
908
 
 
909
QByteArray tst_QTcpSocket::expectedReplyIMAP()
 
910
{
 
911
    if (expectedReplyIMAP_cached.isEmpty()) {
 
912
        fetchExpectedReplyIMAP();
 
913
    }
 
914
 
 
915
    return expectedReplyIMAP_cached;
 
916
}
 
917
 
 
918
// Figure out how the current IMAP server responds
 
919
void tst_QTcpSocket::fetchExpectedReplyIMAP()
 
920
{
 
921
    QTcpSocket *socket = newSocket();
 
922
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
923
    QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
 
924
    QVERIFY2(socket->state() == QTcpSocket::ConnectedState, qPrintable(socket->errorString()));
 
925
 
 
926
    QTRY_VERIFY(socket->canReadLine());
 
927
 
 
928
    QByteArray greeting = socket->readLine();
 
929
    delete socket;
 
930
 
 
931
    QVERIFY2(QtNetworkSettings::compareReplyIMAP(greeting), greeting.constData());
 
932
 
 
933
    expectedReplyIMAP_cached = greeting;
 
934
}
 
935
 
 
936
//----------------------------------------------------------------------------------
 
937
 
 
938
void tst_QTcpSocket::partialRead()
 
939
{
 
940
    QTcpSocket *socket = newSocket();
 
941
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
942
    QVERIFY(socket->waitForConnected(10000));
 
943
    QVERIFY(socket->state() == QTcpSocket::ConnectedState);
 
944
    char buf[512];
 
945
 
 
946
    QByteArray greeting = expectedReplyIMAP();
 
947
    QVERIFY(!greeting.isEmpty());
 
948
 
 
949
    for (int i = 0; i < 10; i += 2) {
 
950
        while (socket->bytesAvailable() < 2)
 
951
            QVERIFY(socket->waitForReadyRead(5000));
 
952
        QVERIFY(socket->read(buf, 2) == 2);
 
953
        buf[2] = '\0';
 
954
        QCOMPARE((char *)buf, greeting.mid(i, 2).data());
 
955
    }
 
956
 
 
957
    delete socket;
 
958
}
 
959
 
 
960
//----------------------------------------------------------------------------------
 
961
 
 
962
void tst_QTcpSocket::unget()
 
963
{
 
964
    QTcpSocket *socket = newSocket();
 
965
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
966
    QVERIFY(socket->waitForConnected(10000));
 
967
    QVERIFY(socket->state() == QTcpSocket::ConnectedState);
 
968
    char buf[512];
 
969
 
 
970
    QByteArray greeting = expectedReplyIMAP();
 
971
    QVERIFY(!greeting.isEmpty());
 
972
 
 
973
    for (int i = 0; i < 10; i += 2) {
 
974
        while (socket->bytesAvailable() < 2)
 
975
            QVERIFY(socket->waitForReadyRead(10000));
 
976
        int bA = socket->bytesAvailable();
 
977
        QVERIFY(socket->read(buf, 2) == 2);
 
978
        buf[2] = '\0';
 
979
        QCOMPARE((char *)buf, greeting.mid(i, 2).data());
 
980
        QCOMPARE((int)socket->bytesAvailable(), bA - 2);
 
981
        socket->ungetChar(buf[1]);
 
982
        socket->ungetChar(buf[0]);
 
983
        QCOMPARE((int)socket->bytesAvailable(), bA);
 
984
        QVERIFY(socket->read(buf, 2) == 2);
 
985
        buf[2] = '\0';
 
986
        QCOMPARE((char *)buf, greeting.mid(i, 2).data());
 
987
    }
 
988
 
 
989
    delete socket;
 
990
}
 
991
 
 
992
//----------------------------------------------------------------------------------
 
993
void tst_QTcpSocket::readRegularFile_readyRead()
 
994
{
 
995
    exitLoop();
 
996
}
 
997
 
 
998
//----------------------------------------------------------------------------------
 
999
void tst_QTcpSocket::readAllAfterClose()
 
1000
{
 
1001
    QTcpSocket *socket = newSocket();
 
1002
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1003
    connect(socket, SIGNAL(readyRead()), SLOT(readRegularFile_readyRead()));
 
1004
    enterLoop(10);
 
1005
    if (timeout())
 
1006
        QFAIL("Network operation timed out");
 
1007
 
 
1008
    socket->close();
 
1009
    QByteArray array = socket->readAll();
 
1010
    QCOMPARE(array.size(), 0);
 
1011
 
 
1012
    delete socket;
 
1013
}
 
1014
 
 
1015
//----------------------------------------------------------------------------------
 
1016
void tst_QTcpSocket::openCloseOpenClose()
 
1017
{
 
1018
    QTcpSocket *socket = newSocket();
 
1019
 
 
1020
    for (int i = 0; i < 3; ++i) {
 
1021
        QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
1022
        QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
 
1023
        QVERIFY(socket->isSequential());
 
1024
        QVERIFY(!socket->isOpen());
 
1025
        QVERIFY(socket->socketType() == QTcpSocket::TcpSocket);
 
1026
 
 
1027
        char c;
 
1028
        QCOMPARE(socket->getChar(&c), false);
 
1029
        QCOMPARE((int) socket->bytesAvailable(), 0);
 
1030
        QCOMPARE(socket->canReadLine(), false);
 
1031
        QCOMPARE(socket->readLine(), QByteArray());
 
1032
        QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
 
1033
        QCOMPARE((int) socket->localPort(), 0);
 
1034
        QVERIFY(socket->localAddress() == QHostAddress());
 
1035
        QCOMPARE((int) socket->peerPort(), 0);
 
1036
        QVERIFY(socket->peerAddress() == QHostAddress());
 
1037
        QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
 
1038
        QCOMPARE(socket->errorString(), QString("Unknown error"));
 
1039
 
 
1040
        QVERIFY(socket->state() == QTcpSocket::UnconnectedState);
 
1041
 
 
1042
        socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1043
        QVERIFY(socket->waitForConnected(10000));
 
1044
        socket->close();
 
1045
    }
 
1046
 
 
1047
    delete socket;
 
1048
}
 
1049
 
 
1050
//----------------------------------------------------------------------------------
 
1051
void tst_QTcpSocket::connectDisconnectConnectDisconnect()
 
1052
{
 
1053
    QTcpSocket *socket = newSocket();
 
1054
 
 
1055
    for (int i = 0; i < 3; ++i) {
 
1056
        QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
1057
        QVERIFY(socket->socketType() == QTcpSocket::TcpSocket);
 
1058
 
 
1059
        socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1060
        QVERIFY(socket->waitForReadyRead(10000));
 
1061
        QCOMPARE(QString::fromLatin1(socket->read(4)), QString("* OK"));
 
1062
 
 
1063
        socket->disconnectFromHost();
 
1064
        if (socket->state() != QTcpSocket::UnconnectedState)
 
1065
            QVERIFY(socket->waitForDisconnected(10000));
 
1066
        QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
 
1067
    }
 
1068
 
 
1069
    delete socket;
 
1070
}
 
1071
 
 
1072
//----------------------------------------------------------------------------------
 
1073
void tst_QTcpSocket::disconnectWhileConnecting_data()
 
1074
{
 
1075
    QTest::addColumn<QByteArray>("data");
 
1076
    QTest::addColumn<bool>("closeDirectly");
 
1077
 
 
1078
    QTest::newRow("without-data") << QByteArray() << false;
 
1079
    QTest::newRow("without-data+close") << QByteArray() << true;
 
1080
    QTest::newRow("with-data") << QByteArray("Hello, world!") << false;
 
1081
    QTest::newRow("with-data+close") << QByteArray("Hello, world!") << true;
 
1082
 
 
1083
    QByteArray bigData(1024*1024, '@');
 
1084
    QTest::newRow("with-big-data") << bigData << false;
 
1085
    QTest::newRow("with-big-data+close") << bigData << true;
 
1086
}
 
1087
 
 
1088
void tst_QTcpSocket::disconnectWhileConnecting()
 
1089
{
 
1090
    QFETCH(QByteArray, data);
 
1091
    QFETCH_GLOBAL(bool, setProxy);
 
1092
    if (setProxy)
 
1093
        return; //proxy not useful for localhost test case
 
1094
 
 
1095
    QTcpServer server;
 
1096
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
1097
 
 
1098
    // proceed to the connect-write-disconnect
 
1099
    QTcpSocket *socket = newSocket();
 
1100
    socket->connectToHost("127.0.0.1", server.serverPort());
 
1101
    if (!data.isEmpty())
 
1102
        socket->write(data);
 
1103
    if (socket->state() == QAbstractSocket::ConnectedState)
 
1104
        QSKIP("localhost connections are immediate, test case is invalid");
 
1105
 
 
1106
    QFETCH(bool, closeDirectly);
 
1107
    if (closeDirectly) {
 
1108
        socket->close();
 
1109
        QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
 
1110
    } else {
 
1111
        socket->disconnectFromHost();
 
1112
    }
 
1113
 
 
1114
    connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
 
1115
    enterLoop(10);
 
1116
    QVERIFY2(!timeout(), "Network timeout");
 
1117
    QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
 
1118
    if (!closeDirectly) {
 
1119
        QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
 
1120
        socket->close();
 
1121
    }
 
1122
    QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
 
1123
 
 
1124
    // accept the other side and verify that it was sent properly:
 
1125
    QVERIFY(server.hasPendingConnections() || server.waitForNewConnection(0));
 
1126
    QTcpSocket *othersocket = server.nextPendingConnection();
 
1127
    if (othersocket->state() != QAbstractSocket::UnconnectedState)
 
1128
        QVERIFY2(othersocket->waitForDisconnected(10000), "Network timeout");
 
1129
    QVERIFY(othersocket->state() == QAbstractSocket::UnconnectedState);
 
1130
    QCOMPARE(othersocket->readAll(), data);
 
1131
 
 
1132
    delete socket;
 
1133
    delete othersocket;
 
1134
}
 
1135
 
 
1136
//----------------------------------------------------------------------------------
 
1137
class ReceiverThread: public QThread
 
1138
{
 
1139
    QTcpServer *server;
 
1140
public:
 
1141
    int serverPort;
 
1142
    bool ok;
 
1143
    QByteArray receivedData;
 
1144
    volatile bool quit;
 
1145
 
 
1146
    ReceiverThread()
 
1147
        : server(0), ok(false), quit(false)
 
1148
    { }
 
1149
 
 
1150
    ~ReceiverThread() { }
 
1151
 
 
1152
    bool listen()
 
1153
    {
 
1154
        server = new QTcpServer;
 
1155
        if (!server->listen(QHostAddress::LocalHost))
 
1156
            return false;
 
1157
        serverPort = server->serverPort();
 
1158
        server->moveToThread(this);
 
1159
        return true;
 
1160
    }
 
1161
 
 
1162
    static void cleanup(void *ptr)
 
1163
    {
 
1164
        ReceiverThread* self = reinterpret_cast<ReceiverThread*>(ptr);
 
1165
        self->quit = true;
 
1166
        self->wait(30000);
 
1167
        delete self;
 
1168
    }
 
1169
 
 
1170
protected:
 
1171
    void run()
 
1172
    {
 
1173
        bool timedOut = false;
 
1174
        while (!quit) {
 
1175
            if (server->waitForNewConnection(500, &timedOut))
 
1176
                break;
 
1177
            if (!timedOut)
 
1178
                return;
 
1179
        }
 
1180
 
 
1181
        QTcpSocket *socket = server->nextPendingConnection();
 
1182
        while (!quit) {
 
1183
            if (socket->waitForDisconnected(500))
 
1184
                break;
 
1185
            if (socket->error() != QAbstractSocket::SocketTimeoutError)
 
1186
                return;
 
1187
        }
 
1188
 
 
1189
        if (!quit) {
 
1190
            receivedData = socket->readAll();
 
1191
            ok = true;
 
1192
        }
 
1193
        delete socket;
 
1194
        delete server;
 
1195
        server = 0;
 
1196
    }
 
1197
};
 
1198
 
 
1199
void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop_data()
 
1200
{
 
1201
    disconnectWhileConnecting_data();
 
1202
}
 
1203
 
 
1204
void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop()
 
1205
{
 
1206
    QFETCH(QByteArray, data);
 
1207
    QFETCH_GLOBAL(bool, setProxy);
 
1208
    if (setProxy)
 
1209
        return; //proxy not useful for localhost test case
 
1210
 
 
1211
    QScopedPointer<ReceiverThread, ReceiverThread> thread (new ReceiverThread);
 
1212
    QVERIFY(thread->listen());
 
1213
    thread->start();
 
1214
 
 
1215
    // proceed to the connect-write-disconnect
 
1216
    QTcpSocket *socket = newSocket();
 
1217
    socket->connectToHost("127.0.0.1", thread->serverPort);
 
1218
    if (!data.isEmpty())
 
1219
        socket->write(data);
 
1220
    if (socket->state() == QAbstractSocket::ConnectedState)
 
1221
        QSKIP("localhost connections are immediate, test case is invalid");
 
1222
 
 
1223
    QFETCH(bool, closeDirectly);
 
1224
    if (closeDirectly) {
 
1225
        socket->close();
 
1226
        QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
 
1227
    } else {
 
1228
        socket->disconnectFromHost();
 
1229
    }
 
1230
 
 
1231
    QVERIFY2(socket->waitForDisconnected(10000), "Network timeout");
 
1232
    QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
 
1233
    if (!closeDirectly) {
 
1234
        QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
 
1235
        socket->close();
 
1236
    }
 
1237
    QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
 
1238
    delete socket;
 
1239
 
 
1240
    // check if the other side received everything ok
 
1241
    QVERIFY(thread->wait(30000));
 
1242
    QVERIFY(thread->ok);
 
1243
    QCOMPARE(thread->receivedData, data);
 
1244
}
 
1245
 
 
1246
//----------------------------------------------------------------------------------
 
1247
void tst_QTcpSocket::disconnectWhileLookingUp_data()
 
1248
{
 
1249
    QTest::addColumn<bool>("doClose");
 
1250
 
 
1251
    QTest::newRow("disconnect") << false;
 
1252
    QTest::newRow("close") << true;
 
1253
}
 
1254
 
 
1255
void tst_QTcpSocket::disconnectWhileLookingUp()
 
1256
{
 
1257
    QFETCH_GLOBAL(bool, setProxy);
 
1258
    if (setProxy)
 
1259
        return;                 // we let the proxies do the lookup now
 
1260
 
 
1261
    // just connect and disconnect, then make sure nothing weird happened
 
1262
    QTcpSocket *socket = newSocket();
 
1263
    socket->connectToHost(QtNetworkSettings::serverName(), 21);
 
1264
 
 
1265
    // check that connect is in progress
 
1266
    QVERIFY(socket->state() != QAbstractSocket::UnconnectedState);
 
1267
 
 
1268
    QFETCH(bool, doClose);
 
1269
    if (doClose) {
 
1270
        socket->close();
 
1271
        QVERIFY(socket->openMode() == QIODevice::NotOpen);
 
1272
    } else {
 
1273
        socket->disconnectFromHost();
 
1274
        QVERIFY(socket->openMode() == QIODevice::ReadWrite);
 
1275
        QVERIFY(socket->waitForDisconnected(5000));
 
1276
    }
 
1277
 
 
1278
    // let anything queued happen
 
1279
    QEventLoop loop;
 
1280
    QTimer::singleShot(50, &loop, SLOT(quit()));
 
1281
    loop.exec();
 
1282
 
 
1283
    // recheck
 
1284
    if (doClose) {
 
1285
        QVERIFY(socket->openMode() == QIODevice::NotOpen);
 
1286
    } else {
 
1287
        QVERIFY(socket->openMode() == QIODevice::ReadWrite);
 
1288
    }
 
1289
 
 
1290
    QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
 
1291
}
 
1292
 
 
1293
//----------------------------------------------------------------------------------
 
1294
void tst_QTcpSocket::downloadBigFile()
 
1295
{
 
1296
    if (tmpSocket)
 
1297
        delete tmpSocket;
 
1298
    tmpSocket = newSocket();
 
1299
 
 
1300
    connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
 
1301
    connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
 
1302
    connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
 
1303
 
 
1304
    tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
 
1305
 
 
1306
    enterLoop(30);
 
1307
    if (timeout()) {
 
1308
        delete tmpSocket;
 
1309
        tmpSocket = 0;
 
1310
        QFAIL("Network operation timed out");
 
1311
    }
 
1312
 
 
1313
    QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
 
1314
    QVERIFY(tmpSocket->state() == QAbstractSocket::ConnectedState);
 
1315
    QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
 
1316
    QVERIFY(tmpSocket->write("HOST: ") > 0);
 
1317
    QVERIFY(tmpSocket->write(hostName.data()) > 0);
 
1318
    QVERIFY(tmpSocket->write("\r\n") > 0);
 
1319
    QVERIFY(tmpSocket->write("\r\n") > 0);
 
1320
 
 
1321
    bytesAvailable = 0;
 
1322
    expectedLength = 0;
 
1323
    readingBody = false;
 
1324
 
 
1325
    QTime stopWatch;
 
1326
    stopWatch.start();
 
1327
 
 
1328
    enterLoop(600);
 
1329
    if (timeout()) {
 
1330
        delete tmpSocket;
 
1331
        tmpSocket = 0;
 
1332
        if (bytesAvailable > 0)
 
1333
            qDebug("Slow Connection, only downloaded %ld of %d", long(bytesAvailable), 10000281);
 
1334
        QFAIL("Network operation timed out");
 
1335
    }
 
1336
 
 
1337
    QCOMPARE(bytesAvailable, expectedLength);
 
1338
 
 
1339
    qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
 
1340
           bytesAvailable / (1024.0 * 1024.0),
 
1341
           stopWatch.elapsed() / 1024.0,
 
1342
           (bytesAvailable / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
 
1343
 
 
1344
    delete tmpSocket;
 
1345
    tmpSocket = 0;
 
1346
}
 
1347
 
 
1348
//----------------------------------------------------------------------------------
 
1349
void tst_QTcpSocket::exitLoopSlot()
 
1350
{
 
1351
    exitLoop();
 
1352
}
 
1353
 
 
1354
//----------------------------------------------------------------------------------
 
1355
void tst_QTcpSocket::downloadBigFileSlot()
 
1356
{
 
1357
    if (!readingBody) {
 
1358
        while (tmpSocket->canReadLine()) {
 
1359
            QByteArray array = tmpSocket->readLine();
 
1360
            if (array.startsWith("Content-Length"))
 
1361
                expectedLength = array.simplified().split(' ').at(1).toInt();
 
1362
            if (array == "\r\n") {
 
1363
                readingBody = true;
 
1364
                break;
 
1365
            }
 
1366
        }
 
1367
    }
 
1368
    if (readingBody) {
 
1369
        bytesAvailable += tmpSocket->readAll().size();
 
1370
        if (bytesAvailable == expectedLength)
 
1371
            exitLoop();
 
1372
    }
 
1373
}
 
1374
 
 
1375
//----------------------------------------------------------------------------------
 
1376
void tst_QTcpSocket::readLine()
 
1377
{
 
1378
    QTcpSocket *socket = newSocket();
 
1379
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1380
    QVERIFY(socket->waitForConnected(5000));
 
1381
 
 
1382
    while (!socket->canReadLine())
 
1383
        QVERIFY(socket->waitForReadyRead(10000));
 
1384
 
 
1385
    char buffer[1024];
 
1386
 
 
1387
    qint64 linelen = socket->readLine(buffer, sizeof(buffer));
 
1388
    QVERIFY(linelen >= 3);
 
1389
    QVERIFY(linelen < 1024);
 
1390
 
 
1391
    QByteArray reply = QByteArray::fromRawData(buffer, linelen);
 
1392
    QCOMPARE((int) buffer[linelen-2], (int) '\r');
 
1393
    QCOMPARE((int) buffer[linelen-1], (int) '\n');
 
1394
    QCOMPARE((int) buffer[linelen],   (int) '\0');
 
1395
 
 
1396
    QVERIFY2(QtNetworkSettings::compareReplyIMAP(reply), reply.constData());
 
1397
 
 
1398
    QCOMPARE(socket->write("1 NOOP\r\n"), qint64(8));
 
1399
 
 
1400
    while (socket->bytesAvailable() < 10)
 
1401
        QVERIFY(socket->waitForReadyRead(10000));
 
1402
 
 
1403
    QCOMPARE(socket->readLine(buffer, 11), qint64(10));
 
1404
    QCOMPARE((const char *)buffer, "1 OK Compl");
 
1405
 
 
1406
    while (socket->bytesAvailable() < 6)
 
1407
        QVERIFY(socket->waitForReadyRead(10000));
 
1408
 
 
1409
    QCOMPARE(socket->readLine(buffer, 11), qint64(6));
 
1410
    QCOMPARE((const char *)buffer, "eted\r\n");
 
1411
 
 
1412
    QVERIFY(!socket->waitForReadyRead(100));
 
1413
    QCOMPARE(socket->readLine(buffer, sizeof(buffer)), qint64(0));
 
1414
    QVERIFY(socket->error() == QAbstractSocket::SocketTimeoutError
 
1415
            || socket->error() == QAbstractSocket::RemoteHostClosedError);
 
1416
    QCOMPARE(socket->bytesAvailable(), qint64(0));
 
1417
 
 
1418
    socket->close();
 
1419
    QCOMPARE(socket->readLine(buffer, sizeof(buffer)), qint64(-1));
 
1420
 
 
1421
    delete socket;
 
1422
}
 
1423
 
 
1424
//----------------------------------------------------------------------------------
 
1425
void tst_QTcpSocket::readLineString()
 
1426
{
 
1427
    QTcpSocket *socket = newSocket();
 
1428
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1429
    QVERIFY(socket->waitForReadyRead(10000));
 
1430
 
 
1431
    QByteArray arr = socket->readLine();
 
1432
    QVERIFY2(QtNetworkSettings::compareReplyIMAP(arr), arr.constData());
 
1433
 
 
1434
    delete socket;
 
1435
}
 
1436
 
 
1437
//----------------------------------------------------------------------------------
 
1438
void tst_QTcpSocket::readChunks()
 
1439
{
 
1440
    QTcpSocket *socket = newSocket();
 
1441
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1442
    QVERIFY(socket->waitForConnected(10000));
 
1443
    QVERIFY(socket->waitForReadyRead(5000));
 
1444
 
 
1445
    char buf[4096];
 
1446
    memset(buf, '@', sizeof(buf));
 
1447
    qint64 dataLength = socket->read(buf, sizeof(buf));
 
1448
    QVERIFY(dataLength > 0);
 
1449
 
 
1450
    QCOMPARE(buf[dataLength - 2], '\r');
 
1451
    QCOMPARE(buf[dataLength - 1], '\n');
 
1452
    QCOMPARE(buf[dataLength], '@');
 
1453
 
 
1454
    delete socket;
 
1455
}
 
1456
 
 
1457
//----------------------------------------------------------------------------------
 
1458
void tst_QTcpSocket::waitForBytesWritten()
 
1459
{
 
1460
    QTcpSocket *socket = newSocket();
 
1461
    socket->connectToHost(QtNetworkSettings::serverName(), 80);
 
1462
    QVERIFY(socket->waitForConnected(10000));
 
1463
 
 
1464
    socket->write("GET / HTTP/1.0\r\n\r\n");
 
1465
    qint64 toWrite = socket->bytesToWrite();
 
1466
    QVERIFY(socket->waitForBytesWritten(5000));
 
1467
    QVERIFY(toWrite > socket->bytesToWrite());
 
1468
 
 
1469
    delete socket;
 
1470
}
 
1471
 
 
1472
//----------------------------------------------------------------------------------
 
1473
void tst_QTcpSocket::waitForBytesWrittenMinusOne()
 
1474
{
 
1475
#ifdef Q_OS_WIN
 
1476
    QSKIP("QTBUG-24451 - indefinite wait may hang");
 
1477
#endif
 
1478
    QTcpSocket *socket = newSocket();
 
1479
    socket->connectToHost(QtNetworkSettings::serverName(), 80);
 
1480
    QVERIFY(socket->waitForConnected(10000));
 
1481
 
 
1482
    socket->write("GET / HTTP/1.0\r\n\r\n");
 
1483
    qint64 toWrite = socket->bytesToWrite();
 
1484
    QVERIFY(socket->waitForBytesWritten(-1));
 
1485
    QVERIFY(toWrite > socket->bytesToWrite());
 
1486
 
 
1487
    delete socket;
 
1488
}
 
1489
 
 
1490
//----------------------------------------------------------------------------------
 
1491
void tst_QTcpSocket::waitForReadyRead()
 
1492
{
 
1493
    QTcpSocket *socket = newSocket();
 
1494
    socket->connectToHost(QtNetworkSettings::serverName(), 80);
 
1495
    socket->write("GET / HTTP/1.0\r\n\r\n");
 
1496
    QVERIFY(socket->waitForReadyRead(5000));
 
1497
    delete socket;
 
1498
}
 
1499
 
 
1500
//----------------------------------------------------------------------------------
 
1501
void tst_QTcpSocket::waitForReadyReadMinusOne()
 
1502
{
 
1503
#ifdef Q_OS_WIN
 
1504
    QSKIP("QTBUG-24451 - indefinite wait may hang");
 
1505
#endif
 
1506
    QTcpSocket *socket = newSocket();
 
1507
    socket->connectToHost(QtNetworkSettings::serverName(), 80);
 
1508
    socket->write("GET / HTTP/1.0\r\n\r\n");
 
1509
    QVERIFY(socket->waitForReadyRead(-1));
 
1510
    delete socket;
 
1511
}
 
1512
 
 
1513
//----------------------------------------------------------------------------------
 
1514
void tst_QTcpSocket::flush()
 
1515
{
 
1516
    QTcpSocket *socket = newSocket();
 
1517
    socket->flush();
 
1518
 
 
1519
    connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
 
1520
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1521
    enterLoop(60);
 
1522
    QVERIFY(socket->isOpen());
 
1523
 
 
1524
    socket->write("1 LOGOUT\r\n");
 
1525
    QCOMPARE(socket->bytesToWrite(), qint64(10));
 
1526
    socket->flush();
 
1527
    QCOMPARE(socket->bytesToWrite(), qint64(0));
 
1528
    socket->close();
 
1529
 
 
1530
    delete socket;
 
1531
}
 
1532
 
 
1533
//----------------------------------------------------------------------------------
 
1534
void tst_QTcpSocket::synchronousApi()
 
1535
{
 
1536
    QTcpSocket *ftpSocket = newSocket();
 
1537
    ftpSocket->connectToHost(QtNetworkSettings::serverName(), 21);
 
1538
    ftpSocket->write("QUIT\r\n");
 
1539
    QVERIFY(ftpSocket->waitForDisconnected(10000));
 
1540
    QVERIFY(ftpSocket->bytesAvailable() > 0);
 
1541
    QByteArray arr = ftpSocket->readAll();
 
1542
    QVERIFY(arr.size() > 0);
 
1543
    delete ftpSocket;
 
1544
}
 
1545
 
 
1546
//----------------------------------------------------------------------------------
 
1547
void tst_QTcpSocket::dontCloseOnTimeout()
 
1548
{
 
1549
    QTcpServer server;
 
1550
    server.setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
 
1551
    QVERIFY(server.listen());
 
1552
 
 
1553
    QHostAddress serverAddress = QHostAddress::LocalHost;
 
1554
    if (!(server.serverAddress() == QHostAddress::AnyIPv4)
 
1555
        && !(server.serverAddress() == QHostAddress::AnyIPv6)
 
1556
        && !(server.serverAddress() == QHostAddress::Any))
 
1557
        serverAddress = server.serverAddress();
 
1558
 
 
1559
    QTcpSocket *socket = newSocket();
 
1560
    socket->connectToHost(serverAddress, server.serverPort());
 
1561
    QVERIFY(!socket->waitForReadyRead(100));
 
1562
    QCOMPARE(socket->error(), QTcpSocket::SocketTimeoutError);
 
1563
    QVERIFY(socket->isOpen());
 
1564
 
 
1565
    QVERIFY(!socket->waitForDisconnected(100));
 
1566
    QCOMPARE(socket->error(), QTcpSocket::SocketTimeoutError);
 
1567
    QVERIFY(socket->isOpen());
 
1568
 
 
1569
    delete socket;
 
1570
}
 
1571
 
 
1572
//----------------------------------------------------------------------------------
 
1573
void tst_QTcpSocket::recursiveReadyRead()
 
1574
{
 
1575
    QTcpSocket *testSocket = newSocket();
 
1576
    connect(testSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
 
1577
    connect(testSocket, SIGNAL(readyRead()), SLOT(recursiveReadyReadSlot()));
 
1578
    tmpSocket = testSocket;
 
1579
 
 
1580
    QSignalSpy spy(testSocket, SIGNAL(readyRead()));
 
1581
 
 
1582
    testSocket->connectToHost(QtNetworkSettings::serverName(), 25);
 
1583
    enterLoop(30);
 
1584
    QVERIFY2(!timeout(),
 
1585
            "Timed out when connecting to QtNetworkSettings::serverName().");
 
1586
 
 
1587
    enterLoop(30);
 
1588
    QVERIFY2(!timeout(),
 
1589
            "Timed out when waiting for the readyRead() signal.");
 
1590
 
 
1591
    QCOMPARE(spy.count(), 1);
 
1592
 
 
1593
    delete testSocket;
 
1594
}
 
1595
 
 
1596
void tst_QTcpSocket::recursiveReadyReadSlot()
 
1597
{
 
1598
    // make sure the server spits out more data
 
1599
    tmpSocket->write("NOOP\r\n");
 
1600
    tmpSocket->flush();
 
1601
 
 
1602
    // indiscriminately enter the event loop and start processing
 
1603
    // events again. but oops! future socket notifications will cause
 
1604
    // undesired recursive behavior. Unless QTcpSocket is smart, which
 
1605
    // it of course is. :-)
 
1606
    QEventLoop loop;
 
1607
    for (int i = 0; i < 100; ++i)
 
1608
        loop.processEvents();
 
1609
 
 
1610
    // all we really wanted to do was process some events, then exit
 
1611
    // the loop
 
1612
    exitLoop();
 
1613
}
 
1614
 
 
1615
//----------------------------------------------------------------------------------
 
1616
void tst_QTcpSocket::atEnd()
 
1617
{
 
1618
    QTcpSocket *socket = newSocket();
 
1619
    socket->connectToHost(QtNetworkSettings::serverName(), 21);
 
1620
 
 
1621
    QVERIFY(socket->waitForReadyRead(15000));
 
1622
    QTextStream stream(socket);
 
1623
    QVERIFY(!stream.atEnd());
 
1624
    QString greeting = stream.readLine();
 
1625
    QVERIFY(stream.atEnd());
 
1626
 
 
1627
    // Test server must use some vsFTPd 2.x.x version
 
1628
    QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
 
1629
    QVERIFY2(greeting.startsWith("220 (vsFTPd 2."), qPrintable(greeting));
 
1630
    QVERIFY2(greeting.endsWith(")"), qPrintable(greeting));
 
1631
 
 
1632
    delete socket;
 
1633
}
 
1634
 
 
1635
class TestThread : public QThread
 
1636
{
 
1637
    Q_OBJECT
 
1638
 
 
1639
public:
 
1640
    inline QByteArray data() const
 
1641
    {
 
1642
        return socketData;
 
1643
    }
 
1644
 
 
1645
protected:
 
1646
    inline void run()
 
1647
    {
 
1648
#ifndef QT_NO_SSL
 
1649
        QFETCH_GLOBAL(bool, ssl);
 
1650
        if (ssl)
 
1651
            socket = new QSslSocket;
 
1652
        else
 
1653
#endif
 
1654
        socket = new QTcpSocket;
 
1655
        connect(socket, SIGNAL(readyRead()), this, SLOT(getData()), Qt::DirectConnection);
 
1656
        connect(socket, SIGNAL(disconnected()), this, SLOT(closed()), Qt::DirectConnection);
 
1657
        connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
1658
                SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), Qt::DirectConnection);
 
1659
 
 
1660
        socket->connectToHost(QtNetworkSettings::serverName(), 21);
 
1661
        socket->write("QUIT\r\n");
 
1662
        exec();
 
1663
 
 
1664
        delete socket;
 
1665
    }
 
1666
 
 
1667
private slots:
 
1668
    inline void getData()
 
1669
    {
 
1670
        socketData += socket->readAll();
 
1671
    }
 
1672
 
 
1673
    inline void closed()
 
1674
    {
 
1675
        quit();
 
1676
    }
 
1677
    inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
 
1678
    {
 
1679
        auth->setUser("qsockstest");
 
1680
        auth->setPassword("password");
 
1681
    }
 
1682
private:
 
1683
    int exitCode;
 
1684
    QTcpSocket *socket;
 
1685
    QByteArray socketData;
 
1686
};
 
1687
 
 
1688
//----------------------------------------------------------------------------------
 
1689
void tst_QTcpSocket::socketInAThread()
 
1690
{
 
1691
    for (int i = 0; i < 3; ++i) {
 
1692
        TestThread thread;
 
1693
        thread.start();
 
1694
        QVERIFY(thread.wait(15000));
 
1695
        QByteArray data = thread.data();
 
1696
        QVERIFY2(QtNetworkSettings::compareReplyFtp(data), data.constData());
 
1697
    }
 
1698
}
 
1699
 
 
1700
//----------------------------------------------------------------------------------
 
1701
void tst_QTcpSocket::socketsInThreads()
 
1702
{
 
1703
    for (int i = 0; i < 3; ++i) {
 
1704
        TestThread thread1;
 
1705
        TestThread thread2;
 
1706
        TestThread thread3;
 
1707
 
 
1708
        thread1.start();
 
1709
        thread2.start();
 
1710
        thread3.start();
 
1711
 
 
1712
        QVERIFY(thread2.wait(15000));
 
1713
        QVERIFY(thread3.wait(15000));
 
1714
        QVERIFY(thread1.wait(15000));
 
1715
 
 
1716
        QByteArray data1 = thread1.data();
 
1717
        QByteArray data2 = thread2.data();
 
1718
        QByteArray data3 = thread3.data();
 
1719
 
 
1720
        QVERIFY2(QtNetworkSettings::compareReplyFtp(data1), data1.constData());
 
1721
        QVERIFY2(QtNetworkSettings::compareReplyFtp(data2), data2.constData());
 
1722
        QVERIFY2(QtNetworkSettings::compareReplyFtp(data3), data3.constData());
 
1723
    }
 
1724
}
 
1725
 
 
1726
//----------------------------------------------------------------------------------
 
1727
void tst_QTcpSocket::waitForReadyReadInASlot()
 
1728
{
 
1729
    QTcpSocket *socket = newSocket();
 
1730
    tmpSocket = socket;
 
1731
    connect(socket, SIGNAL(connected()), this, SLOT(waitForReadyReadInASlotSlot()));
 
1732
 
 
1733
    socket->connectToHost(QtNetworkSettings::serverName(), 80);
 
1734
    socket->write("GET / HTTP/1.0\r\n\r\n");
 
1735
 
 
1736
    enterLoop(30);
 
1737
    QVERIFY(!timeout());
 
1738
 
 
1739
    delete socket;
 
1740
}
 
1741
 
 
1742
void tst_QTcpSocket::waitForReadyReadInASlotSlot()
 
1743
{
 
1744
    QVERIFY(tmpSocket->waitForReadyRead(10000));
 
1745
    exitLoop();
 
1746
}
 
1747
 
 
1748
class RemoteCloseErrorServer : public QTcpServer
 
1749
{
 
1750
    Q_OBJECT
 
1751
public:
 
1752
    RemoteCloseErrorServer()
 
1753
    {
 
1754
        connect(this, SIGNAL(newConnection()),
 
1755
                this, SLOT(getConnection()));
 
1756
    }
 
1757
 
 
1758
private slots:
 
1759
    void getConnection()
 
1760
    {
 
1761
        tst_QTcpSocket::exitLoop();
 
1762
    }
 
1763
};
 
1764
 
 
1765
//----------------------------------------------------------------------------------
 
1766
void tst_QTcpSocket::remoteCloseError()
 
1767
{
 
1768
    QFETCH_GLOBAL(bool, setProxy);
 
1769
    if (setProxy)
 
1770
        return; //proxy not useful for localhost test case
 
1771
    RemoteCloseErrorServer server;
 
1772
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
1773
 
 
1774
    QCoreApplication::instance()->processEvents();
 
1775
 
 
1776
    QTcpSocket *clientSocket = newSocket();
 
1777
    connect(clientSocket, SIGNAL(readyRead()), this, SLOT(exitLoopSlot()));
 
1778
 
 
1779
    clientSocket->connectToHost(server.serverAddress(), server.serverPort());
 
1780
 
 
1781
    enterLoop(30);
 
1782
    QVERIFY(!timeout());
 
1783
 
 
1784
    QVERIFY(server.hasPendingConnections());
 
1785
    QTcpSocket *serverSocket = server.nextPendingConnection();
 
1786
    connect(clientSocket, SIGNAL(disconnected()), this, SLOT(exitLoopSlot()));
 
1787
 
 
1788
    serverSocket->write("Hello");
 
1789
 
 
1790
    enterLoop(30);
 
1791
    QVERIFY(!timeout());
 
1792
 
 
1793
    QCOMPARE(clientSocket->bytesAvailable(), qint64(5));
 
1794
 
 
1795
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
 
1796
    QSignalSpy errorSpy(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
 
1797
    QSignalSpy disconnectedSpy(clientSocket, SIGNAL(disconnected()));
 
1798
 
 
1799
    clientSocket->write("World");
 
1800
    serverSocket->disconnectFromHost();
 
1801
 
 
1802
    tmpSocket = clientSocket;
 
1803
    connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
 
1804
            this, SLOT(remoteCloseErrorSlot()));
 
1805
 
 
1806
    enterLoop(30);
 
1807
    QVERIFY(!timeout());
 
1808
 
 
1809
    QCOMPARE(disconnectedSpy.count(), 1);
 
1810
    QCOMPARE(errorSpy.count(), 1);
 
1811
    QCOMPARE(clientSocket->error(), QAbstractSocket::RemoteHostClosedError);
 
1812
 
 
1813
    delete serverSocket;
 
1814
 
 
1815
    clientSocket->connectToHost(server.serverAddress(), server.serverPort());
 
1816
 
 
1817
    enterLoop(30);
 
1818
    QVERIFY(!timeout());
 
1819
 
 
1820
    QVERIFY(server.hasPendingConnections());
 
1821
    serverSocket = server.nextPendingConnection();
 
1822
    serverSocket->disconnectFromHost();
 
1823
 
 
1824
    enterLoop(30);
 
1825
    QVERIFY(!timeout());
 
1826
 
 
1827
    QCOMPARE(clientSocket->state(), QAbstractSocket::UnconnectedState);
 
1828
 
 
1829
    delete clientSocket;
 
1830
}
 
1831
 
 
1832
void tst_QTcpSocket::remoteCloseErrorSlot()
 
1833
{
 
1834
    QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
 
1835
    static_cast<QTcpSocket *>(sender())->close();
 
1836
}
 
1837
 
 
1838
void tst_QTcpSocket::enterLoopSlot()
 
1839
{
 
1840
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
 
1841
    socket->deleteLater();
 
1842
 
 
1843
    // enter nested event loop
 
1844
    QEventLoop loop;
 
1845
    QTimer::singleShot(100, &loop, SLOT(quit()));
 
1846
    loop.exec();
 
1847
 
 
1848
    // Fire a non-0 singleshot to leave time for the delete
 
1849
    QTimer::singleShot(250, this, SLOT(exitLoopSlot()));
 
1850
}
 
1851
//----------------------------------------------------------------------------------
 
1852
void tst_QTcpSocket::nestedEventLoopInErrorSlot()
 
1853
{
 
1854
    QTcpSocket *socket = newSocket();
 
1855
    QPointer<QTcpSocket> p(socket);
 
1856
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(enterLoopSlot()));
 
1857
 
 
1858
    socket->connectToHost("hostnotfoundhostnotfound.qt-project.org", 9999);
 
1859
    enterLoop(30);
 
1860
    QVERIFY(!p);
 
1861
}
 
1862
 
 
1863
//----------------------------------------------------------------------------------
 
1864
#ifndef Q_OS_WIN
 
1865
void tst_QTcpSocket::connectToLocalHostNoService()
 
1866
{
 
1867
    // This test was created after we received a report that claimed
 
1868
    // QTcpSocket would crash if trying to connect to "localhost" on a random
 
1869
    // port with no service listening.
 
1870
    QTcpSocket *socket = newSocket();
 
1871
    socket->connectToHost("localhost", 31415); // no service running here, one suspects
 
1872
 
 
1873
    while(socket->state() == QTcpSocket::HostLookupState || socket->state() == QTcpSocket::ConnectingState) {
 
1874
        QTest::qWait(100);
 
1875
    }
 
1876
    QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
 
1877
    delete socket;
 
1878
}
 
1879
#endif
 
1880
 
 
1881
//----------------------------------------------------------------------------------
 
1882
void tst_QTcpSocket::waitForConnectedInHostLookupSlot()
 
1883
{
 
1884
    // This test tries to reproduce the problem where waitForConnected() is
 
1885
    // called at a point where the host lookup is already done. QTcpSocket
 
1886
    // will try to abort the "pending lookup", but since it's already done and
 
1887
    // the queued signal is already underway, we will receive the signal after
 
1888
    // waitForConnected() has returned, and control goes back to the event
 
1889
    // loop. When the signal has been received, the connection is torn down,
 
1890
    // then reopened. Yikes. If we reproduce this by calling
 
1891
    // waitForConnected() inside hostLookupSlot(), it will even crash.
 
1892
    tmpSocket = newSocket();
 
1893
    QEventLoop loop;
 
1894
    connect(tmpSocket, SIGNAL(connected()), &loop, SLOT(quit()));
 
1895
    QTimer timer;
 
1896
    connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
 
1897
    QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
 
1898
    timer.start(15000);
 
1899
 
 
1900
    connect(tmpSocket, SIGNAL(hostFound()), this, SLOT(hostLookupSlot()));
 
1901
    tmpSocket->connectToHost(QtNetworkSettings::serverName(), 143);
 
1902
 
 
1903
    // only execute the loop if not already connected
 
1904
    if (tmpSocket->state() != QAbstractSocket::ConnectedState)
 
1905
        loop.exec();
 
1906
 
 
1907
    QCOMPARE(timerSpy.count(), 0);
 
1908
 
 
1909
    delete tmpSocket;
 
1910
}
 
1911
 
 
1912
void tst_QTcpSocket::hostLookupSlot()
 
1913
{
 
1914
    // This will fail to cancel the pending signal
 
1915
    QVERIFY(tmpSocket->waitForConnected(10000));
 
1916
}
 
1917
 
 
1918
class Foo : public QObject
 
1919
{
 
1920
    Q_OBJECT
 
1921
    QTcpSocket *sock;
 
1922
public:
 
1923
    bool attemptedToConnect;
 
1924
    bool networkTimeout;
 
1925
    int count;
 
1926
 
 
1927
    inline Foo(QObject *parent = 0) : QObject(parent)
 
1928
    {
 
1929
        attemptedToConnect = false;
 
1930
        networkTimeout = false;
 
1931
        count = 0;
 
1932
#ifndef QT_NO_SSL
 
1933
        QFETCH_GLOBAL(bool, ssl);
 
1934
        if (ssl)
 
1935
            sock = new QSslSocket;
 
1936
        else
 
1937
#endif
 
1938
        sock = new QTcpSocket;
 
1939
        connect(sock, SIGNAL(connected()), this, SLOT(connectedToIt()));
 
1940
        connect(sock, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
1941
                SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
 
1942
    }
 
1943
 
 
1944
    inline ~Foo()
 
1945
    {
 
1946
        delete sock;
 
1947
    }
 
1948
 
 
1949
public slots:
 
1950
    inline void connectedToIt()
 
1951
    { count++; }
 
1952
 
 
1953
    inline void doIt()
 
1954
    {
 
1955
        attemptedToConnect = true;
 
1956
        sock->connectToHost(QtNetworkSettings::serverName(), 80);
 
1957
 
 
1958
#ifdef Q_OS_MAC
 
1959
        pthread_yield_np();
 
1960
#elif defined Q_OS_LINUX
 
1961
        pthread_yield();
 
1962
#endif
 
1963
        if (!sock->waitForConnected()) {
 
1964
            networkTimeout = true;
 
1965
        }
 
1966
        tst_QTcpSocket::exitLoop();
 
1967
    }
 
1968
 
 
1969
    inline void exitLoop()
 
1970
    {
 
1971
        tst_QTcpSocket::exitLoop();
 
1972
    }
 
1973
 
 
1974
    inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
 
1975
    {
 
1976
        auth->setUser("qsockstest");
 
1977
        auth->setPassword("password");
 
1978
    }
 
1979
};
 
1980
 
 
1981
//----------------------------------------------------------------------------------
 
1982
void tst_QTcpSocket::waitForConnectedInHostLookupSlot2()
 
1983
{
 
1984
    Foo foo;
 
1985
 
 
1986
    QTimer::singleShot(100, &foo, SLOT(doIt()));
 
1987
    QTimer::singleShot(5000, &foo, SLOT(exitLoop()));
 
1988
 
 
1989
    enterLoop(30);
 
1990
    if (timeout() || foo.networkTimeout)
 
1991
        QFAIL("Network timeout");
 
1992
 
 
1993
    QVERIFY(foo.attemptedToConnect);
 
1994
    QCOMPARE(foo.count, 1);
 
1995
}
 
1996
 
 
1997
//----------------------------------------------------------------------------------
 
1998
void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
 
1999
{
 
2000
    QTcpSocket *socket = newSocket();
 
2001
 
 
2002
    QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
 
2003
 
 
2004
    // Connect
 
2005
    socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
2006
 
 
2007
    // Wait for the read
 
2008
    QVERIFY(socket->waitForReadyRead(10000));
 
2009
 
 
2010
    QCOMPARE(readyReadSpy.count(), 1);
 
2011
 
 
2012
    QString s = socket->readLine();
 
2013
    QVERIFY2(QtNetworkSettings::compareReplyIMAP(s.toLatin1()), s.toLatin1().constData());
 
2014
    QCOMPARE(socket->bytesAvailable(), qint64(0));
 
2015
 
 
2016
    QCoreApplication::instance()->processEvents();
 
2017
    QCOMPARE(socket->bytesAvailable(), qint64(0));
 
2018
    QCOMPARE(readyReadSpy.count(), 1);
 
2019
 
 
2020
    delete socket;
 
2021
}
 
2022
 
 
2023
class TestThread2 : public QThread
 
2024
{
 
2025
    Q_OBJECT
 
2026
public:
 
2027
    void run()
 
2028
    {
 
2029
        QFile fileWriter("fifo");
 
2030
        QVERIFY(fileWriter.open(QFile::WriteOnly));
 
2031
        QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
 
2032
        QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
 
2033
        QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
 
2034
        QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
 
2035
    }
 
2036
};
 
2037
 
 
2038
//----------------------------------------------------------------------------------
 
2039
#ifdef Q_OS_LINUX
 
2040
void tst_QTcpSocket::linuxKernelBugLocalSocket()
 
2041
{
 
2042
    QFile::remove("fifo");
 
2043
    mkfifo("fifo", 0666);
 
2044
 
 
2045
    TestThread2 test;
 
2046
    test.start();
 
2047
 
 
2048
    QFile fileReader("fifo");
 
2049
    QVERIFY(fileReader.open(QFile::ReadOnly));
 
2050
 
 
2051
    test.wait();
 
2052
 
 
2053
    QTcpSocket *socket = newSocket();
 
2054
    socket->setSocketDescriptor(fileReader.handle());
 
2055
    QVERIFY(socket->waitForReadyRead(5000));
 
2056
    QCOMPARE(socket->bytesAvailable(), qint64(128));
 
2057
 
 
2058
    QFile::remove("fifo");
 
2059
 
 
2060
    delete socket;
 
2061
}
 
2062
#endif
 
2063
 
 
2064
//----------------------------------------------------------------------------------
 
2065
void tst_QTcpSocket::abortiveClose()
 
2066
{
 
2067
    QFETCH_GLOBAL(bool, setProxy);
 
2068
    if (setProxy)
 
2069
        return; //proxy not useful for localhost test case
 
2070
    QTcpServer server;
 
2071
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
2072
    connect(&server, SIGNAL(newConnection()), this, SLOT(exitLoopSlot()));
 
2073
 
 
2074
    QTcpSocket *clientSocket = newSocket();
 
2075
    clientSocket->connectToHost(server.serverAddress(), server.serverPort());
 
2076
 
 
2077
    enterLoop(10);
 
2078
    QVERIFY(server.hasPendingConnections());
 
2079
 
 
2080
    QVERIFY(tmpSocket = server.nextPendingConnection());
 
2081
 
 
2082
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
 
2083
    QSignalSpy readyReadSpy(clientSocket, SIGNAL(readyRead()));
 
2084
    QSignalSpy errorSpy(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
 
2085
 
 
2086
    connect(clientSocket, SIGNAL(disconnected()), this, SLOT(exitLoopSlot()));
 
2087
    QTimer::singleShot(0, this, SLOT(abortiveClose_abortSlot()));
 
2088
 
 
2089
    enterLoop(5);
 
2090
 
 
2091
    QCOMPARE(readyReadSpy.count(), 0);
 
2092
    QCOMPARE(errorSpy.count(), 1);
 
2093
 
 
2094
    QCOMPARE(*static_cast<const int *>(errorSpy.at(0).at(0).constData()),
 
2095
             int(QAbstractSocket::RemoteHostClosedError));
 
2096
 
 
2097
    delete clientSocket;
 
2098
}
 
2099
 
 
2100
void tst_QTcpSocket::abortiveClose_abortSlot()
 
2101
{
 
2102
    tmpSocket->abort();
 
2103
}
 
2104
 
 
2105
//----------------------------------------------------------------------------------
 
2106
void tst_QTcpSocket::localAddressEmptyOnBSD()
 
2107
{
 
2108
#ifdef Q_OS_WIN
 
2109
    QSKIP("QTBUG-24451 - indefinite wait may hang");
 
2110
#endif
 
2111
    QFETCH_GLOBAL(bool, setProxy);
 
2112
    if (setProxy)
 
2113
        return; //proxy not useful for localhost test case
 
2114
    QTcpServer server;
 
2115
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
2116
 
 
2117
    QTcpSocket *tcpSocket = 0;
 
2118
    // we try 10 times, but note that this doesn't always provoke the bug
 
2119
    for (int i = 0; i < 10; ++i) {
 
2120
        delete tcpSocket;
 
2121
        tcpSocket = newSocket();
 
2122
        tcpSocket->connectToHost(QHostAddress::LocalHost, server.serverPort());
 
2123
        if (!tcpSocket->waitForConnected(0)) {
 
2124
            // to provoke the bug, we need a local socket that connects immediately
 
2125
            // --i;
 
2126
            tcpSocket->abort();
 
2127
            if (tcpSocket->state() != QTcpSocket::UnconnectedState)
 
2128
                QVERIFY(tcpSocket->waitForDisconnected(-1));
 
2129
            continue;
 
2130
        }
 
2131
        QCOMPARE(tcpSocket->localAddress(), QHostAddress(QHostAddress::LocalHost));
 
2132
    }
 
2133
    delete tcpSocket;
 
2134
}
 
2135
 
 
2136
//----------------------------------------------------------------------------------
 
2137
void tst_QTcpSocket::zeroAndMinusOneReturns()
 
2138
{
 
2139
    QTcpSocket *socket = newSocket();
 
2140
    socket->connectToHost(QtNetworkSettings::serverName(), 80);
 
2141
    socket->write("GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
 
2142
    QVERIFY(socket->waitForReadyRead(15000));
 
2143
 
 
2144
    char c[16];
 
2145
    QVERIFY(socket->getChar(c));
 
2146
    QCOMPARE(socket->read(c, 16), qint64(16));
 
2147
    QVERIFY(socket->readLine(c, 16) > 0);
 
2148
    QVERIFY(!socket->readAll().isEmpty());
 
2149
 
 
2150
    // the last operation emptied the read buffer
 
2151
    // all read operations from this point on should fail
 
2152
    // with return 0 because the socket is still open
 
2153
    QVERIFY(socket->readAll().isEmpty());
 
2154
    QCOMPARE(socket->read(c, 16), qint64(0));
 
2155
    QCOMPARE(socket->readLine(c, 16), qint64(0));
 
2156
    QVERIFY(!socket->getChar(c));
 
2157
 
 
2158
    socket->write("GET / HTTP/1.0\r\n\r\n");
 
2159
    QVERIFY(socket->waitForDisconnected(15000));
 
2160
    QCOMPARE(socket->error(), QAbstractSocket::RemoteHostClosedError);
 
2161
 
 
2162
    QCOMPARE(socket->write("BLUBBER"), qint64(-1));
 
2163
    QVERIFY(socket->getChar(c));
 
2164
    QCOMPARE(socket->read(c, 16), qint64(16));
 
2165
    QVERIFY(socket->readLine(c, 16) > 0);
 
2166
    QVERIFY(!socket->readAll().isEmpty());
 
2167
 
 
2168
    // the last operation emptied the read buffer
 
2169
    // all read operations from this point on should fail
 
2170
    // with return -1 because the socket is not connected
 
2171
    QVERIFY(socket->readAll().isEmpty());
 
2172
    QCOMPARE(socket->read(c, 16), qint64(-1));
 
2173
    QCOMPARE(socket->readLine(c, 16), qint64(-1));
 
2174
    QVERIFY(!socket->getChar(c));
 
2175
    QVERIFY(!socket->putChar('a'));
 
2176
 
 
2177
    socket->close();
 
2178
 
 
2179
    // now the QIODevice is closed, which means getChar complains
 
2180
    QCOMPARE(socket->write("BLUBBER"), qint64(-1));
 
2181
    QCOMPARE(socket->read(c, 16), qint64(-1));
 
2182
    QCOMPARE(socket->readLine(c, 16), qint64(-1));
 
2183
    QVERIFY(!socket->getChar(c));
 
2184
    QVERIFY(!socket->putChar('a'));
 
2185
 
 
2186
    delete socket;
 
2187
}
 
2188
 
 
2189
//----------------------------------------------------------------------------------
 
2190
void tst_QTcpSocket::connectionRefused()
 
2191
{
 
2192
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
 
2193
    qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
 
2194
 
 
2195
    QTcpSocket *socket = newSocket();
 
2196
    QSignalSpy stateSpy(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
 
2197
    QSignalSpy errorSpy(socket, SIGNAL(error(QAbstractSocket::SocketError)));
 
2198
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
 
2199
            &QTestEventLoop::instance(), SLOT(exitLoop()));
 
2200
 
 
2201
    socket->connectToHost(QtNetworkSettings::serverName(), 144);
 
2202
 
 
2203
    enterLoop(10);
 
2204
    disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
 
2205
               &QTestEventLoop::instance(), SLOT(exitLoop()));
 
2206
    QVERIFY2(!timeout(), "Network timeout");
 
2207
 
 
2208
    QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
 
2209
    QCOMPARE(socket->error(), QAbstractSocket::ConnectionRefusedError);
 
2210
 
 
2211
    QCOMPARE(stateSpy.count(), 3);
 
2212
    QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(0).at(0)), QAbstractSocket::HostLookupState);
 
2213
    QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(1).at(0)), QAbstractSocket::ConnectingState);
 
2214
    QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(2).at(0)), QAbstractSocket::UnconnectedState);
 
2215
    QCOMPARE(errorSpy.count(), 1);
 
2216
 
 
2217
    delete socket;
 
2218
}
 
2219
 
 
2220
//----------------------------------------------------------------------------------
 
2221
void tst_QTcpSocket::suddenRemoteDisconnect_data()
 
2222
{
 
2223
    QTest::addColumn<QString>("client");
 
2224
    QTest::addColumn<QString>("server");
 
2225
 
 
2226
    QTest::newRow("Qt4 Client <-> Qt4 Server") << QString::fromLatin1("qt4client") << QString::fromLatin1("qt4server");
 
2227
}
 
2228
 
 
2229
void tst_QTcpSocket::suddenRemoteDisconnect()
 
2230
{
 
2231
    QFETCH(QString, client);
 
2232
    QFETCH(QString, server);
 
2233
 
 
2234
    QFETCH_GLOBAL(bool, setProxy);
 
2235
    if (setProxy)
 
2236
        return;
 
2237
    QFETCH_GLOBAL(bool, ssl);
 
2238
    if (ssl)
 
2239
        return;
 
2240
 
 
2241
    QString processExe = stressTestDir + "/stressTest";
 
2242
 
 
2243
    // Start server
 
2244
    QProcess serverProcess;
 
2245
    serverProcess.setReadChannel(QProcess::StandardError);
 
2246
    serverProcess.start(processExe, QStringList(server), QIODevice::ReadWrite | QIODevice::Text);
 
2247
    QVERIFY2(serverProcess.waitForStarted(), qPrintable(
 
2248
        QString::fromLatin1("Could not start %1: %2").arg(processExe, serverProcess.errorString())));
 
2249
    while (!serverProcess.canReadLine())
 
2250
        QVERIFY(serverProcess.waitForReadyRead(10000));
 
2251
    QCOMPARE(serverProcess.readLine().data(), QByteArray(server.toLatin1() + "\n").data());
 
2252
 
 
2253
    // Start client
 
2254
    QProcess clientProcess;
 
2255
    clientProcess.setReadChannel(QProcess::StandardError);
 
2256
    clientProcess.start(processExe, QStringList(client), QIODevice::ReadWrite | QIODevice::Text);
 
2257
    QVERIFY2(clientProcess.waitForStarted(), qPrintable(
 
2258
        QString::fromLatin1("Could not start %1: %2").arg(processExe, clientProcess.errorString())));
 
2259
    while (!clientProcess.canReadLine())
 
2260
        QVERIFY(clientProcess.waitForReadyRead(10000));
 
2261
    QCOMPARE(clientProcess.readLine().data(), QByteArray(client.toLatin1() + "\n").data());
 
2262
 
 
2263
    // Let them play for a while
 
2264
    qDebug("Running stress test for 5 seconds");
 
2265
    QEventLoop loop;
 
2266
    connect(&serverProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
 
2267
    connect(&clientProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
 
2268
    QTime stopWatch;
 
2269
    stopWatch.start();
 
2270
    QTimer::singleShot(20000, &loop, SLOT(quit()));
 
2271
 
 
2272
    while ((serverProcess.state() == QProcess::Running
 
2273
           || clientProcess.state() == QProcess::Running) && stopWatch.elapsed() < 20000)
 
2274
        loop.exec();
 
2275
 
 
2276
    QVERIFY(stopWatch.elapsed() < 20000);
 
2277
 
 
2278
    // Check that both exited normally.
 
2279
#if defined(UBUNTU_ONEIRIC) && defined(__x86_64__)
 
2280
    QEXPECT_FAIL("", "Fails on this platform", Abort);
 
2281
#endif
 
2282
    QCOMPARE(clientProcess.readAll().constData(), "SUCCESS\n");
 
2283
    QCOMPARE(serverProcess.readAll().constData(), "SUCCESS\n");
 
2284
}
 
2285
 
 
2286
//----------------------------------------------------------------------------------
 
2287
 
 
2288
void tst_QTcpSocket::connectToMultiIP()
 
2289
{
 
2290
    QSKIP("TODO: setup DNS in the new network");
 
2291
#if defined(Q_OS_VXWORKS)
 
2292
    QSKIP("VxSim in standard config doesn't even run a DNS resolver");
 
2293
#else
 
2294
    QFETCH_GLOBAL(bool, ssl);
 
2295
    if (ssl)
 
2296
        return;
 
2297
    QFETCH_GLOBAL(bool, setProxy);
 
2298
    if (setProxy)
 
2299
        QSKIP("This test takes too long if we also add the proxies.");
 
2300
 
 
2301
    qDebug("Please wait, this test can take a while...");
 
2302
 
 
2303
    QTcpSocket *socket = newSocket();
 
2304
    // rationale: this domain resolves to 3 A-records, 2 of them are
 
2305
    // invalid. QTcpSocket should never spend more than 30 seconds per IP, and
 
2306
    // 30s*2 = 60s.
 
2307
    QTime stopWatch;
 
2308
    stopWatch.start();
 
2309
    socket->connectToHost("multi.dev.qt-project.org", 80);
 
2310
    QVERIFY(socket->waitForConnected(60500));
 
2311
    QVERIFY(stopWatch.elapsed() < 70000);
 
2312
    socket->abort();
 
2313
 
 
2314
    stopWatch.restart();
 
2315
    socket->connectToHost("multi.dev.qt-project.org", 81);
 
2316
    QVERIFY(!socket->waitForConnected(2000));
 
2317
    QVERIFY(stopWatch.elapsed() < 2000);
 
2318
    QCOMPARE(socket->error(), QAbstractSocket::SocketTimeoutError);
 
2319
 
 
2320
    delete socket;
 
2321
#endif
 
2322
}
 
2323
 
 
2324
//----------------------------------------------------------------------------------
 
2325
void tst_QTcpSocket::moveToThread0()
 
2326
{
 
2327
    QFETCH_GLOBAL(int, proxyType);
 
2328
    if (proxyType & AuthMask)
 
2329
        return;
 
2330
 
 
2331
    {
 
2332
        // Case 1: Moved after connecting, before waiting for connection.
 
2333
        QTcpSocket *socket = newSocket();;
 
2334
        socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
2335
        socket->moveToThread(0);
 
2336
        QVERIFY(socket->waitForConnected(5000));
 
2337
        socket->write("XXX LOGOUT\r\n");
 
2338
        QVERIFY(socket->waitForBytesWritten(5000));
 
2339
        QVERIFY(socket->waitForDisconnected());
 
2340
        delete socket;
 
2341
    }
 
2342
    {
 
2343
        // Case 2: Moved before connecting
 
2344
        QTcpSocket *socket = newSocket();
 
2345
        socket->moveToThread(0);
 
2346
        socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
2347
        QVERIFY(socket->waitForConnected(5000));
 
2348
        socket->write("XXX LOGOUT\r\n");
 
2349
        QVERIFY(socket->waitForBytesWritten(5000));
 
2350
        QVERIFY(socket->waitForDisconnected());
 
2351
        delete socket;
 
2352
    }
 
2353
    {
 
2354
        // Case 3: Moved after writing, while waiting for bytes to be written.
 
2355
        QTcpSocket *socket = newSocket();
 
2356
        socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
2357
        QVERIFY(socket->waitForConnected(5000));
 
2358
        socket->write("XXX LOGOUT\r\n");
 
2359
        socket->moveToThread(0);
 
2360
        QVERIFY(socket->waitForBytesWritten(5000));
 
2361
        QVERIFY(socket->waitForDisconnected());
 
2362
        delete socket;
 
2363
    }
 
2364
    {
 
2365
        // Case 4: Moved after writing, while waiting for response.
 
2366
        QTcpSocket *socket = newSocket();
 
2367
        socket->connectToHost(QtNetworkSettings::serverName(), 143);
 
2368
        QVERIFY(socket->waitForConnected(5000));
 
2369
        socket->write("XXX LOGOUT\r\n");
 
2370
        QVERIFY(socket->waitForBytesWritten(5000));
 
2371
        socket->moveToThread(0);
 
2372
        QVERIFY(socket->waitForDisconnected());
 
2373
        delete socket;
 
2374
    }
 
2375
}
 
2376
 
 
2377
void tst_QTcpSocket::increaseReadBufferSize()
 
2378
{
 
2379
    QFETCH_GLOBAL(bool, setProxy);
 
2380
    if (setProxy)
 
2381
        return; //proxy not useful for localhost test case
 
2382
    QTcpServer server;
 
2383
    QTcpSocket *active = newSocket();
 
2384
    connect(active, SIGNAL(readyRead()), SLOT(exitLoopSlot()));
 
2385
 
 
2386
    // connect two sockets to each other:
 
2387
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
2388
    active->connectToHost("127.0.0.1", server.serverPort());
 
2389
    QVERIFY(active->waitForConnected(5000));
 
2390
    QVERIFY(server.waitForNewConnection(5000));
 
2391
 
 
2392
    QTcpSocket *passive = server.nextPendingConnection();
 
2393
    QVERIFY(passive);
 
2394
 
 
2395
    // now write 512 bytes of data on one end
 
2396
    QByteArray data(512, 'a');
 
2397
    passive->write(data);
 
2398
    QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout");
 
2399
 
 
2400
    // set the read buffer size to less than what was written and iterate:
 
2401
    active->setReadBufferSize(256);
 
2402
    enterLoop(10);
 
2403
    QVERIFY2(!timeout(), "Network timeout");
 
2404
    QCOMPARE(active->bytesAvailable(), active->readBufferSize());
 
2405
 
 
2406
    // increase the buffer size and iterate again:
 
2407
    active->setReadBufferSize(384);
 
2408
    enterLoop(10);
 
2409
    QVERIFY2(!timeout(), "Network timeout");
 
2410
    QCOMPARE(active->bytesAvailable(), active->readBufferSize());
 
2411
 
 
2412
    // once more, but now it should read everything there was to read
 
2413
    active->setReadBufferSize(1024);
 
2414
    enterLoop(10);
 
2415
    QVERIFY2(!timeout(), "Network timeout");
 
2416
    QCOMPARE(active->bytesAvailable(), qint64(data.size()));
 
2417
 
 
2418
    // drain it and compare
 
2419
    QCOMPARE(active->readAll(), data);
 
2420
 
 
2421
    // now one more test by setting the buffer size to unlimited:
 
2422
    passive->write(data);
 
2423
    QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout");
 
2424
    active->setReadBufferSize(256);
 
2425
    enterLoop(10);
 
2426
    QVERIFY2(!timeout(), "Network timeout");
 
2427
    QCOMPARE(active->bytesAvailable(), active->readBufferSize());
 
2428
    active->setReadBufferSize(0);
 
2429
    enterLoop(10);
 
2430
    QVERIFY2(!timeout(), "Network timeout");
 
2431
    QCOMPARE(active->bytesAvailable(), qint64(data.size()));
 
2432
    QCOMPARE(active->readAll(), data);
 
2433
 
 
2434
    delete active;
 
2435
}
 
2436
 
 
2437
void tst_QTcpSocket::taskQtBug5799ConnectionErrorWaitForConnected()
 
2438
{
 
2439
    QFETCH_GLOBAL(bool, setProxy);
 
2440
    if (setProxy)
 
2441
        return;
 
2442
 
 
2443
    // check that we get a proper error connecting to port 12346
 
2444
    // use waitForConnected, e.g. this should use a synchronous select() on the OS level
 
2445
 
 
2446
    QTcpSocket socket;
 
2447
    socket.connectToHost(QtNetworkSettings::serverName(), 12346);
 
2448
    QTime timer;
 
2449
    timer.start();
 
2450
    socket.waitForConnected(10000);
 
2451
    QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
 
2452
    QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
 
2453
    QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
 
2454
             QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
 
2455
}
 
2456
 
 
2457
void tst_QTcpSocket::taskQtBug5799ConnectionErrorEventLoop()
 
2458
{
 
2459
    QFETCH_GLOBAL(bool, setProxy);
 
2460
    if (setProxy)
 
2461
        return;
 
2462
 
 
2463
    // check that we get a proper error connecting to port 12346
 
2464
    // This testcase uses an event loop
 
2465
    QTcpSocket socket;
 
2466
    connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
 
2467
    socket.connectToHost(QtNetworkSettings::serverName(), 12346);
 
2468
 
 
2469
    QTestEventLoop::instance().enterLoop(10);
 
2470
    QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong");
 
2471
    QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
 
2472
    QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
 
2473
             QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
 
2474
}
 
2475
 
 
2476
void tst_QTcpSocket::taskQtBug7054TimeoutErrorResetting()
 
2477
{
 
2478
    QTcpSocket *socket = newSocket();
 
2479
 
 
2480
    socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
2481
    QVERIFY(socket->waitForConnected(5*1000));
 
2482
    QVERIFY(socket->error() == QAbstractSocket::UnknownSocketError);
 
2483
 
 
2484
    // We connected to the HTTPS port. Wait two seconds to receive data. We will receive
 
2485
    // nothing because we would need to start the SSL handshake
 
2486
    QVERIFY(!socket->waitForReadyRead(2*1000));
 
2487
    QVERIFY(socket->error() == QAbstractSocket::SocketTimeoutError);
 
2488
 
 
2489
    // Now write some crap to make the server disconnect us. 4 lines are enough.
 
2490
    socket->write("a\r\nb\r\nc\r\nd\r\n");
 
2491
    socket->waitForBytesWritten(2*1000);
 
2492
 
 
2493
    // we try to waitForReadyRead another time, but this time instead of a timeout we
 
2494
    // should get a better error since the server disconnected us
 
2495
    QVERIFY(!socket->waitForReadyRead(2*1000));
 
2496
    // It must NOT be the SocketTimeoutError that had been set before
 
2497
    QVERIFY(socket->error() == QAbstractSocket::RemoteHostClosedError);
 
2498
}
 
2499
 
 
2500
void tst_QTcpSocket::invalidProxy_data()
 
2501
{
 
2502
    QTest::addColumn<int>("type");
 
2503
    QTest::addColumn<QString>("host");
 
2504
    QTest::addColumn<int>("port");
 
2505
    QTest::addColumn<bool>("failsAtConnect");
 
2506
    QTest::addColumn<int>("expectedError");
 
2507
 
 
2508
    QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
 
2509
    QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 21 << true
 
2510
                               << int(QAbstractSocket::UnsupportedSocketOperationError);
 
2511
    QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << fluke << 3128 << true
 
2512
                                        << int(QAbstractSocket::UnsupportedSocketOperationError);
 
2513
    QTest::newRow("no-such-host-socks5") << int(QNetworkProxy::Socks5Proxy)
 
2514
                                         << "this-host-will-never-exist.qt-project.org" << 1080 << false
 
2515
                                         << int(QAbstractSocket::ProxyNotFoundError);
 
2516
    QTest::newRow("no-such-host-http") << int(QNetworkProxy::HttpProxy)
 
2517
                                       << "this-host-will-never-exist.qt-project.org" << 3128 << false
 
2518
                                       << int(QAbstractSocket::ProxyNotFoundError);
 
2519
    QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << fluke << 1080 << false
 
2520
                                    << int(QAbstractSocket::ProxyConnectionClosedError);
 
2521
    QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128 << false
 
2522
                                    << int(QAbstractSocket::SocketTimeoutError);
 
2523
}
 
2524
 
 
2525
void tst_QTcpSocket::invalidProxy()
 
2526
{
 
2527
    QFETCH_GLOBAL(bool, setProxy);
 
2528
    if (setProxy)
 
2529
        return;
 
2530
 
 
2531
    QFETCH(int, type);
 
2532
    QFETCH(QString, host);
 
2533
    QFETCH(int, port);
 
2534
    QFETCH(bool, failsAtConnect);
 
2535
    QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
 
2536
    QNetworkProxy proxy(proxyType, host, port);
 
2537
 
 
2538
    QTcpSocket *socket = newSocket();
 
2539
    socket->setProxy(proxy);
 
2540
    socket->connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 80);
 
2541
 
 
2542
    if (failsAtConnect) {
 
2543
        QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
 
2544
    } else {
 
2545
        QCOMPARE(socket->state(), QAbstractSocket::ConnectingState);
 
2546
        QVERIFY(!socket->waitForConnected(5000));
 
2547
    }
 
2548
    QVERIFY(!socket->errorString().isEmpty());
 
2549
 
 
2550
    // note: the following test is not a hard failure.
 
2551
    // Sometimes, error codes change for the better
 
2552
    QTEST(int(socket->error()), "expectedError");
 
2553
 
 
2554
    delete socket;
 
2555
}
 
2556
 
 
2557
// copied from tst_qnetworkreply.cpp
 
2558
class MyProxyFactory: public QNetworkProxyFactory
 
2559
{
 
2560
public:
 
2561
    int callCount;
 
2562
    QList<QNetworkProxy> toReturn;
 
2563
    QNetworkProxyQuery lastQuery;
 
2564
    inline MyProxyFactory() { clear(); }
 
2565
 
 
2566
    inline void clear()
 
2567
    {
 
2568
        callCount = 0;
 
2569
        toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
 
2570
        lastQuery = QNetworkProxyQuery();
 
2571
    }
 
2572
 
 
2573
    virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
 
2574
    {
 
2575
        lastQuery = query;
 
2576
        ++callCount;
 
2577
        return toReturn;
 
2578
    }
 
2579
};
 
2580
 
 
2581
void tst_QTcpSocket::proxyFactory_data()
 
2582
{
 
2583
    QTest::addColumn<QList<QNetworkProxy> >("proxyList");
 
2584
    QTest::addColumn<QNetworkProxy>("proxyUsed");
 
2585
    QTest::addColumn<bool>("failsAtConnect");
 
2586
    QTest::addColumn<int>("expectedError");
 
2587
 
 
2588
    QList<QNetworkProxy> proxyList;
 
2589
 
 
2590
    // tests that do connect
 
2591
 
 
2592
    proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
 
2593
    QTest::newRow("http")
 
2594
        << proxyList << proxyList.at(0)
 
2595
        << false << int(QAbstractSocket::UnknownSocketError);
 
2596
 
 
2597
    proxyList.clear();
 
2598
    proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
 
2599
    QTest::newRow("socks5")
 
2600
        << proxyList << proxyList.at(0)
 
2601
        << false << int(QAbstractSocket::UnknownSocketError);
 
2602
 
 
2603
    proxyList.clear();
 
2604
    proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
 
2605
              << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
 
2606
    QTest::newRow("cachinghttp+socks5")
 
2607
        << proxyList << proxyList.at(1)
 
2608
        << false << int(QAbstractSocket::UnknownSocketError);
 
2609
 
 
2610
    proxyList.clear();
 
2611
    proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
 
2612
              << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
 
2613
              << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
 
2614
    QTest::newRow("ftp+cachinghttp+socks5")
 
2615
        << proxyList << proxyList.at(2)
 
2616
        << false << int(QAbstractSocket::UnknownSocketError);
 
2617
 
 
2618
    // tests that fail to connect
 
2619
    proxyList.clear();
 
2620
    proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
 
2621
    QTest::newRow("cachinghttp")
 
2622
        << proxyList << QNetworkProxy()
 
2623
        << true << int(QAbstractSocket::UnsupportedSocketOperationError);
 
2624
 
 
2625
    proxyList.clear();
 
2626
    proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
 
2627
    QTest::newRow("ftp")
 
2628
        << proxyList << QNetworkProxy()
 
2629
        << true << int(QAbstractSocket::UnsupportedSocketOperationError);
 
2630
 
 
2631
    proxyList.clear();
 
2632
    proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
 
2633
              << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
 
2634
    QTest::newRow("ftp+cachinghttp")
 
2635
        << proxyList << QNetworkProxy()
 
2636
        << true << int(QAbstractSocket::UnsupportedSocketOperationError);
 
2637
}
 
2638
 
 
2639
void tst_QTcpSocket::proxyFactory()
 
2640
{
 
2641
    QFETCH_GLOBAL(bool, setProxy);
 
2642
    if (setProxy)
 
2643
        return;
 
2644
 
 
2645
    QFETCH(QList<QNetworkProxy>, proxyList);
 
2646
    QFETCH(QNetworkProxy, proxyUsed);
 
2647
    QFETCH(bool, failsAtConnect);
 
2648
 
 
2649
    MyProxyFactory *factory = new MyProxyFactory;
 
2650
    factory->toReturn = proxyList;
 
2651
    QNetworkProxyFactory::setApplicationProxyFactory(factory);
 
2652
 
 
2653
    QTcpSocket *socket = newSocket();
 
2654
    QString host = QtNetworkSettings::serverName();
 
2655
    socket->connectToHost(host, 80);
 
2656
 
 
2657
    // Verify that the factory was called properly
 
2658
    QCOMPARE(factory->callCount, 1);
 
2659
    QCOMPARE(factory->lastQuery, QNetworkProxyQuery(host, 80));
 
2660
 
 
2661
    if (failsAtConnect) {
 
2662
        QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
 
2663
    } else {
 
2664
        QCOMPARE(socket->state(), QAbstractSocket::ConnectingState);
 
2665
        QVERIFY(socket->waitForConnected(5000));
 
2666
        QCOMPARE(proxyAuthCalled, 1);
 
2667
    }
 
2668
    QVERIFY(!socket->errorString().isEmpty());
 
2669
 
 
2670
    // note: the following test is not a hard failure.
 
2671
    // Sometimes, error codes change for the better
 
2672
    QTEST(int(socket->error()), "expectedError");
 
2673
 
 
2674
    delete socket;
 
2675
}
 
2676
 
 
2677
// there is a similar test inside tst_qtcpserver that uses the event loop instead
 
2678
void tst_QTcpSocket::qtbug14268_peek()
 
2679
{
 
2680
    QFETCH_GLOBAL(bool, setProxy);
 
2681
    if (setProxy)
 
2682
        return;
 
2683
 
 
2684
    SocketPair socketPair;
 
2685
    QVERIFY(socketPair.create());
 
2686
    QTcpSocket *outgoing = socketPair.endPoints[0];
 
2687
    QTcpSocket *incoming = socketPair.endPoints[1];
 
2688
 
 
2689
    QVERIFY(incoming->state() == QTcpSocket::ConnectedState);
 
2690
    QVERIFY(outgoing->state() == QTcpSocket::ConnectedState);
 
2691
 
 
2692
    outgoing->write("abc\n");
 
2693
    QVERIFY(outgoing->waitForBytesWritten(2000));
 
2694
    QVERIFY(incoming->waitForReadyRead(2000));
 
2695
    QVERIFY(incoming->peek(128*1024) == QByteArray("abc\n"));
 
2696
 
 
2697
    outgoing->write("def\n");
 
2698
    QVERIFY(outgoing->waitForBytesWritten(2000));
 
2699
    QVERIFY(incoming->waitForReadyRead(2000));
 
2700
    QVERIFY(incoming->peek(128*1024) == QByteArray("abc\ndef\n"));
 
2701
 
 
2702
    outgoing->write("ghi\n");
 
2703
    QVERIFY(outgoing->waitForBytesWritten(2000));
 
2704
    QVERIFY(incoming->waitForReadyRead(2000));
 
2705
    QVERIFY(incoming->peek(128*1024) == QByteArray("abc\ndef\nghi\n"));
 
2706
 
 
2707
    QVERIFY(incoming->read(128*1024) == QByteArray("abc\ndef\nghi\n"));
 
2708
}
 
2709
 
 
2710
void tst_QTcpSocket::setSocketOption()
 
2711
{
 
2712
    QFETCH_GLOBAL(bool, setProxy);
 
2713
    if (setProxy)
 
2714
        return;
 
2715
 
 
2716
    SocketPair socketPair;
 
2717
    QVERIFY(socketPair.create());
 
2718
    QTcpSocket *outgoing = socketPair.endPoints[0];
 
2719
    QTcpSocket *incoming = socketPair.endPoints[1];
 
2720
 
 
2721
    QVERIFY(incoming->state() == QTcpSocket::ConnectedState);
 
2722
    QVERIFY(outgoing->state() == QTcpSocket::ConnectedState);
 
2723
 
 
2724
    outgoing->setSocketOption(QAbstractSocket::LowDelayOption, true);
 
2725
    QVariant v = outgoing->socketOption(QAbstractSocket::LowDelayOption);
 
2726
    QVERIFY(v.isValid() && v.toBool());
 
2727
    outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, true);
 
2728
    v = outgoing->socketOption(QAbstractSocket::KeepAliveOption);
 
2729
    QVERIFY(v.isValid() && v.toBool());
 
2730
 
 
2731
    outgoing->setSocketOption(QAbstractSocket::LowDelayOption, false);
 
2732
    v = outgoing->socketOption(QAbstractSocket::LowDelayOption);
 
2733
    QVERIFY(v.isValid() && !v.toBool());
 
2734
    outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, false);
 
2735
    v = outgoing->socketOption(QAbstractSocket::KeepAliveOption);
 
2736
    QVERIFY(v.isValid() && !v.toBool());
 
2737
 
 
2738
#ifdef Q_OS_WIN
 
2739
    QEXPECT_FAIL("", "QTBUG-23323", Abort);
 
2740
#endif
 
2741
    outgoing->setSocketOption(QAbstractSocket::TypeOfServiceOption, 32); //high priority
 
2742
    v = outgoing->socketOption(QAbstractSocket::TypeOfServiceOption);
 
2743
    QVERIFY(v.isValid() && v.toInt() == 32);
 
2744
}
 
2745
 
 
2746
QTEST_MAIN(tst_QTcpSocket)
 
2747
#include "tst_qtcpsocket.moc"