5a62f2a by Thiago Macieira at 2009-05-22 1
/****************************************************************************
2
**
89c08c0 by Jason McDonald at 2012-01-11 3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
04e3b30 by Jason McDonald at 2009-09-09 4
** All rights reserved.
858c70f by Jason McDonald at 2009-06-16 5
** Contact: Nokia Corporation (qt-info@nokia.com)
5a62f2a by Thiago Macieira at 2009-05-22 6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
1eea52e by Jyri Tahtela at 2011-05-13 11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
5a62f2a by Thiago Macieira at 2009-05-22 17
**
04e3b30 by Jason McDonald at 2009-09-09 18
** In addition, as a special exception, Nokia gives you certain additional
1eea52e by Jyri Tahtela at 2011-05-13 19
** rights. These rights are described in the Nokia Qt LGPL Exception
04e3b30 by Jason McDonald at 2009-09-09 20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
5a62f2a by Thiago Macieira at 2009-05-22 21
**
1eea52e by Jyri Tahtela at 2011-05-13 22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
309db73 by Jason McDonald at 2009-08-31 33
**
34
**
35
**
36
**
5a62f2a by Thiago Macieira at 2009-05-22 37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include <QtTest/QtTest>
43
#include <QtNetwork/QtNetwork>
30fffab by Aleksandar Sasha Babic at 2009-09-25 44
5c9581b by Thiago Macieira at 2010-04-22 45
#include <time.h>
46
a970c33 by Shane Kearns at 2011-03-29 47
#ifndef QT_NO_BEARERMANAGEMENT
48
#include <QtNetwork/qnetworkconfigmanager.h>
49
#include <QtNetwork/qnetworkconfiguration.h>
50
#include <QtNetwork/qnetworksession.h>
51
#endif
52
30fffab by Aleksandar Sasha Babic at 2009-09-25 53
#ifdef Q_OS_SYMBIAN
54
// In Symbian OS test data is located in applications private dir
55
// Current path (C:\private\<UID>) contains only ascii chars
56
//#define SRCDIR QDir::currentPath()
57
#define SRCDIR "."
58
#endif
59
5a62f2a by Thiago Macieira at 2009-05-22 60
#include "../network-settings.h"
61
62
class tst_NetworkSelfTest: public QObject
63
{
64
    Q_OBJECT
d47b7e6 by Thiago Macieira at 2009-10-06 65
    QHostAddress cachedIpAddress;
9173729 by Janne Anttila at 2009-06-03 66
public:
67
    tst_NetworkSelfTest();
cd10d1a by Janne Anttila at 2009-08-04 68
    virtual ~tst_NetworkSelfTest();
69
d47b7e6 by Thiago Macieira at 2009-10-06 70
    QHostAddress serverIpAddress();
71
5a62f2a by Thiago Macieira at 2009-05-22 72
private slots:
a970c33 by Shane Kearns at 2011-03-29 73
    void initTestCase();
5a62f2a by Thiago Macieira at 2009-05-22 74
    void hostTest();
75
    void dnsResolution_data();
76
    void dnsResolution();
77
    void serverReachability();
78
    void remotePortsOpen_data();
79
    void remotePortsOpen();
30fffab by Aleksandar Sasha Babic at 2009-09-25 80
    void fileLineEndingTest();
5a62f2a by Thiago Macieira at 2009-05-22 81
82
    // specific protocol tests
83
    void ftpServer();
d60a1d0 by Thiago Macieira at 2010-04-22 84
    void ftpProxyServer();
5a62f2a by Thiago Macieira at 2009-05-22 85
    void imapServer();
86
    void httpServer();
fbc94a7 by Thiago Macieira at 2010-04-22 87
    void httpServerFiles_data();
88
    void httpServerFiles();
9da275a by Thiago Macieira at 2010-04-22 89
    void httpServerCGI_data();
90
    void httpServerCGI();
5a62f2a by Thiago Macieira at 2009-05-22 91
    void httpsServer();
92
    void httpProxy();
cd10d1a by Janne Anttila at 2009-08-04 93
    void httpProxyBasicAuth();
5a62f2a by Thiago Macieira at 2009-05-22 94
    void httpProxyNtlmAuth();
95
    void socks5Proxy();
96
    void socks5ProxyAuth();
1692e48 by Thiago Macieira at 2010-04-22 97
    void smbServer();
2b4c35d by Markus Goetz at 2009-11-06 98
99
    // ssl supported test
100
    void supportsSsl();
a970c33 by Shane Kearns at 2011-03-29 101
private:
102
#ifndef QT_NO_BEARERMANAGEMENT
103
    QNetworkConfigurationManager *netConfMan;
104
    QNetworkConfiguration networkConfiguration;
105
    QScopedPointer<QNetworkSession> networkSession;
106
#endif
5a62f2a by Thiago Macieira at 2009-05-22 107
};
108
109
class Chat
110
{
111
public:
112
    enum Type {
113
        Reconnect,
114
        Send,
115
        Expect,
116
        SkipBytes,
117
        DiscardUntil,
118
        DiscardUntilDisconnect,
119
        Disconnect,
120
        RemoteDisconnect,
121
        StartEncryption
122
    };
123
    Chat(Type t, const QByteArray &d)
124
        : data(d), type(t)
125
    {
126
    }
127
    Chat(Type t, int val = 0)
128
        : value(val), type(t)
129
    {
130
    }
131
132
    static inline Chat send(const QByteArray &data)
133
    { return Chat(Send, data); }
134
    static inline Chat expect(const QByteArray &data)
135
    { return Chat(Expect, data); }
136
    static inline Chat discardUntil(const QByteArray &data)
137
    { return Chat(DiscardUntil, data); }
138
    static inline Chat skipBytes(int count)
139
    { return Chat(SkipBytes, count); }
140
141
    QByteArray data;
142
    int value;
143
    Type type;
144
};
145
146
static QString prettyByteArray(const QByteArray &array)
147
{
148
    // any control chars?
149
    QString result;
150
    result.reserve(array.length() + array.length() / 3);
151
    for (int i = 0; i < array.length(); ++i) {
152
        char c = array.at(i);
153
        switch (c) {
154
        case '\n':
155
            result += "\\n";
156
            continue;
157
        case '\r':
158
            result += "\\r";
159
            continue;
160
        case '\t':
161
            result += "\\t";
162
            continue;
163
        case '"':
164
            result += "\\\"";
165
            continue;
166
        default:
167
            break;
168
        }
169
170
        if (c < 0x20 || uchar(c) >= 0x7f) {
171
            result += '\\';
172
            result += QString::number(uchar(c), 8);
173
        } else {
174
            result += c;
175
        }
176
    }
177
    return result;
178
}
179
03e133e by Rohan McGovern at 2012-02-08 180
static bool doSocketRead(QTcpSocket *socket, int minBytesAvailable, int timeout = 30000)
5a62f2a by Thiago Macieira at 2009-05-22 181
{
fbc94a7 by Thiago Macieira at 2010-04-22 182
    QElapsedTimer timer;
5a62f2a by Thiago Macieira at 2009-05-22 183
    timer.start();
184
    forever {
185
        if (socket->bytesAvailable() >= minBytesAvailable)
186
            return true;
187
        if (socket->state() == QAbstractSocket::UnconnectedState
188
            || timer.elapsed() >= timeout)
189
            return false;
190
        if (!socket->waitForReadyRead(timeout - timer.elapsed()))
191
            return false;
192
    }
193
}
194
03e133e by Rohan McGovern at 2012-02-08 195
static bool doSocketFlush(QTcpSocket *socket, int timeout = 30000)
5a62f2a by Thiago Macieira at 2009-05-22 196
{
197
#ifndef QT_NO_OPENSSL
198
    QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
199
#endif
200
    QTime timer;
201
    timer.start();
202
    forever {
203
        if (socket->bytesToWrite() == 0
204
#ifndef QT_NO_OPENSSL
205
            && sslSocket->encryptedBytesToWrite() == 0
206
#endif
207
            )
208
            return true;
209
        if (socket->state() == QAbstractSocket::UnconnectedState
210
            || timer.elapsed() >= timeout)
211
            return false;
212
        if (!socket->waitForBytesWritten(timeout - timer.elapsed()))
213
            return false;
214
    }
215
}
216
217
static void netChat(int port, const QList<Chat> &chat)
218
{
219
#ifndef QT_NO_OPENSSL
220
    QSslSocket socket;
221
#else
222
    QTcpSocket socket;
223
#endif
224
225
    socket.connectToHost(QtNetworkSettings::serverName(), port);
226
    qDebug() << 0 << "Connecting to server on port" << port;
03e133e by Rohan McGovern at 2012-02-08 227
    QVERIFY2(socket.waitForConnected(30000),
5a62f2a by Thiago Macieira at 2009-05-22 228
             QString("Failed to connect to server in step 0: %1").arg(socket.errorString()).toLocal8Bit());
229
230
    // now start the chat
231
    QList<Chat>::ConstIterator it = chat.constBegin();
232
    for (int i = 1; it != chat.constEnd(); ++it, ++i) {
233
        switch (it->type) {
234
            case Chat::Expect: {
235
                    qDebug() << i << "Expecting" << prettyByteArray(it->data);
236
                    if (!doSocketRead(&socket, it->data.length()))
237
                        QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit());
238
239
                    // pop that many bytes off the socket
240
                    QByteArray received = socket.read(it->data.length());
241
242
                    // is it what we expected?
243
                    QVERIFY2(received == it->data,
244
                             QString("Did not receive expected data in step %1: data received was:\n%2")
245
                             .arg(i).arg(prettyByteArray(received)).toLocal8Bit());
246
247
                    break;
248
                }
249
250
            case Chat::DiscardUntil:
251
                qDebug() << i << "Discarding until" << prettyByteArray(it->data);
252
                while (true) {
253
                    // scan the buffer until we have our string
254
                    if (!doSocketRead(&socket, it->data.length()))
255
                        QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit());
256
257
                    QByteArray buffer;
258
                    buffer.resize(socket.bytesAvailable());
259
                    socket.peek(buffer.data(), socket.bytesAvailable());
260
261
                    int pos = buffer.indexOf(it->data);
262
                    if (pos == -1) {
263
                        // data not found, keep trying
264
                        continue;
265
                    }
266
267
                    buffer = socket.read(pos + it->data.length());
268
                    qDebug() << i << "Discarded" << prettyByteArray(buffer);
269
                    break;
270
                }
271
                break;
272
273
            case Chat::SkipBytes: {
274
                    qDebug() << i << "Skipping" << it->value << "bytes";
275
                    if (!doSocketRead(&socket, it->value))
276
                        QFAIL(QString("Failed to receive data in step %1: timeout").arg(i).toLocal8Bit());
277
278
                    // now discard the bytes
279
                    QByteArray buffer = socket.read(it->value);
280
                    qDebug() << i << "Skipped" << prettyByteArray(buffer);
281
                    break;
282
                }
283
284
            case Chat::Send: {
285
                    qDebug() << i << "Sending" << prettyByteArray(it->data);
286
                    socket.write(it->data);
287
                    if (!doSocketFlush(&socket)) {
288
                        QVERIFY2(socket.state() == QAbstractSocket::ConnectedState,
289
                                 QString("Socket disconnected while sending data in step %1").arg(i).toLocal8Bit());
290
                        QFAIL(QString("Failed to send data in step %1: timeout").arg(i).toLocal8Bit());
291
                    }
292
                    break;
293
                }
294
295
            case Chat::Disconnect:
296
                qDebug() << i << "Disconnecting from host";
297
                socket.disconnectFromHost();
298
299
                // is this the last command?
300
                if (it + 1 != chat.constEnd())
301
                    break;
302
303
                // fall through:
304
            case Chat::RemoteDisconnect:
305
            case Chat::DiscardUntilDisconnect:
306
                qDebug() << i << "Waiting for remote disconnect";
307
                if (socket.state() != QAbstractSocket::UnconnectedState)
03e133e by Rohan McGovern at 2012-02-08 308
                    socket.waitForDisconnected(30000);
5a62f2a by Thiago Macieira at 2009-05-22 309
                QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState,
310
                         QString("Socket did not disconnect as expected in step %1").arg(i).toLocal8Bit());
311
312
                // any data left?
313
                if (it->type == Chat::DiscardUntilDisconnect) {
314
                    QByteArray buffer = socket.readAll();
315
                    qDebug() << i << "Discarded in the process:" << prettyByteArray(buffer);
316
                }
317
318
                if (socket.bytesAvailable() != 0)
319
                    QFAIL(QString("Unexpected bytes still on buffer when disconnecting in step %1:\n%2")
320
                          .arg(i).arg(prettyByteArray(socket.readAll())).toLocal8Bit());
321
                break;
322
323
            case Chat::Reconnect:
324
                qDebug() << i << "Reconnecting to server on port" << port;
325
                socket.connectToHost(QtNetworkSettings::serverName(), port);
03e133e by Rohan McGovern at 2012-02-08 326
                QVERIFY2(socket.waitForConnected(30000),
5a62f2a by Thiago Macieira at 2009-05-22 327
                         QString("Failed to reconnect to server in step %1: %2").arg(i).arg(socket.errorString()).toLocal8Bit());
328
                break;
329
330
            case Chat::StartEncryption:
331
#ifdef QT_NO_OPENSSL
332
                QFAIL("Internal error: SSL required for this test");
333
#else
334
                qDebug() << i << "Starting client encryption";
335
                socket.ignoreSslErrors();
336
                socket.startClientEncryption();
03e133e by Rohan McGovern at 2012-02-08 337
                QVERIFY2(socket.waitForEncrypted(30000),
5a62f2a by Thiago Macieira at 2009-05-22 338
                         QString("Failed to start client encryption in step %1: %2").arg(i)
339
                         .arg(socket.errorString()).toLocal8Bit());
340
                break;
341
#endif
342
            }
343
    }
344
}
345
9173729 by Janne Anttila at 2009-06-03 346
tst_NetworkSelfTest::tst_NetworkSelfTest()
347
{
348
    Q_SET_DEFAULT_IAP
349
}
350
351
tst_NetworkSelfTest::~tst_NetworkSelfTest()
352
{
353
}
354
d47b7e6 by Thiago Macieira at 2009-10-06 355
QHostAddress tst_NetworkSelfTest::serverIpAddress()
356
{
357
    if (cachedIpAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
358
        // need resolving
359
        QHostInfo resolved = QHostInfo::fromName(QtNetworkSettings::serverName());
32815bd by Shane Kearns at 2009-10-26 360
        if(resolved.error() != QHostInfo::NoError ||
8365b86 by Rohan McGovern at 2010-12-30 361
            resolved.addresses().isEmpty()) {
32815bd by Shane Kearns at 2009-10-26 362
            qWarning("QHostInfo::fromName failed (%d).", resolved.error());
363
            return QHostAddress(QHostAddress::Null);
364
        }
d47b7e6 by Thiago Macieira at 2009-10-06 365
        cachedIpAddress = resolved.addresses().first();
366
    }
367
    return cachedIpAddress;
368
}
369
a970c33 by Shane Kearns at 2011-03-29 370
void tst_NetworkSelfTest::initTestCase()
371
{
372
#ifndef QT_NO_BEARERMANAGEMENT
373
    netConfMan = new QNetworkConfigurationManager(this);
a7cf6e2 by Shane Kearns at 2011-05-25 374
    netConfMan->updateConfigurations();
375
    connect(netConfMan, SIGNAL(updateCompleted()), &QTestEventLoop::instance(), SLOT(exitLoop()));
376
    QTestEventLoop::instance().enterLoop(10);
a970c33 by Shane Kearns at 2011-03-29 377
    networkConfiguration = netConfMan->defaultConfiguration();
a7cf6e2 by Shane Kearns at 2011-05-25 378
    if (networkConfiguration.isValid()) {
379
        networkSession.reset(new QNetworkSession(networkConfiguration));
380
        if (!networkSession->isOpen()) {
381
            networkSession->open();
382
            QVERIFY(networkSession->waitForOpened(30000));
383
        }
384
    } else {
385
        QVERIFY(!(netConfMan->capabilities() & QNetworkConfigurationManager::NetworkSessionRequired));
a970c33 by Shane Kearns at 2011-03-29 386
    }
387
#endif
388
}
389
5a62f2a by Thiago Macieira at 2009-05-22 390
void tst_NetworkSelfTest::hostTest()
391
{
392
    // this is a localhost self-test
393
    QHostInfo localhost = QHostInfo::fromName("localhost");
394
    QCOMPARE(localhost.error(), QHostInfo::NoError);
395
    QVERIFY(!localhost.addresses().isEmpty());
396
397
    QTcpServer server;
398
    QVERIFY(server.listen());
399
400
    QTcpSocket socket;
401
    socket.connectToHost("127.0.0.1", server.serverPort());
402
    QVERIFY(socket.waitForConnected(10000));
403
}
404
405
void tst_NetworkSelfTest::dnsResolution_data()
406
{
407
    QTest::addColumn<QString>("hostName");
408
    QTest::newRow("local-name") << QtNetworkSettings::serverLocalName();
409
    QTest::newRow("fqdn") << QtNetworkSettings::serverName();
410
}
411
412
void tst_NetworkSelfTest::dnsResolution()
413
{
414
    QFETCH(QString, hostName);
415
    QHostInfo resolved = QHostInfo::fromName(hostName);
416
    QVERIFY2(resolved.error() == QHostInfo::NoError,
417
             QString("Failed to resolve hostname %1: %2").arg(hostName, resolved.errorString()).toLocal8Bit());
d47b7e6 by Thiago Macieira at 2009-10-06 418
    QVERIFY2(resolved.addresses().size() > 0, "Got 0 addresses for server IP");
419
420
    cachedIpAddress = resolved.addresses().first();
5a62f2a by Thiago Macieira at 2009-05-22 421
}
422
423
void tst_NetworkSelfTest::serverReachability()
424
{
9cf6184 by Thiago Macieira at 2009-10-06 425
    // check that we get a proper error connecting to port 12346
5a62f2a by Thiago Macieira at 2009-05-22 426
    QTcpSocket socket;
9cf6184 by Thiago Macieira at 2009-10-06 427
    socket.connectToHost(QtNetworkSettings::serverName(), 12346);
428
429
    QTime timer;
430
    timer.start();
03e133e by Rohan McGovern at 2012-02-08 431
    socket.waitForConnected(30000);
9cf6184 by Thiago Macieira at 2009-10-06 432
    QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
433
5a62f2a by Thiago Macieira at 2009-05-22 434
    QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
435
    QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
436
             QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
437
}
438
439
void tst_NetworkSelfTest::remotePortsOpen_data()
440
{
441
    QTest::addColumn<int>("portNumber");
272a144 by Rohan McGovern at 2011-01-10 442
    QTest::newRow("echo") << 7;
443
    QTest::newRow("daytime") << 13;
5a62f2a by Thiago Macieira at 2009-05-22 444
    QTest::newRow("ftp") << 21;
445
    QTest::newRow("ssh") << 22;
446
    QTest::newRow("imap") << 143;
447
    QTest::newRow("http") << 80;
448
    QTest::newRow("https") << 443;
449
    QTest::newRow("http-proxy") << 3128;
450
    QTest::newRow("http-proxy-auth-basic") << 3129;
cd10d1a by Janne Anttila at 2009-08-04 451
    QTest::newRow("http-proxy-auth-ntlm") << 3130;
5a62f2a by Thiago Macieira at 2009-05-22 452
    QTest::newRow("socks5-proxy") << 1080;
453
    QTest::newRow("socks5-proxy-auth") << 1081;
26eb229 by Thiago Macieira at 2010-04-22 454
    QTest::newRow("ftp-proxy") << 2121;
455
    QTest::newRow("smb") << 139;
5a62f2a by Thiago Macieira at 2009-05-22 456
}
457
458
void tst_NetworkSelfTest::remotePortsOpen()
459
{
9173729 by Janne Anttila at 2009-06-03 460
#ifdef Q_OS_SYMBIAN
461
    if (qstrcmp(QTest::currentDataTag(), "http-proxy-auth-ntlm") == 0)
462
        QSKIP("NTML authentication not yet supported in Symbian", SkipSingle);
cd10d1a by Janne Anttila at 2009-08-04 463
#endif
464
5a62f2a by Thiago Macieira at 2009-05-22 465
    QFETCH(int, portNumber);
466
    QTcpSocket socket;
467
    socket.connectToHost(QtNetworkSettings::serverName(), portNumber);
468
03e133e by Rohan McGovern at 2012-02-08 469
    if (!socket.waitForConnected(30000)) {
5a62f2a by Thiago Macieira at 2009-05-22 470
        if (socket.error() == QAbstractSocket::SocketTimeoutError)
471
            QFAIL(QString("Network timeout connecting to the server on port %1").arg(portNumber).toLocal8Bit());
472
        else
473
            QFAIL(QString("Error connecting to server on port %1: %2").arg(portNumber).arg(socket.errorString()).toLocal8Bit());
474
    }
475
    QVERIFY(socket.state() == QAbstractSocket::ConnectedState);
476
}
477
30fffab by Aleksandar Sasha Babic at 2009-09-25 478
479
void tst_NetworkSelfTest::fileLineEndingTest()
480
{
481
    QString referenceName = SRCDIR "/rfc3252.txt";
482
    long long expectedReferenceSize = 25962;
483
484
    QString lineEndingType("LF");
485
486
    QFile reference(referenceName);
487
    QVERIFY(reference.open(QIODevice::ReadOnly));
488
    QByteArray byteLine = reference.readLine();
489
    if(byteLine.endsWith("\r\n"))
490
        lineEndingType = "CRLF";
491
    else if(byteLine.endsWith("\r"))
492
        lineEndingType = "CR";
493
494
    QString referenceAsTextData;
495
    QFile referenceAsText(referenceName);
496
    QVERIFY(referenceAsText.open(QIODevice::ReadOnly));
497
    referenceAsTextData = referenceAsText.readAll();
498
499
    QVERIFY2(expectedReferenceSize == referenceAsTextData.length(), QString("Reference file %1 has %2 as line ending and file size not matching - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit());
500
    QVERIFY2(!lineEndingType.compare("LF"), QString("Reference file %1 has %2 as line ending - Git checkout issue !?!").arg(referenceName, lineEndingType).toLocal8Bit());
501
}
502
d60a1d0 by Thiago Macieira at 2010-04-22 503
static QList<Chat> ftpChat(const QByteArray &userSuffix = QByteArray())
5a62f2a by Thiago Macieira at 2009-05-22 504
{
aa67255 by Shane Kearns at 2011-03-29 505
    QList<Chat> rv;
506
    rv << Chat::expect("220")
5a62f2a by Thiago Macieira at 2009-05-22 507
            << Chat::discardUntil("\r\n")
d60a1d0 by Thiago Macieira at 2010-04-22 508
            << Chat::send("USER anonymous" + userSuffix + "\r\n")
5a62f2a by Thiago Macieira at 2009-05-22 509
            << Chat::expect("331")
510
            << Chat::discardUntil("\r\n")
511
            << Chat::send("PASS user@hostname\r\n")
512
            << Chat::expect("230")
513
            << Chat::discardUntil("\r\n")
6e4ea4a by Thiago Macieira at 2010-04-22 514
515
            << Chat::send("CWD pub\r\n")
516
            << Chat::expect("250")
517
            << Chat::discardUntil("\r\n")
518
            << Chat::send("CWD dir-not-readable\r\n")
519
            << Chat::expect("550")
520
            << Chat::discardUntil("\r\n")
521
            << Chat::send("PWD\r\n")
522
            << Chat::expect("257 \"/pub\"\r\n")
523
            << Chat::send("SIZE file-not-readable.txt\r\n")
524
            << Chat::expect("213 41\r\n")
525
            << Chat::send("CWD qxmlquery\r\n")
526
            << Chat::expect("250")
527
            << Chat::discardUntil("\r\n")
528
529
            << Chat::send("CWD /qtest\r\n")
530
            << Chat::expect("250")
531
            << Chat::discardUntil("\r\n")
532
            << Chat::send("SIZE bigfile\r\n")
533
            << Chat::expect("213 519240\r\n")
534
            << Chat::send("SIZE rfc3252\r\n")
535
            << Chat::expect("213 25962\r\n")
536
            << Chat::send("SIZE rfc3252.txt\r\n")
537
            << Chat::expect("213 25962\r\n")
538
//            << Chat::send("SIZE nonASCII/german_\344\366\374\304\326\334\337\r\n")
539
//            << Chat::expect("213 40\r\n")
540
aa67255 by Shane Kearns at 2011-03-29 541
            << Chat::send("QUIT\r\n");
542
#ifdef Q_OS_SYMBIAN
543
    if (userSuffix.length() == 0) // received but unacknowledged packets are discarded by TCP RST, so this doesn't work with frox proxy
544
#endif
545
        rv  << Chat::expect("221")
546
            << Chat::discardUntil("\r\n");
547
548
    rv << Chat::RemoteDisconnect;
549
    return rv;
5a62f2a by Thiago Macieira at 2009-05-22 550
}
551
552
void tst_NetworkSelfTest::ftpServer()
553
{
554
    netChat(21, ftpChat());
555
}
556
d60a1d0 by Thiago Macieira at 2010-04-22 557
void tst_NetworkSelfTest::ftpProxyServer()
558
{
559
    netChat(2121, ftpChat("@" + QtNetworkSettings::serverName().toLatin1()));
560
}
561
5a62f2a by Thiago Macieira at 2009-05-22 562
void tst_NetworkSelfTest::imapServer()
563
{
564
    netChat(143, QList<Chat>()
565
            << Chat::expect("* OK ")
566
            << Chat::discardUntil("\r\n")
567
            << Chat::send("1 CAPABILITY\r\n")
568
            << Chat::expect("* CAPABILITY ")
569
            << Chat::discardUntil("1 OK")
570
            << Chat::discardUntil("\r\n")
571
            << Chat::send("2 LOGOUT\r\n")
572
            << Chat::discardUntil("2 OK")
573
            << Chat::discardUntil("\r\n")
574
            << Chat::RemoteDisconnect);
575
}
576
577
void tst_NetworkSelfTest::httpServer()
578
{
5c9581b by Thiago Macieira at 2010-04-22 579
    QString uniqueExtension;
580
    qsrand(time(0));
581
#ifndef Q_OS_WINCE
582
    uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(qrand()).arg((qulonglong)time(0));
583
#else
584
    uniqueExtension = QString("%1%2").arg((qulonglong)this).arg(qrand());
585
#endif
586
5a62f2a by Thiago Macieira at 2009-05-22 587
    netChat(80, QList<Chat>()
588
            // HTTP/0.9 chat:
589
            << Chat::send("GET /\r\n")
590
            << Chat::DiscardUntilDisconnect
591
592
            // HTTP/1.0 chat:
593
            << Chat::Reconnect
594
            << Chat::send("GET / HTTP/1.0\r\n"
595
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
596
                          "Connection: close\r\n"
597
                          "\r\n")
598
            << Chat::expect("HTTP/1.")
599
            << Chat::discardUntil(" ")
600
            << Chat::expect("200 ")
601
            << Chat::DiscardUntilDisconnect
602
603
            // HTTP/1.0 POST:
604
            << Chat::Reconnect
605
            << Chat::send("POST / HTTP/1.0\r\n"
606
                          "Content-Length: 5\r\n"
607
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
608
                          "Connection: close\r\n"
609
                          "\r\n"
610
                          "Hello")
611
            << Chat::expect("HTTP/1.")
612
            << Chat::discardUntil(" ")
613
            << Chat::expect("200 ")
614
            << Chat::DiscardUntilDisconnect
5c9581b by Thiago Macieira at 2010-04-22 615
616
            // HTTP protected area
617
            << Chat::Reconnect
618
            << Chat::send("GET /qtest/protected/rfc3252.txt HTTP/1.0\r\n"
619
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
620
                          "Connection: close\r\n"
621
                          "\r\n")
622
            << Chat::expect("HTTP/1.")
623
            << Chat::discardUntil(" ")
624
            << Chat::expect("401 ")
625
            << Chat::DiscardUntilDisconnect
626
627
            << Chat::Reconnect
628
            << Chat::send("HEAD /qtest/protected/rfc3252.txt HTTP/1.0\r\n"
629
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
630
                          "Connection: close\r\n"
631
                          "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n"
632
                          "\r\n")
633
            << Chat::expect("HTTP/1.")
634
            << Chat::discardUntil(" ")
635
            << Chat::expect("200 ")
636
            << Chat::DiscardUntilDisconnect
637
638
            // DAV area
639
            << Chat::Reconnect
640
            << Chat::send("HEAD /dav/ HTTP/1.0\r\n"
641
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
642
                          "Connection: close\r\n"
643
                          "\r\n")
644
            << Chat::expect("HTTP/1.")
645
            << Chat::discardUntil(" ")
646
            << Chat::expect("200 ")
647
            << Chat::DiscardUntilDisconnect
648
649
            // HTTP/1.0 PUT
650
            << Chat::Reconnect
651
            << Chat::send("PUT /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n"
652
                          "Content-Length: 5\r\n"
653
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
654
                          "Connection: close\r\n"
655
                          "\r\n"
656
                          "Hello")
657
            << Chat::expect("HTTP/1.")
658
            << Chat::discardUntil(" ")
659
            << Chat::expect("201 ")
660
            << Chat::DiscardUntilDisconnect
661
662
            // check that the file did get uploaded
663
            << Chat::Reconnect
664
            << Chat::send("HEAD /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n"
665
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
666
                          "Connection: close\r\n"
667
                          "\r\n")
668
            << Chat::expect("HTTP/1.")
669
            << Chat::discardUntil(" ")
670
            << Chat::expect("200 ")
671
            << Chat::discardUntil("\r\nContent-Length: 5\r\n")
672
            << Chat::DiscardUntilDisconnect
673
674
            // HTTP/1.0 DELETE
675
            << Chat::Reconnect
676
            << Chat::send("DELETE /dav/networkselftest-" + uniqueExtension.toLatin1() + ".txt HTTP/1.0\r\n"
677
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
678
                          "Connection: close\r\n"
679
                          "\r\n")
680
            << Chat::expect("HTTP/1.")
681
            << Chat::discardUntil(" ")
682
            << Chat::expect("204 ")
683
            << Chat::DiscardUntilDisconnect
5a62f2a by Thiago Macieira at 2009-05-22 684
            );
685
}
686
fbc94a7 by Thiago Macieira at 2010-04-22 687
void tst_NetworkSelfTest::httpServerFiles_data()
688
{
689
    QTest::addColumn<QString>("uri");
690
    QTest::addColumn<int>("size");
691
692
    QTest::newRow("fluke.gif") << "/qtest/fluke.gif" << -1;
693
    QTest::newRow("bigfile") << "/qtest/bigfile" << 519240;
694
    QTest::newRow("rfc3252.txt") << "/qtest/rfc3252.txt" << 25962;
695
    QTest::newRow("protected/rfc3252.txt") << "/qtest/protected/rfc3252.txt" << 25962;
696
    QTest::newRow("completelyEmptyQuery.xq") << "/qtest/qxmlquery/completelyEmptyQuery.xq" << -1;
697
    QTest::newRow("notWellformedViaHttps.xml") << "/qtest/qxmlquery/notWellformedViaHttps.xml" << -1;
698
    QTest::newRow("notWellformed.xml") << "/qtest/qxmlquery/notWellformed.xml" << -1;
699
    QTest::newRow("viaHttp.xq") << "/qtest/qxmlquery/viaHttp.xq" << -1;
700
    QTest::newRow("wellFormedViaHttps.xml") << "/qtest/qxmlquery/wellFormedViaHttps.xml" << -1;
701
    QTest::newRow("wellFormed.xml") << "/qtest/qxmlquery/wellFormed.xml" << -1;
702
}
703
704
void tst_NetworkSelfTest::httpServerFiles()
705
{
706
    QFETCH(QString, uri);
707
    QFETCH(int, size);
708
709
    QList<Chat> chat;
710
    chat << Chat::send("HEAD " + QUrl::toPercentEncoding(uri, "/") + " HTTP/1.0\r\n"
711
                       "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
712
                       "Connection: close\r\n"
713
                       "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n"
714
                       "\r\n")
715
         << Chat::expect("HTTP/1.")
716
         << Chat::skipBytes(1) // HTTP/1.0 or 1.1 reply
717
         << Chat::expect(" 200 ");
718
    if (size != -1)
719
        chat << Chat::discardUntil("\r\nContent-Length: " + QByteArray::number(size) + "\r\n");
720
    chat << Chat::DiscardUntilDisconnect;
721
    netChat(80, chat);
722
}
723
9da275a by Thiago Macieira at 2010-04-22 724
void tst_NetworkSelfTest::httpServerCGI_data()
725
{
726
    QTest::addColumn<QByteArray>("request");
727
    QTest::addColumn<QByteArray>("result");
728
    QTest::addColumn<QByteArray>("additionalHeader");
729
730
    QTest::newRow("echo.cgi")
731
            << QByteArray("GET /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n"
732
                          "Connection: close\r\n"
733
                          "\r\n")
734
            << QByteArray("Hello+World")
735
            << QByteArray();
736
737
    QTest::newRow("echo.cgi(POST)")
738
            << QByteArray("POST /qtest/cgi-bin/echo.cgi?Hello+World HTTP/1.0\r\n"
739
                          "Connection: close\r\n"
740
                          "Content-Length: 15\r\n"
741
                          "\r\n"
742
                          "Hello, World!\r\n")
743
            << QByteArray("Hello, World!\r\n")
744
            << QByteArray();
745
746
    QTest::newRow("md5sum.cgi")
747
            << QByteArray("POST /qtest/cgi-bin/md5sum.cgi HTTP/1.0\r\n"
748
                          "Connection: close\r\n"
749
                          "Content-Length: 15\r\n"
750
                          "\r\n"
751
                          "Hello, World!\r\n")
752
            << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n")
753
            << QByteArray();
754
755
    QTest::newRow("protected/md5sum.cgi")
756
            << QByteArray("POST /qtest/protected/cgi-bin/md5sum.cgi HTTP/1.0\r\n"
757
                          "Connection: close\r\n"
758
                          "Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n"
759
                          "Content-Length: 15\r\n"
760
                          "\r\n"
761
                          "Hello, World!\r\n")
762
            << QByteArray("29b933a8d9a0fcef0af75f1713f4940e\n")
763
            << QByteArray();
764
765
    QTest::newRow("set-cookie.cgi")
766
            << QByteArray("POST /qtest/cgi-bin/set-cookie.cgi HTTP/1.0\r\n"
767
                          "Connection: close\r\n"
768
                          "Content-Length: 8\r\n"
769
                          "\r\n"
770
                          "foo=bar\n")
771
            << QByteArray("Success\n")
772
            << QByteArray("\r\nSet-Cookie: foo=bar\r\n");
773
}
774
775
void tst_NetworkSelfTest::httpServerCGI()
776
{
777
    QFETCH(QByteArray, request);
778
    QFETCH(QByteArray, result);
779
    QFETCH(QByteArray, additionalHeader);
780
    QList<Chat> chat;
781
    chat << Chat::send(request)
782
         << Chat::expect("HTTP/1.") << Chat::skipBytes(1)
783
         << Chat::expect(" 200 ");
784
785
    if (!additionalHeader.isEmpty())
786
        chat << Chat::discardUntil(additionalHeader);
787
788
    chat << Chat::discardUntil("\r\n\r\n")
789
         << Chat::expect(result)
790
         << Chat::RemoteDisconnect;
791
    netChat(80, chat);
792
}
793
5a62f2a by Thiago Macieira at 2009-05-22 794
void tst_NetworkSelfTest::httpsServer()
795
{
796
#ifndef QT_NO_OPENSSL
797
    netChat(443, QList<Chat>()
798
            << Chat::StartEncryption
799
            << Chat::send("GET / HTTP/1.0\r\n"
800
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
801
                          "Connection: close\r\n"
802
                          "\r\n")
803
            << Chat::expect("HTTP/1.")
804
            << Chat::discardUntil(" ")
805
            << Chat::expect("200 ")
806
            << Chat::DiscardUntilDisconnect);
807
#else
b469fd9 by Joerg Bornemann at 2009-06-03 808
    QSKIP("SSL not enabled, cannot test", SkipAll);
5a62f2a by Thiago Macieira at 2009-05-22 809
#endif
810
}
811
812
void tst_NetworkSelfTest::httpProxy()
813
{
814
    netChat(3128, QList<Chat>()
d47b7e6 by Thiago Macieira at 2009-10-06 815
            // proxy GET by IP
816
            << Chat::send("GET http://" + serverIpAddress().toString().toLatin1() + "/ HTTP/1.0\r\n"
817
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
818
                          "Proxy-connection: close\r\n"
819
                          "\r\n")
820
            << Chat::expect("HTTP/1.")
821
            << Chat::discardUntil(" ")
822
            << Chat::expect("200 ")
823
            << Chat::DiscardUntilDisconnect
824
825
            // proxy GET by hostname
826
            << Chat::Reconnect
5a62f2a by Thiago Macieira at 2009-05-22 827
            << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n"
828
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
829
                          "Proxy-connection: close\r\n"
830
                          "\r\n")
831
            << Chat::expect("HTTP/1.")
832
            << Chat::discardUntil(" ")
833
            << Chat::expect("200 ")
834
            << Chat::DiscardUntilDisconnect
835
d47b7e6 by Thiago Macieira at 2009-10-06 836
            // proxy CONNECT by IP
837
            << Chat::Reconnect
838
            << Chat::send("CONNECT " + serverIpAddress().toString().toLatin1() + ":21 HTTP/1.0\r\n"
839
                          "\r\n")
840
            << Chat::expect("HTTP/1.")
841
            << Chat::discardUntil(" ")
842
            << Chat::expect("200 ")
843
            << Chat::discardUntil("\r\n\r\n")
844
            << ftpChat()
845
846
            // proxy CONNECT by hostname
5a62f2a by Thiago Macieira at 2009-05-22 847
            << Chat::Reconnect
848
            << Chat::send("CONNECT " + QtNetworkSettings::serverName().toLatin1() + ":21 HTTP/1.0\r\n"
849
                          "\r\n")
850
            << Chat::expect("HTTP/1.")
851
            << Chat::discardUntil(" ")
852
            << Chat::expect("200 ")
853
            << Chat::discardUntil("\r\n\r\n")
d47b7e6 by Thiago Macieira at 2009-10-06 854
            << ftpChat()
855
            );
5a62f2a by Thiago Macieira at 2009-05-22 856
}
857
858
void tst_NetworkSelfTest::httpProxyBasicAuth()
859
{
860
    netChat(3129, QList<Chat>()
861
            // test auth required response
862
            << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n"
863
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
864
                          "Proxy-connection: close\r\n"
865
                          "\r\n")
866
            << Chat::expect("HTTP/1.")
867
            << Chat::discardUntil(" ")
868
            << Chat::expect("407 ")
869
            << Chat::discardUntil("\r\nProxy-Authenticate: Basic realm=\"")
870
            << Chat::DiscardUntilDisconnect
871
872
            // now try sending our credentials
873
            << Chat::Reconnect
874
            << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n"
875
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
876
                          "Proxy-connection: close\r\n"
877
                          "Proxy-Authorization: Basic cXNvY2tzdGVzdDpwYXNzd29yZA==\r\n"
878
                          "\r\n")
879
            << Chat::expect("HTTP/1.")
880
            << Chat::discardUntil(" ")
881
            << Chat::expect("200 ")
882
            << Chat::DiscardUntilDisconnect);
883
}
884
885
void tst_NetworkSelfTest::httpProxyNtlmAuth()
886
{
9173729 by Janne Anttila at 2009-06-03 887
#ifdef Q_OS_SYMBIAN
888
    QSKIP("NTML authentication not yet supported in Symbian", SkipAll);
cd10d1a by Janne Anttila at 2009-08-04 889
#else
5a62f2a by Thiago Macieira at 2009-05-22 890
    netChat(3130, QList<Chat>()
891
            // test auth required response
892
            << Chat::send("GET http://" + QtNetworkSettings::serverName().toLatin1() + "/ HTTP/1.0\r\n"
893
                          "Host: " + QtNetworkSettings::serverName().toLatin1() + "\r\n"
894
                          "Proxy-connection: keep-alive\r\n" // NTLM auth will disconnect
895
                          "\r\n")
896
            << Chat::expect("HTTP/1.")
897
            << Chat::discardUntil(" ")
898
            << Chat::expect("407 ")
899
            << Chat::discardUntil("\r\nProxy-Authenticate: NTLM\r\n")
900
            << Chat::DiscardUntilDisconnect
901
            );
cd10d1a by Janne Anttila at 2009-08-04 902
#endif
5a62f2a by Thiago Macieira at 2009-05-22 903
}
904
905
// SOCKSv5 is a binary protocol
906
static const char handshakeNoAuth[] = "\5\1\0";
907
static const char handshakeOkNoAuth[] = "\5\0";
908
static const char handshakeAuthPassword[] = "\5\1\2\1\12qsockstest\10password";
909
static const char handshakeOkPasswdAuth[] = "\5\2\1\0";
910
static const char handshakeAuthNotOk[] = "\5\377";
911
static const char connect1[] = "\5\1\0\1\177\0\0\1\0\25"; // Connect IPv4 127.0.0.1 port 21
d47b7e6 by Thiago Macieira at 2009-10-06 912
static const char connect1a[] = "\5\1\0\1"; // just "Connect to IPv4"
913
static const char connect1b[] = "\0\25"; // just "port 21"
5a62f2a by Thiago Macieira at 2009-05-22 914
static const char connect2[] = "\5\1\0\3\11localhost\0\25"; // Connect hostname localhost 21
d47b7e6 by Thiago Macieira at 2009-10-06 915
static const char connect2a[] = "\5\1\0\3"; // just "Connect to hostname"
5a62f2a by Thiago Macieira at 2009-05-22 916
static const char connected[] = "\5\0\0";
917
d47b7e6 by Thiago Macieira at 2009-10-06 918
#define QBA(x) (QByteArray::fromRawData(x, -1 + sizeof(x)))
919
5a62f2a by Thiago Macieira at 2009-05-22 920
void tst_NetworkSelfTest::socks5Proxy()
921
{
d47b7e6 by Thiago Macieira at 2009-10-06 922
    union {
923
        char buf[4];
924
        quint32 data;
925
    } ip4Address;
926
    ip4Address.data = qToBigEndian(serverIpAddress().toIPv4Address());
927
5a62f2a by Thiago Macieira at 2009-05-22 928
    netChat(1080, QList<Chat>()
929
            // IP address connection
930
            << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth))
931
            << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth))
932
            << Chat::send(QByteArray(connect1, -1 + sizeof connect1))
933
            << Chat::expect(QByteArray(connected, -1 + sizeof connected))
934
            << Chat::expect("\1") // IPv4 address following
935
            << Chat::skipBytes(6) // the server's local address and port
936
            << ftpChat()
937
d47b7e6 by Thiago Macieira at 2009-10-06 938
            // connect by IP
939
            << Chat::Reconnect
940
            << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth))
941
            << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth))
942
            << Chat::send(QBA(connect1a) + QByteArray::fromRawData(ip4Address.buf, 4) + QBA(connect1b))
943
            << Chat::expect(QByteArray(connected, -1 + sizeof connected))
944
            << Chat::expect("\1") // IPv4 address following
945
            << Chat::skipBytes(6) // the server's local address and port
946
            << ftpChat()
947
948
            // connect to "localhost" by hostname
5a62f2a by Thiago Macieira at 2009-05-22 949
            << Chat::Reconnect
950
            << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth))
951
            << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth))
952
            << Chat::send(QByteArray(connect2, -1 + sizeof connect2))
953
            << Chat::expect(QByteArray(connected, -1 + sizeof connected))
954
            << Chat::expect("\1") // IPv4 address following
955
            << Chat::skipBytes(6) // the server's local address and port
956
            << ftpChat()
d47b7e6 by Thiago Macieira at 2009-10-06 957
958
            // connect to server by its official name
959
            << Chat::Reconnect
960
            << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth))
961
            << Chat::expect(QByteArray(handshakeOkNoAuth, -1 + sizeof handshakeOkNoAuth))
962
            << Chat::send(QBA(connect2a) + char(QtNetworkSettings::serverName().size()) + QtNetworkSettings::serverName().toLatin1() + QBA(connect1b))
963
            << Chat::expect(QByteArray(connected, -1 + sizeof connected))
964
            << Chat::expect("\1") // IPv4 address following
965
            << Chat::skipBytes(6) // the server's local address and port
966
            << ftpChat()
5a62f2a by Thiago Macieira at 2009-05-22 967
            );
968
}
969
970
void tst_NetworkSelfTest::socks5ProxyAuth()
971
{
972
    netChat(1081, QList<Chat>()
973
            // unauthenticated connect -- will get error
974
            << Chat::send(QByteArray(handshakeNoAuth, -1 + sizeof handshakeNoAuth))
975
            << Chat::expect(QByteArray(handshakeAuthNotOk, -1 + sizeof handshakeAuthNotOk))
976
            << Chat::RemoteDisconnect
977
978
            // now try to connect with authentication
979
            << Chat::Reconnect
980
            << Chat::send(QByteArray(handshakeAuthPassword, -1 + sizeof handshakeAuthPassword))
981
            << Chat::expect(QByteArray(handshakeOkPasswdAuth, -1 + sizeof handshakeOkPasswdAuth))
982
            << Chat::send(QByteArray(connect1, -1 + sizeof connect1))
983
            << Chat::expect(QByteArray(connected, -1 + sizeof connected))
984
            << Chat::expect("\1") // IPv4 address following
985
            << Chat::skipBytes(6) // the server's local address and port
986
            << ftpChat()
987
            );
988
}
989
2b4c35d by Markus Goetz at 2009-11-06 990
void tst_NetworkSelfTest::supportsSsl()
991
{
992
#ifdef QT_NO_OPENSSL
993
    QFAIL("SSL not compiled in");
994
#else
26eb229 by Thiago Macieira at 2010-04-22 995
    QVERIFY2(QSslSocket::supportsSsl(), "Could not load SSL libraries");
2b4c35d by Markus Goetz at 2009-11-06 996
#endif
997
}
998
1692e48 by Thiago Macieira at 2010-04-22 999
void tst_NetworkSelfTest::smbServer()
1000
{
1001
    static const char contents[] = "This is 34 bytes. Do not change...";
1002
#ifdef Q_OS_WIN
1003
    // use Windows's native UNC support to try and open a file on the server
1004
    QString filepath = QString("\\\\%1\\testshare\\test.pri").arg(QtNetworkSettings::winServerName());
1005
    FILE *f = fopen(filepath.toLatin1(), "rb");
1006
    QVERIFY2(f, qt_error_string().toLocal8Bit());
1007
1008
    char buf[128];
2576f3b by Martin Petersson at 2011-02-18 1009
    size_t ret = fread(buf, 1, sizeof buf, f);
1692e48 by Thiago Macieira at 2010-04-22 1010
    fclose(f);
1011
1012
    QCOMPARE(ret, strlen(contents));
2d1199e by Thiago Macieira at 2010-04-27 1013
    QVERIFY(memcmp(buf, contents, strlen(contents)) == 0);
1692e48 by Thiago Macieira at 2010-04-22 1014
#else
1015
    // try to use Samba
1016
    QString progname = "smbclient";
1017
    QProcess smbclient;
1018
    smbclient.start(progname, QIODevice::ReadOnly);
03e133e by Rohan McGovern at 2012-02-08 1019
    if (!smbclient.waitForStarted())
1692e48 by Thiago Macieira at 2010-04-22 1020
        QSKIP("Could not find smbclient (from Samba), cannot continue testing", SkipAll);
03e133e by Rohan McGovern at 2012-02-08 1021
    if (!smbclient.waitForFinished() || smbclient.exitStatus() != QProcess::NormalExit)
1692e48 by Thiago Macieira at 2010-04-22 1022
        QSKIP("smbclient isn't working, cannot continue testing", SkipAll);
1023
    smbclient.close();
1024
1025
    // try listing the server
1026
    smbclient.start(progname, QStringList() << "-g" << "-N" << "-L" << QtNetworkSettings::winServerName(), QIODevice::ReadOnly);
03e133e by Rohan McGovern at 2012-02-08 1027
    QVERIFY(smbclient.waitForFinished());
1692e48 by Thiago Macieira at 2010-04-22 1028
    if (smbclient.exitStatus() != QProcess::NormalExit)
1029
        QSKIP("smbclient crashed", SkipAll);
1030
    QVERIFY2(smbclient.exitCode() == 0, "Test server not found");
1031
1032
    QByteArray output = smbclient.readAll();
1033
    QVERIFY(output.contains("Disk|testshare|"));
1034
    QVERIFY(output.contains("Disk|testsharewritable|"));
1035
    QVERIFY(output.contains("Disk|testsharelargefile|"));
1036
    qDebug() << "Test server found and shares are correct";
1037
1038
    // try getting a file
1039
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
1040
    env.insert("PAGER", "/bin/cat"); // just in case
1041
    smbclient.setProcessEnvironment(env);
1042
    smbclient.start(progname, QStringList() << "-N" << "-c" << "more test.pri"
1043
                    << QString("\\\\%1\\testshare").arg(QtNetworkSettings::winServerName()), QIODevice::ReadOnly);
03e133e by Rohan McGovern at 2012-02-08 1044
    QVERIFY(smbclient.waitForFinished());
1692e48 by Thiago Macieira at 2010-04-22 1045
    if (smbclient.exitStatus() != QProcess::NormalExit)
1046
        QSKIP("smbclient crashed", SkipAll);
1047
    QVERIFY2(smbclient.exitCode() == 0, "File //qt-test-server/testshare/test.pri not found");
1048
1049
    output = smbclient.readAll();
1050
    QCOMPARE(output.constData(), contents);
1051
    qDebug() << "Test file is correct";
1052
#endif
1053
}
1054
5a62f2a by Thiago Macieira at 2009-05-22 1055
QTEST_MAIN(tst_NetworkSelfTest)
1056
#include "tst_networkselftest.moc"