--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/qftp/tst_qftp.cpp Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,2057 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qfile.h>
+#include <qbuffer.h>
+#include "qftp.h"
+#include <qmap.h>
+#include <time.h>
+#include <stdlib.h>
+#include <QNetworkProxy>
+
+#ifndef TEST_QNETWORK_PROXY
+#define TEST_QNETWORK_PROXY
+#endif
+#include "../network-settings.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+// Application private dir is default serach path for files, so SRCDIR can be set to empty
+#define SRCDIR ""
+#endif
+
+
+
+class tst_QFtp : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QFtp();
+ virtual ~tst_QFtp();
+
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void connectToHost_data();
+ void connectToHost();
+ void connectToUnresponsiveHost();
+ void login_data();
+ void login();
+ void close_data();
+ void close();
+
+ void list_data();
+ void list();
+ void cd_data();
+ void cd();
+ void get_data();
+ void get();
+ void put_data();
+ void put();
+ void remove();
+ void mkdir_data();
+ void mkdir();
+ void mkdir2();
+ void rmdir();
+ void rename_data();
+ void rename();
+
+ void commandSequence_data();
+ void commandSequence();
+
+ void abort_data();
+ void abort();
+
+ void bytesAvailable_data();
+ void bytesAvailable();
+
+ void activeMode();
+
+ void proxy_data();
+ void proxy();
+
+ void binaryAscii();
+
+ void doneSignal();
+ void queueMoreCommandsInDoneSlot();
+
+protected slots:
+ void stateChanged( int );
+ void listInfo( const QUrlInfo & );
+ void readyRead();
+ void dataTransferProgress(qint64, qint64);
+
+ void commandStarted( int );
+ void commandFinished( int, bool );
+ void done( bool );
+ void activeModeDone( bool );
+ void mkdir2Slot(int id, bool error);
+ void cdUpSlot(bool);
+
+private:
+ QFtp *newFtp();
+ void addCommand( QFtp::Command, int );
+ bool fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir = QString::null );
+ bool dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate );
+
+ void renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile );
+ void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete );
+
+ QFtp *ftp;
+
+ QList<int> ids; // helper to make sure that all expected signals are emitted
+ int current_id;
+
+ int connectToHost_state;
+ int close_state;
+ int login_state;
+ int cur_state;
+ struct CommandResult
+ {
+ int id;
+ int success;
+ };
+ QMap< QFtp::Command, CommandResult > resultMap;
+ typedef QMap<QFtp::Command,CommandResult>::Iterator ResMapIt;
+
+ int done_success;
+ int commandSequence_success;
+
+ qlonglong bytesAvailable_finishedGet;
+ qlonglong bytesAvailable_finished;
+ qlonglong bytesAvailable_done;
+
+ QList<QUrlInfo> listInfo_i;
+ QByteArray newData_ba;
+ qlonglong bytesTotal;
+ qlonglong bytesDone;
+
+ bool inFileDirExistsFunction;
+
+ QString uniqueExtension;
+};
+
+//#define DUMP_SIGNALS
+
+const int bytesTotal_init = -10;
+const int bytesDone_init = -10;
+
+tst_QFtp::tst_QFtp()
+{
+ Q_SET_DEFAULT_IAP
+}
+
+tst_QFtp::~tst_QFtp()
+{
+}
+
+void tst_QFtp::initTestCase_data()
+{
+ QTest::addColumn<bool>("setProxy");
+ QTest::addColumn<int>("proxyType");
+
+ QTest::newRow("WithoutProxy") << false << 0;
+#ifdef TEST_QNETWORK_PROXY
+ QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy);
+ //### doesn't work well yet.
+ //QTest::newRow("WithHttpProxy") << true << int(QNetworkProxy::HttpProxy);
+#endif
+}
+
+void tst_QFtp::initTestCase()
+{
+}
+
+void tst_QFtp::cleanupTestCase()
+{
+}
+
+void tst_QFtp::init()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ } else if (proxyType == QNetworkProxy::HttpProxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+ }
+ }
+
+ ftp = 0;
+
+ ids.clear();
+ current_id = 0;
+
+ resultMap.clear();
+ connectToHost_state = -1;
+ close_state = -1;
+ login_state = -1;
+ cur_state = QFtp::Unconnected;
+
+ listInfo_i.clear();
+ newData_ba = QByteArray();
+ bytesTotal = bytesTotal_init;
+ bytesDone = bytesDone_init;
+
+ done_success = -1;
+ commandSequence_success = -1;
+
+ bytesAvailable_finishedGet = 1234567890;
+ bytesAvailable_finished = 1234567890;
+ bytesAvailable_done = 1234567890;
+
+ inFileDirExistsFunction = FALSE;
+
+#if !defined(Q_OS_WINCE)
+ srand(time(0));
+ uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)time(0));
+#else
+ srand(0);
+ uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)(0));
+#endif
+}
+
+void tst_QFtp::cleanup()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
+ }
+}
+
+void tst_QFtp::connectToHost_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<int>("state");
+
+ QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << (int)QFtp::Connected;
+ QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)2222 << (int)QFtp::Unconnected;
+ QTest::newRow( "error02" ) << QString("foo.bar") << (uint)21 << (int)QFtp::Unconnected;
+}
+
+void tst_QFtp::connectToHost()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+
+ QTestEventLoop::instance().enterLoop( 61 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QTEST( connectToHost_state, "state" );
+
+ ResMapIt it = resultMap.find( QFtp::ConnectToHost );
+ QVERIFY( it != resultMap.end() );
+ QFETCH( int, state );
+ if ( state == QFtp::Connected ) {
+ QVERIFY( it.value().success == 1 );
+ } else {
+ QVERIFY( it.value().success == 0 );
+ }
+}
+
+void tst_QFtp::connectToUnresponsiveHost()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ QSKIP( "This test takes too long if we test with proxies too", SkipSingle );
+
+ QString host = "1.2.3.4";
+ uint port = 21;
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+
+ qDebug( "About to connect to host that won't reply (this test takes 60 seconds)" );
+ QTestEventLoop::instance().enterLoop( 61 );
+#ifdef Q_OS_WIN
+ /* On Windows, we do not get a timeout, because Winsock is behaving in a strange way:
+ We issue two "WSAConnect()" calls, after the first, as a result we get WSAEWOULDBLOCK,
+ after the second, we get WSAEISCONN, which means that the socket is connected, which cannot be.
+ However, after some seconds we get a socket error saying that the remote host closed the connection,
+ which can neither be. For this test, that would actually enable us to finish before timout, but handling that case
+ (in void QFtpPI::error(QAbstractSocket::SocketError e)) breaks
+ a lot of other stuff in QFtp, so we just expect this test to fail on Windows.
+ */
+ QEXPECT_FAIL("", "timeout not working due to strange Windows socket behaviour (see source file of this test for explanation)", Abort);
+#endif
+ QVERIFY2(! QTestEventLoop::instance().timeout(), "Network timeout longer than expected (should have been 60 seconds)");
+
+ QVERIFY( ftp->state() == QFtp::Unconnected);
+ ResMapIt it = resultMap.find( QFtp::ConnectToHost );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 0 );
+
+ delete ftp;
+}
+
+void tst_QFtp::login_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<int>("success");
+
+ QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << 1;
+ QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << 1;
+ QTest::newRow( "ok03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << 1;
+ QTest::newRow( "ok04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << 1;
+
+ QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString() << 0;
+ QTest::newRow( "error02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("bar") << 0;
+}
+
+void tst_QFtp::login()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Login );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+
+ if ( it.value().success ) {
+ QVERIFY( login_state == QFtp::LoggedIn );
+ } else {
+ QVERIFY( login_state != QFtp::LoggedIn );
+ }
+}
+
+void tst_QFtp::close_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<bool>("login");
+
+ QTest::newRow( "login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << (bool)TRUE;
+ QTest::newRow( "login02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << (bool)TRUE;
+ QTest::newRow( "login03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << (bool)TRUE;
+ QTest::newRow( "login04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << (bool)TRUE;
+
+ QTest::newRow( "no-login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("") << QString("") << (bool)FALSE;
+}
+
+void tst_QFtp::close()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( bool, login );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ if ( login )
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QCOMPARE( close_state, (int)QFtp::Unconnected );
+
+ ResMapIt it = resultMap.find( QFtp::Close );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+}
+
+void tst_QFtp::list_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("dir");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
+
+ QStringList flukeRoot;
+ flukeRoot << "pub";
+ flukeRoot << "qtest";
+ QStringList flukeQtest;
+ flukeQtest << "bigfile";
+ flukeQtest << "nonASCII";
+ flukeQtest << "rfc3252";
+ flukeQtest << "rfc3252.txt";
+ flukeQtest << "upload";
+
+ QTest::newRow( "workDir01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
+ QTest::newRow( "workDir02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
+
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
+ // ### The microsoft server does not seem to work properly at the moment --
+ // I am also not able to open a data connection with other, non-Qt FTP
+ // clients to it.
+ // QTest::newRow( "nonExist03" ) << "ftp.microsoft.com" << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+
+ QStringList susePub;
+ susePub << "README.mirror-policy" << "axp" << "i386" << "ia64" << "install" << "noarch" << "pubring.gpg-build.suse.de" << "update" << "x86_64";
+ QTest::newRow( "epsvNotSupported" ) << QString("ftp.funet.fi") << (uint)21 << QString::fromLatin1("ftp") << QString::fromLatin1("root@") << QString("/pub/Linux/suse/suse") << 1 << susePub;
+}
+
+void tst_QFtp::list()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, dir );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::List, ftp->list( dir ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::List );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ QFETCH( QStringList, entryNames );
+ QCOMPARE( listInfo_i.count(), entryNames.count() );
+ for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
+ QCOMPARE( listInfo_i[i].name(), entryNames[i] );
+ }
+}
+
+void tst_QFtp::cd_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("dir");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
+
+ QStringList flukeRoot;
+ flukeRoot << "qtest";
+ QStringList flukeQtest;
+ flukeQtest << "bigfile";
+ flukeQtest << "nonASCII";
+ flukeQtest << "rfc3252";
+ flukeQtest << "rfc3252.txt";
+ flukeQtest << "upload";
+
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+}
+
+void tst_QFtp::cd()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, dir );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( dir ) );
+ addCommand( QFtp::List, ftp->list() );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() ) {
+ QFAIL( "Network operation timed out" );
+ }
+
+ ResMapIt it = resultMap.find( QFtp::Cd );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ QFETCH( QStringList, entryNames );
+ QCOMPARE( listInfo_i.count(), entryNames.count() );
+ for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
+ QCOMPARE( listInfo_i[i].name(), entryNames[i] );
+ }
+}
+
+void tst_QFtp::get_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QByteArray>("res");
+ QTest::addColumn<bool>("useIODevice");
+
+ // ### move this into external testdata
+ QFile file( SRCDIR "rfc3252.txt" );
+ QVERIFY( file.open( QIODevice::ReadOnly ) );
+ QByteArray rfc3252 = file.readAll();
+
+ // test the two get() overloads in one routine
+ for ( int i=0; i<2; i++ ) {
+ QTest::newRow( QString("relPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+ QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+
+ QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+ QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "/var/ftp/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
+
+ QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("foo") << 0 << QByteArray() << (bool)(i==1);
+ QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("/foo") << 0 << QByteArray() << (bool)(i==1);
+ }
+}
+
+void tst_QFtp::get()
+{
+ // for the overload that takes a QIODevice
+ QByteArray buf_ba;
+ QBuffer buf( &buf_ba );
+
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, file );
+ QFETCH( bool, useIODevice );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( useIODevice ) {
+ buf.open( QIODevice::WriteOnly );
+ addCommand( QFtp::Get, ftp->get( file, &buf ) );
+ } else {
+ addCommand( QFtp::Get, ftp->get( file ) );
+ }
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Get );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ if ( useIODevice ) {
+ QTEST( buf_ba, "res" );
+ } else {
+ QTEST( newData_ba, "res" );
+ }
+ QVERIFY( bytesTotal != bytesTotal_init );
+ if ( bytesTotal != -1 ) {
+ QVERIFY( bytesDone == bytesTotal );
+ }
+ if ( useIODevice ) {
+ if ( bytesDone != bytesDone_init ) {
+ QVERIFY( (int)buf_ba.size() == bytesDone );
+ }
+ } else {
+ if ( bytesDone != bytesDone_init ) {
+ QVERIFY( (int)newData_ba.size() == bytesDone );
+ }
+ }
+}
+
+void tst_QFtp::put_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QByteArray>("fileData");
+ QTest::addColumn<bool>("useIODevice");
+ QTest::addColumn<int>("success");
+
+ // ### move this into external testdata
+ QFile file( SRCDIR "rfc3252.txt" );
+ QVERIFY( file.open( QIODevice::ReadOnly ) );
+ QByteArray rfc3252 = file.readAll();
+
+ QByteArray bigData( 10*1024*1024, 0 );
+ bigData.fill( 'A' );
+
+ // test the two put() overloads in one routine
+ for ( int i=0; i<2; i++ ) {
+ QTest::newRow( QString("relPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("qtest/upload/rel01_%1") << rfc3252
+ << (bool)(i==1) << 1;
+ /*
+ QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("qtest/upload/rel02_%1") << rfc3252
+ << (bool)(i==1) << 1;
+ QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("qtest/upload/rel03_%1") << QByteArray()
+ << (bool)(i==1) << 1;
+ QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("qtest/upload/rel04_%1") << bigData
+ << (bool)(i==1) << 1;
+
+ QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("/qtest/upload/abs01_%1") << rfc3252
+ << (bool)(i==1) << 1;
+ QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << QString("/srv/ftp/qtest/upload/abs02_%1") << rfc3252
+ << (bool)(i==1) << 1;
+
+ QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("foo") << QByteArray()
+ << (bool)(i==1) << 0;
+ QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << QString("/foo") << QByteArray()
+ << (bool)(i==1) << 0;
+*/
+ }
+}
+
+void tst_QFtp::put()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, file );
+ QFETCH( QByteArray, fileData );
+ QFETCH( bool, useIODevice );
+
+#ifdef Q_OS_WIN
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("With socks5 the put() test takes too long time on Windows.", SkipAll);
+ }
+ }
+#endif
+
+ const int timestep = 50;
+
+ if(file.contains('%'))
+ file = file.arg(uniqueExtension);
+
+ // for the overload that takes a QIODevice
+ QBuffer buf_fileData( &fileData );
+ buf_fileData.open( QIODevice::ReadOnly );
+
+ ResMapIt it;
+ //////////////////////////////////////////////////////////////////
+ // upload the file
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( useIODevice )
+ addCommand( QFtp::Put, ftp->put( &buf_fileData, file ) );
+ else
+ addCommand( QFtp::Put, ftp->put( fileData, file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ for(int time = 0; time <= fileData.length() / 20000; time += timestep) {
+ QTestEventLoop::instance().enterLoop( timestep );
+ if(ftp->currentCommand() == QFtp::None)
+ break;
+ }
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Put );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ if ( !it.value().success ) {
+ QVERIFY( !fileExists( host, port, user, password, file ) );
+ return; // the following tests are only meaningful if the file could be put
+ }
+ QVERIFY( bytesTotal == (int)fileData.size() );
+ QVERIFY( bytesDone == bytesTotal );
+
+ QVERIFY( fileExists( host, port, user, password, file ) );
+
+ //////////////////////////////////////////////////////////////////
+ // fetch file to make sure that it is equal to the uploaded file
+ init();
+ ftp = newFtp();
+ QBuffer buf;
+ buf.open( QIODevice::WriteOnly );
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Get, ftp->get( file, &buf ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ for(int time = 0; time <= fileData.length() / 20000; time += timestep) {
+ QTestEventLoop::instance().enterLoop( timestep );
+ if(ftp->currentCommand() == QFtp::None)
+ break;
+ }
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QVERIFY( done_success == 1 );
+ QTEST( buf.buffer(), "fileData" );
+
+ //////////////////////////////////////////////////////////////////
+ // cleanup (i.e. remove the file) -- this also tests the remove command
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Remove, ftp->remove( file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( timestep );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 1 );
+
+ QVERIFY( !fileExists( host, port, user, password, file ) );
+}
+
+void tst_QFtp::remove()
+{
+ DEPENDS_ON( "put" );
+}
+
+void tst_QFtp::mkdir_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("cdDir");
+ QTest::addColumn<QString>("dirToCreate");
+ QTest::addColumn<int>("success");
+
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "qtest/upload" << QString("rel01_%1") << 1;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "qtest/upload" << QString("rel02_%1") << 1;
+ QTest::newRow( "relPath03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "qtest/upload" << QString("rel03_%1") << 1;
+
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "." << QString("/qtest/upload/abs01_%1") << 1;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ << "." << QString("/var/ftp/qtest/upload/abs02_%1") << 1;
+
+ // QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0;
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "." << QString("foo") << 0;
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ << "." << QString("/foo") << 0;
+}
+
+void tst_QFtp::mkdir()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, cdDir );
+ QFETCH( QString, dirToCreate );
+
+ if(dirToCreate.contains('%'))
+ dirToCreate = dirToCreate.arg(uniqueExtension);
+
+ //////////////////////////////////////////////////////////////////
+ // create the directory
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Mkdir, ftp->mkdir( dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Mkdir );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+ if ( !it.value().success ) {
+ QVERIFY( !dirExists( host, port, user, password, cdDir, dirToCreate ) );
+ return; // the following tests are only meaningful if the dir could be created
+ }
+ QVERIFY( dirExists( host, port, user, password, cdDir, dirToCreate ) );
+
+ //////////////////////////////////////////////////////////////////
+ // create the directory again (should always fail!)
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Mkdir, ftp->mkdir( dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Mkdir );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 0 );
+
+ //////////////////////////////////////////////////////////////////
+ // remove the directory
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Rmdir, ftp->rmdir( dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Rmdir );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 1 );
+
+ QVERIFY( !dirExists( host, port, user, password, cdDir, dirToCreate ) );
+}
+
+void tst_QFtp::mkdir2()
+{
+ ftp = new QFtp;
+ ftp->connectToHost(QtNetworkSettings::serverName());
+ ftp->login();
+ current_id = ftp->cd("kake/test");
+
+ QEventLoop loop;
+ connect(ftp, SIGNAL(done(bool)), &loop, SLOT(quit()));
+ connect(ftp, SIGNAL(commandFinished(int, bool)), this, SLOT(mkdir2Slot(int, bool)));
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+
+ QSignalSpy commandStartedSpy(ftp, SIGNAL(commandStarted(int)));
+ QSignalSpy commandFinishedSpy(ftp, SIGNAL(commandFinished(int, bool)));
+
+ loop.exec();
+
+ QCOMPARE(commandStartedSpy.count(), 4); // connect, login, cd, mkdir
+ QCOMPARE(commandFinishedSpy.count(), 4);
+
+ for (int i = 0; i < 4; ++i)
+ QCOMPARE(commandFinishedSpy.at(i).at(0), commandStartedSpy.at(i).at(0));
+
+ QVERIFY(!commandFinishedSpy.at(0).at(1).toBool());
+ QVERIFY(!commandFinishedSpy.at(1).at(1).toBool());
+ QVERIFY(commandFinishedSpy.at(2).at(1).toBool());
+ QVERIFY(commandFinishedSpy.at(3).at(1).toBool());
+
+ delete ftp;
+}
+
+void tst_QFtp::mkdir2Slot(int id, bool)
+{
+ if (id == current_id)
+ ftp->mkdir("kake/test");
+}
+
+void tst_QFtp::rmdir()
+{
+ DEPENDS_ON( "mkdir" );
+}
+
+void tst_QFtp::rename_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("cdDir");
+ QTest::addColumn<QString>("oldfile");
+ QTest::addColumn<QString>("newfile");
+ QTest::addColumn<QString>("createFile");
+ QTest::addColumn<QString>("renamedFile");
+ QTest::addColumn<int>("success");
+
+ QTest::newRow("relPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ << "qtest/upload"
+ << QString("rel_old01_%1") << QString("rel_new01_%1")
+ << QString("qtest/upload/rel_old01_%1") << QString("qtest/upload/rel_new01_%1")
+ << 1;
+ QTest::newRow("relPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ << "qtest/upload"
+ << QString("rel_old02_%1") << QString("rel_new02_%1")
+ << QString("qtest/upload/rel_old02_%1") << QString("qtest/upload/rel_new02_%1")
+ << 1;
+ QTest::newRow("relPath03") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ << "qtest/upload"
+ << QString("rel_old03_%1")<< QString("rel_new03_%1")
+ << QString("qtest/upload/rel_old03_%1") << QString("qtest/upload/rel_new03_%1")
+ << 1;
+
+ QTest::newRow("absPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ << QString()
+ << QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
+ << QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
+ << 1;
+ QTest::newRow("absPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ << QString()
+ << QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
+ << QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
+ << 1;
+
+ QTest::newRow("nonExist01") << QtNetworkSettings::serverName() << QString() << QString()
+ << QString()
+ << QString("foo") << "new_foo"
+ << QString() << QString()
+ << 0;
+ QTest::newRow("nonExist02") << QtNetworkSettings::serverName() << QString() << QString()
+ << QString()
+ << QString("/foo") << QString("/new_foo")
+ << QString() << QString()
+ << 0;
+}
+
+void tst_QFtp::renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile )
+{
+ if ( !createFile.isNull() ) {
+ // upload the file
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Put, ftp->put( QByteArray(), createFile ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Put );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+
+ QVERIFY( fileExists( host, 21, user, password, createFile ) );
+ }
+}
+
+void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete )
+{
+ if ( !fileToDelete.isNull() ) {
+ // cleanup (i.e. remove the file)
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Remove, ftp->remove( fileToDelete ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+
+ QVERIFY( !fileExists( host, 21, user, password, fileToDelete ) );
+ }
+}
+
+void tst_QFtp::rename()
+{
+ QFETCH( QString, host );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, cdDir );
+ QFETCH( QString, oldfile );
+ QFETCH( QString, newfile );
+ QFETCH( QString, createFile );
+ QFETCH( QString, renamedFile );
+
+ if(oldfile.contains('%'))
+ oldfile = oldfile.arg(uniqueExtension);
+ if(newfile.contains('%'))
+ newfile = newfile.arg(uniqueExtension);
+ if(createFile.contains('%'))
+ createFile = createFile.arg(uniqueExtension);
+ if(renamedFile.contains('%'))
+ renamedFile = renamedFile.arg(uniqueExtension);
+
+ renameInit( host, user, password, createFile );
+
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( !cdDir.isNull() )
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::Rename, ftp->rename( oldfile, newfile ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Rename );
+ QVERIFY( it != resultMap.end() );
+ QTEST( it.value().success, "success" );
+
+ if ( it.value().success ) {
+ QVERIFY( !fileExists( host, 21, user, password, oldfile, cdDir ) );
+ QVERIFY( fileExists( host, 21, user, password, newfile, cdDir ) );
+ QVERIFY( fileExists( host, 21, user, password, renamedFile ) );
+ } else {
+ QVERIFY( !fileExists( host, 21, user, password, newfile, cdDir ) );
+ QVERIFY( !fileExists( host, 21, user, password, renamedFile ) );
+ }
+
+ renameCleanup( host, user, password, renamedFile );
+}
+
+/*
+ The commandSequence() test does not test any particular function. It rather
+ tests a sequence of arbitrary commands specified in the test data.
+*/
+class FtpCommand
+{
+public:
+ FtpCommand() :
+ cmd(QFtp::None)
+ { }
+
+ FtpCommand( QFtp::Command command ) :
+ cmd(command)
+ { }
+
+ FtpCommand( QFtp::Command command, const QStringList &arguments ) :
+ cmd(command), args(arguments)
+ { }
+
+ FtpCommand( const FtpCommand &c )
+ { *this = c; }
+
+ FtpCommand &operator=( const FtpCommand &c )
+ {
+ this->cmd = c.cmd;
+ this->args = c.args;
+ return *this;
+ }
+
+ QFtp::Command cmd;
+ QStringList args;
+};
+QDataStream &operator<<( QDataStream &s, const FtpCommand &command )
+{
+ s << (int)command.cmd;
+ s << command.args;
+ return s;
+}
+QDataStream &operator>>( QDataStream &s, FtpCommand &command )
+{
+ int tmp;
+ s >> tmp;
+ command.cmd = (QFtp::Command)tmp;
+ s >> command.args;
+ return s;
+}
+Q_DECLARE_METATYPE(QList<FtpCommand>)
+
+void tst_QFtp::commandSequence_data()
+{
+ // some "constants"
+ QStringList argConnectToHost01;
+ argConnectToHost01 << QtNetworkSettings::serverName() << "21";
+
+ QStringList argLogin01, argLogin02, argLogin03, argLogin04;
+ argLogin01 << QString() << QString();
+ argLogin02 << "ftp" << QString();
+ argLogin03 << "ftp" << "foo";
+ argLogin04 << QString("ftptest") << "password";
+
+ FtpCommand connectToHost01( QFtp::ConnectToHost, argConnectToHost01 );
+ FtpCommand login01( QFtp::Login, argLogin01 );
+ FtpCommand login02( QFtp::Login, argLogin01 );
+ FtpCommand login03( QFtp::Login, argLogin01 );
+ FtpCommand login04( QFtp::Login, argLogin01 );
+ FtpCommand close01( QFtp::Close );
+
+ QTest::addColumn<QList<FtpCommand> >("cmds");
+ QTest::addColumn<int>("success");
+
+ // success data
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ QTest::newRow( "simple_ok01" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ QTest::newRow( "simple_ok02" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ cmds << close01;
+ QTest::newRow( "simple_ok03" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << close01;
+ QTest::newRow( "simple_ok04" ) << cmds << 1;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ cmds << close01;
+ cmds << connectToHost01;
+ cmds << login02;
+ cmds << close01;
+ QTest::newRow( "connect_twice" ) << cmds << 1;
+ }
+
+ // error data
+ {
+ QList<FtpCommand> cmds;
+ cmds << close01;
+ QTest::newRow( "error01" ) << cmds << 0;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << login01;
+ QTest::newRow( "error02" ) << cmds << 0;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << login01;
+ cmds << close01;
+ QTest::newRow( "error03" ) << cmds << 0;
+ }
+ {
+ QList<FtpCommand> cmds;
+ cmds << connectToHost01;
+ cmds << login01;
+ cmds << close01;
+ cmds << login01;
+ QTest::newRow( "error04" ) << cmds << 0;
+ }
+}
+
+void tst_QFtp::commandSequence()
+{
+ QFETCH( QList<FtpCommand>, cmds );
+
+ ftp = newFtp();
+ QList<FtpCommand>::iterator it;
+ for ( it = cmds.begin(); it != cmds.end(); ++it ) {
+ switch ( (*it).cmd ) {
+ case QFtp::ConnectToHost:
+ {
+ QVERIFY( (*it).args.count() == 2 );
+ uint port;
+ bool portOk;
+ port = (*it).args[1].toUInt( &portOk );
+ QVERIFY( portOk );
+ ids << ftp->connectToHost( (*it).args[0], port );
+ }
+ break;
+ case QFtp::Login:
+ QVERIFY( (*it).args.count() == 2 );
+ ids << ftp->login( (*it).args[0], (*it).args[1] );
+ break;
+ case QFtp::Close:
+ QVERIFY( (*it).args.count() == 0 );
+ ids << ftp->close();
+ break;
+ default:
+ QFAIL( "Error in test: unexpected enum value" );
+ break;
+ }
+ }
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ QTEST( commandSequence_success, "success" );
+}
+
+void tst_QFtp::abort_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QByteArray>("uploadData");
+
+ QTest::newRow( "get_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
+ QTest::newRow( "get_fluke02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
+
+ // Qt/CE and Symbian test environment has to less memory for this test
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ QByteArray bigData( 10*1024*1024, 0 );
+ bigData.fill( 'B' );
+
+ QTest::newRow( "put_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
+#endif
+}
+
+void tst_QFtp::abort()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, file );
+ QFETCH( QByteArray, uploadData );
+
+ QFtp::Command cmd;
+ if ( uploadData.size() == 0 )
+ cmd = QFtp::Get;
+ else
+ cmd = QFtp::Put;
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login() );
+ if ( cmd == QFtp::Get )
+ addCommand( cmd, ftp->get( file ) );
+ else
+ addCommand( cmd, ftp->put( uploadData, file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ for(int time = 0; time <= uploadData.length() / 30000; time += 30) {
+ QTestEventLoop::instance().enterLoop( 30 );
+ if(ftp->currentCommand() == QFtp::None)
+ break;
+ }
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( cmd );
+ QVERIFY( it != resultMap.end() );
+ // ### how to test the abort?
+ if ( it.value().success ) {
+ // The FTP server on fluke is sadly returning a success, even when
+ // the operation was aborted. So we have to use some heuristics.
+ if ( host == QtNetworkSettings::serverName() ) {
+ if ( cmd == QFtp::Get ) {
+ QVERIFY(bytesDone <= bytesTotal);
+ } else {
+ // put commands should always be aborted, since we use really
+ // big data
+ QVERIFY( bytesDone != bytesTotal );
+ }
+ } else {
+ // this could be tested by verifying that no more progress signals are emited
+ QVERIFY(bytesDone <= bytesTotal);
+ }
+ } else {
+ QVERIFY( bytesDone != bytesTotal );
+ }
+
+ if ( cmd == QFtp::Put ) {
+ //////////////////////////////////////
+ // cleanup (i.e. remove the file)
+ init();
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login() );
+ addCommand( QFtp::Remove, ftp->remove( file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == 1 );
+ }
+}
+
+void tst_QFtp::bytesAvailable_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<int>("type");
+ QTest::addColumn<qlonglong>("bytesAvailFinishedGet");
+ QTest::addColumn<qlonglong>("bytesAvailFinished");
+ QTest::addColumn<qlonglong>("bytesAvailDone");
+
+ QTest::newRow( "fluke01" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
+ QTest::newRow( "fluke02" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
+
+ QTest::newRow( "fluke03" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
+ QTest::newRow( "fluke04" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
+}
+
+void tst_QFtp::bytesAvailable()
+{
+ QFETCH( QString, host );
+ QFETCH( QString, file );
+ QFETCH( int, type );
+
+ ftp = newFtp();
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host ) );
+ addCommand( QFtp::Login, ftp->login() );
+ addCommand( QFtp::Get, ftp->get( file ) );
+ if ( type != 0 )
+ addCommand( QFtp::Close, ftp->close() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find( QFtp::Get );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success );
+
+ QFETCH(qlonglong, bytesAvailFinishedGet);
+ QCOMPARE(bytesAvailable_finishedGet, bytesAvailFinishedGet);
+
+ QFETCH(qlonglong, bytesAvailFinished);
+ QCOMPARE(bytesAvailable_finished, bytesAvailFinished);
+
+ QFETCH(qlonglong, bytesAvailDone);
+ QCOMPARE(bytesAvailable_done, bytesAvailDone);
+
+ ftp->readAll();
+ QVERIFY( ftp->bytesAvailable() == 0 );
+ delete ftp;
+}
+
+void tst_QFtp::activeMode()
+{
+ QFile file("tst_QFtp_activeMode_inittab");
+ file.open(QIODevice::ReadWrite);
+ QFtp ftp;
+ ftp.setTransferMode(QFtp::Active);
+ ftp.connectToHost(QtNetworkSettings::serverName(), 21);
+ ftp.login();
+ ftp.list();
+ ftp.get("/qtest/rfc3252.txt", &file);
+ connect(&ftp, SIGNAL(done(bool)), SLOT(activeModeDone(bool)));
+ QTestEventLoop::instance().enterLoop(900);
+ QFile::remove("tst_QFtp_activeMode_inittab");
+ QVERIFY(done_success == 1);
+
+}
+
+void tst_QFtp::activeModeDone(bool error)
+{
+ done_success = error ? -1 : 1;
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QFtp::proxy_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<uint>("port");
+ QTest::addColumn<QString>("user");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<QString>("dir");
+ QTest::addColumn<int>("success");
+ QTest::addColumn<QStringList>("entryNames"); // ### we should rather use a QList<QUrlInfo> here
+
+ QStringList flukeRoot;
+ flukeRoot << "qtest";
+ QStringList flukeQtest;
+ flukeQtest << "bigfile";
+ flukeQtest << "nonASCII";
+ flukeQtest << "rfc3252";
+ flukeQtest << "rfc3252.txt";
+ flukeQtest << "upload";
+
+ QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+
+ QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+}
+
+void tst_QFtp::proxy()
+{
+ QFETCH( QString, host );
+ QFETCH( uint, port );
+ QFETCH( QString, user );
+ QFETCH( QString, password );
+ QFETCH( QString, dir );
+
+ ftp = newFtp();
+ addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::serverName(), 2121 ) );
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ addCommand( QFtp::Cd, ftp->cd( dir ) );
+ addCommand( QFtp::List, ftp->list() );
+
+ QTestEventLoop::instance().enterLoop( 30 );
+
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() ) {
+ QFAIL( "Network operation timed out" );
+ }
+
+ ResMapIt it = resultMap.find( QFtp::Cd );
+ QVERIFY( it != resultMap.end() );
+ QFETCH( int, success );
+ QCOMPARE( it.value().success, success );
+ QFETCH( QStringList, entryNames );
+ QCOMPARE( listInfo_i.count(), entryNames.count() );
+ for ( uint i=0; i < (uint) entryNames.count(); i++ ) {
+ QCOMPARE( listInfo_i[i].name(), entryNames[i] );
+ }
+}
+
+
+void tst_QFtp::binaryAscii()
+{
+ QString file = "asciifile%1.txt";
+
+ if(file.contains('%'))
+ file = file.arg(uniqueExtension);
+
+ QByteArray putData = "a line of text\r\n";
+
+ init();
+ ftp = newFtp();
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::Login, ftp->login("ftptest", "password"));
+ addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
+ addCommand(QFtp::Put, ftp->put(putData, file, QFtp::Ascii));
+ addCommand(QFtp::Close, ftp->close());
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it = resultMap.find(QFtp::Put);
+ QVERIFY(it != resultMap.end());
+ QVERIFY(it.value().success);
+
+ QByteArray getData;
+ QBuffer getBuf(&getData);
+ getBuf.open(QBuffer::WriteOnly);
+
+ init();
+ ftp = newFtp();
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::Login, ftp->login("ftptest", "password"));
+ addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
+ addCommand(QFtp::Get, ftp->get(file, &getBuf, QFtp::Binary));
+ addCommand(QFtp::Close, ftp->close());
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ ResMapIt it2 = resultMap.find(QFtp::Get);
+ QVERIFY(it2 != resultMap.end());
+ QVERIFY(it2.value().success);
+ // most modern ftp servers leave the file as it is by default
+ // (and do not remove the windows line ending), the -1 below could be
+ // deleted in the future
+ QVERIFY(getData.size() == putData.size()-1);
+ //////////////////////////////////////////////////////////////////
+ // cleanup (i.e. remove the file) -- this also tests the remove command
+ init();
+ ftp = newFtp();
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::Login, ftp->login("ftptest", "password"));
+ addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
+ addCommand(QFtp::Remove, ftp->remove(file));
+ addCommand(QFtp::Close, ftp->close());
+
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() )
+ QFAIL( "Network operation timed out" );
+
+ it = resultMap.find( QFtp::Remove );
+ QVERIFY( it != resultMap.end() );
+ QCOMPARE( it.value().success, 1 );
+
+ QVERIFY(!fileExists(QtNetworkSettings::serverName(), 21, "ftptest", "password", file));
+}
+
+
+// test QFtp::currentId() and QFtp::currentCommand()
+#define CURRENTCOMMAND_TEST \
+{ \
+ ResMapIt it; \
+ for ( it = resultMap.begin(); it != resultMap.end(); ++it ) { \
+ if ( it.value().id == ftp->currentId() ) { \
+ QVERIFY( it.key() == ftp->currentCommand() ); \
+ } \
+} \
+}
+
+void tst_QFtp::commandStarted( int id )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:commandStarted( %d )", ftp->currentId(), id );
+#endif
+ // make sure that the commandStarted and commandFinished are nested correctly
+ QVERIFY( current_id == 0 );
+ current_id = id;
+
+ QVERIFY( !ids.isEmpty() );
+ QVERIFY( ids.first() == id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+
+ QVERIFY( ftp->currentId() == id );
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ QVERIFY( ftp->error() == QFtp::NoError );
+}
+
+void tst_QFtp::commandFinished( int id, bool error )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:commandFinished( %d, %d ) -- errorString: '%s'",
+ ftp->currentId(), id, (int)error, ftp->errorString().toLatin1().constData() );
+#endif
+ if ( ftp->currentCommand() == QFtp::Get ) {
+ bytesAvailable_finishedGet = ftp->bytesAvailable();
+ }
+ bytesAvailable_finished = ftp->bytesAvailable();
+
+ // make sure that the commandStarted and commandFinished are nested correctly
+ QVERIFY( current_id == id );
+ current_id = 0;
+
+ QVERIFY( !ids.isEmpty() );
+ QVERIFY( ids.first() == id );
+ if ( !error && ids.count() > 1) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ if ( error ) {
+ QVERIFY( ftp->error() != QFtp::NoError );
+ ids.clear();
+ } else {
+ QVERIFY( ftp->error() == QFtp::NoError );
+ ids.pop_front();
+ }
+
+ QVERIFY( ftp->currentId() == id );
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( QTest::currentTestFunction() != QLatin1String("commandSequence") ) {
+ ResMapIt it = resultMap.find( ftp->currentCommand() );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( it.value().success == -1 );
+ if ( error )
+ it.value().success = 0;
+ else
+ it.value().success = 1;
+ }
+}
+
+void tst_QFtp::done( bool error )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d:done( %d )", ftp->currentId(), (int)error );
+#endif
+ bytesAvailable_done = ftp->bytesAvailable();
+
+ QVERIFY( ftp->currentId() == 0 );
+ QVERIFY( current_id == 0 );
+ QVERIFY( ids.isEmpty() );
+ QVERIFY( cur_state == ftp->state() );
+ QVERIFY( !ftp->hasPendingCommands() );
+
+ if ( QTest::currentTestFunction() == QLatin1String("commandSequence") ) {
+ QVERIFY( commandSequence_success == -1 );
+ if ( error )
+ commandSequence_success = 0;
+ else
+ commandSequence_success = 1;
+ }
+ QVERIFY( done_success == -1 );
+ if ( error ) {
+ QVERIFY( ftp->error() != QFtp::NoError );
+ done_success = 0;
+ } else {
+ QVERIFY( ftp->error() == QFtp::NoError );
+ done_success = 1;
+ }
+ QTestEventLoop::instance().exitLoop();
+}
+
+void tst_QFtp::stateChanged( int state )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: stateChanged( %d )", ftp->currentId(), state );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ CURRENTCOMMAND_TEST;
+
+ QVERIFY( state != cur_state );
+ QCOMPARE( state, (int)ftp->state() );
+ if ( state != QFtp::Unconnected ) {
+ // make sure that the states are always emitted in the right order (for
+ // this, we assume an ordering on the enum values, which they have at
+ // the moment)
+ QVERIFY( cur_state < state );
+
+ // make sure that state changes are only emitted in response to certain
+ // commands
+ switch ( state ) {
+ case QFtp::HostLookup:
+ case QFtp::Connecting:
+ case QFtp::Connected:
+ QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::ConnectToHost );
+ break;
+ case QFtp::LoggedIn:
+ QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::Login );
+ break;
+ case QFtp::Closing:
+ QCOMPARE( (int)ftp->currentCommand(), (int)QFtp::Close );
+ break;
+ default:
+ QWARN( QString("Unexpected state '%1'").arg(state).toLatin1().constData() );
+ break;
+ }
+ }
+ cur_state = state;
+
+ if ( QTest::currentTestFunction() == QLatin1String("connectToHost") ) {
+ switch ( state ) {
+ case QFtp::HostLookup:
+ case QFtp::Connecting:
+ case QFtp::LoggedIn:
+ case QFtp::Closing:
+ // ignore
+ break;
+ case QFtp::Connected:
+ case QFtp::Unconnected:
+ QVERIFY( connectToHost_state == -1 );
+ connectToHost_state = state;
+ break;
+ default:
+ QWARN( QString("Unknown state '%1'").arg(state).toLatin1().constData() );
+ break;
+ }
+ } else if ( QTest::currentTestFunction() == QLatin1String("close") ) {
+ ResMapIt it = resultMap.find( QFtp::Close );
+ if ( it!=resultMap.end() && ftp->currentId()==it.value().id ) {
+ if ( state == QFtp::Closing ) {
+ QVERIFY( close_state == -1 );
+ close_state = state;
+ } else if ( state == QFtp::Unconnected ) {
+ QVERIFY( close_state == QFtp::Closing );
+ close_state = state;
+ }
+ }
+ } else if ( QTest::currentTestFunction() == QLatin1String("login") ) {
+ ResMapIt it = resultMap.find( QFtp::Login );
+ if ( it!=resultMap.end() && ftp->currentId()==it.value().id ) {
+ if ( state == QFtp::LoggedIn ) {
+ QVERIFY( login_state == -1 );
+ login_state = state;
+ }
+ }
+ }
+}
+
+void tst_QFtp::listInfo( const QUrlInfo &i )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: listInfo( %s )", ftp->currentId(), i.name().toLatin1().constData() );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( QTest::currentTestFunction()==QLatin1String("list") || QTest::currentTestFunction()==QLatin1String("cd") || QTest::currentTestFunction()==QLatin1String("proxy") || inFileDirExistsFunction ) {
+ ResMapIt it = resultMap.find( QFtp::List );
+ QVERIFY( it != resultMap.end() );
+ QVERIFY( ftp->currentId() == it.value().id );
+ listInfo_i << i;
+ }
+}
+
+void tst_QFtp::readyRead()
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: readyRead(), bytesAvailable == %lu", ftp->currentId(), ftp->bytesAvailable() );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( QTest::currentTestFunction() != QLatin1String("bytesAvailable") ) {
+ int oldSize = newData_ba.size();
+ qlonglong bytesAvail = ftp->bytesAvailable();
+ QByteArray ba = ftp->readAll();
+ QVERIFY( ba.size() == (int) bytesAvail );
+ newData_ba.resize( oldSize + ba.size() );
+ memcpy( newData_ba.data()+oldSize, ba.data(), ba.size() );
+
+ if ( bytesTotal != -1 ) {
+ QVERIFY( (int)newData_ba.size() <= bytesTotal );
+ }
+ QVERIFY( (int)newData_ba.size() == bytesDone );
+ }
+}
+
+void tst_QFtp::dataTransferProgress( qint64 done, qint64 total )
+{
+#if defined( DUMP_SIGNALS )
+ qDebug( "%d: dataTransferProgress( %lli, %lli )", ftp->currentId(), done, total );
+#endif
+ QCOMPARE( ftp->currentId(), current_id );
+ if ( ids.count() > 1 ) {
+ QVERIFY( ftp->hasPendingCommands() );
+ } else {
+ QVERIFY( !ftp->hasPendingCommands() );
+ }
+ QVERIFY( cur_state == ftp->state() );
+ CURRENTCOMMAND_TEST;
+
+ if ( bytesTotal == bytesTotal_init ) {
+ bytesTotal = total;
+ } else {
+ QVERIFY( bytesTotal == total );
+ }
+
+ QVERIFY( bytesTotal != bytesTotal_init );
+ QVERIFY( bytesDone <= done );
+ bytesDone = done;
+ if ( bytesTotal != -1 ) {
+ QVERIFY( bytesDone <= bytesTotal );
+ }
+
+ if ( QTest::currentTestFunction() == QLatin1String("abort") ) {
+ // ### it would be nice if we could specify in our testdata when to do
+ // the abort
+ if ( done >= total/100000 ) {
+ if ( ids.count() != 1 ) {
+ // do abort only once
+ int tmpId = ids.first();
+ ids.clear();
+ ids << tmpId;
+ ftp->abort();
+ }
+ }
+ }
+}
+
+
+QFtp *tst_QFtp::newFtp()
+{
+ QFtp *nFtp = new QFtp( this );
+ connect( nFtp, SIGNAL(commandStarted(int)),
+ SLOT(commandStarted(int)) );
+ connect( nFtp, SIGNAL(commandFinished(int,bool)),
+ SLOT(commandFinished(int,bool)) );
+ connect( nFtp, SIGNAL(done(bool)),
+ SLOT(done(bool)) );
+ connect( nFtp, SIGNAL(stateChanged(int)),
+ SLOT(stateChanged(int)) );
+ connect( nFtp, SIGNAL(listInfo(const QUrlInfo&)),
+ SLOT(listInfo(const QUrlInfo&)) );
+ connect( nFtp, SIGNAL(readyRead()),
+ SLOT(readyRead()) );
+ connect( nFtp, SIGNAL(dataTransferProgress(qint64, qint64)),
+ SLOT(dataTransferProgress(qint64, qint64)) );
+
+ return nFtp;
+}
+
+void tst_QFtp::addCommand( QFtp::Command cmd, int id )
+{
+ ids << id;
+ CommandResult res;
+ res.id = id;
+ res.success = -1;
+ resultMap[ cmd ] = res;
+}
+
+bool tst_QFtp::fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir )
+{
+ init();
+ ftp = newFtp();
+ // ### make these tests work
+ if (ftp->currentId() != 0) {
+ qWarning("ftp->currentId() != 0");
+ return FALSE;
+ }
+
+ if (ftp->state() != QFtp::Unconnected) {
+ qWarning("ftp->state() != QFtp::Unconnected");
+ return FALSE;
+ }
+
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( !cdDir.isNull() )
+ addCommand( QFtp::Cd, ftp->cd( cdDir ) );
+ addCommand( QFtp::List, ftp->list( file ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ inFileDirExistsFunction = TRUE;
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() ) {
+ // ### make this test work
+ qWarning("Network operation timed out");
+ return FALSE;
+ }
+ inFileDirExistsFunction = FALSE;
+
+ ResMapIt it = resultMap.find( QFtp::ConnectToHost );
+ // ### make these tests work
+ if (it == resultMap.end()) {
+ qWarning("it != resultMap.end()");
+ return FALSE;
+ }
+
+ if (it.value().success == -1) {
+ qWarning("it.value().success != -1");
+ return FALSE;
+ }
+
+ if ( it.value().success == 1 ) {
+ for ( uint i=0; i < (uint) listInfo_i.count(); i++ ) {
+ if ( QFileInfo(listInfo_i[i].name()).fileName() == QFileInfo(file).fileName() )
+ return TRUE;
+ }
+ }
+
+ //this is not a good warning considering sometime this function is used to test that a file does not exist
+ //qWarning("file doesn't exist");
+ return FALSE;
+}
+
+bool tst_QFtp::dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate )
+{
+ init();
+ ftp = newFtp();
+ // ### make these tests work
+ // QCOMPARE( ftp->currentId(), 0 );
+ // QCOMPARE( (int)ftp->state(), (int)QFtp::Unconnected );
+
+ addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
+ addCommand( QFtp::Login, ftp->login( user, password ) );
+ if ( dirToCreate.startsWith( "/" ) )
+ addCommand( QFtp::Cd, ftp->cd( dirToCreate ) );
+ else
+ addCommand( QFtp::Cd, ftp->cd( cdDir + "/" + dirToCreate ) );
+ addCommand( QFtp::Close, ftp->close() );
+
+ inFileDirExistsFunction = TRUE;
+ QTestEventLoop::instance().enterLoop( 30 );
+ delete ftp;
+ if ( QTestEventLoop::instance().timeout() ) {
+ // ### make this test work
+ // QFAIL( "Network operation timed out" );
+ return FALSE;
+ }
+ inFileDirExistsFunction = FALSE;
+
+ ResMapIt it = resultMap.find( QFtp::Cd );
+ // ### make these tests work
+ // QVERIFY( it != resultMap.end() );
+ // QVERIFY( it.value().success != -1 );
+ return it.value().success == 1;
+}
+
+void tst_QFtp::doneSignal()
+{
+ QFtp ftp;
+ QSignalSpy spy(&ftp, SIGNAL(done(bool)));
+
+ ftp.connectToHost(QtNetworkSettings::serverName());
+ ftp.login("anonymous");
+ ftp.list();
+ ftp.close();
+
+ done_success = 0;
+ while ( ftp.hasPendingCommands() )
+ QCoreApplication::instance()->processEvents();
+ QTest::qWait(200);
+
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.first().first().toBool(), false);
+}
+
+void tst_QFtp::queueMoreCommandsInDoneSlot()
+{
+ QSKIP("Task 127050 && 113966", SkipSingle);
+
+ QFtp ftp;
+ QSignalSpy doneSpy(&ftp, SIGNAL(done(bool)));
+ QSignalSpy commandFinishedSpy(&ftp, SIGNAL(commandFinished(int, bool)));
+
+ this->ftp = &ftp;
+ connect(&ftp, SIGNAL(done(bool)), this, SLOT(cdUpSlot(bool)));
+
+ ftp.connectToHost("ftp.qt.nokia.com");
+ ftp.login();
+ ftp.cd("qt");
+ ftp.rmdir("qtest-removedir-noexist");
+
+ while ( ftp.hasPendingCommands() || ftp.currentCommand() != QFtp::None ) {
+ QCoreApplication::instance()->processEvents(QEventLoop::AllEvents
+ | QEventLoop::WaitForMoreEvents);
+ }
+
+ QCOMPARE(doneSpy.count(), 2);
+ QCOMPARE(doneSpy.first().first().toBool(), true);
+ QCOMPARE(doneSpy.last().first().toBool(), false);
+
+ QCOMPARE(commandFinishedSpy.count(), 6);
+ int firstId = commandFinishedSpy.at(0).at(0).toInt();
+ QCOMPARE(commandFinishedSpy.at(0).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(1).at(0).toInt(), firstId + 1);
+ QCOMPARE(commandFinishedSpy.at(1).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(2).at(0).toInt(), firstId + 2);
+ QCOMPARE(commandFinishedSpy.at(2).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(3).at(0).toInt(), firstId + 3);
+ QCOMPARE(commandFinishedSpy.at(3).at(1).toBool(), true);
+ QCOMPARE(commandFinishedSpy.at(4).at(0).toInt(), firstId + 4);
+ QCOMPARE(commandFinishedSpy.at(4).at(1).toBool(), false);
+ QCOMPARE(commandFinishedSpy.at(5).at(0).toInt(), firstId + 5);
+ QCOMPARE(commandFinishedSpy.at(5).at(1).toBool(), false);
+
+ this->ftp = 0;
+}
+
+void tst_QFtp::cdUpSlot(bool error)
+{
+ if (error) {
+ ftp->cd("..");
+ ftp->cd("qt");
+ }
+}
+
+QTEST_MAIN(tst_QFtp)
+
+#include "tst_qftp.moc"