1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #include <qcoreapplication.h>
46 #include <qfile.h>
47 #include <qbuffer.h>
48 #include "qftp.h"
49 #include <qmap.h>
50 #include <time.h>
51 #include <stdlib.h>
52 #include <QNetworkProxy>
53 #include <QNetworkConfiguration>
54 #include <qnetworkconfigmanager.h>
55 #include <QNetworkSession>
56 #include <QtNetwork/private/qnetworksession_p.h>
57
58 #include "../network-settings.h"
59
60 //TESTED_CLASS=
61 //TESTED_FILES=
62
63 #ifdef Q_OS_SYMBIAN
64 // In Symbian OS test data is located in applications private dir
65 // Application private dir is default serach path for files, so SRCDIR can be set to empty
66 #define SRCDIR ""
67 #endif
68
69 #ifndef QT_NO_BEARERMANAGEMENT
70 Q_DECLARE_METATYPE(QNetworkConfiguration)
71 #endif
72
73 class tst_QFtp : public QObject
74 {
75 Q_OBJECT
76
77 public:
78 tst_QFtp();
79 virtual ~tst_QFtp();
80
81
82 public slots:
83 void initTestCase_data();
84 void initTestCase();
85 void cleanupTestCase();
86 void init();
87 void cleanup();
88 private slots:
89 void connectToHost_data();
90 void connectToHost();
91 void connectToUnresponsiveHost();
92 void login_data();
93 void login();
94 void close_data();
95 void close();
96
97 void list_data();
98 void list();
99 void cd_data();
100 void cd();
101 void get_data();
102 void get();
103 void put_data();
104 void put();
105 void remove();
106 void mkdir_data();
107 void mkdir();
108 void mkdir2();
109 void rmdir();
110 void rename_data();
111 void rename();
112
113 void commandSequence_data();
114 void commandSequence();
115
116 void abort_data();
117 void abort();
118
119 void bytesAvailable_data();
120 void bytesAvailable();
121
122 void activeMode();
123
124 void proxy_data();
125 void proxy();
126
127 void binaryAscii();
128
129 void doneSignal();
130 void queueMoreCommandsInDoneSlot();
131
132 void qtbug7359Crash();
133
134 protected slots:
135 void stateChanged( int );
136 void listInfo( const QUrlInfo & );
137 void readyRead();
138 void dataTransferProgress(qint64, qint64);
139
140 void commandStarted( int );
141 void commandFinished( int, bool );
142 void done( bool );
143 void activeModeDone( bool );
144 void mkdir2Slot(int id, bool error);
145 void cdUpSlot(bool);
146
147 private:
148 QFtp *newFtp();
149 void addCommand( QFtp::Command, int );
150 bool fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir = QString::null );
151 bool dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate );
152
153 void renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile );
154 void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete );
155
156 QFtp *ftp;
157 #ifndef QT_NO_BEARERMANAGEMENT
158 QNetworkConfigurationManager *netConfMan;
159 QSharedPointer<QNetworkSession> networkSessionExplicit;
160 QSharedPointer<QNetworkSession> networkSessionImplicit;
161 #endif
162
163 QList<int> ids; // helper to make sure that all expected signals are emitted
164 int current_id;
165
166 int connectToHost_state;
167 int close_state;
168 int login_state;
169 int cur_state;
170 struct CommandResult
171 {
172 int id;
173 int success;
174 };
175 QMap< QFtp::Command, CommandResult > resultMap;
176 typedef QMap<QFtp::Command,CommandResult>::Iterator ResMapIt;
177
178 int done_success;
179 int commandSequence_success;
180
181 qlonglong bytesAvailable_finishedGet;
182 qlonglong bytesAvailable_finished;
183 qlonglong bytesAvailable_done;
184
185 QList<QUrlInfo> listInfo_i;
186 QByteArray newData_ba;
187 qlonglong bytesTotal;
188 qlonglong bytesDone;
189
190 bool inFileDirExistsFunction;
191
192 QString uniqueExtension;
193 };
194
195 //#define DUMP_SIGNALS
196
197 const int bytesTotal_init = -10;
198 const int bytesDone_init = -10;
199
tst_QFtp()200 tst_QFtp::tst_QFtp() :
201 ftp(0)
202 {
203 }
204
~tst_QFtp()205 tst_QFtp::~tst_QFtp()
206 {
207 }
208
initTestCase_data()209 void tst_QFtp::initTestCase_data()
210 {
211 QTest::addColumn<bool>("setProxy");
212 QTest::addColumn<int>("proxyType");
213 QTest::addColumn<bool>("setSession");
214
215 QTest::newRow("WithoutProxy") << false << 0 << false;
216 QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy) << false;
217 //### doesn't work well yet.
218 //QTest::newRow("WithHttpProxy") << true << int(QNetworkProxy::HttpProxy);
219
220 #ifndef QT_NO_BEARERMANAGEMENT
221 QTest::newRow("WithoutProxyWithSession") << false << 0 << true;
222 QTest::newRow("WithSocks5ProxyAndSession") << true << int(QNetworkProxy::Socks5Proxy) << true;
223 #endif
224 }
225
initTestCase()226 void tst_QFtp::initTestCase()
227 {
228 #ifndef QT_NO_BEARERMANAGEMENT
229 netConfMan = new QNetworkConfigurationManager(this);
230 netConfMan->updateConfigurations();
231 connect(netConfMan, SIGNAL(updateCompleted()), &QTestEventLoop::instance(), SLOT(exitLoop()));
232 QTestEventLoop::instance().enterLoop(10);
233 QNetworkConfiguration networkConfiguration = netConfMan->defaultConfiguration();
234 if (networkConfiguration.isValid()) {
235 networkSessionImplicit = QSharedPointer<QNetworkSession>(new QNetworkSession(networkConfiguration));
236 if (!networkSessionImplicit->isOpen()) {
237 networkSessionImplicit->open();
238 QVERIFY(networkSessionImplicit->waitForOpened(30000));
239 }
240 } else {
241 QVERIFY(!(netConfMan->capabilities() & QNetworkConfigurationManager::NetworkSessionRequired));
242 }
243 #endif
244 }
245
cleanupTestCase()246 void tst_QFtp::cleanupTestCase()
247 {
248 #ifndef QT_NO_BEARERMANAGEMENT
249 networkSessionExplicit.clear();
250 networkSessionImplicit.clear();
251 #endif
252 }
253
init()254 void tst_QFtp::init()
255 {
256 QFETCH_GLOBAL(bool, setProxy);
257 QFETCH_GLOBAL(int, proxyType);
258 QFETCH_GLOBAL(bool, setSession);
259 if (setProxy) {
260 if (proxyType == QNetworkProxy::Socks5Proxy) {
261 QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
262 } else if (proxyType == QNetworkProxy::HttpProxy) {
263 QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
264 }
265 }
266 #ifndef QT_NO_BEARERMANAGEMENT
267 if (setSession) {
268 if (!networkSessionImplicit)
269 QSKIP("test requires a valid default network configuration", SkipSingle);
270 networkSessionExplicit = networkSessionImplicit;
271 if (!networkSessionExplicit->isOpen()) {
272 networkSessionExplicit->open();
273 QVERIFY(networkSessionExplicit->waitForOpened(30000));
274 }
275 } else {
276 networkSessionExplicit.clear();
277 }
278 #endif
279
280 delete ftp;
281 ftp = 0;
282
283 ids.clear();
284 current_id = 0;
285
286 resultMap.clear();
287 connectToHost_state = -1;
288 close_state = -1;
289 login_state = -1;
290 cur_state = QFtp::Unconnected;
291
292 listInfo_i.clear();
293 newData_ba = QByteArray();
294 bytesTotal = bytesTotal_init;
295 bytesDone = bytesDone_init;
296
297 done_success = -1;
298 commandSequence_success = -1;
299
300 bytesAvailable_finishedGet = 1234567890;
301 bytesAvailable_finished = 1234567890;
302 bytesAvailable_done = 1234567890;
303
304 inFileDirExistsFunction = FALSE;
305
306 #if !defined(Q_OS_WINCE)
307 srand(time(0));
308 uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)time(0));
309 #else
310 srand(0);
311 uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)(0));
312 #endif
313 }
314
cleanup()315 void tst_QFtp::cleanup()
316 {
317 if (ftp) {
318 delete ftp;
319 ftp = 0;
320 }
321 QFETCH_GLOBAL(bool, setProxy);
322 if (setProxy) {
323 QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
324 }
325
326 delete ftp;
327 ftp = 0;
328 #ifndef QT_NO_BEARERMANAGEMENT
329 networkSessionExplicit.clear();
330 #endif
331 }
332
connectToHost_data()333 void tst_QFtp::connectToHost_data()
334 {
335 QTest::addColumn<QString>("host");
336 QTest::addColumn<uint>("port");
337 QTest::addColumn<int>("state");
338
339 QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << (int)QFtp::Connected;
340 QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)2222 << (int)QFtp::Unconnected;
341 QTest::newRow( "error02" ) << QString("foo.bar") << (uint)21 << (int)QFtp::Unconnected;
342 }
343
connectToHost()344 void tst_QFtp::connectToHost()
345 {
346 QFETCH( QString, host );
347 QFETCH( uint, port );
348
349 ftp = newFtp();
350 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
351
352 QTestEventLoop::instance().enterLoop( 61 );
353 delete ftp;
354 ftp = 0;
355 if ( QTestEventLoop::instance().timeout() )
356 QFAIL( "Network operation timed out" );
357
358 QTEST( connectToHost_state, "state" );
359
360 ResMapIt it = resultMap.find( QFtp::ConnectToHost );
361 QVERIFY( it != resultMap.end() );
362 QFETCH( int, state );
363 if ( state == QFtp::Connected ) {
364 QVERIFY( it.value().success == 1 );
365 } else {
366 QVERIFY( it.value().success == 0 );
367 }
368 }
369
connectToUnresponsiveHost()370 void tst_QFtp::connectToUnresponsiveHost()
371 {
372 QFETCH_GLOBAL(bool, setProxy);
373 if (setProxy)
374 QSKIP( "This test takes too long if we test with proxies too", SkipSingle );
375
376 QString host = "192.0.2.42"; // IP out of TEST-NET, should be unreachable
377 uint port = 21;
378
379 ftp = newFtp();
380 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
381
382 qDebug( "About to connect to host that won't reply (this test takes 60 seconds)" );
383 QTestEventLoop::instance().enterLoop( 61 );
384 #ifdef Q_OS_WIN
385 /* On Windows, we do not get a timeout, because Winsock is behaving in a strange way:
386 We issue two "WSAConnect()" calls, after the first, as a result we get WSAEWOULDBLOCK,
387 after the second, we get WSAEISCONN, which means that the socket is connected, which cannot be.
388 However, after some seconds we get a socket error saying that the remote host closed the connection,
389 which can neither be. For this test, that would actually enable us to finish before timout, but handling that case
390 (in void QFtpPI::error(QAbstractSocket::SocketError e)) breaks
391 a lot of other stuff in QFtp, so we just expect this test to fail on Windows.
392 */
393 QEXPECT_FAIL("", "timeout not working due to strange Windows socket behaviour (see source file of this test for explanation)", Abort);
394 #endif
395 QVERIFY2(! QTestEventLoop::instance().timeout(), "Network timeout longer than expected (should have been 60 seconds)");
396
397 QVERIFY( ftp->state() == QFtp::Unconnected);
398 ResMapIt it = resultMap.find( QFtp::ConnectToHost );
399 QVERIFY( it != resultMap.end() );
400 QVERIFY( it.value().success == 0 );
401
402 delete ftp;
403 ftp = 0;
404 }
405
login_data()406 void tst_QFtp::login_data()
407 {
408 QTest::addColumn<QString>("host");
409 QTest::addColumn<uint>("port");
410 QTest::addColumn<QString>("user");
411 QTest::addColumn<QString>("password");
412 QTest::addColumn<int>("success");
413
414 QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << 1;
415 QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << 1;
416 QTest::newRow( "ok03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << 1;
417 QTest::newRow( "ok04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << 1;
418
419 QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString() << 0;
420 QTest::newRow( "error02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("bar") << 0;
421 }
422
login()423 void tst_QFtp::login()
424 {
425 QFETCH( QString, host );
426 QFETCH( uint, port );
427 QFETCH( QString, user );
428 QFETCH( QString, password );
429
430 ftp = newFtp();
431 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
432 addCommand( QFtp::Login, ftp->login( user, password ) );
433
434 QTestEventLoop::instance().enterLoop( 30 );
435 delete ftp;
436 ftp = 0;
437 if ( QTestEventLoop::instance().timeout() )
438 QFAIL( "Network operation timed out" );
439
440 ResMapIt it = resultMap.find( QFtp::Login );
441 QVERIFY( it != resultMap.end() );
442 QTEST( it.value().success, "success" );
443
444 if ( it.value().success ) {
445 QVERIFY( login_state == QFtp::LoggedIn );
446 } else {
447 QVERIFY( login_state != QFtp::LoggedIn );
448 }
449 }
450
close_data()451 void tst_QFtp::close_data()
452 {
453 QTest::addColumn<QString>("host");
454 QTest::addColumn<uint>("port");
455 QTest::addColumn<QString>("user");
456 QTest::addColumn<QString>("password");
457 QTest::addColumn<bool>("login");
458
459 QTest::newRow( "login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << (bool)TRUE;
460 QTest::newRow( "login02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << (bool)TRUE;
461 QTest::newRow( "login03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << (bool)TRUE;
462 QTest::newRow( "login04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << (bool)TRUE;
463
464 QTest::newRow( "no-login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("") << QString("") << (bool)FALSE;
465 }
466
close()467 void tst_QFtp::close()
468 {
469 QFETCH( QString, host );
470 QFETCH( uint, port );
471 QFETCH( QString, user );
472 QFETCH( QString, password );
473 QFETCH( bool, login );
474
475 ftp = newFtp();
476 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
477 if ( login )
478 addCommand( QFtp::Login, ftp->login( user, password ) );
479 addCommand( QFtp::Close, ftp->close() );
480
481 QTestEventLoop::instance().enterLoop( 30 );
482 delete ftp;
483 ftp = 0;
484 if ( QTestEventLoop::instance().timeout() )
485 QFAIL( "Network operation timed out" );
486
487 QCOMPARE( close_state, (int)QFtp::Unconnected );
488
489 ResMapIt it = resultMap.find( QFtp::Close );
490 QVERIFY( it != resultMap.end() );
491 QVERIFY( it.value().success == 1 );
492 }
493
list_data()494 void tst_QFtp::list_data()
495 {
496 QTest::addColumn<QString>("host");
497 QTest::addColumn<uint>("port");
498 QTest::addColumn<QString>("user");
499 QTest::addColumn<QString>("password");
500 QTest::addColumn<QString>("dir");
501 QTest::addColumn<int>("success");
502 QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
503
504 QStringList flukeRoot;
505 flukeRoot << "pub";
506 flukeRoot << "qtest";
507 QStringList flukeQtest;
508 flukeQtest << "bigfile";
509 flukeQtest << "nonASCII";
510 flukeQtest << "rfc3252";
511 flukeQtest << "rfc3252.txt";
512 flukeQtest << "upload";
513
514 QTest::newRow( "workDir01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
515 QTest::newRow( "workDir02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
516
517 QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
518 QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
519
520 QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
521 QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
522
523 QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
524 QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
525 // ### The microsoft server does not seem to work properly at the moment --
526 // I am also not able to open a data connection with other, non-Qt FTP
527 // clients to it.
528 // QTest::newRow( "nonExist03" ) << "ftp.microsoft.com" << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
529
530 QStringList susePub;
531 susePub << "README.mirror-policy" << "axp" << "i386" << "ia64" << "install" << "noarch" << "pubring.gpg-build.suse.de" << "update" << "x86_64";
532 QTest::newRow( "epsvNotSupported" ) << QString("ftp.funet.fi") << (uint)21 << QString::fromLatin1("ftp") << QString::fromLatin1("root@") << QString("/pub/Linux/suse/suse") << 1 << susePub;
533 }
534
list()535 void tst_QFtp::list()
536 {
537 QFETCH( QString, host );
538 QFETCH( uint, port );
539 QFETCH( QString, user );
540 QFETCH( QString, password );
541 QFETCH( QString, dir );
542
543 ftp = newFtp();
544 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
545 addCommand( QFtp::Login, ftp->login( user, password ) );
546 addCommand( QFtp::List, ftp->list( dir ) );
547 addCommand( QFtp::Close, ftp->close() );
548
549 QTestEventLoop::instance().enterLoop( 30 );
550 delete ftp;
551 ftp = 0;
552 if ( QTestEventLoop::instance().timeout() )
553 QFAIL( "Network operation timed out" );
554
555 ResMapIt it = resultMap.find( QFtp::List );
556 QVERIFY( it != resultMap.end() );
557 QTEST( it.value().success, "success" );
558 QFETCH( QStringList, entryNames );
559 QCOMPARE( listInfo_i.count(), entryNames.count() );
560 for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
561 QCOMPARE( listInfo_i[i].name(), entryNames[i] );
562 }
563 }
564
cd_data()565 void tst_QFtp::cd_data()
566 {
567 QTest::addColumn<QString>("host");
568 QTest::addColumn<uint>("port");
569 QTest::addColumn<QString>("user");
570 QTest::addColumn<QString>("password");
571 QTest::addColumn<QString>("dir");
572 QTest::addColumn<int>("success");
573 QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
574
575 QStringList flukeRoot;
576 flukeRoot << "qtest";
577 QStringList flukeQtest;
578 flukeQtest << "bigfile";
579 flukeQtest << "nonASCII";
580 flukeQtest << "rfc3252";
581 flukeQtest << "rfc3252.txt";
582 flukeQtest << "upload";
583
584 QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
585 QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
586
587 QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
588 QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
589
590 QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
591 QTest::newRow( "nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
592 }
593
cd()594 void tst_QFtp::cd()
595 {
596 QFETCH( QString, host );
597 QFETCH( uint, port );
598 QFETCH( QString, user );
599 QFETCH( QString, password );
600 QFETCH( QString, dir );
601
602 ftp = newFtp();
603 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
604 addCommand( QFtp::Login, ftp->login( user, password ) );
605 addCommand( QFtp::Cd, ftp->cd( dir ) );
606 addCommand( QFtp::List, ftp->list() );
607 addCommand( QFtp::Close, ftp->close() );
608
609 QTestEventLoop::instance().enterLoop( 30 );
610
611 delete ftp;
612 ftp = 0;
613 if ( QTestEventLoop::instance().timeout() ) {
614 QFAIL( "Network operation timed out" );
615 }
616
617 ResMapIt it = resultMap.find( QFtp::Cd );
618 QVERIFY( it != resultMap.end() );
619 QTEST( it.value().success, "success" );
620 QFETCH( QStringList, entryNames );
621 QCOMPARE( listInfo_i.count(), entryNames.count() );
622 for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
623 QCOMPARE( listInfo_i[i].name(), entryNames[i] );
624 }
625 }
626
get_data()627 void tst_QFtp::get_data()
628 {
629 QTest::addColumn<QString>("host");
630 QTest::addColumn<uint>("port");
631 QTest::addColumn<QString>("user");
632 QTest::addColumn<QString>("password");
633 QTest::addColumn<QString>("file");
634 QTest::addColumn<int>("success");
635 QTest::addColumn<QByteArray>("res");
636 QTest::addColumn<bool>("useIODevice");
637
638 // ### move this into external testdata
639 QFile file( SRCDIR "rfc3252.txt" );
640 QVERIFY( file.open( QIODevice::ReadOnly ) );
641 QByteArray rfc3252 = file.readAll();
642
643 // test the two get() overloads in one routine
644 for ( int i=0; i<2; i++ ) {
645 QTest::newRow( QString("relPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
646 << "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
647 QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
648 << "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
649
650 QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
651 << "/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
652 QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
653 << "/var/ftp/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
654
655 QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
656 << QString("foo") << 0 << QByteArray() << (bool)(i==1);
657 QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
658 << QString("/foo") << 0 << QByteArray() << (bool)(i==1);
659 }
660 }
661
get()662 void tst_QFtp::get()
663 {
664 // for the overload that takes a QIODevice
665 QByteArray buf_ba;
666 QBuffer buf( &buf_ba );
667
668 QFETCH( QString, host );
669 QFETCH( uint, port );
670 QFETCH( QString, user );
671 QFETCH( QString, password );
672 QFETCH( QString, file );
673 QFETCH( bool, useIODevice );
674
675 ftp = newFtp();
676 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
677 addCommand( QFtp::Login, ftp->login( user, password ) );
678 if ( useIODevice ) {
679 buf.open( QIODevice::WriteOnly );
680 addCommand( QFtp::Get, ftp->get( file, &buf ) );
681 } else {
682 addCommand( QFtp::Get, ftp->get( file ) );
683 }
684 addCommand( QFtp::Close, ftp->close() );
685
686 QTestEventLoop::instance().enterLoop( 50 );
687 delete ftp;
688 ftp = 0;
689 if ( QTestEventLoop::instance().timeout() )
690 QFAIL( "Network operation timed out" );
691
692 ResMapIt it = resultMap.find( QFtp::Get );
693 QVERIFY( it != resultMap.end() );
694 QTEST( it.value().success, "success" );
695 if ( useIODevice ) {
696 QTEST( buf_ba, "res" );
697 } else {
698 QTEST( newData_ba, "res" );
699 }
700 QVERIFY( bytesTotal != bytesTotal_init );
701 if ( bytesTotal != -1 ) {
702 QVERIFY( bytesDone == bytesTotal );
703 }
704 if ( useIODevice ) {
705 if ( bytesDone != bytesDone_init ) {
706 QVERIFY( (int)buf_ba.size() == bytesDone );
707 }
708 } else {
709 if ( bytesDone != bytesDone_init ) {
710 QVERIFY( (int)newData_ba.size() == bytesDone );
711 }
712 }
713 }
714
put_data()715 void tst_QFtp::put_data()
716 {
717 QTest::addColumn<QString>("host");
718 QTest::addColumn<uint>("port");
719 QTest::addColumn<QString>("user");
720 QTest::addColumn<QString>("password");
721 QTest::addColumn<QString>("file");
722 QTest::addColumn<QByteArray>("fileData");
723 QTest::addColumn<bool>("useIODevice");
724 QTest::addColumn<int>("success");
725
726 // ### move this into external testdata
727 QFile file( SRCDIR "rfc3252.txt" );
728 QVERIFY( file.open( QIODevice::ReadOnly ) );
729 QByteArray rfc3252 = file.readAll();
730
731 QByteArray bigData( 10*1024*1024, 0 );
732 bigData.fill( 'A' );
733
734 // test the two put() overloads in one routine
735 for ( int i=0; i<2; i++ ) {
736 QTest::newRow( QString("relPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
737 << QString("qtest/upload/rel01_%1") << rfc3252
738 << (bool)(i==1) << 1;
739 /*
740 QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
741 << QString("qtest/upload/rel02_%1") << rfc3252
742 << (bool)(i==1) << 1;
743 QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
744 << QString("qtest/upload/rel03_%1") << QByteArray()
745 << (bool)(i==1) << 1;
746 QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
747 << QString("qtest/upload/rel04_%1") << bigData
748 << (bool)(i==1) << 1;
749
750 QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
751 << QString("/qtest/upload/abs01_%1") << rfc3252
752 << (bool)(i==1) << 1;
753 QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
754 << QString("/srv/ftp/qtest/upload/abs02_%1") << rfc3252
755 << (bool)(i==1) << 1;
756
757 QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
758 << QString("foo") << QByteArray()
759 << (bool)(i==1) << 0;
760 QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
761 << QString("/foo") << QByteArray()
762 << (bool)(i==1) << 0;
763 */
764 }
765 }
766
put()767 void tst_QFtp::put()
768 {
769 QFETCH( QString, host );
770 QFETCH( uint, port );
771 QFETCH( QString, user );
772 QFETCH( QString, password );
773 QFETCH( QString, file );
774 QFETCH( QByteArray, fileData );
775 QFETCH( bool, useIODevice );
776
777 #ifdef Q_OS_WIN
778 QFETCH_GLOBAL(bool, setProxy);
779 if (setProxy) {
780 QFETCH_GLOBAL(int, proxyType);
781 if (proxyType == QNetworkProxy::Socks5Proxy) {
782 QSKIP("With socks5 the put() test takes too long time on Windows.", SkipAll);
783 }
784 }
785 #endif
786
787 const int timestep = 50;
788
789 if(file.contains('%'))
790 file = file.arg(uniqueExtension);
791
792 // for the overload that takes a QIODevice
793 QBuffer buf_fileData( &fileData );
794 buf_fileData.open( QIODevice::ReadOnly );
795
796 ResMapIt it;
797 //////////////////////////////////////////////////////////////////
798 // upload the file
799 init();
800 ftp = newFtp();
801 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
802 addCommand( QFtp::Login, ftp->login( user, password ) );
803 if ( useIODevice )
804 addCommand( QFtp::Put, ftp->put( &buf_fileData, file ) );
805 else
806 addCommand( QFtp::Put, ftp->put( fileData, file ) );
807 addCommand( QFtp::Close, ftp->close() );
808
809 for(int time = 0; time <= fileData.length() / 20000; time += timestep) {
810 QTestEventLoop::instance().enterLoop( timestep );
811 if(ftp->currentCommand() == QFtp::None)
812 break;
813 }
814 delete ftp;
815 ftp = 0;
816 if ( QTestEventLoop::instance().timeout() )
817 QFAIL( "Network operation timed out" );
818
819 it = resultMap.find( QFtp::Put );
820 QVERIFY( it != resultMap.end() );
821 QTEST( it.value().success, "success" );
822 if ( !it.value().success ) {
823 QVERIFY( !fileExists( host, port, user, password, file ) );
824 return; // the following tests are only meaningful if the file could be put
825 }
826 QVERIFY( bytesTotal == (int)fileData.size() );
827 QVERIFY( bytesDone == bytesTotal );
828
829 QVERIFY( fileExists( host, port, user, password, file ) );
830
831 //////////////////////////////////////////////////////////////////
832 // fetch file to make sure that it is equal to the uploaded file
833 init();
834 ftp = newFtp();
835 QBuffer buf;
836 buf.open( QIODevice::WriteOnly );
837 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
838 addCommand( QFtp::Login, ftp->login( user, password ) );
839 addCommand( QFtp::Get, ftp->get( file, &buf ) );
840 addCommand( QFtp::Close, ftp->close() );
841
842 for(int time = 0; time <= fileData.length() / 20000; time += timestep) {
843 QTestEventLoop::instance().enterLoop( timestep );
844 if(ftp->currentCommand() == QFtp::None)
845 break;
846 }
847 delete ftp;
848 ftp = 0;
849 if ( QTestEventLoop::instance().timeout() )
850 QFAIL( "Network operation timed out" );
851
852 QVERIFY( done_success == 1 );
853 QTEST( buf.buffer(), "fileData" );
854
855 //////////////////////////////////////////////////////////////////
856 // cleanup (i.e. remove the file) -- this also tests the remove command
857 init();
858 ftp = newFtp();
859 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
860 addCommand( QFtp::Login, ftp->login( user, password ) );
861 addCommand( QFtp::Remove, ftp->remove( file ) );
862 addCommand( QFtp::Close, ftp->close() );
863
864 QTestEventLoop::instance().enterLoop( timestep );
865 delete ftp;
866 ftp = 0;
867 if ( QTestEventLoop::instance().timeout() )
868 QFAIL( "Network operation timed out" );
869
870 it = resultMap.find( QFtp::Remove );
871 QVERIFY( it != resultMap.end() );
872 QCOMPARE( it.value().success, 1 );
873
874 QVERIFY( !fileExists( host, port, user, password, file ) );
875 }
876
remove()877 void tst_QFtp::remove()
878 {
879 DEPENDS_ON( "put" );
880 }
881
mkdir_data()882 void tst_QFtp::mkdir_data()
883 {
884 QTest::addColumn<QString>("host");
885 QTest::addColumn<uint>("port");
886 QTest::addColumn<QString>("user");
887 QTest::addColumn<QString>("password");
888 QTest::addColumn<QString>("cdDir");
889 QTest::addColumn<QString>("dirToCreate");
890 QTest::addColumn<int>("success");
891
892 QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
893 << "qtest/upload" << QString("rel01_%1") << 1;
894 QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
895 << "qtest/upload" << QString("rel02_%1") << 1;
896 QTest::newRow( "relPath03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
897 << "qtest/upload" << QString("rel03_%1") << 1;
898
899 QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
900 << "." << QString("/qtest/upload/abs01_%1") << 1;
901 QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
902 << "." << QString("/var/ftp/qtest/upload/abs02_%1") << 1;
903
904 // QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0;
905 QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
906 << "." << QString("foo") << 0;
907 QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
908 << "." << QString("/foo") << 0;
909 }
910
mkdir()911 void tst_QFtp::mkdir()
912 {
913 QFETCH( QString, host );
914 QFETCH( uint, port );
915 QFETCH( QString, user );
916 QFETCH( QString, password );
917 QFETCH( QString, cdDir );
918 QFETCH( QString, dirToCreate );
919
920 if(dirToCreate.contains('%'))
921 dirToCreate = dirToCreate.arg(uniqueExtension);
922
923 //////////////////////////////////////////////////////////////////
924 // create the directory
925 init();
926 ftp = newFtp();
927 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
928 addCommand( QFtp::Login, ftp->login( user, password ) );
929 addCommand( QFtp::Cd, ftp->cd( cdDir ) );
930 addCommand( QFtp::Mkdir, ftp->mkdir( dirToCreate ) );
931 addCommand( QFtp::Close, ftp->close() );
932
933 QTestEventLoop::instance().enterLoop( 30 );
934 delete ftp;
935 ftp = 0;
936 if ( QTestEventLoop::instance().timeout() )
937 QFAIL( "Network operation timed out" );
938
939 ResMapIt it = resultMap.find( QFtp::Mkdir );
940 QVERIFY( it != resultMap.end() );
941 QTEST( it.value().success, "success" );
942 if ( !it.value().success ) {
943 QVERIFY( !dirExists( host, port, user, password, cdDir, dirToCreate ) );
944 return; // the following tests are only meaningful if the dir could be created
945 }
946 QVERIFY( dirExists( host, port, user, password, cdDir, dirToCreate ) );
947
948 //////////////////////////////////////////////////////////////////
949 // create the directory again (should always fail!)
950 init();
951 ftp = newFtp();
952 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
953 addCommand( QFtp::Login, ftp->login( user, password ) );
954 addCommand( QFtp::Cd, ftp->cd( cdDir ) );
955 addCommand( QFtp::Mkdir, ftp->mkdir( dirToCreate ) );
956 addCommand( QFtp::Close, ftp->close() );
957
958 QTestEventLoop::instance().enterLoop( 30 );
959 delete ftp;
960 ftp = 0;
961 if ( QTestEventLoop::instance().timeout() )
962 QFAIL( "Network operation timed out" );
963
964 it = resultMap.find( QFtp::Mkdir );
965 QVERIFY( it != resultMap.end() );
966 QCOMPARE( it.value().success, 0 );
967
968 //////////////////////////////////////////////////////////////////
969 // remove the directory
970 init();
971 ftp = newFtp();
972 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
973 addCommand( QFtp::Login, ftp->login( user, password ) );
974 addCommand( QFtp::Cd, ftp->cd( cdDir ) );
975 addCommand( QFtp::Rmdir, ftp->rmdir( dirToCreate ) );
976 addCommand( QFtp::Close, ftp->close() );
977
978 QTestEventLoop::instance().enterLoop( 30 );
979 delete ftp;
980 ftp = 0;
981 if ( QTestEventLoop::instance().timeout() )
982 QFAIL( "Network operation timed out" );
983
984 it = resultMap.find( QFtp::Rmdir );
985 QVERIFY( it != resultMap.end() );
986 QCOMPARE( it.value().success, 1 );
987
988 QVERIFY( !dirExists( host, port, user, password, cdDir, dirToCreate ) );
989 }
990
mkdir2()991 void tst_QFtp::mkdir2()
992 {
993 ftp = new QFtp;
994 ftp->connectToHost(QtNetworkSettings::serverName());
995 ftp->login();
996 current_id = ftp->cd("kake/test");
997
998 QEventLoop loop;
999 connect(ftp, SIGNAL(done(bool)), &loop, SLOT(quit()));
1000 connect(ftp, SIGNAL(commandFinished(int, bool)), this, SLOT(mkdir2Slot(int, bool)));
1001 QTimer::singleShot(5000, &loop, SLOT(quit()));
1002
1003 QSignalSpy commandStartedSpy(ftp, SIGNAL(commandStarted(int)));
1004 QSignalSpy commandFinishedSpy(ftp, SIGNAL(commandFinished(int, bool)));
1005
1006 loop.exec();
1007
1008 QCOMPARE(commandStartedSpy.count(), 4); // connect, login, cd, mkdir
1009 QCOMPARE(commandFinishedSpy.count(), 4);
1010
1011 for (int i = 0; i < 4; ++i)
1012 QCOMPARE(commandFinishedSpy.at(i).at(0), commandStartedSpy.at(i).at(0));
1013
1014 QVERIFY(!commandFinishedSpy.at(0).at(1).toBool());
1015 QVERIFY(!commandFinishedSpy.at(1).at(1).toBool());
1016 QVERIFY(commandFinishedSpy.at(2).at(1).toBool());
1017 QVERIFY(commandFinishedSpy.at(3).at(1).toBool());
1018
1019 delete ftp;
1020 ftp = 0;
1021 }
1022
mkdir2Slot(int id,bool)1023 void tst_QFtp::mkdir2Slot(int id, bool)
1024 {
1025 if (id == current_id)
1026 ftp->mkdir("kake/test");
1027 }
1028
rmdir()1029 void tst_QFtp::rmdir()
1030 {
1031 DEPENDS_ON( "mkdir" );
1032 }
1033
rename_data()1034 void tst_QFtp::rename_data()
1035 {
1036 QTest::addColumn<QString>("host");
1037 QTest::addColumn<QString>("user");
1038 QTest::addColumn<QString>("password");
1039 QTest::addColumn<QString>("cdDir");
1040 QTest::addColumn<QString>("oldfile");
1041 QTest::addColumn<QString>("newfile");
1042 QTest::addColumn<QString>("createFile");
1043 QTest::addColumn<QString>("renamedFile");
1044 QTest::addColumn<int>("success");
1045
1046 QTest::newRow("relPath01") << QtNetworkSettings::serverName() << QString() << QString()
1047 << "qtest/upload"
1048 << QString("rel_old01_%1") << QString("rel_new01_%1")
1049 << QString("qtest/upload/rel_old01_%1") << QString("qtest/upload/rel_new01_%1")
1050 << 1;
1051 QTest::newRow("relPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
1052 << "qtest/upload"
1053 << QString("rel_old02_%1") << QString("rel_new02_%1")
1054 << QString("qtest/upload/rel_old02_%1") << QString("qtest/upload/rel_new02_%1")
1055 << 1;
1056 QTest::newRow("relPath03") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
1057 << "qtest/upload"
1058 << QString("rel_old03_%1")<< QString("rel_new03_%1")
1059 << QString("qtest/upload/rel_old03_%1") << QString("qtest/upload/rel_new03_%1")
1060 << 1;
1061
1062 QTest::newRow("absPath01") << QtNetworkSettings::serverName() << QString() << QString()
1063 << QString()
1064 << QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
1065 << QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
1066 << 1;
1067 QTest::newRow("absPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
1068 << QString()
1069 << QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
1070 << QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
1071 << 1;
1072
1073 QTest::newRow("nonExist01") << QtNetworkSettings::serverName() << QString() << QString()
1074 << QString()
1075 << QString("foo") << "new_foo"
1076 << QString() << QString()
1077 << 0;
1078 QTest::newRow("nonExist02") << QtNetworkSettings::serverName() << QString() << QString()
1079 << QString()
1080 << QString("/foo") << QString("/new_foo")
1081 << QString() << QString()
1082 << 0;
1083 }
1084
renameInit(const QString & host,const QString & user,const QString & password,const QString & createFile)1085 void tst_QFtp::renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile )
1086 {
1087 if ( !createFile.isNull() ) {
1088 // upload the file
1089 init();
1090 ftp = newFtp();
1091 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
1092 addCommand( QFtp::Login, ftp->login( user, password ) );
1093 addCommand( QFtp::Put, ftp->put( QByteArray(), createFile ) );
1094 addCommand( QFtp::Close, ftp->close() );
1095
1096 QTestEventLoop::instance().enterLoop( 50 );
1097 delete ftp;
1098 ftp = 0;
1099 if ( QTestEventLoop::instance().timeout() )
1100 QFAIL( "Network operation timed out" );
1101
1102 ResMapIt it = resultMap.find( QFtp::Put );
1103 QVERIFY( it != resultMap.end() );
1104 QVERIFY( it.value().success == 1 );
1105
1106 QVERIFY( fileExists( host, 21, user, password, createFile ) );
1107 }
1108 }
1109
renameCleanup(const QString & host,const QString & user,const QString & password,const QString & fileToDelete)1110 void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete )
1111 {
1112 if ( !fileToDelete.isNull() ) {
1113 // cleanup (i.e. remove the file)
1114 init();
1115 ftp = newFtp();
1116 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
1117 addCommand( QFtp::Login, ftp->login( user, password ) );
1118 addCommand( QFtp::Remove, ftp->remove( fileToDelete ) );
1119 addCommand( QFtp::Close, ftp->close() );
1120
1121 QTestEventLoop::instance().enterLoop( 30 );
1122 delete ftp;
1123 ftp = 0;
1124 if ( QTestEventLoop::instance().timeout() )
1125 QFAIL( "Network operation timed out" );
1126
1127 ResMapIt it = resultMap.find( QFtp::Remove );
1128 QVERIFY( it != resultMap.end() );
1129 QVERIFY( it.value().success == 1 );
1130
1131 QVERIFY( !fileExists( host, 21, user, password, fileToDelete ) );
1132 }
1133 }
1134
rename()1135 void tst_QFtp::rename()
1136 {
1137 QFETCH( QString, host );
1138 QFETCH( QString, user );
1139 QFETCH( QString, password );
1140 QFETCH( QString, cdDir );
1141 QFETCH( QString, oldfile );
1142 QFETCH( QString, newfile );
1143 QFETCH( QString, createFile );
1144 QFETCH( QString, renamedFile );
1145
1146 if(oldfile.contains('%'))
1147 oldfile = oldfile.arg(uniqueExtension);
1148 if(newfile.contains('%'))
1149 newfile = newfile.arg(uniqueExtension);
1150 if(createFile.contains('%'))
1151 createFile = createFile.arg(uniqueExtension);
1152 if(renamedFile.contains('%'))
1153 renamedFile = renamedFile.arg(uniqueExtension);
1154
1155 renameInit( host, user, password, createFile );
1156
1157 init();
1158 ftp = newFtp();
1159 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
1160 addCommand( QFtp::Login, ftp->login( user, password ) );
1161 if ( !cdDir.isNull() )
1162 addCommand( QFtp::Cd, ftp->cd( cdDir ) );
1163 addCommand( QFtp::Rename, ftp->rename( oldfile, newfile ) );
1164 addCommand( QFtp::Close, ftp->close() );
1165
1166 QTestEventLoop::instance().enterLoop( 30 );
1167 delete ftp;
1168 ftp = 0;
1169 if ( QTestEventLoop::instance().timeout() )
1170 QFAIL( "Network operation timed out" );
1171
1172 ResMapIt it = resultMap.find( QFtp::Rename );
1173 QVERIFY( it != resultMap.end() );
1174 QTEST( it.value().success, "success" );
1175
1176 if ( it.value().success ) {
1177 QVERIFY( !fileExists( host, 21, user, password, oldfile, cdDir ) );
1178 QVERIFY( fileExists( host, 21, user, password, newfile, cdDir ) );
1179 QVERIFY( fileExists( host, 21, user, password, renamedFile ) );
1180 } else {
1181 QVERIFY( !fileExists( host, 21, user, password, newfile, cdDir ) );
1182 QVERIFY( !fileExists( host, 21, user, password, renamedFile ) );
1183 }
1184
1185 renameCleanup( host, user, password, renamedFile );
1186 }
1187
1188 /*
1189 The commandSequence() test does not test any particular function. It rather
1190 tests a sequence of arbitrary commands specified in the test data.
1191 */
1192 class FtpCommand
1193 {
1194 public:
FtpCommand()1195 FtpCommand() :
1196 cmd(QFtp::None)
1197 { }
1198
FtpCommand(QFtp::Command command)1199 FtpCommand( QFtp::Command command ) :
1200 cmd(command)
1201 { }
1202
FtpCommand(QFtp::Command command,const QStringList & arguments)1203 FtpCommand( QFtp::Command command, const QStringList &arguments ) :
1204 cmd(command), args(arguments)
1205 { }
1206
FtpCommand(const FtpCommand & c)1207 FtpCommand( const FtpCommand &c )
1208 { *this = c; }
1209
operator =(const FtpCommand & c)1210 FtpCommand &operator=( const FtpCommand &c )
1211 {
1212 this->cmd = c.cmd;
1213 this->args = c.args;
1214 return *this;
1215 }
1216
1217 QFtp::Command cmd;
1218 QStringList args;
1219 };
operator <<(QDataStream & s,const FtpCommand & command)1220 QDataStream &operator<<( QDataStream &s, const FtpCommand &command )
1221 {
1222 s << (int)command.cmd;
1223 s << command.args;
1224 return s;
1225 }
operator >>(QDataStream & s,FtpCommand & command)1226 QDataStream &operator>>( QDataStream &s, FtpCommand &command )
1227 {
1228 int tmp;
1229 s >> tmp;
1230 command.cmd = (QFtp::Command)tmp;
1231 s >> command.args;
1232 return s;
1233 }
Q_DECLARE_METATYPE(QList<FtpCommand>)1234 Q_DECLARE_METATYPE(QList<FtpCommand>)
1235
1236 void tst_QFtp::commandSequence_data()
1237 {
1238 // some "constants"
1239 QStringList argConnectToHost01;
1240 argConnectToHost01 << QtNetworkSettings::serverName() << "21";
1241
1242 QStringList argLogin01, argLogin02, argLogin03, argLogin04;
1243 argLogin01 << QString() << QString();
1244 argLogin02 << "ftp" << QString();
1245 argLogin03 << "ftp" << "foo";
1246 argLogin04 << QString("ftptest") << "password";
1247
1248 FtpCommand connectToHost01( QFtp::ConnectToHost, argConnectToHost01 );
1249 FtpCommand login01( QFtp::Login, argLogin01 );
1250 FtpCommand login02( QFtp::Login, argLogin01 );
1251 FtpCommand login03( QFtp::Login, argLogin01 );
1252 FtpCommand login04( QFtp::Login, argLogin01 );
1253 FtpCommand close01( QFtp::Close );
1254
1255 QTest::addColumn<QList<FtpCommand> >("cmds");
1256 QTest::addColumn<int>("success");
1257
1258 // success data
1259 {
1260 QList<FtpCommand> cmds;
1261 cmds << connectToHost01;
1262 QTest::newRow( "simple_ok01" ) << cmds << 1;
1263 }
1264 {
1265 QList<FtpCommand> cmds;
1266 cmds << connectToHost01;
1267 cmds << login01;
1268 QTest::newRow( "simple_ok02" ) << cmds << 1;
1269 }
1270 {
1271 QList<FtpCommand> cmds;
1272 cmds << connectToHost01;
1273 cmds << login01;
1274 cmds << close01;
1275 QTest::newRow( "simple_ok03" ) << cmds << 1;
1276 }
1277 {
1278 QList<FtpCommand> cmds;
1279 cmds << connectToHost01;
1280 cmds << close01;
1281 QTest::newRow( "simple_ok04" ) << cmds << 1;
1282 }
1283 {
1284 QList<FtpCommand> cmds;
1285 cmds << connectToHost01;
1286 cmds << login01;
1287 cmds << close01;
1288 cmds << connectToHost01;
1289 cmds << login02;
1290 cmds << close01;
1291 QTest::newRow( "connect_twice" ) << cmds << 1;
1292 }
1293
1294 // error data
1295 {
1296 QList<FtpCommand> cmds;
1297 cmds << close01;
1298 QTest::newRow( "error01" ) << cmds << 0;
1299 }
1300 {
1301 QList<FtpCommand> cmds;
1302 cmds << login01;
1303 QTest::newRow( "error02" ) << cmds << 0;
1304 }
1305 {
1306 QList<FtpCommand> cmds;
1307 cmds << login01;
1308 cmds << close01;
1309 QTest::newRow( "error03" ) << cmds << 0;
1310 }
1311 {
1312 QList<FtpCommand> cmds;
1313 cmds << connectToHost01;
1314 cmds << login01;
1315 cmds << close01;
1316 cmds << login01;
1317 QTest::newRow( "error04" ) << cmds << 0;
1318 }
1319 }
1320
commandSequence()1321 void tst_QFtp::commandSequence()
1322 {
1323 QFETCH( QList<FtpCommand>, cmds );
1324
1325 ftp = newFtp();
1326 QList<FtpCommand>::iterator it;
1327 for ( it = cmds.begin(); it != cmds.end(); ++it ) {
1328 switch ( (*it).cmd ) {
1329 case QFtp::ConnectToHost:
1330 {
1331 QVERIFY( (*it).args.count() == 2 );
1332 uint port;
1333 bool portOk;
1334 port = (*it).args[1].toUInt( &portOk );
1335 QVERIFY( portOk );
1336 ids << ftp->connectToHost( (*it).args[0], port );
1337 }
1338 break;
1339 case QFtp::Login:
1340 QVERIFY( (*it).args.count() == 2 );
1341 ids << ftp->login( (*it).args[0], (*it).args[1] );
1342 break;
1343 case QFtp::Close:
1344 QVERIFY( (*it).args.count() == 0 );
1345 ids << ftp->close();
1346 break;
1347 default:
1348 QFAIL( "Error in test: unexpected enum value" );
1349 break;
1350 }
1351 }
1352
1353 QTestEventLoop::instance().enterLoop( 30 );
1354 delete ftp;
1355 ftp = 0;
1356 if ( QTestEventLoop::instance().timeout() )
1357 QFAIL( "Network operation timed out" );
1358
1359 QTEST( commandSequence_success, "success" );
1360 }
1361
abort_data()1362 void tst_QFtp::abort_data()
1363 {
1364 QTest::addColumn<QString>("host");
1365 QTest::addColumn<uint>("port");
1366 QTest::addColumn<QString>("file");
1367 QTest::addColumn<QByteArray>("uploadData");
1368
1369 QTest::newRow( "get_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
1370 QTest::newRow( "get_fluke02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
1371
1372 // Qt/CE and Symbian test environment has to less memory for this test
1373 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
1374 QByteArray bigData( 10*1024*1024, 0 );
1375 #else
1376 QByteArray bigData( 1*1024*1024, 0 );
1377 #endif
1378 bigData.fill( 'B' );
1379 QTest::newRow( "put_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
1380 }
1381
abort()1382 void tst_QFtp::abort()
1383 {
1384 // In case you wonder where the abort() actually happens, look into
1385 // tst_QFtp::dataTransferProgress
1386 //
1387 QFETCH( QString, host );
1388 QFETCH( uint, port );
1389 QFETCH( QString, file );
1390 QFETCH( QByteArray, uploadData );
1391
1392 QFtp::Command cmd;
1393 if ( uploadData.size() == 0 )
1394 cmd = QFtp::Get;
1395 else
1396 cmd = QFtp::Put;
1397
1398 ftp = newFtp();
1399 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
1400 addCommand( QFtp::Login, ftp->login() );
1401 if ( cmd == QFtp::Get )
1402 addCommand( cmd, ftp->get( file ) );
1403 else
1404 addCommand( cmd, ftp->put( uploadData, file ) );
1405 addCommand( QFtp::Close, ftp->close() );
1406
1407 for(int time = 0; time <= uploadData.length() / 30000; time += 30) {
1408 QTestEventLoop::instance().enterLoop( 50 );
1409 if(ftp->currentCommand() == QFtp::None)
1410 break;
1411 }
1412 delete ftp;
1413 ftp = 0;
1414 if ( QTestEventLoop::instance().timeout() )
1415 QFAIL( "Network operation timed out" );
1416
1417 ResMapIt it = resultMap.find( cmd );
1418 QVERIFY( it != resultMap.end() );
1419 // ### how to test the abort?
1420 if ( it.value().success ) {
1421 // The FTP server on fluke is sadly returning a success, even when
1422 // the operation was aborted. So we have to use some heuristics.
1423 if ( host == QtNetworkSettings::serverName() ) {
1424 if ( cmd == QFtp::Get ) {
1425 QVERIFY(bytesDone <= bytesTotal);
1426 } else {
1427 // put commands should always be aborted, since we use really
1428 // big data
1429 QVERIFY( bytesDone != bytesTotal );
1430 }
1431 } else {
1432 // this could be tested by verifying that no more progress signals are emitted
1433 QVERIFY(bytesDone <= bytesTotal);
1434 }
1435 } else {
1436 QVERIFY( bytesDone != bytesTotal );
1437 }
1438
1439 if ( cmd == QFtp::Put ) {
1440 //////////////////////////////////////
1441 // cleanup (i.e. remove the file)
1442 init();
1443 ftp = newFtp();
1444 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
1445 addCommand( QFtp::Login, ftp->login() );
1446 addCommand( QFtp::Remove, ftp->remove( file ) );
1447 addCommand( QFtp::Close, ftp->close() );
1448
1449 QTestEventLoop::instance().enterLoop( 30 );
1450 delete ftp;
1451 ftp = 0;
1452 if ( QTestEventLoop::instance().timeout() )
1453 QFAIL( "Network operation timed out" );
1454
1455 it = resultMap.find( QFtp::Remove );
1456 QVERIFY( it != resultMap.end() );
1457 QVERIFY( it.value().success == 1 );
1458 }
1459 }
1460
bytesAvailable_data()1461 void tst_QFtp::bytesAvailable_data()
1462 {
1463 QTest::addColumn<QString>("host");
1464 QTest::addColumn<QString>("file");
1465 QTest::addColumn<int>("type");
1466 QTest::addColumn<qlonglong>("bytesAvailFinishedGet");
1467 QTest::addColumn<qlonglong>("bytesAvailFinished");
1468 QTest::addColumn<qlonglong>("bytesAvailDone");
1469
1470 QTest::newRow( "fluke01" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
1471 QTest::newRow( "fluke02" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
1472
1473 QTest::newRow( "fluke03" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
1474 QTest::newRow( "fluke04" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
1475 }
1476
bytesAvailable()1477 void tst_QFtp::bytesAvailable()
1478 {
1479 QFETCH( QString, host );
1480 QFETCH( QString, file );
1481 QFETCH( int, type );
1482
1483 ftp = newFtp();
1484 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
1485 addCommand( QFtp::Login, ftp->login() );
1486 addCommand( QFtp::Get, ftp->get( file ) );
1487 if ( type != 0 )
1488 addCommand( QFtp::Close, ftp->close() );
1489
1490 QTestEventLoop::instance().enterLoop( 40 );
1491 if ( QTestEventLoop::instance().timeout() )
1492 QFAIL( "Network operation timed out" );
1493
1494 ResMapIt it = resultMap.find( QFtp::Get );
1495 QVERIFY( it != resultMap.end() );
1496 QVERIFY( it.value().success );
1497
1498 QFETCH(qlonglong, bytesAvailFinishedGet);
1499 QCOMPARE(bytesAvailable_finishedGet, bytesAvailFinishedGet);
1500
1501 QFETCH(qlonglong, bytesAvailFinished);
1502 QCOMPARE(bytesAvailable_finished, bytesAvailFinished);
1503
1504 QFETCH(qlonglong, bytesAvailDone);
1505 QCOMPARE(bytesAvailable_done, bytesAvailDone);
1506
1507 ftp->readAll();
1508 QVERIFY( ftp->bytesAvailable() == 0 );
1509 delete ftp;
1510 ftp = 0;
1511 }
1512
activeMode()1513 void tst_QFtp::activeMode()
1514 {
1515 QFile file("tst_QFtp_activeMode_inittab");
1516 file.open(QIODevice::ReadWrite);
1517 QFtp ftp;
1518 ftp.setTransferMode(QFtp::Active);
1519 ftp.connectToHost(QtNetworkSettings::serverName(), 21);
1520 ftp.login();
1521 ftp.list();
1522 ftp.get("/qtest/rfc3252.txt", &file);
1523 connect(&ftp, SIGNAL(done(bool)), SLOT(activeModeDone(bool)));
1524 QTestEventLoop::instance().enterLoop(900);
1525 QFile::remove("tst_QFtp_activeMode_inittab");
1526 QVERIFY(done_success == 1);
1527
1528 }
1529
activeModeDone(bool error)1530 void tst_QFtp::activeModeDone(bool error)
1531 {
1532 done_success = error ? -1 : 1;
1533 QTestEventLoop::instance().exitLoop();
1534 }
1535
proxy_data()1536 void tst_QFtp::proxy_data()
1537 {
1538 QTest::addColumn<QString>("host");
1539 QTest::addColumn<uint>("port");
1540 QTest::addColumn<QString>("user");
1541 QTest::addColumn<QString>("password");
1542 QTest::addColumn<QString>("dir");
1543 QTest::addColumn<int>("success");
1544 QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
1545
1546 QStringList flukeRoot;
1547 flukeRoot << "qtest";
1548 QStringList flukeQtest;
1549 flukeQtest << "bigfile";
1550 flukeQtest << "nonASCII";
1551 flukeQtest << "rfc3252";
1552 flukeQtest << "rfc3252.txt";
1553 flukeQtest << "upload";
1554
1555 QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
1556 QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
1557
1558 QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
1559 QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
1560
1561 QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
1562 QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
1563 }
1564
proxy()1565 void tst_QFtp::proxy()
1566 {
1567 QFETCH( QString, host );
1568 QFETCH( uint, port );
1569 QFETCH( QString, user );
1570 QFETCH( QString, password );
1571 QFETCH( QString, dir );
1572
1573 ftp = newFtp();
1574 addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::serverName(), 2121 ) );
1575 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
1576 addCommand( QFtp::Login, ftp->login( user, password ) );
1577 addCommand( QFtp::Cd, ftp->cd( dir ) );
1578 addCommand( QFtp::List, ftp->list() );
1579
1580 QTestEventLoop::instance().enterLoop( 50 );
1581
1582 delete ftp;
1583 ftp = 0;
1584 if ( QTestEventLoop::instance().timeout() ) {
1585 QFAIL( "Network operation timed out" );
1586 }
1587
1588 ResMapIt it = resultMap.find( QFtp::Cd );
1589 QVERIFY( it != resultMap.end() );
1590 QFETCH( int, success );
1591 QCOMPARE( it.value().success, success );
1592 QFETCH( QStringList, entryNames );
1593 QCOMPARE( listInfo_i.count(), entryNames.count() );
1594 for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
1595 QCOMPARE( listInfo_i[i].name(), entryNames[i] );
1596 }
1597 }
1598
binaryAscii()1599 void tst_QFtp::binaryAscii()
1600 {
1601 QString file = "asciifile%1.txt";
1602
1603 if(file.contains('%'))
1604 file = file.arg(uniqueExtension);
1605
1606 QByteArray putData = "a line of text\r\n";
1607
1608 init();
1609 ftp = newFtp();
1610 addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
1611 addCommand(QFtp::Login, ftp->login("ftptest", "password"));
1612 addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
1613 addCommand(QFtp::Put, ftp->put(putData, file, QFtp::Ascii));
1614 addCommand(QFtp::Close, ftp->close());
1615
1616 QTestEventLoop::instance().enterLoop( 30 );
1617 delete ftp;
1618 ftp = 0;
1619 if ( QTestEventLoop::instance().timeout() )
1620 QFAIL( "Network operation timed out" );
1621
1622 ResMapIt it = resultMap.find(QFtp::Put);
1623 QVERIFY(it != resultMap.end());
1624 QVERIFY(it.value().success);
1625
1626 QByteArray getData;
1627 QBuffer getBuf(&getData);
1628 getBuf.open(QBuffer::WriteOnly);
1629
1630 init();
1631 ftp = newFtp();
1632 addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
1633 addCommand(QFtp::Login, ftp->login("ftptest", "password"));
1634 addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
1635 addCommand(QFtp::Get, ftp->get(file, &getBuf, QFtp::Binary));
1636 addCommand(QFtp::Close, ftp->close());
1637
1638 QTestEventLoop::instance().enterLoop( 30 );
1639 delete ftp;
1640 ftp = 0;
1641 if ( QTestEventLoop::instance().timeout() )
1642 QFAIL( "Network operation timed out" );
1643
1644 ResMapIt it2 = resultMap.find(QFtp::Get);
1645 QVERIFY(it2 != resultMap.end());
1646 QVERIFY(it2.value().success);
1647 // most modern ftp servers leave the file as it is by default
1648 // (and do not remove the windows line ending), the -1 below could be
1649 // deleted in the future
1650 QVERIFY(getData.size() == putData.size()-1);
1651 //////////////////////////////////////////////////////////////////
1652 // cleanup (i.e. remove the file) -- this also tests the remove command
1653 init();
1654 ftp = newFtp();
1655 addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
1656 addCommand(QFtp::Login, ftp->login("ftptest", "password"));
1657 addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
1658 addCommand(QFtp::Remove, ftp->remove(file));
1659 addCommand(QFtp::Close, ftp->close());
1660
1661 QTestEventLoop::instance().enterLoop( 30 );
1662 delete ftp;
1663 ftp = 0;
1664 if ( QTestEventLoop::instance().timeout() )
1665 QFAIL( "Network operation timed out" );
1666
1667 it = resultMap.find( QFtp::Remove );
1668 QVERIFY( it != resultMap.end() );
1669 QCOMPARE( it.value().success, 1 );
1670
1671 QVERIFY(!fileExists(QtNetworkSettings::serverName(), 21, "ftptest", "password", file));
1672 }
1673
1674
1675 // test QFtp::currentId() and QFtp::currentCommand()
1676 #define CURRENTCOMMAND_TEST \
1677 { \
1678 ResMapIt it; \
1679 for ( it = resultMap.begin(); it != resultMap.end(); ++it ) { \
1680 if ( it.value().id == ftp->currentId() ) { \
1681 QVERIFY( it.key() == ftp->currentCommand() ); \
1682 } \
1683 } \
1684 }
1685
commandStarted(int id)1686 void tst_QFtp::commandStarted( int id )
1687 {
1688 #if defined( DUMP_SIGNALS )
1689 qDebug( "%d:commandStarted( %d )", ftp->currentId(), id );
1690 #endif
1691 // make sure that the commandStarted and commandFinished are nested correctly
1692 QVERIFY( current_id == 0 );
1693 current_id = id;
1694
1695 QVERIFY( !ids.isEmpty() );
1696 QVERIFY( ids.first() == id );
1697 if ( ids.count() > 1 ) {
1698 QVERIFY( ftp->hasPendingCommands() );
1699 } else {
1700 QVERIFY( !ftp->hasPendingCommands() );
1701 }
1702
1703 QVERIFY( ftp->currentId() == id );
1704 QVERIFY( cur_state == ftp->state() );
1705 CURRENTCOMMAND_TEST;
1706
1707 QVERIFY( ftp->error() == QFtp::NoError );
1708 }
1709
commandFinished(int id,bool error)1710 void tst_QFtp::commandFinished( int id, bool error )
1711 {
1712 #if defined( DUMP_SIGNALS )
1713 qDebug( "%d:commandFinished( %d, %d ) -- errorString: '%s'",
1714 ftp->currentId(), id, (int)error, ftp->errorString().toLatin1().constData() );
1715 #endif
1716 if ( ftp->currentCommand() == QFtp::Get ) {
1717 bytesAvailable_finishedGet = ftp->bytesAvailable();
1718 }
1719 bytesAvailable_finished = ftp->bytesAvailable();
1720
1721 // make sure that the commandStarted and commandFinished are nested correctly
1722 QVERIFY( current_id == id );
1723 current_id = 0;
1724
1725 QVERIFY( !ids.isEmpty() );
1726 QVERIFY( ids.first() == id );
1727 if ( !error && ids.count() > 1) {
1728 QVERIFY( ftp->hasPendingCommands() );
1729 } else {
1730 QVERIFY( !ftp->hasPendingCommands() );
1731 }
1732 if ( error ) {
1733 QVERIFY( ftp->error() != QFtp::NoError );
1734 ids.clear();
1735 } else {
1736 QVERIFY( ftp->error() == QFtp::NoError );
1737 ids.pop_front();
1738 }
1739
1740 QVERIFY( ftp->currentId() == id );
1741 QVERIFY( cur_state == ftp->state() );
1742 CURRENTCOMMAND_TEST;
1743
1744 if ( QTest::currentTestFunction() != QLatin1String("commandSequence") ) {
1745 ResMapIt it = resultMap.find( ftp->currentCommand() );
1746 QVERIFY( it != resultMap.end() );
1747 QVERIFY( it.value().success == -1 );
1748 if ( error )
1749 it.value().success = 0;
1750 else
1751 it.value().success = 1;
1752 }
1753 }
1754
done(bool error)1755 void tst_QFtp::done( bool error )
1756 {
1757 #if defined( DUMP_SIGNALS )
1758 qDebug( "%d:done( %d )", ftp->currentId(), (int)error );
1759 #endif
1760 bytesAvailable_done = ftp->bytesAvailable();
1761
1762 QVERIFY( ftp->currentId() == 0 );
1763 QVERIFY( current_id == 0 );
1764 QVERIFY( ids.isEmpty() );
1765 QVERIFY( cur_state == ftp->state() );
1766 QVERIFY( !ftp->hasPendingCommands() );
1767
1768 if ( QTest::currentTestFunction() == QLatin1String("commandSequence") ) {
1769 QVERIFY( commandSequence_success == -1 );
1770 if ( error )
1771 commandSequence_success = 0;
1772 else
1773 commandSequence_success = 1;
1774 }
1775 QVERIFY( done_success == -1 );
1776 if ( error ) {
1777 QVERIFY( ftp->error() != QFtp::NoError );
1778 done_success = 0;
1779 } else {
1780 QVERIFY( ftp->error() == QFtp::NoError );
1781 done_success = 1;
1782 }
1783 QTestEventLoop::instance().exitLoop();
1784 }
1785
stateChanged(int state)1786 void tst_QFtp::stateChanged( int state )
1787 {
1788 #if defined( DUMP_SIGNALS )
1789 qDebug( "%d: stateChanged( %d )", ftp->currentId(), state );
1790 #endif
1791 QCOMPARE( ftp->currentId(), current_id );
1792 CURRENTCOMMAND_TEST;
1793
1794 QVERIFY( state != cur_state );
1795 QCOMPARE( state, (int)ftp->state() );
1796 if ( state != QFtp::Unconnected ) {
1797 // make sure that the states are always emitted in the right order (for
1798 // this, we assume an ordering on the enum values, which they have at
1799 // the moment)
1800 QVERIFY( cur_state < state );
1801
1802 // make sure that state changes are only emitted in response to certain
1803 // commands
1804 switch ( state ) {
1805 case QFtp::HostLookup:
1806 case QFtp::Connecting:
1807 case QFtp::Connected:
1808 QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::ConnectToHost );
1809 break;
1810 case QFtp::LoggedIn:
1811 QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::Login );
1812 break;
1813 case QFtp::Closing:
1814 QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::Close );
1815 break;
1816 default:
1817 QWARN( QString("Unexpected state '%1'").arg(state).toLatin1().constData() );
1818 break;
1819 }
1820 }
1821 cur_state = state;
1822
1823 if ( QTest::currentTestFunction() == QLatin1String("connectToHost") ) {
1824 switch ( state ) {
1825 case QFtp::HostLookup:
1826 case QFtp::Connecting:
1827 case QFtp::LoggedIn:
1828 case QFtp::Closing:
1829 // ignore
1830 break;
1831 case QFtp::Connected:
1832 case QFtp::Unconnected:
1833 QVERIFY( connectToHost_state == -1 );
1834 connectToHost_state = state;
1835 break;
1836 default:
1837 QWARN( QString("Unknown state '%1'").arg(state).toLatin1().constData() );
1838 break;
1839 }
1840 } else if ( QTest::currentTestFunction() == QLatin1String("close") ) {
1841 ResMapIt it = resultMap.find( QFtp::Close );
1842 if ( it!=resultMap.end() && ftp->currentId()==it.value().id ) {
1843 if ( state == QFtp::Closing ) {
1844 QVERIFY( close_state == -1 );
1845 close_state = state;
1846 } else if ( state == QFtp::Unconnected ) {
1847 QVERIFY( close_state == QFtp::Closing );
1848 close_state = state;
1849 }
1850 }
1851 } else if ( QTest::currentTestFunction() == QLatin1String("login") ) {
1852 ResMapIt it = resultMap.find( QFtp::Login );
1853 if ( it!=resultMap.end() && ftp->currentId()==it.value().id ) {
1854 if ( state == QFtp::LoggedIn ) {
1855 QVERIFY( login_state == -1 );
1856 login_state = state;
1857 }
1858 }
1859 }
1860 }
1861
listInfo(const QUrlInfo & i)1862 void tst_QFtp::listInfo( const QUrlInfo &i )
1863 {
1864 #if defined( DUMP_SIGNALS )
1865 qDebug( "%d: listInfo( %s )", ftp->currentId(), i.name().toLatin1().constData() );
1866 #endif
1867 QCOMPARE( ftp->currentId(), current_id );
1868 if ( ids.count() > 1 ) {
1869 QVERIFY( ftp->hasPendingCommands() );
1870 } else {
1871 QVERIFY( !ftp->hasPendingCommands() );
1872 }
1873 QVERIFY( cur_state == ftp->state() );
1874 CURRENTCOMMAND_TEST;
1875
1876 if ( QTest::currentTestFunction()==QLatin1String("list") || QTest::currentTestFunction()==QLatin1String("cd") || QTest::currentTestFunction()==QLatin1String("proxy") || inFileDirExistsFunction ) {
1877 ResMapIt it = resultMap.find( QFtp::List );
1878 QVERIFY( it != resultMap.end() );
1879 QVERIFY( ftp->currentId() == it.value().id );
1880 listInfo_i << i;
1881 }
1882 }
1883
readyRead()1884 void tst_QFtp::readyRead()
1885 {
1886 #if defined( DUMP_SIGNALS )
1887 qDebug( "%d: readyRead(), bytesAvailable == %lu", ftp->currentId(), ftp->bytesAvailable() );
1888 #endif
1889 QCOMPARE( ftp->currentId(), current_id );
1890 if ( ids.count() > 1 ) {
1891 QVERIFY( ftp->hasPendingCommands() );
1892 } else {
1893 QVERIFY( !ftp->hasPendingCommands() );
1894 }
1895 QVERIFY( cur_state == ftp->state() );
1896 CURRENTCOMMAND_TEST;
1897
1898 if ( QTest::currentTestFunction() != QLatin1String("bytesAvailable") ) {
1899 int oldSize = newData_ba.size();
1900 qlonglong bytesAvail = ftp->bytesAvailable();
1901 QByteArray ba = ftp->readAll();
1902 QVERIFY( ba.size() == (int) bytesAvail );
1903 newData_ba.resize( oldSize + ba.size() );
1904 memcpy( newData_ba.data()+oldSize, ba.data(), ba.size() );
1905
1906 if ( bytesTotal != -1 ) {
1907 QVERIFY( (int)newData_ba.size() <= bytesTotal );
1908 }
1909 QVERIFY( (int)newData_ba.size() == bytesDone );
1910 }
1911 }
1912
dataTransferProgress(qint64 done,qint64 total)1913 void tst_QFtp::dataTransferProgress( qint64 done, qint64 total )
1914 {
1915 #if defined( DUMP_SIGNALS )
1916 qDebug( "%d: dataTransferProgress( %lli, %lli )", ftp->currentId(), done, total );
1917 #endif
1918 QCOMPARE( ftp->currentId(), current_id );
1919 if ( ids.count() > 1 ) {
1920 QVERIFY( ftp->hasPendingCommands() );
1921 } else {
1922 QVERIFY( !ftp->hasPendingCommands() );
1923 }
1924 QVERIFY( cur_state == ftp->state() );
1925 CURRENTCOMMAND_TEST;
1926
1927 if ( bytesTotal == bytesTotal_init ) {
1928 bytesTotal = total;
1929 } else {
1930 QVERIFY( bytesTotal == total );
1931 }
1932
1933 QVERIFY( bytesTotal != bytesTotal_init );
1934 QVERIFY( bytesDone <= done );
1935 bytesDone = done;
1936 if ( bytesTotal != -1 ) {
1937 QVERIFY( bytesDone <= bytesTotal );
1938 }
1939
1940 if ( QTest::currentTestFunction() == QLatin1String("abort") ) {
1941 // ### it would be nice if we could specify in our testdata when to do
1942 // the abort
1943 if ( done >= total/100000 ) {
1944 if ( ids.count() != 1 ) {
1945 // do abort only once
1946 int tmpId = ids.first();
1947 ids.clear();
1948 ids << tmpId;
1949 ftp->abort();
1950 }
1951 }
1952 }
1953 }
1954
1955
newFtp()1956 QFtp *tst_QFtp::newFtp()
1957 {
1958 QFtp *nFtp = new QFtp( this );
1959 #ifndef QT_NO_BEARERMANAGEMENT
1960 if (networkSessionExplicit) {
1961 nFtp->setProperty("_q_networksession", QVariant::fromValue(networkSessionExplicit));
1962 }
1963 #endif
1964 connect( nFtp, SIGNAL(commandStarted(int)),
1965 SLOT(commandStarted(int)) );
1966 connect( nFtp, SIGNAL(commandFinished(int,bool)),
1967 SLOT(commandFinished(int,bool)) );
1968 connect( nFtp, SIGNAL(done(bool)),
1969 SLOT(done(bool)) );
1970 connect( nFtp, SIGNAL(stateChanged(int)),
1971 SLOT(stateChanged(int)) );
1972 connect( nFtp, SIGNAL(listInfo(const QUrlInfo&)),
1973 SLOT(listInfo(const QUrlInfo&)) );
1974 connect( nFtp, SIGNAL(readyRead()),
1975 SLOT(readyRead()) );
1976 connect( nFtp, SIGNAL(dataTransferProgress(qint64, qint64)),
1977 SLOT(dataTransferProgress(qint64, qint64)) );
1978
1979 return nFtp;
1980 }
1981
addCommand(QFtp::Command cmd,int id)1982 void tst_QFtp::addCommand( QFtp::Command cmd, int id )
1983 {
1984 ids << id;
1985 CommandResult res;
1986 res.id = id;
1987 res.success = -1;
1988 resultMap[ cmd ] = res;
1989 }
1990
fileExists(const QString & host,quint16 port,const QString & user,const QString & password,const QString & file,const QString & cdDir)1991 bool tst_QFtp::fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir )
1992 {
1993 init();
1994 ftp = newFtp();
1995 // ### make these tests work
1996 if (ftp->currentId() != 0) {
1997 qWarning("ftp->currentId() != 0");
1998 return FALSE;
1999 }
2000
2001 if (ftp->state() != QFtp::Unconnected) {
2002 qWarning("ftp->state() != QFtp::Unconnected");
2003 return FALSE;
2004 }
2005
2006 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
2007 addCommand( QFtp::Login, ftp->login( user, password ) );
2008 if ( !cdDir.isNull() )
2009 addCommand( QFtp::Cd, ftp->cd( cdDir ) );
2010 addCommand( QFtp::List, ftp->list( file ) );
2011 addCommand( QFtp::Close, ftp->close() );
2012
2013 inFileDirExistsFunction = TRUE;
2014 QTestEventLoop::instance().enterLoop( 30 );
2015 delete ftp;
2016 ftp = 0;
2017 if ( QTestEventLoop::instance().timeout() ) {
2018 // ### make this test work
2019 qWarning("tst_QFtp::fileExists: Network operation timed out");
2020 return FALSE;
2021 }
2022 inFileDirExistsFunction = FALSE;
2023
2024 ResMapIt it = resultMap.find( QFtp::ConnectToHost );
2025 // ### make these tests work
2026 if (it == resultMap.end()) {
2027 qWarning("it != resultMap.end()");
2028 return FALSE;
2029 }
2030
2031 if (it.value().success == -1) {
2032 qWarning("it.value().success != -1");
2033 return FALSE;
2034 }
2035
2036 if ( it.value().success == 1 ) {
2037 for ( uint i=0; i < (uint) listInfo_i.count(); i++ ) {
2038 if ( QFileInfo(listInfo_i[i].name()).fileName() == QFileInfo(file).fileName() )
2039 return TRUE;
2040 }
2041 }
2042
2043 //this is not a good warning considering sometime this function is used to test that a file does not exist
2044 //qWarning("file doesn't exist");
2045 return FALSE;
2046 }
2047
dirExists(const QString & host,quint16 port,const QString & user,const QString & password,const QString & cdDir,const QString & dirToCreate)2048 bool tst_QFtp::dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate )
2049 {
2050 init();
2051 ftp = newFtp();
2052 // ### make these tests work
2053 // QCOMPARE( ftp->currentId(), 0 );
2054 // QCOMPARE( (int)ftp->state(), (int)QFtp::Unconnected );
2055
2056 addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
2057 addCommand( QFtp::Login, ftp->login( user, password ) );
2058 if ( dirToCreate.startsWith( "/" ) )
2059 addCommand( QFtp::Cd, ftp->cd( dirToCreate ) );
2060 else
2061 addCommand( QFtp::Cd, ftp->cd( cdDir + "/" + dirToCreate ) );
2062 addCommand( QFtp::Close, ftp->close() );
2063
2064 inFileDirExistsFunction = TRUE;
2065 QTestEventLoop::instance().enterLoop( 30 );
2066 delete ftp;
2067 ftp = 0;
2068 if ( QTestEventLoop::instance().timeout() ) {
2069 // ### make this test work
2070 // QFAIL( "Network operation timed out" );
2071 qWarning("tst_QFtp::dirExists: Network operation timed out");
2072 return FALSE;
2073 }
2074 inFileDirExistsFunction = FALSE;
2075
2076 ResMapIt it = resultMap.find( QFtp::Cd );
2077 // ### make these tests work
2078 // QVERIFY( it != resultMap.end() );
2079 // QVERIFY( it.value().success != -1 );
2080 return it.value().success == 1;
2081 }
2082
doneSignal()2083 void tst_QFtp::doneSignal()
2084 {
2085 QFtp ftp;
2086 QSignalSpy spy(&ftp, SIGNAL(done(bool)));
2087
2088 ftp.connectToHost(QtNetworkSettings::serverName());
2089 ftp.login("anonymous");
2090 ftp.list();
2091 ftp.close();
2092
2093 done_success = 0;
2094 connect(&ftp, SIGNAL(done(bool)), &(QTestEventLoop::instance()), SLOT(exitLoop()));
2095 QTestEventLoop::instance().enterLoop(61);
2096 if (QTestEventLoop::instance().timeout())
2097 QFAIL("Network operation timed out");
2098
2099 QTest::qWait(200);
2100
2101 QCOMPARE(spy.count(), 1);
2102 QCOMPARE(spy.first().first().toBool(), false);
2103 }
2104
queueMoreCommandsInDoneSlot()2105 void tst_QFtp::queueMoreCommandsInDoneSlot()
2106 {
2107 QSKIP("Task 127050 && 113966", SkipSingle);
2108
2109 QFtp ftp;
2110 QSignalSpy doneSpy(&ftp, SIGNAL(done(bool)));
2111 QSignalSpy commandFinishedSpy(&ftp, SIGNAL(commandFinished(int, bool)));
2112
2113 this->ftp = &ftp;
2114 connect(&ftp, SIGNAL(done(bool)), this, SLOT(cdUpSlot(bool)));
2115
2116 ftp.connectToHost("ftp.qt.nokia.com");
2117 ftp.login();
2118 ftp.cd("qt");
2119 ftp.rmdir("qtest-removedir-noexist");
2120
2121 while ( ftp.hasPendingCommands() || ftp.currentCommand() != QFtp::None ) {
2122 QCoreApplication::instance()->processEvents(QEventLoop::AllEvents
2123 | QEventLoop::WaitForMoreEvents);
2124 }
2125
2126 QCOMPARE(doneSpy.count(), 2);
2127 QCOMPARE(doneSpy.first().first().toBool(), true);
2128 QCOMPARE(doneSpy.last().first().toBool(), false);
2129
2130 QCOMPARE(commandFinishedSpy.count(), 6);
2131 int firstId = commandFinishedSpy.at(0).at(0).toInt();
2132 QCOMPARE(commandFinishedSpy.at(0).at(1).toBool(), false);
2133 QCOMPARE(commandFinishedSpy.at(1).at(0).toInt(), firstId + 1);
2134 QCOMPARE(commandFinishedSpy.at(1).at(1).toBool(), false);
2135 QCOMPARE(commandFinishedSpy.at(2).at(0).toInt(), firstId + 2);
2136 QCOMPARE(commandFinishedSpy.at(2).at(1).toBool(), false);
2137 QCOMPARE(commandFinishedSpy.at(3).at(0).toInt(), firstId + 3);
2138 QCOMPARE(commandFinishedSpy.at(3).at(1).toBool(), true);
2139 QCOMPARE(commandFinishedSpy.at(4).at(0).toInt(), firstId + 4);
2140 QCOMPARE(commandFinishedSpy.at(4).at(1).toBool(), false);
2141 QCOMPARE(commandFinishedSpy.at(5).at(0).toInt(), firstId + 5);
2142 QCOMPARE(commandFinishedSpy.at(5).at(1).toBool(), false);
2143
2144 this->ftp = 0;
2145 }
2146
cdUpSlot(bool error)2147 void tst_QFtp::cdUpSlot(bool error)
2148 {
2149 if (error) {
2150 ftp->cd("..");
2151 ftp->cd("qt");
2152 }
2153 }
2154
qtbug7359Crash()2155 void tst_QFtp::qtbug7359Crash()
2156 {
2157 QFtp ftp;
2158 ftp.connectToHost("127.0.0.1");
2159
2160 QTime t;
2161 int elapsed;
2162
2163 t.start();
2164 while ((elapsed = t.elapsed()) < 200)
2165 QCoreApplication::processEvents(QEventLoop::AllEvents, 200 - elapsed);
2166
2167 ftp.close();
2168 t.restart();
2169 while ((elapsed = t.elapsed()) < 1000)
2170 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000 - elapsed);
2171
2172 ftp.connectToHost("127.0.0.1");
2173
2174 t.restart();
2175 while ((elapsed = t.elapsed()) < 2000)
2176 QCoreApplication::processEvents(QEventLoop::AllEvents, 2000 - elapsed);
2177 }
2178
2179 QTEST_MAIN(tst_QFtp)
2180
2181 #include "tst_qftp.moc"
2182