tests/auto/q3urloperator/tst_q3urloperator.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <q3urloperator.h>
       
    46 #include <qtimer.h>
       
    47 #include <qapplication.h>
       
    48 #include <qfile.h>
       
    49 #include <qfileinfo.h>
       
    50 #include <qurlinfo.h>
       
    51 #include <q3network.h>
       
    52 #include <q3networkprotocol.h>
       
    53 #include <qtimer.h>
       
    54 #include <q3ptrlist.h>
       
    55 #include <q3valuelist.h>
       
    56 #include <qlist.h>
       
    57 
       
    58 #include "../network-settings.h"
       
    59 
       
    60 //TESTED_CLASS=
       
    61 //TESTED_FILES=
       
    62 
       
    63 QT_FORWARD_DECLARE_CLASS(Q3NetworkOperation)
       
    64 
       
    65 class tst_Q3UrlOperator : public QObject
       
    66 {
       
    67     Q_OBJECT
       
    68 
       
    69 public:
       
    70     tst_Q3UrlOperator();
       
    71     virtual ~tst_Q3UrlOperator();
       
    72 
       
    73 
       
    74 
       
    75 public slots:
       
    76     void initTestCase();
       
    77     void cleanupTestCase();
       
    78     void init();
       
    79     void cleanup();
       
    80 private slots:
       
    81     void copy_data();
       
    82     void copy();
       
    83     void put_data();
       
    84     void put();
       
    85     void rename_data();
       
    86     void rename();
       
    87     void stop_data();
       
    88     void stop();
       
    89     void listChildren_data();
       
    90     void listChildren();
       
    91 
       
    92 protected slots:
       
    93     void slotFinished_init( Q3NetworkOperation* );
       
    94     void slotFinished_cleanup( Q3NetworkOperation* );
       
    95 
       
    96     void slotFinished_copy( Q3NetworkOperation* );
       
    97 
       
    98     void slotFinished_put( Q3NetworkOperation* );
       
    99     void slotData_put( const QByteArray&, Q3NetworkOperation* );
       
   100 
       
   101     void slotFinished_rename( Q3NetworkOperation* );
       
   102     void slotItemChanged_rename( Q3NetworkOperation* );
       
   103 
       
   104     void slotFinished_stop( Q3NetworkOperation* );
       
   105     void slotDataTransferProgress_stop( int, int, Q3NetworkOperation* );
       
   106 
       
   107     void slotFinished_listChildren( Q3NetworkOperation* );
       
   108     void slotNewChildren_listChildren( const Q3ValueList<QUrlInfo> &, Q3NetworkOperation * );
       
   109 
       
   110     void stopOperation();
       
   111 
       
   112 private:
       
   113     Q3UrlOperator *urlOp;
       
   114     QString ftpQtestUpload;
       
   115     bool doStop;
       
   116     bool finished;
       
   117 
       
   118     Q3PtrList<Q3NetworkOperation> pendingOperations;
       
   119     Q3NetworkProtocol::State finishedState;
       
   120     int	finishedErrorCode;
       
   121     QString finishedProtocolDetail;
       
   122     Q3ValueList<QUrlInfo> listChildrenInfo;
       
   123     QByteArray baData;
       
   124     uint timeout_count;
       
   125 };
       
   126 
       
   127 //#define DUMP_SIGNALS
       
   128 
       
   129 tst_Q3UrlOperator::tst_Q3UrlOperator()
       
   130 {
       
   131     q3InitNetworkProtocols();
       
   132     timeout_count = 0;
       
   133 
       
   134 }
       
   135 
       
   136 tst_Q3UrlOperator::~tst_Q3UrlOperator()
       
   137 {
       
   138 }
       
   139 
       
   140 void tst_Q3UrlOperator::initTestCase()
       
   141 {
       
   142     // create files for checking permissions
       
   143     QFile textFile("listData/readOnly");
       
   144     textFile.open(QIODevice::WriteOnly);
       
   145     textFile.close();
       
   146     textFile.setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther);
       
   147     QFile exe("listData/executable.exe");
       
   148     exe.open(QIODevice::WriteOnly);
       
   149     exe.close();
       
   150     exe.setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther |
       
   151     		QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
       
   152 
       
   153     // prepare: make sure that there is a unique directory for FTP upload
       
   154     // testing (to avoid parallel executed tests interfere with each other)
       
   155     ftpQtestUpload = QString("ftp://%1/").arg(QtNetworkSettings::serverLocalName());
       
   156     QString dir = QString( "qtest/upload/%1" ).arg( (ulong)this );
       
   157 
       
   158     Q3UrlOperator opMkdir( ftpQtestUpload );
       
   159 
       
   160     connect( &opMkdir, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_init(Q3NetworkOperation*)) );
       
   161     if ( opMkdir.mkdir( dir ) != 0 ) {
       
   162         QTestEventLoop::instance().enterLoop( 30 );
       
   163 	if ( QTestEventLoop::instance().timeout() )
       
   164 	    qWarning( "Prepare: Network operation timed out for create directory" );
       
   165     }
       
   166     ftpQtestUpload += dir;
       
   167 }
       
   168 
       
   169 void tst_Q3UrlOperator::slotFinished_init( Q3NetworkOperation *op )
       
   170 {
       
   171     if ( op->state() == Q3NetworkProtocol::StFailed )
       
   172 	qWarning( QString( "Prepare: Can't create directory: network operation failed ('%1'). " ).arg(op->protocolDetail()) );
       
   173     QTestEventLoop::instance().exitLoop();
       
   174 }
       
   175 
       
   176 void tst_Q3UrlOperator::cleanupTestCase()
       
   177 {
       
   178 	// remove the files created before
       
   179     QFile textFile("listData/readOnly");
       
   180     textFile.setPermissions(textFile.permissions() | QFile::WriteOwner);
       
   181     if (! textFile.remove())
       
   182     	qWarning() << "could not remove file:" << textFile.error();
       
   183     QFile exe("listData/executable.exe");
       
   184     exe.setPermissions(textFile.permissions() | QFile::WriteOwner);
       
   185     if (! exe.remove())
       
   186     	qWarning() << "could not remove file:" << exe.error();
       
   187 
       
   188     // cleanup: delete the unique directory for FTP upload testing
       
   189     QStringList tmp = QStringList::split( '/', ftpQtestUpload, TRUE );
       
   190     QString dir = tmp.last();
       
   191     tmp.pop_back();
       
   192     QString url = tmp.join( "/" );
       
   193 
       
   194     Q3UrlOperator opRemove( url );
       
   195     connect( &opRemove, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_cleanup(Q3NetworkOperation*)) );
       
   196     if ( opRemove.remove( dir ) != 0 ) {
       
   197 	QTestEventLoop::instance().enterLoop( 30 );
       
   198 	if ( QTestEventLoop::instance().timeout() )
       
   199 	    qWarning( "Cleanup: Network operation timed out for removing directory" );
       
   200     }
       
   201 }
       
   202 
       
   203 void tst_Q3UrlOperator::slotFinished_cleanup( Q3NetworkOperation *op )
       
   204 {
       
   205     if ( op->state() == Q3NetworkProtocol::StFailed )
       
   206 	qWarning( QString( "Cleanup: Can't remove directory: network operation failed ('%1'). " ).arg(op->protocolDetail()) );
       
   207     QTestEventLoop::instance().exitLoop();
       
   208 }
       
   209 
       
   210 void tst_Q3UrlOperator::init()
       
   211 {
       
   212     doStop = FALSE;
       
   213     finished = FALSE;
       
   214     pendingOperations.clear();
       
   215 }
       
   216 
       
   217 void tst_Q3UrlOperator::cleanup()
       
   218 {
       
   219 }
       
   220 
       
   221 void tst_Q3UrlOperator::copy_data()
       
   222 {
       
   223     const QString ftpQtest( QString("ftp://%1/qtest").arg(QtNetworkSettings::serverLocalName()) );
       
   224     const QString httpQtest( QString("http://%1/qtest").arg(QtNetworkSettings::serverLocalName()) );
       
   225 
       
   226     // argument for the constructor
       
   227     QTest::addColumn<QString>("url");
       
   228     // arguments for the copy()
       
   229     QTest::addColumn<QString>("from");
       
   230     QTest::addColumn<QString>("to");
       
   231     QTest::addColumn<bool>("move");
       
   232     QTest::addColumn<bool>("toPath");
       
   233 
       
   234     // FTP data
       
   235     // QTest::newRow( "ftp00" ) << QString() << QString("%1/rfc3252.txt").arg(ftpQtest)	<< QString(".")		    << (bool)FALSE << (bool)TRUE;
       
   236     QTest::newRow( "ftp01" ) << QString() << QString("%1/rfc3252").arg(ftpQtest)	<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   237 
       
   238     QTest::newRow( "ftp02" ) << QString("%1/").arg(ftpQtest) << QString("rfc3252.txt") << QString(".")		<< (bool)FALSE << (bool)TRUE;
       
   239     QTest::newRow( "ftp03" ) << QString("%1/").arg(ftpQtest) << QString("rfc3252") << QString("rfc3252.txt")	<< (bool)FALSE << (bool)FALSE;
       
   240 
       
   241     QTest::newRow( "ftp04" ) << QString("%1").arg(ftpQtest) << QString("rfc3252.txt")  << QString(".")		<< (bool)FALSE << (bool)TRUE;
       
   242     QTest::newRow( "ftp05" ) << QString("%1").arg(ftpQtest) << QString("rfc3252")	    << QString("rfc3252.txt")	<< (bool)FALSE << (bool)FALSE;
       
   243 
       
   244     // the ftp.faqs.org host is down that often, that it does not make sense to
       
   245     // use it for automated tests
       
   246     // QTest::newRow( "ftp06" ) << QString() << QString("ftp://ftp.faqs.org/rfc/rfc3252.txt") << QString(".") << (bool)FALSE << (bool)TRUE;
       
   247 
       
   248     // HTTP data
       
   249     QTest::newRow( "http00" ) << QString() << QString("%1/rfc3252.txt").arg(httpQtest)    << QString(".")		<< (bool)FALSE << (bool)TRUE;
       
   250     QTest::newRow( "http01" ) << QString() << QString("%1/rfc3252").arg(httpQtest)	    << QString("rfc3252.txt")	<< (bool)FALSE << (bool)FALSE;
       
   251     QTest::newRow( "http02" ) << QString() << QString("%1/").arg(httpQtest)		    << QString("rfc3252.txt")	<< (bool)FALSE << (bool)FALSE;
       
   252 
       
   253     QTest::newRow( "http03" ) << QString("%1/").arg(httpQtest) << QString("rfc3252.txt")	<< QString(".")		    << (bool)FALSE << (bool)TRUE;
       
   254     QTest::newRow( "http04" ) << QString("%1/").arg(httpQtest) << QString("rfc3252")	<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   255     QTest::newRow( "http05" ) << QString("%1/").arg(httpQtest) << QString("")		<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   256     QTest::newRow( "http06" ) << QString("%1/").arg(httpQtest) << QString()	<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   257 
       
   258     QTest::newRow( "http07" ) << QString("%1").arg(httpQtest) << QString("rfc3252.txt")	<< QString(".")		    << (bool)FALSE << (bool)TRUE;
       
   259     QTest::newRow( "http08" ) << QString("%1").arg(httpQtest) << QString("rfc3252")	<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   260     QTest::newRow( "http09" ) << QString("%1").arg(httpQtest) << QString("")		<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   261     QTest::newRow( "http10" ) << QString("%1").arg(httpQtest) << QString()	<< QString("rfc3252.txt")    << (bool)FALSE << (bool)FALSE;
       
   262 
       
   263     // Unstable host:
       
   264     // QTest::newRow( "http11" ) << QString() << QString("http://www.ietf.org/rfc/rfc3252.txt") << QString(".") << (bool)FALSE << (bool)TRUE;
       
   265 }
       
   266 
       
   267 void tst_Q3UrlOperator::copy()
       
   268 {
       
   269     if (timeout_count >= 3) {
       
   270         QFAIL( "Too many timeout's. Aborting test prematurely." );
       
   271     }
       
   272 
       
   273     QFETCH( QString, url );
       
   274     QFETCH( QString, from );
       
   275     QFETCH( QString, to );
       
   276     QFETCH( bool, move );
       
   277     QFETCH( bool, toPath );
       
   278 
       
   279     if ( url.isNull() ) {
       
   280 	urlOp = new Q3UrlOperator();
       
   281     } else {
       
   282 	urlOp = new Q3UrlOperator( url );
       
   283     }
       
   284     pendingOperations = urlOp->copy( from, to, move, toPath );
       
   285 
       
   286     connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_copy(Q3NetworkOperation*)) );
       
   287 
       
   288     QTestEventLoop::instance().enterLoop( 60 );
       
   289     delete urlOp;
       
   290     if ( QTestEventLoop::instance().timeout() )
       
   291 	QFAIL( "Network operation timed out" );
       
   292 
       
   293     // test the results of the operation
       
   294     if ( finished ) {
       
   295 	QVERIFY( finishedState==Q3NetworkProtocol::StDone || finishedState==Q3NetworkProtocol::StFailed );
       
   296 	if ( finishedState == Q3NetworkProtocol::StDone ) {
       
   297 	    QFile file( "rfc3252.txt" );
       
   298 	    if ( !file.open( QIODevice::ReadOnly ) )
       
   299 		QFAIL( "Could not open downloaded file" );
       
   300 
       
   301 	    // ### this should move in the tesdata
       
   302 	    QFile fileRes( "copy.res/rfc3252.txt" );
       
   303 	    if ( !fileRes.open( QIODevice::ReadOnly ) )
       
   304 		QFAIL( "Could not open result file" );
       
   305 
       
   306         QCOMPARE(file.readAll(), fileRes.readAll());
       
   307 
       
   308 	    // delete the downloaded file
       
   309 	    if ( !file.remove() )
       
   310 		QFAIL( QString("Cleanup failed: could not remove the downloaded file '%1'").arg(file.name()) );
       
   311             timeout_count = 0;
       
   312 	} else {
       
   313 	    QFAIL( QString( "Network operation failed ('%1'). "
       
   314 			"This could be due to a temporary network failure. "
       
   315 			"If this test continues to fail, take a closer look").arg(finishedProtocolDetail) );
       
   316             timeout_count++;
       
   317 	}
       
   318     }
       
   319 }
       
   320 
       
   321 void tst_Q3UrlOperator::slotFinished_copy( Q3NetworkOperation *op )
       
   322 {
       
   323 #if defined( DUMP_SIGNALS )
       
   324     qDebug( "finished( %p )", op );
       
   325 #endif
       
   326     QVERIFY( op != 0 );
       
   327     pendingOperations.remove( op );
       
   328     // We are finished if either of this happens:
       
   329     // - both, the get and the put of the copy are finished
       
   330     // - we are in an error case (for the case that the get fails, no
       
   331     //   finished() signal for the put is emitted since it is never executed)
       
   332     if ( pendingOperations.isEmpty() || op->state()==Q3NetworkProtocol::StFailed ) {
       
   333 	finished = TRUE;
       
   334 	finishedState = op->state();
       
   335 	finishedErrorCode = op->errorCode();
       
   336 	finishedProtocolDetail = op->protocolDetail();
       
   337 
       
   338 	QTestEventLoop::instance().exitLoop();
       
   339     }
       
   340 }
       
   341 
       
   342 void tst_Q3UrlOperator::put_data()
       
   343 {
       
   344     const QString httpQtest( QString("http://%1/qtest/cgi-bin").arg(QtNetworkSettings::serverLocalName()) );
       
   345     const QString httpQtestGet( QString("http://%1/qtest/cgi-bin/retrieve_testfile.cgi").arg(QtNetworkSettings::serverLocalName()) );
       
   346 
       
   347     QByteArray putData_1( 5 );
       
   348     putData_1[0] = 'a';
       
   349     putData_1[1] = 'b';
       
   350     putData_1[2] = '\n';
       
   351     putData_1[3] = 'c';
       
   352     putData_1[4] = 'd';
       
   353 
       
   354     QTest::addColumn<QString>("url");
       
   355     QTest::addColumn<QString>("to");
       
   356     QTest::addColumn<QByteArray>("putData");
       
   357     QTest::addColumn<QString>("getUrl");
       
   358     QTest::addColumn<QString>("rmUrl");
       
   359     QTest::addColumn<QString>("rmFile");
       
   360 
       
   361     // FTP data
       
   362     QTest::newRow( "ftp00" )
       
   363 	<< ftpQtestUpload << "put_ftp00" << putData_1
       
   364 	<< QString("%1/put_ftp00").arg(ftpQtestUpload)
       
   365 	<< ftpQtestUpload << "put_ftp00";
       
   366     QTest::newRow( "ftp01" )
       
   367 	<< QString() << QString("%1/put_ftp01").arg(ftpQtestUpload) << putData_1
       
   368 	<< QString("%1/put_ftp01").arg(ftpQtestUpload)
       
   369 	<< ftpQtestUpload << "put_ftp01";
       
   370 
       
   371     QTest::newRow( "ftp02" )
       
   372 	<< ftpQtestUpload << "put_ftp02" << QByteArray(0)
       
   373 	<< QString("%1/put_ftp02").arg(ftpQtestUpload)
       
   374 	<< ftpQtestUpload << "put_ftp02";
       
   375     QTest::newRow( "ftp03" )
       
   376 	<< QString() << QString("%1/put_ftp03").arg(ftpQtestUpload) << QByteArray(0)
       
   377 	<< QString("%1/put_ftp03").arg(ftpQtestUpload)
       
   378 	<< ftpQtestUpload << "put_ftp03";
       
   379     // HTTP data
       
   380     QTest::newRow( "http00" )
       
   381 	<< httpQtest << "store_testfile.cgi" << putData_1
       
   382 	<< httpQtestGet
       
   383 	<< httpQtest << QString();
       
   384     QTest::newRow( "http01" )
       
   385 	<< QString() << QString("%1/store_testfile.cgi").arg(httpQtest) << putData_1
       
   386 	<< httpQtestGet
       
   387 	<< httpQtest << QString();
       
   388     QTest::newRow( "http02" )
       
   389 	<< httpQtest     << "store_testfile.cgi" << QByteArray(0)
       
   390 	<< httpQtestGet
       
   391 	<< httpQtest << QString();
       
   392     QTest::newRow( "http03" ) << QString() << QString("%1/store_testfile.cgi").arg(httpQtest) << QByteArray(0)
       
   393 	<< httpQtestGet
       
   394 	<< httpQtest << QString();
       
   395 }
       
   396 
       
   397 void tst_Q3UrlOperator::put()
       
   398 {
       
   399     {
       
   400 	// do the put
       
   401 	QFETCH( QString, url );
       
   402 	QFETCH( QString, to );
       
   403 	QFETCH( QByteArray, putData );
       
   404 
       
   405 	if ( url.isNull() ) {
       
   406 	    urlOp = new Q3UrlOperator();
       
   407 	} else {
       
   408 	    urlOp = new Q3UrlOperator( url );
       
   409 	}
       
   410 
       
   411 	pendingOperations.append( urlOp->put( putData, to) );
       
   412 
       
   413 	connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_put(Q3NetworkOperation*)) );
       
   414 
       
   415 	QTestEventLoop::instance().enterLoop( 30 );
       
   416 	delete urlOp;
       
   417 	if ( QTestEventLoop::instance().timeout() )
       
   418 	    QFAIL( "Network operation timed out" );
       
   419     }
       
   420     {
       
   421 	// In order to test that the put was really successful, we have to get the
       
   422 	// file from the server.
       
   423 	QFETCH( QString, getUrl );
       
   424 	baData.resize( 0 );
       
   425 	Q3UrlOperator opGet( getUrl );
       
   426 	opGet.get();
       
   427 	connect( &opGet, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_put(Q3NetworkOperation*)) );
       
   428 	connect( &opGet, SIGNAL(data(const QByteArray&,Q3NetworkOperation*)), SLOT(slotData_put(const QByteArray&,Q3NetworkOperation*)) );
       
   429 	QTestEventLoop::instance().enterLoop( 30 );
       
   430 	if ( QTestEventLoop::instance().timeout() )
       
   431 	    QFAIL( "Network operation timed out" );
       
   432 
       
   433 	QTEST( baData, "putData" );
       
   434     }
       
   435     {
       
   436 	// cleanup: delete file (if possible)
       
   437 	QFETCH( QString, rmUrl );
       
   438 	QFETCH( QString, rmFile );
       
   439 	Q3UrlOperator opRemove( rmUrl );
       
   440         connect( &opRemove, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_put(Q3NetworkOperation*)) );
       
   441 	if ( opRemove.remove( rmFile ) != 0 ) {
       
   442             QTestEventLoop::instance().enterLoop( 30 );
       
   443 	    if ( QTestEventLoop::instance().timeout() )
       
   444 		QFAIL( "Network operation timed out" );
       
   445 	    QVERIFY( finishedState==Q3NetworkProtocol::StDone || finishedState==Q3NetworkProtocol::StFailed );
       
   446 	    if ( finishedState != Q3NetworkProtocol::StDone ) {
       
   447 		QFAIL( QString( "Can't remove file: network operation failed ('%1'). " ).arg(finishedProtocolDetail) );
       
   448 	    }
       
   449 	}
       
   450     }
       
   451 }
       
   452 
       
   453 void tst_Q3UrlOperator::slotFinished_put( Q3NetworkOperation *op )
       
   454 {
       
   455 #if defined( DUMP_SIGNALS )
       
   456     qDebug( "finished( %p )", op );
       
   457 #endif
       
   458     QVERIFY( op != 0 );
       
   459     pendingOperations.remove( op );
       
   460     QVERIFY( pendingOperations.isEmpty() );
       
   461 
       
   462     finished = TRUE;
       
   463     finishedState = op->state();
       
   464     finishedErrorCode = op->errorCode();
       
   465     finishedProtocolDetail = op->protocolDetail();
       
   466 
       
   467     if (op->state() != Q3NetworkProtocol::StFailed)
       
   468         QTestEventLoop::instance().exitLoop();
       
   469 }
       
   470 
       
   471 void tst_Q3UrlOperator::slotData_put( const QByteArray& ba, Q3NetworkOperation *op )
       
   472 {
       
   473 #if defined( DUMP_SIGNALS )
       
   474     qDebug( "data( %d, %p )", ba.size(), op );
       
   475 #endif
       
   476     QVERIFY( op != 0 );
       
   477     int oldSize = baData.size();
       
   478     baData.resize( ba.size() + oldSize );
       
   479     memcpy( baData.data()+oldSize, ba.data(), ba.size() );
       
   480 }
       
   481 
       
   482 void tst_Q3UrlOperator::rename_data()
       
   483 {
       
   484     QTest::addColumn<QString>("url");
       
   485     QTest::addColumn<QString>("oldname");
       
   486     QTest::addColumn<QString>("newname");
       
   487 
       
   488     QTest::newRow( "local00" ) << QString(".") << QString("foo") << QString("bar");
       
   489 }
       
   490 
       
   491 void tst_Q3UrlOperator::rename()
       
   492 {
       
   493     {
       
   494 	// create direcotry first
       
   495 	QFETCH( QString, url );
       
   496 	QFETCH( QString, oldname );
       
   497 
       
   498 	if ( url.isNull() ) {
       
   499 	    urlOp = new Q3UrlOperator();
       
   500 	} else {
       
   501 	    urlOp = new Q3UrlOperator( url );
       
   502 	}
       
   503 
       
   504 	pendingOperations.append( urlOp->mkdir( oldname ) );
       
   505 
       
   506 	connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_rename(Q3NetworkOperation*)) );
       
   507 
       
   508 	QTestEventLoop::instance().enterLoop( 30 );
       
   509 	delete urlOp;
       
   510 	if ( QTestEventLoop::instance().timeout() )
       
   511 	    QFAIL( "Network operation timed out" );
       
   512 
       
   513 	QVERIFY( finishedState == Q3NetworkProtocol::StDone );
       
   514     }
       
   515     {
       
   516 	// rename directory
       
   517 	QFETCH( QString, url );
       
   518 	QFETCH( QString, oldname );
       
   519 	QFETCH( QString, newname );
       
   520 
       
   521 	if ( url.isNull() ) {
       
   522 	    urlOp = new Q3UrlOperator();
       
   523 	} else {
       
   524 	    urlOp = new Q3UrlOperator( url );
       
   525 	}
       
   526 
       
   527 	pendingOperations.append( urlOp->rename( oldname, newname ) );
       
   528 
       
   529 	connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_rename(Q3NetworkOperation*)) );
       
   530 	connect( urlOp, SIGNAL(itemChanged(Q3NetworkOperation*)), SLOT(slotItemChanged_rename(Q3NetworkOperation*)) );
       
   531 
       
   532 	QTestEventLoop::instance().enterLoop( 30 );
       
   533 	delete urlOp;
       
   534 	if ( QTestEventLoop::instance().timeout() )
       
   535 	    QFAIL( "Network operation timed out" );
       
   536 
       
   537 	QVERIFY( finishedState == Q3NetworkProtocol::StDone );
       
   538     }
       
   539     {
       
   540 	// delete direcotry
       
   541 	QFETCH( QString, url );
       
   542 	QFETCH( QString, newname );
       
   543 
       
   544 	if ( url.isNull() ) {
       
   545 	    urlOp = new Q3UrlOperator();
       
   546 	} else {
       
   547 	    urlOp = new Q3UrlOperator( url );
       
   548 	}
       
   549 
       
   550 	pendingOperations.append( urlOp->remove( newname ) );
       
   551 
       
   552 	connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_rename(Q3NetworkOperation*)) );
       
   553 
       
   554 	QTestEventLoop::instance().enterLoop( 30 );
       
   555 	delete urlOp;
       
   556 	if ( QTestEventLoop::instance().timeout() )
       
   557 	    QFAIL( "Network operation timed out" );
       
   558 
       
   559 	QVERIFY( finishedState == Q3NetworkProtocol::StDone );
       
   560     }
       
   561 }
       
   562 
       
   563 void tst_Q3UrlOperator::slotFinished_rename( Q3NetworkOperation *op )
       
   564 {
       
   565 #if defined( DUMP_SIGNALS )
       
   566     qDebug( "finished( %p )", op );
       
   567 #endif
       
   568     QVERIFY( op != 0 );
       
   569     pendingOperations.remove( op );
       
   570     QVERIFY( pendingOperations.isEmpty() );
       
   571 
       
   572     finished = TRUE;
       
   573     finishedState = op->state();
       
   574     finishedErrorCode = op->errorCode();
       
   575     finishedProtocolDetail = op->protocolDetail();
       
   576 
       
   577     QTestEventLoop::instance().exitLoop();
       
   578 }
       
   579 
       
   580 void tst_Q3UrlOperator::slotItemChanged_rename( Q3NetworkOperation *op )
       
   581 {
       
   582 #if defined( DUMP_SIGNALS )
       
   583     qDebug( "itemChanged( %p )", op );
       
   584 #endif
       
   585     QVERIFY( op != 0 );
       
   586     // ### what to do here?
       
   587 }
       
   588 
       
   589 void tst_Q3UrlOperator::stop_data()
       
   590 {
       
   591     QTest::addColumn<QString>("from");
       
   592     QTest::addColumn<QString>("to");
       
   593     QTest::addColumn<QString>("rmUrl");
       
   594     QTest::addColumn<QString>("rmFile");
       
   595 
       
   596     // FTP data
       
   597     QTest::newRow( "ftp01" )
       
   598 	<< "stop/bigfile" << ftpQtestUpload
       
   599 	<< ftpQtestUpload << "bigfile";
       
   600 }
       
   601 
       
   602 void tst_Q3UrlOperator::stop()
       
   603 {
       
   604     doStop = TRUE;
       
   605     urlOp = new Q3UrlOperator();
       
   606     connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)),
       
   607 	    SLOT(slotFinished_stop(Q3NetworkOperation*)) );
       
   608     connect( urlOp, SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)),
       
   609 	    SLOT(slotDataTransferProgress_stop(int,int,Q3NetworkOperation*)) );
       
   610     {
       
   611 	// do the upload
       
   612 	QFETCH( QString, from );
       
   613 	QFETCH( QString, to );
       
   614 	pendingOperations = urlOp->copy( from, to );
       
   615 
       
   616 	QTestEventLoop::instance().enterLoop( 30 );
       
   617 	if ( QTestEventLoop::instance().timeout() )
       
   618 	    QFAIL( "Network operation timed out" );
       
   619     }
       
   620     doStop = FALSE;
       
   621     {
       
   622 	// do the upload again (this time without stop) -- this used to fail
       
   623 	// until change 71380
       
   624 	QFETCH( QString, from );
       
   625 	QFETCH( QString, to );
       
   626 	pendingOperations = urlOp->copy( from, to );
       
   627 
       
   628 	QTestEventLoop::instance().enterLoop( 30 );
       
   629 	if ( QTestEventLoop::instance().timeout() )
       
   630 	    QFAIL( "Network operation timed out" );
       
   631     }
       
   632     delete urlOp;
       
   633 
       
   634     {
       
   635 	// cleanup: delete file (if possible)
       
   636 	QFETCH( QString, rmUrl );
       
   637 	QFETCH( QString, rmFile );
       
   638 	Q3UrlOperator opRemove( rmUrl );
       
   639 	connect( &opRemove, SIGNAL(finished(Q3NetworkOperation*)), SLOT(slotFinished_stop(Q3NetworkOperation*)) );
       
   640 	if ( opRemove.remove( rmFile ) != 0 ) {
       
   641 	    QTestEventLoop::instance().enterLoop( 30 );
       
   642 	    if ( QTestEventLoop::instance().timeout() )
       
   643 		QFAIL( "Network operation timed out" );
       
   644 	    QVERIFY( finishedState==Q3NetworkProtocol::StDone || finishedState==Q3NetworkProtocol::StFailed );
       
   645 	    if ( finishedState != Q3NetworkProtocol::StDone )
       
   646 		QFAIL( QString( "Can't remove file: network operation failed ('%1'). " ).arg(finishedProtocolDetail) );
       
   647 	}
       
   648     }
       
   649 }
       
   650 
       
   651 void tst_Q3UrlOperator::slotFinished_stop( Q3NetworkOperation *op )
       
   652 {
       
   653 #if defined( DUMP_SIGNALS )
       
   654     qDebug( "finished( %p )", op );
       
   655 #endif
       
   656     QVERIFY( op != 0 );
       
   657 
       
   658     pendingOperations.remove( op );
       
   659     // We are finished if either of this happens:
       
   660     // - both, the get and the put of the copy are finished
       
   661     // - we are in an error case (for the case that the get fails, no
       
   662     //   finished() signal for the put is emitted since it is never executed)
       
   663     if ( pendingOperations.isEmpty() || op->state()==Q3NetworkProtocol::StFailed ) {
       
   664 	finished = TRUE;
       
   665 	finishedState = op->state();
       
   666 	finishedErrorCode = op->errorCode();
       
   667 	finishedProtocolDetail = op->protocolDetail();
       
   668 
       
   669 	QTestEventLoop::instance().exitLoop();
       
   670     }
       
   671 }
       
   672 
       
   673 void tst_Q3UrlOperator::slotDataTransferProgress_stop( int done, int total, Q3NetworkOperation *op )
       
   674 {
       
   675 #if defined( DUMP_SIGNALS )
       
   676     qDebug( "dataTransferProgress( %d, %d, %p )", done, total, op );
       
   677 #endif
       
   678     QVERIFY( op != 0 );
       
   679     QVERIFY( done <= total );
       
   680 
       
   681     if ( QTest::currentTestFunction() == QLatin1String("stop") ) {
       
   682 	// ### it would be nice if we could specify in our testdata when to do
       
   683 	// the stop
       
   684 	if ( doStop && pendingOperations.count()==1 ) {
       
   685 	    if ( done > 0 && done >= total/100000 ) {
       
   686 		// it is not safe to call stop() in a slot connected to the
       
   687 		// dataTransferProgress() signal (and it is not trivial to make
       
   688 		// it work)
       
   689 		QTimer::singleShot( 0, this, SLOT(stopOperation()) );
       
   690 		doStop = FALSE;
       
   691 	    }
       
   692 	}
       
   693     }
       
   694 }
       
   695 
       
   696 void tst_Q3UrlOperator::stopOperation()
       
   697 {
       
   698     if ( urlOp )
       
   699 	urlOp->stop();
       
   700 }
       
   701 
       
   702 void tst_Q3UrlOperator::listChildren_data()
       
   703 {
       
   704     QTest::addColumn<QString>("url");
       
   705     QTest::addColumn<QString>("nameFilter");
       
   706     QTest::addColumn<bool>("readable");
       
   707     QTest::addColumn<bool>("writable");
       
   708     QTest::addColumn<bool>("executable");
       
   709     QTest::addColumn<int>("permissions");
       
   710 
       
   711     QTest::newRow( "localfs00" )
       
   712 	<< QString("listData") << QString("readOnly")
       
   713 	<< (bool)TRUE << (bool)FALSE << (bool)FALSE << 0444;
       
   714     QTest::newRow( "localfs01" )
       
   715 	<< QString("listData") << QString("executable.exe")
       
   716 	<< (bool)TRUE << (bool)FALSE << (bool)TRUE << 0555;
       
   717     int permissions = 0755;
       
   718 #ifdef Q_OS_WIN
       
   719     permissions = 0777;
       
   720 #endif
       
   721     QTest::newRow( "localfs02" )
       
   722 	<< QString("listData") << QString("readWriteExec.exe")
       
   723 	<< (bool)TRUE << (bool)TRUE << (bool)TRUE << permissions;
       
   724 }
       
   725 
       
   726 void tst_Q3UrlOperator::listChildren()
       
   727 {
       
   728     QFETCH( QString, url );
       
   729     QFETCH( QString, nameFilter );
       
   730     urlOp = new Q3UrlOperator( "listData" );
       
   731     urlOp->setNameFilter( nameFilter );
       
   732 
       
   733     pendingOperations.append( urlOp->listChildren() );
       
   734 
       
   735     connect( urlOp, SIGNAL(finished(Q3NetworkOperation*)),
       
   736 	    SLOT(slotFinished_listChildren(Q3NetworkOperation*)) );
       
   737     connect( urlOp, SIGNAL(newChildren(const Q3ValueList<QUrlInfo>&, Q3NetworkOperation*)),
       
   738 	    SLOT(slotNewChildren_listChildren(const Q3ValueList<QUrlInfo>&, Q3NetworkOperation*)) );
       
   739 
       
   740     QTestEventLoop::instance().enterLoop( 30 );
       
   741     delete urlOp;
       
   742     if ( QTestEventLoop::instance().timeout() )
       
   743 	QFAIL( "Network operation timed out" );
       
   744 
       
   745     QVERIFY( finishedState == Q3NetworkProtocol::StDone );
       
   746     for ( int i=0; i<(int)listChildrenInfo.count(); i++ ) {
       
   747 	if ( listChildrenInfo[i].name() == "." || listChildrenInfo[i].name() == ".." )
       
   748 	    continue;
       
   749 
       
   750 	QFETCH( bool, readable );
       
   751 	QFETCH( bool, writable );
       
   752 	QFETCH( bool, executable );
       
   753 	QFETCH( int, permissions );
       
   754 	QCOMPARE( listChildrenInfo[i].isReadable(),   readable );
       
   755 	QCOMPARE( listChildrenInfo[i].isWritable(),   writable );
       
   756 
       
   757 	QCOMPARE( listChildrenInfo[i].isExecutable(), executable);
       
   758 	QCOMPARE( listChildrenInfo[i].permissions(), permissions );
       
   759     }
       
   760 }
       
   761 
       
   762 void tst_Q3UrlOperator::slotFinished_listChildren( Q3NetworkOperation *op )
       
   763 {
       
   764 #if defined( DUMP_SIGNALS )
       
   765     qDebug( "finished( %p )", op );
       
   766 #endif
       
   767     QVERIFY( op != 0 );
       
   768     pendingOperations.remove( op );
       
   769     QVERIFY( pendingOperations.isEmpty() );
       
   770 
       
   771     finished = TRUE;
       
   772     finishedState = op->state();
       
   773     finishedErrorCode = op->errorCode();
       
   774     finishedProtocolDetail = op->protocolDetail();
       
   775 
       
   776     QTestEventLoop::instance().exitLoop();
       
   777 }
       
   778 
       
   779 void tst_Q3UrlOperator::slotNewChildren_listChildren( const Q3ValueList<QUrlInfo> &i, Q3NetworkOperation * )
       
   780 {
       
   781     listChildrenInfo = i;
       
   782 }
       
   783 
       
   784 QTEST_MAIN(tst_Q3UrlOperator)
       
   785 #include "tst_q3urloperator.moc"