tests/auto/qfuture/tst_qfuture.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 #include <QCoreApplication>
       
    42 #include <QDebug>
       
    43 
       
    44 #define QFUTURE_TEST
       
    45 
       
    46 #include <QtTest/QtTest>
       
    47 #include <qfuture.h>
       
    48 #include "versioncheck.h"
       
    49 #include <qfuturewatcher.h>
       
    50 #include <qtconcurrentresultstore.h>
       
    51 #include <qtconcurrentexception.h>
       
    52 
       
    53 #ifndef QT_NO_CONCURRENT_TEST
       
    54 #include <private/qfutureinterface_p.h>
       
    55 
       
    56 using namespace QtConcurrent;
       
    57 
       
    58 //TESTED_CLASS=
       
    59 //TESTED_FILES=
       
    60 
       
    61 class tst_QFuture: public QObject
       
    62 {
       
    63     Q_OBJECT
       
    64 private slots:
       
    65     void resultStore();
       
    66     void future();
       
    67     void futureInterface();
       
    68     void refcounting();
       
    69     void cancel();
       
    70     void statePropagation();
       
    71     void multipleResults();
       
    72     void indexedResults();
       
    73     void progress();
       
    74     void progressText();
       
    75     void resultsAfterFinished();
       
    76     void resultsAsList();
       
    77     void implicitConversions();
       
    78     void iterators();
       
    79     void pause();
       
    80     void throttling();
       
    81     void voidConversions();
       
    82 #ifndef QT_NO_EXCEPTIONS
       
    83     void exceptions();
       
    84 #endif
       
    85 };
       
    86 
       
    87 QTEST_MAIN(tst_QFuture)
       
    88 
       
    89 void tst_QFuture::resultStore()
       
    90 {
       
    91     int int0 = 0;
       
    92     int int1 = 1;
       
    93     int int2 = 2;
       
    94 
       
    95     {
       
    96         ResultStore<int> store;
       
    97         ResultIteratorBase it = store.begin();
       
    98         QVERIFY(store.begin() == store.end());
       
    99         QVERIFY(store.resultAt(0) == store.end());
       
   100         QVERIFY(store.resultAt(1) == store.end());
       
   101     }
       
   102 
       
   103 
       
   104     {
       
   105         ResultStoreBase store;
       
   106         store.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since
       
   107         store.addResult(1, &int1);  // ResultStoreBase does not take ownership, only ResultStore<> does.
       
   108         ResultIteratorBase it = store.begin();
       
   109         QCOMPARE(it.resultIndex(), 0);
       
   110         QVERIFY(it == store.begin());
       
   111         QVERIFY(it != store.end());
       
   112 
       
   113         ++it;
       
   114         QCOMPARE(it.resultIndex(), 1);
       
   115         QVERIFY(it != store.begin());
       
   116         QVERIFY(it != store.end());
       
   117 
       
   118         ++it;
       
   119         QVERIFY(it != store.begin());
       
   120         QVERIFY(it == store.end());
       
   121     }
       
   122 
       
   123     QVector<int> vec0 = QVector<int>() << 2 << 3;
       
   124     QVector<int> vec1 = QVector<int>() << 4 << 5;
       
   125 
       
   126     {
       
   127         ResultStoreBase store;
       
   128         store.addResults(-1, &vec0, 2, 2);
       
   129         store.addResults(-1, &vec1, 2, 2);
       
   130         ResultIteratorBase it = store.begin();
       
   131         QCOMPARE(it.resultIndex(), 0);
       
   132         QVERIFY(it == store.begin());
       
   133         QVERIFY(it != store.end());
       
   134 
       
   135         ++it;
       
   136         QCOMPARE(it.resultIndex(), 1);
       
   137         QVERIFY(it != store.begin());
       
   138         QVERIFY(it != store.end());
       
   139 
       
   140         ++it;
       
   141         QCOMPARE(it.resultIndex(), 2);
       
   142 
       
   143         ++it;
       
   144         QCOMPARE(it.resultIndex(), 3);
       
   145 
       
   146         ++it;
       
   147         QVERIFY(it == store.end());
       
   148     }
       
   149     {
       
   150         ResultStoreBase store;
       
   151         store.addResult(-1, &int0);
       
   152         store.addResults(-1, &vec1, 2, 2);
       
   153         store.addResult(-1, &int1);
       
   154 
       
   155         ResultIteratorBase it = store.begin();
       
   156         QCOMPARE(it.resultIndex(), 0);
       
   157         QVERIFY(it == store.begin());
       
   158         QVERIFY(it != store.end());
       
   159 
       
   160         ++it;
       
   161         QCOMPARE(it.resultIndex(), 1);
       
   162         QVERIFY(it != store.begin());
       
   163         QVERIFY(it != store.end());
       
   164 
       
   165         ++it;
       
   166         QCOMPARE(it.resultIndex(), 2);
       
   167         QVERIFY(it != store.end());
       
   168         ++it;
       
   169         QCOMPARE(it.resultIndex(), 3);
       
   170         QVERIFY(it != store.end());
       
   171         ++it;
       
   172         QVERIFY(it == store.end());
       
   173 
       
   174         QCOMPARE(store.resultAt(0).resultIndex(), 0);
       
   175         QCOMPARE(store.resultAt(1).resultIndex(), 1);
       
   176         QCOMPARE(store.resultAt(2).resultIndex(), 2);
       
   177         QCOMPARE(store.resultAt(3).resultIndex(), 3);
       
   178         QCOMPARE(store.resultAt(4), store.end());
       
   179     }
       
   180     {
       
   181         ResultStore<int> store;
       
   182         store.addResult(-1, &int0);
       
   183         store.addResults(-1, &vec0);
       
   184         store.addResult(-1, &int1);
       
   185 
       
   186         ResultIteratorBase it = store.begin();
       
   187         QCOMPARE(it.resultIndex(), 0);
       
   188         QVERIFY(it == store.begin());
       
   189         QVERIFY(it != store.end());
       
   190 
       
   191         ++it;
       
   192         QCOMPARE(it.resultIndex(), 1);
       
   193         QVERIFY(it != store.begin());
       
   194         QVERIFY(it != store.end());
       
   195 
       
   196         ++it;
       
   197         QCOMPARE(it.resultIndex(), 2);
       
   198         QVERIFY(it != store.end());
       
   199         ++it;
       
   200         QCOMPARE(it.resultIndex(), 3);
       
   201         QVERIFY(it != store.end());
       
   202         ++it;
       
   203         QVERIFY(it == store.end());
       
   204 
       
   205         QCOMPARE(store.resultAt(0).value(), int0);
       
   206         QCOMPARE(store.resultAt(1).value(), vec0[0]);
       
   207         QCOMPARE(store.resultAt(2).value(), vec0[1]);
       
   208         QCOMPARE(store.resultAt(3).value(), int1);
       
   209     }
       
   210     {
       
   211         ResultStore<int> store;
       
   212         store.addResult(-1, &int0);
       
   213         store.addResults(-1, &vec0);
       
   214         store.addResult(200, &int1);
       
   215 
       
   216         QCOMPARE(store.resultAt(0).value(), int0);
       
   217         QCOMPARE(store.resultAt(1).value(), vec0[0]);
       
   218         QCOMPARE(store.resultAt(2).value(), vec0[1]);
       
   219         QCOMPARE(store.resultAt(200).value(), int1);
       
   220     }
       
   221 
       
   222     {
       
   223         ResultStore<int> store;
       
   224         store.addResult(1, &int1);
       
   225         store.addResult(0, &int0);
       
   226         store.addResult(-1, &int2);
       
   227 
       
   228         QCOMPARE(store.resultAt(0).value(), int0);
       
   229         QCOMPARE(store.resultAt(1).value(), int1);
       
   230         QCOMPARE(store.resultAt(2).value(), int2);
       
   231     }
       
   232 
       
   233     {
       
   234         ResultStore<int> store;
       
   235         QCOMPARE(store.contains(0), false);
       
   236         QCOMPARE(store.contains(1), false);
       
   237         QCOMPARE(store.contains(INT_MAX), false);
       
   238     }
       
   239 
       
   240     {
       
   241         // Test filter mode, where "gaps" in the result array aren't allowed.
       
   242         ResultStore<int> store;
       
   243         store.setFilterMode(true);
       
   244 
       
   245         store.addResult(0, &int0);
       
   246         QCOMPARE(store.contains(0), true);
       
   247 
       
   248         store.addResult(2, &int2); // add result at index 2
       
   249         QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet.
       
   250 
       
   251         store.addResult(1, &int1); 
       
   252         QCOMPARE(store.contains(1), true);
       
   253         QCOMPARE(store.contains(2), true); // 2 should be visible now.
       
   254 
       
   255         store.addResult(4, &int0); 
       
   256         store.addResult(5, &int0); 
       
   257         store.addResult(7, &int0); 
       
   258         QCOMPARE(store.contains(4), false);
       
   259         QCOMPARE(store.contains(5), false);
       
   260         QCOMPARE(store.contains(7), false);
       
   261 
       
   262         store.addResult(3, &int0);  // adding 3 makes 4 and 5 visible
       
   263         QCOMPARE(store.contains(4), true);
       
   264         QCOMPARE(store.contains(5), true);
       
   265         QCOMPARE(store.contains(7), false);
       
   266 
       
   267         store.addResult(6, &int0);  // adding 6 makes 7 visible
       
   268 
       
   269         QCOMPARE(store.contains(6), true);
       
   270         QCOMPARE(store.contains(7), true);
       
   271         QCOMPARE(store.contains(8), false);
       
   272     }
       
   273 
       
   274     {
       
   275         // test canceled results
       
   276         ResultStore<int> store;
       
   277         store.setFilterMode(true);
       
   278 
       
   279         store.addResult(0, &int0);
       
   280         QCOMPARE(store.contains(0), true);
       
   281         
       
   282         store.addResult(2, &int0);
       
   283         QCOMPARE(store.contains(2), false);       
       
   284 
       
   285         store.addCanceledResult(1); // report no result at 1
       
   286 
       
   287         QCOMPARE(store.contains(0), true);
       
   288         QCOMPARE(store.contains(1), true); // 2 gets renamed to 1
       
   289         QCOMPARE(store.contains(2), false);
       
   290 
       
   291         store.addResult(3, &int0);
       
   292         QCOMPARE(store.contains(2), true); //3 gets renamed to 2
       
   293 
       
   294         store.addResult(6, &int0);
       
   295         store.addResult(7, &int0);
       
   296         QCOMPARE(store.contains(3), false);
       
   297  
       
   298         store.addCanceledResult(4);
       
   299         store.addCanceledResult(5);
       
   300 
       
   301         QCOMPARE(store.contains(3), true); //6 gets renamed to 3
       
   302         QCOMPARE(store.contains(4), true); //7 gets renamed to 4
       
   303 
       
   304         store.addResult(8, &int0);
       
   305         QCOMPARE(store.contains(5), true); //8 gets renamed to 4
       
   306 
       
   307         QCOMPARE(store.contains(6), false);
       
   308         QCOMPARE(store.contains(7), false);
       
   309     }
       
   310 
       
   311     {
       
   312         // test addResult return value
       
   313         ResultStore<int> store;
       
   314         store.setFilterMode(true);
       
   315 
       
   316         store.addResult(0, &int0);
       
   317         QCOMPARE(store.count(), 1); // result 0 becomes available
       
   318         QCOMPARE(store.contains(0), true);
       
   319         
       
   320         store.addResult(2, &int0);
       
   321         QCOMPARE(store.count(), 1);
       
   322         QCOMPARE(store.contains(2), false);       
       
   323 
       
   324         store.addCanceledResult(1);
       
   325         QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available
       
   326 
       
   327         QCOMPARE(store.contains(0), true);
       
   328         QCOMPARE(store.contains(1), true);
       
   329         QCOMPARE(store.contains(2), false);
       
   330 
       
   331         store.addResult(3, &int0);
       
   332         QCOMPARE(store.count(), 3);
       
   333         QCOMPARE(store.contains(2), true);
       
   334 
       
   335         store.addResult(6, &int0);
       
   336         QCOMPARE(store.count(), 3);
       
   337         store.addResult(7, &int0);
       
   338         QCOMPARE(store.count(), 3);
       
   339         QCOMPARE(store.contains(3), false);
       
   340  
       
   341         store.addCanceledResult(4);
       
   342         store.addCanceledResult(5);
       
   343         QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available
       
   344 
       
   345         QCOMPARE(store.contains(3), true);
       
   346         QCOMPARE(store.contains(4), true);
       
   347 
       
   348         store.addResult(8, &int0);
       
   349         QCOMPARE(store.contains(5), true);
       
   350         QCOMPARE(store.count(), 6);
       
   351 
       
   352         QCOMPARE(store.contains(6), false);
       
   353         QCOMPARE(store.contains(7), false);
       
   354     }
       
   355     
       
   356     {
       
   357         // test resultCount in non-filtered mode. It should always be possible
       
   358         // to iterate through the results 0 to resultCount.
       
   359         ResultStore<int> store;
       
   360         store.addResult(0, &int0);
       
   361         
       
   362         QCOMPARE(store.count(), 1);
       
   363 
       
   364         store.addResult(2, &int0);
       
   365 
       
   366         QCOMPARE(store.count(), 1);
       
   367 
       
   368         store.addResult(1, &int0);
       
   369         QCOMPARE(store.count(), 3);
       
   370     }
       
   371 
       
   372     {
       
   373         ResultStore<int> store;
       
   374         store.addResult(2, &int0);
       
   375         QCOMPARE(store.count(), 0);
       
   376 
       
   377         store.addResult(1, &int0);
       
   378         QCOMPARE(store.count(), 0);
       
   379 
       
   380         store.addResult(0, &int0);
       
   381         QCOMPARE(store.count(), 3);
       
   382     }
       
   383 
       
   384     {
       
   385         ResultStore<int> store;
       
   386         store.addResults(2, &vec1);
       
   387         QCOMPARE(store.count(), 0);
       
   388 
       
   389         store.addResult(1, &int0);
       
   390         QCOMPARE(store.count(), 0);
       
   391 
       
   392         store.addResult(0, &int0);
       
   393         QCOMPARE(store.count(), 4);
       
   394     }
       
   395 
       
   396     {
       
   397         ResultStore<int> store;
       
   398         store.addResults(2, &vec1);
       
   399         QCOMPARE(store.count(), 0);
       
   400 
       
   401         store.addResults(0, &vec0);
       
   402         QCOMPARE(store.count(), 4);
       
   403     }
       
   404     {
       
   405         ResultStore<int> store;
       
   406         store.addResults(3, &vec1);
       
   407         QCOMPARE(store.count(), 0);
       
   408 
       
   409         store.addResults(0, &vec0);
       
   410         QCOMPARE(store.count(), 2);
       
   411 
       
   412         store.addResult(2, &int0);
       
   413         QCOMPARE(store.count(), 5);
       
   414     }
       
   415 
       
   416     {
       
   417         ResultStore<int> store;
       
   418         store.setFilterMode(true);
       
   419         store.addResults(3, &vec1);
       
   420         QCOMPARE(store.count(), 0);
       
   421 
       
   422         store.addResults(0, &vec0);
       
   423         QCOMPARE(store.count(), 2);
       
   424 
       
   425         store.addCanceledResult(2);
       
   426         QCOMPARE(store.count(), 4);
       
   427     }
       
   428 
       
   429     {
       
   430         ResultStore<int> store;
       
   431         store.setFilterMode(true);
       
   432         store.addResults(3, &vec1);
       
   433         QCOMPARE(store.count(), 0);
       
   434 
       
   435         store.addCanceledResults(0, 3);
       
   436         QCOMPARE(store.count(), 2);
       
   437     }
       
   438 
       
   439     {
       
   440         ResultStore<int> store;
       
   441         store.setFilterMode(true);
       
   442         store.addResults(3, &vec1);
       
   443         QCOMPARE(store.count(), 0);
       
   444 
       
   445         store.addCanceledResults(0, 3);
       
   446         QCOMPARE(store.count(), 2);  // results at 3 and 4 become available at index 0, 1
       
   447 
       
   448         store.addResult(5, &int0); 
       
   449         QCOMPARE(store.count(), 3);// result 5 becomes available at index 2
       
   450     }
       
   451 
       
   452     {
       
   453         ResultStore<int> store;
       
   454         store.addResult(1, &int0);
       
   455         store.addResult(3, &int0);
       
   456         store.addResults(6, &vec0);
       
   457         QCOMPARE(store.contains(0), false);
       
   458         QCOMPARE(store.contains(1), true);
       
   459         QCOMPARE(store.contains(2), false);
       
   460         QCOMPARE(store.contains(3), true);
       
   461         QCOMPARE(store.contains(4), false);
       
   462         QCOMPARE(store.contains(5), false);
       
   463         QCOMPARE(store.contains(6), true);
       
   464         QCOMPARE(store.contains(7), true);
       
   465     }
       
   466 
       
   467     {
       
   468         ResultStore<int> store;
       
   469         store.setFilterMode(true);
       
   470         store.addResult(1, &int0);
       
   471         store.addResult(3, &int0);
       
   472         store.addResults(6, &vec0);
       
   473         QCOMPARE(store.contains(0), false);
       
   474         QCOMPARE(store.contains(1), false);
       
   475         QCOMPARE(store.contains(2), false);
       
   476         QCOMPARE(store.contains(3), false);
       
   477         QCOMPARE(store.contains(4), false);
       
   478         QCOMPARE(store.contains(5), false);
       
   479         QCOMPARE(store.contains(6), false);
       
   480         QCOMPARE(store.contains(7), false);
       
   481 
       
   482         store.addCanceledResult(0);
       
   483         store.addCanceledResult(2);
       
   484         store.addCanceledResults(4, 2);
       
   485 
       
   486         QCOMPARE(store.contains(0), true);
       
   487         QCOMPARE(store.contains(1), true);
       
   488         QCOMPARE(store.contains(2), true);
       
   489         QCOMPARE(store.contains(3), true);
       
   490         QCOMPARE(store.contains(4), false);
       
   491         QCOMPARE(store.contains(5), false);
       
   492         QCOMPARE(store.contains(6), false);
       
   493         QCOMPARE(store.contains(7), false);
       
   494     }
       
   495     {
       
   496         ResultStore<int> store;
       
   497         store.setFilterMode(true);
       
   498         store.addCanceledResult(0);
       
   499         QCOMPARE(store.contains(0), false);
       
   500 
       
   501         store.addResult(1, &int0);
       
   502         QCOMPARE(store.contains(0), true);
       
   503         QCOMPARE(store.contains(1), false);
       
   504     }
       
   505 }
       
   506 
       
   507 void tst_QFuture::future()
       
   508 {
       
   509     // default constructors
       
   510     QFuture<int> intFuture;
       
   511     intFuture.waitForFinished();
       
   512     QFuture<QString> stringFuture;
       
   513     stringFuture.waitForFinished();
       
   514     QFuture<void> voidFuture;
       
   515     voidFuture.waitForFinished();
       
   516     QFuture<void> defaultVoidFuture;
       
   517     defaultVoidFuture.waitForFinished();
       
   518 
       
   519     // copy constructor
       
   520     QFuture<int> intFuture2(intFuture);
       
   521     QFuture<void> voidFuture2(defaultVoidFuture);
       
   522 
       
   523     // assigmnent operator
       
   524     intFuture2 = QFuture<int>();
       
   525     voidFuture2 = QFuture<void>();
       
   526 
       
   527     // state
       
   528     QCOMPARE(intFuture2.isStarted(), true);
       
   529     QCOMPARE(intFuture2.isFinished(), true);
       
   530 }
       
   531 
       
   532 class IntResult : public QFutureInterface<int>
       
   533 {
       
   534 public:
       
   535     QFuture<int> run()
       
   536     {
       
   537         this->reportStarted();
       
   538         QFuture<int> future = QFuture<int>(this);
       
   539 
       
   540         int res = 10;
       
   541         reportFinished(&res);
       
   542         return future;
       
   543     }
       
   544 };
       
   545 
       
   546 int value = 10;
       
   547 
       
   548 class VoidResult : public QFutureInterfaceBase
       
   549 {
       
   550 public:
       
   551     QFuture<void> run()
       
   552     {
       
   553         this->reportStarted();
       
   554         QFuture<void> future = QFuture<void>(this);
       
   555         reportFinished();
       
   556         return future;
       
   557     }
       
   558 };
       
   559 
       
   560 void tst_QFuture::futureInterface()
       
   561 {
       
   562     {
       
   563         QFuture<void> future;
       
   564         {
       
   565             QFutureInterface<void> i;
       
   566             i.reportStarted();
       
   567             future = i.future();
       
   568             i.reportFinished();
       
   569         }
       
   570     }
       
   571     {
       
   572         QFuture<int> future;
       
   573         {
       
   574             QFutureInterface<int> i;
       
   575             i.reportStarted();
       
   576             i.reportResult(10);
       
   577             future = i.future();
       
   578             i.reportFinished();
       
   579         }
       
   580         QCOMPARE(future.resultAt(0), 10);
       
   581     }
       
   582 
       
   583     {
       
   584         QFuture<int> intFuture;
       
   585 
       
   586         QCOMPARE(intFuture.isStarted(), true);
       
   587         QCOMPARE(intFuture.isFinished(), true);
       
   588 
       
   589         IntResult result;
       
   590 
       
   591         result.reportStarted();
       
   592         intFuture = result.future();
       
   593 
       
   594         QCOMPARE(intFuture.isStarted(), true);
       
   595         QCOMPARE(intFuture.isFinished(), false);
       
   596 
       
   597         result.reportFinished(&value);
       
   598 
       
   599         QCOMPARE(intFuture.isStarted(), true);
       
   600         QCOMPARE(intFuture.isFinished(), true);
       
   601 
       
   602         int e = intFuture.result();
       
   603 
       
   604         QCOMPARE(intFuture.isStarted(), true);
       
   605         QCOMPARE(intFuture.isFinished(), true);
       
   606         QCOMPARE(intFuture.isCanceled(), false);
       
   607 
       
   608         QCOMPARE(e, value);
       
   609         intFuture.waitForFinished();
       
   610 
       
   611         IntResult intAlgo;
       
   612         intFuture = intAlgo.run();
       
   613         QFuture<int> intFuture2(intFuture);
       
   614         QCOMPARE(intFuture.result(), value);
       
   615         QCOMPARE(intFuture2.result(), value);
       
   616         intFuture.waitForFinished();
       
   617 
       
   618         VoidResult a;
       
   619         a.run().waitForFinished();
       
   620     }
       
   621 }
       
   622 
       
   623 template <typename T>
       
   624 void testRefCounting()
       
   625 {
       
   626     QFutureInterface<T> interface;
       
   627     QCOMPARE(int(interface.d->refCount), 1);
       
   628 
       
   629     {
       
   630         interface.reportStarted();
       
   631 
       
   632         QFuture<T> f = interface.future();
       
   633         QCOMPARE(int(interface.d->refCount), 2);
       
   634 
       
   635         QFuture<T> f2(f);
       
   636         QCOMPARE(int(interface.d->refCount), 3);
       
   637 
       
   638         QFuture<T> f3;
       
   639         f3 = f2;
       
   640         QCOMPARE(int(interface.d->refCount), 4);
       
   641 
       
   642         interface.reportFinished(0);
       
   643         QCOMPARE(int(interface.d->refCount), 4);
       
   644     }
       
   645 
       
   646     QCOMPARE(int(interface.d->refCount), 1);
       
   647 }
       
   648 
       
   649 void tst_QFuture::refcounting()
       
   650 {
       
   651     testRefCounting<int>();
       
   652 }
       
   653 
       
   654 void tst_QFuture::cancel()
       
   655 {
       
   656     {
       
   657         QFuture<void> f;
       
   658         QFutureInterface<void> result;
       
   659 
       
   660         result.reportStarted();
       
   661         f = result.future();
       
   662         QVERIFY(f.isCanceled() == false);
       
   663         result.reportCanceled();
       
   664         QVERIFY(f.isCanceled());
       
   665         result.reportFinished();
       
   666         QVERIFY(f.isCanceled());
       
   667         f.waitForFinished();
       
   668         QVERIFY(f.isCanceled());
       
   669     }
       
   670 
       
   671     // Cancel from the QFuture side and test if the result
       
   672     // interface detects it.
       
   673     {
       
   674         QFutureInterface<void> result;
       
   675 
       
   676         QFuture<void> f;
       
   677         QVERIFY(f.isStarted() == true);
       
   678 
       
   679         result.reportStarted();
       
   680         f = result.future();
       
   681 
       
   682         QVERIFY(f.isStarted() == true);
       
   683 
       
   684         QVERIFY(result.isCanceled() == false);
       
   685         f.cancel();
       
   686 
       
   687         QVERIFY(result.isCanceled());
       
   688 
       
   689         result.reportFinished();
       
   690     }
       
   691 
       
   692     // Test that finished futures can be canceled.
       
   693     {
       
   694         QFutureInterface<void> result;
       
   695 
       
   696         QFuture<void> f;
       
   697         QVERIFY(f.isStarted() == true);
       
   698 
       
   699         result.reportStarted();
       
   700         f = result.future();
       
   701 
       
   702         QVERIFY(f.isStarted() == true);
       
   703 
       
   704         result.reportFinished();
       
   705 
       
   706         f.cancel();
       
   707 
       
   708         QVERIFY(result.isCanceled());
       
   709         QVERIFY(f.isCanceled());
       
   710     }
       
   711 
       
   712     // Results reported after canceled is called should not be propagated.
       
   713     {
       
   714 
       
   715         QFutureInterface<int> futureInterface;
       
   716         futureInterface.reportStarted();
       
   717         QFuture<int> f = futureInterface.future();
       
   718 
       
   719         int result = 0;
       
   720         futureInterface.reportResult(&result);
       
   721         result = 1;
       
   722         futureInterface.reportResult(&result);
       
   723         f.cancel();
       
   724         result = 2;
       
   725         futureInterface.reportResult(&result);
       
   726         result = 3;
       
   727         futureInterface.reportResult(&result);
       
   728         futureInterface.reportFinished();
       
   729         QCOMPARE(f.results(), QList<int>());
       
   730     }
       
   731 }
       
   732 
       
   733 void tst_QFuture::statePropagation()
       
   734 {
       
   735     QFuture<void> f1;
       
   736     QFuture<void> f2;
       
   737 
       
   738     QCOMPARE(f1.isStarted(), true);
       
   739 
       
   740     QFutureInterface<void> result;
       
   741     result.reportStarted();
       
   742     f1 = result.future();
       
   743 
       
   744     f2 = f1;
       
   745 
       
   746     QCOMPARE(f2.isStarted(), true);
       
   747 
       
   748     result.reportCanceled();
       
   749 
       
   750     QCOMPARE(f2.isStarted(), true);
       
   751     QCOMPARE(f2.isCanceled(), true);
       
   752 
       
   753     QFuture<void> f3 = f2;
       
   754 
       
   755     QCOMPARE(f3.isStarted(), true);
       
   756     QCOMPARE(f3.isCanceled(), true);
       
   757 
       
   758     result.reportFinished();
       
   759 
       
   760     QCOMPARE(f2.isStarted(), true);
       
   761     QCOMPARE(f2.isCanceled(), true);
       
   762 
       
   763     QCOMPARE(f3.isStarted(), true);
       
   764     QCOMPARE(f3.isCanceled(), true);
       
   765 }
       
   766 
       
   767 /*
       
   768     Tests that a QFuture can return multiple results.
       
   769 */
       
   770 void tst_QFuture::multipleResults()
       
   771 {
       
   772     IntResult a;
       
   773     a.reportStarted();
       
   774     QFuture<int> f = a.future();
       
   775 
       
   776     QFuture<int> copy = f;
       
   777     int result;
       
   778 
       
   779     result = 1;
       
   780     a.reportResult(&result);
       
   781     QCOMPARE(f.resultAt(0), 1);
       
   782 
       
   783     result = 2;
       
   784     a.reportResult(&result);
       
   785     QCOMPARE(f.resultAt(1), 2);
       
   786 
       
   787     result = 3;
       
   788     a.reportResult(&result);
       
   789 
       
   790     result = 4;
       
   791     a.reportFinished(&result);
       
   792 
       
   793     QCOMPARE(f.results(), QList<int>() << 1 << 2 << 3 << 4);
       
   794 
       
   795     // test foreach
       
   796     QList<int> fasit = QList<int>() << 1 << 2 << 3 << 4;
       
   797     {
       
   798         QList<int> results;
       
   799         foreach(int result, f)
       
   800             results.append(result);
       
   801         QCOMPARE(results, fasit);
       
   802     }
       
   803     {
       
   804         QList<int> results;
       
   805         foreach(int result, copy)
       
   806             results.append(result);
       
   807         QCOMPARE(results, fasit);
       
   808     }
       
   809 }
       
   810 
       
   811 /*
       
   812     Test out-of-order result reporting using indexes
       
   813 */
       
   814 void tst_QFuture::indexedResults()
       
   815 {
       
   816     {
       
   817         QFutureInterface<QChar> Interface;
       
   818         QFuture<QChar> f;
       
   819         QVERIFY(f.isStarted() == true);
       
   820 
       
   821         Interface.reportStarted();
       
   822         f = Interface.future();
       
   823 
       
   824         QVERIFY(f.isStarted() == true);
       
   825 
       
   826         QChar result;
       
   827 
       
   828         result = 'B';
       
   829         Interface.reportResult(&result, 1);
       
   830 
       
   831         QCOMPARE(f.resultAt(1), result);
       
   832 
       
   833         result = 'A';
       
   834         Interface.reportResult(&result, 0);
       
   835         QCOMPARE(f.resultAt(0), result);
       
   836 
       
   837         result = 'C';
       
   838         Interface.reportResult(&result); // no index
       
   839         QCOMPARE(f.resultAt(2), result);
       
   840 
       
   841         Interface.reportFinished();
       
   842 
       
   843         QCOMPARE(f.results(), QList<QChar>() << 'A' << 'B' << 'C');
       
   844     }
       
   845 
       
   846     {
       
   847         // Test result reporting with a missing result in the middle
       
   848         QFutureInterface<int> Interface;
       
   849         Interface.reportStarted();
       
   850         QFuture<int> f = Interface.future();
       
   851         int result;
       
   852 
       
   853         result = 0;
       
   854         Interface.reportResult(&result, 0);
       
   855         QVERIFY(f.isResultReadyAt(0));
       
   856         QCOMPARE(f.resultAt(0), 0);
       
   857 
       
   858         result = 3;
       
   859         Interface.reportResult(&result, 3);
       
   860         QVERIFY(f.isResultReadyAt(3));
       
   861         QCOMPARE(f.resultAt(3), 3);
       
   862 
       
   863         result = 2;
       
   864         Interface.reportResult(&result, 2);
       
   865         QVERIFY(f.isResultReadyAt(2));
       
   866         QCOMPARE(f.resultAt(2), 2);
       
   867 
       
   868         result = 4;
       
   869         Interface.reportResult(&result); // no index
       
   870         QVERIFY(f.isResultReadyAt(4));
       
   871         QCOMPARE(f.resultAt(4), 4);
       
   872 
       
   873         Interface.reportFinished();
       
   874 
       
   875         QCOMPARE(f.results(), QList<int>() << 0 << 2 << 3 << 4);
       
   876     }
       
   877 }
       
   878 
       
   879 void tst_QFuture::progress()
       
   880 {
       
   881     QFutureInterface<QChar> result;
       
   882     QFuture<QChar> f;
       
   883 
       
   884     QCOMPARE (f.progressValue(), 0);
       
   885 
       
   886     result.reportStarted();
       
   887     f = result.future();
       
   888 
       
   889     QCOMPARE (f.progressValue(), 0);
       
   890 
       
   891     result.setProgressValue(50);
       
   892 
       
   893     QCOMPARE (f.progressValue(), 50);
       
   894 
       
   895     result.reportFinished();
       
   896 
       
   897     QCOMPARE (f.progressValue(), 50);
       
   898 }
       
   899 
       
   900 void tst_QFuture::progressText()
       
   901 {
       
   902     QFutureInterface<void> i;
       
   903     i.reportStarted();
       
   904     QFuture<void> f = i.future();
       
   905 
       
   906     QCOMPARE(f.progressText(), QLatin1String(""));
       
   907     i.setProgressValueAndText(1, QLatin1String("foo"));
       
   908     QCOMPARE(f.progressText(), QLatin1String("foo"));
       
   909     i.reportFinished();
       
   910 }
       
   911 
       
   912 /*
       
   913     Test that results reported after finished are ignored.
       
   914 */
       
   915 void tst_QFuture::resultsAfterFinished()
       
   916 {
       
   917     {
       
   918         IntResult a;
       
   919         a.reportStarted();
       
   920         QFuture<int> f =  a.future();
       
   921         int result;
       
   922 
       
   923         QCOMPARE(f.resultCount(), 0);
       
   924 
       
   925         result = 1;
       
   926         a.reportResult(&result);
       
   927         QCOMPARE(f.resultAt(0), 1);
       
   928 
       
   929         a.reportFinished();
       
   930 
       
   931         QCOMPARE(f.resultAt(0), 1);
       
   932         QCOMPARE(f.resultCount(), 1);
       
   933         result = 2;
       
   934         a.reportResult(&result);
       
   935         QCOMPARE(f.resultCount(), 1);
       
   936     }
       
   937     // cancel it
       
   938     {
       
   939         IntResult a;
       
   940         a.reportStarted();
       
   941         QFuture<int> f =  a.future();
       
   942         int result;
       
   943 
       
   944         QCOMPARE(f.resultCount(), 0);
       
   945 
       
   946         result = 1;
       
   947         a.reportResult(&result);
       
   948         QCOMPARE(f.resultAt(0), 1);
       
   949         QCOMPARE(f.resultCount(), 1);
       
   950 
       
   951         a.reportCanceled();
       
   952 
       
   953         QCOMPARE(f.resultAt(0), 1);
       
   954         QCOMPARE(f.resultCount(), 1);
       
   955 
       
   956         result = 2;
       
   957         a.reportResult(&result);
       
   958         a.reportFinished();
       
   959     }
       
   960 }
       
   961 
       
   962 void tst_QFuture::resultsAsList()
       
   963 {
       
   964     IntResult a;
       
   965     a.reportStarted();
       
   966     QFuture<int> f = a.future();
       
   967 
       
   968     int result;
       
   969     result = 1;
       
   970     a.reportResult(&result);
       
   971     result = 2;
       
   972     a.reportResult(&result);
       
   973 
       
   974     a.reportFinished();
       
   975 
       
   976     QList<int> results = f.results();
       
   977     QCOMPARE(results, QList<int>() << 1 << 2);
       
   978 }
       
   979 
       
   980 /*
       
   981     Test that QFuture<T> can be implicitly converted to T
       
   982 */
       
   983 void tst_QFuture::implicitConversions()
       
   984 {
       
   985     QFutureInterface<QString> iface;
       
   986     iface.reportStarted();
       
   987 
       
   988     QFuture<QString> f(&iface);
       
   989 
       
   990     const QString input("FooBar 2000");
       
   991     iface.reportFinished(&input);
       
   992 
       
   993     const QString result = f;
       
   994     QCOMPARE(result, input);
       
   995     QCOMPARE(QString(f), input);
       
   996     QCOMPARE(static_cast<QString>(f), input);
       
   997 }
       
   998 
       
   999 void tst_QFuture::iterators()
       
  1000 {
       
  1001     {
       
  1002         QFutureInterface<int> e;
       
  1003         e.reportStarted();
       
  1004         QFuture<int> f = e.future();
       
  1005 
       
  1006         int result;
       
  1007         result = 1;
       
  1008         e.reportResult(&result);
       
  1009         result = 2;
       
  1010         e.reportResult(&result);
       
  1011         result = 3;
       
  1012         e.reportResult(&result);
       
  1013         e.reportFinished();
       
  1014 
       
  1015         QList<int> results;
       
  1016         QFutureIterator<int> i(f);
       
  1017         while (i.hasNext()) {
       
  1018             results.append(i.next());
       
  1019         }
       
  1020 
       
  1021         QCOMPARE(results, f.results());
       
  1022 
       
  1023         QFuture<int>::const_iterator i1 = f.begin(), i2 = i1 + 1;
       
  1024         QFuture<int>::const_iterator c1 = i1, c2 = c1 + 1;
       
  1025 
       
  1026         QVERIFY(i1 == i1);
       
  1027         QVERIFY(i1 == c1);
       
  1028         QVERIFY(c1 == i1);
       
  1029         QVERIFY(c1 == c1);
       
  1030         QVERIFY(i2 == i2);
       
  1031         QVERIFY(i2 == c2);
       
  1032         QVERIFY(c2 == i2);
       
  1033         QVERIFY(c2 == c2);
       
  1034 
       
  1035         QVERIFY(i1 != i2);
       
  1036         QVERIFY(i1 != c2);
       
  1037         QVERIFY(c1 != i2);
       
  1038         QVERIFY(c1 != c2);
       
  1039         QVERIFY(i2 != i1);
       
  1040         QVERIFY(i2 != c1);
       
  1041         QVERIFY(c2 != i1);
       
  1042         QVERIFY(c2 != c1);
       
  1043 
       
  1044         int x1 = *i1;
       
  1045         Q_UNUSED(x1);
       
  1046         int x2 = *i2;
       
  1047         Q_UNUSED(x2);
       
  1048         int y1 = *c1;
       
  1049         Q_UNUSED(y1);
       
  1050         int y2 = *c2;
       
  1051         Q_UNUSED(y2);
       
  1052     }
       
  1053 
       
  1054     {
       
  1055         QFutureInterface<QString> e;
       
  1056         e.reportStarted();
       
  1057         QFuture<QString> f =  e.future();
       
  1058 
       
  1059         e.reportResult(QString("one"));
       
  1060         e.reportResult(QString("two"));
       
  1061         e.reportResult(QString("three"));
       
  1062         e.reportFinished();
       
  1063 
       
  1064         QList<QString> results;
       
  1065         QFutureIterator<QString> i(f);
       
  1066         while (i.hasNext()) {
       
  1067             results.append(i.next());
       
  1068         }
       
  1069 
       
  1070         QCOMPARE(results, f.results());
       
  1071 
       
  1072         QFuture<QString>::const_iterator i1 = f.begin(), i2 = i1 + 1;
       
  1073         QFuture<QString>::const_iterator c1 = i1, c2 = c1 + 1;
       
  1074 
       
  1075         QVERIFY(i1 == i1);
       
  1076         QVERIFY(i1 == c1);
       
  1077         QVERIFY(c1 == i1);
       
  1078         QVERIFY(c1 == c1);
       
  1079         QVERIFY(i2 == i2);
       
  1080         QVERIFY(i2 == c2);
       
  1081         QVERIFY(c2 == i2);
       
  1082         QVERIFY(c2 == c2);
       
  1083 
       
  1084         QVERIFY(i1 != i2);
       
  1085         QVERIFY(i1 != c2);
       
  1086         QVERIFY(c1 != i2);
       
  1087         QVERIFY(c1 != c2);
       
  1088         QVERIFY(i2 != i1);
       
  1089         QVERIFY(i2 != c1);
       
  1090         QVERIFY(c2 != i1);
       
  1091         QVERIFY(c2 != c1);
       
  1092 
       
  1093         QString x1 = *i1;
       
  1094         QString x2 = *i2;
       
  1095         QString y1 = *c1;
       
  1096         QString y2 = *c2;
       
  1097 
       
  1098         QCOMPARE(x1, y1);
       
  1099         QCOMPARE(x2, y2);
       
  1100 
       
  1101         int i1Size = i1->size();
       
  1102         int i2Size = i2->size();
       
  1103         int c1Size = c1->size();
       
  1104         int c2Size = c2->size();
       
  1105 
       
  1106         QCOMPARE(i1Size, c1Size);
       
  1107         QCOMPARE(i2Size, c2Size);
       
  1108     }
       
  1109 
       
  1110     {
       
  1111         const int resultCount = 20;
       
  1112 
       
  1113         QFutureInterface<int> e;
       
  1114         e.reportStarted();
       
  1115         QFuture<int> f =  e.future();
       
  1116 
       
  1117         for (int i = 0; i < resultCount; ++i) {
       
  1118             e.reportResult(i);
       
  1119         }
       
  1120     
       
  1121         e.reportFinished();
       
  1122     
       
  1123         {
       
  1124             QFutureIterator<int> it(f);
       
  1125             QFutureIterator<int> it2(it);
       
  1126         }
       
  1127 
       
  1128         {
       
  1129             QFutureIterator<int> it(f);
       
  1130     
       
  1131             for (int i = 0; i < resultCount - 1; ++i) {
       
  1132                 QVERIFY(it.hasNext());
       
  1133                 QCOMPARE(it.peekNext(), i);
       
  1134                 QCOMPARE(it.next(), i);
       
  1135             }
       
  1136 
       
  1137             QVERIFY(it.hasNext());
       
  1138             QCOMPARE(it.peekNext(), resultCount - 1);
       
  1139             QCOMPARE(it.next(), resultCount - 1);
       
  1140             QVERIFY(it.hasNext() == false);
       
  1141         }
       
  1142 
       
  1143         {
       
  1144             QFutureIterator<int> it(f);
       
  1145             QVERIFY(it.hasNext());
       
  1146             it.toBack();
       
  1147             QVERIFY(it.hasNext() == false);
       
  1148             it.toFront();
       
  1149             QVERIFY(it.hasNext());
       
  1150         }
       
  1151     }
       
  1152 }
       
  1153 
       
  1154 class SignalSlotObject : public QObject
       
  1155 {
       
  1156 Q_OBJECT
       
  1157 public:
       
  1158     SignalSlotObject()
       
  1159     : finishedCalled(false),
       
  1160       canceledCalled(false),
       
  1161       rangeBegin(0),
       
  1162       rangeEnd(0) { }
       
  1163 
       
  1164 public slots:
       
  1165     void finished()
       
  1166     {
       
  1167 //        qDebug() << "finished called";
       
  1168         finishedCalled = true;
       
  1169     }
       
  1170 
       
  1171     void canceled()
       
  1172     {
       
  1173 //        qDebug() << "canceled called";
       
  1174         canceledCalled = true;
       
  1175     }
       
  1176 
       
  1177     void resultReady(int index)
       
  1178     {
       
  1179 //        qDebug() << "result" << index << "ready";
       
  1180         results.insert(index);
       
  1181     }
       
  1182 
       
  1183     void progressRange(int begin, int end)
       
  1184     {
       
  1185 //        qDebug() << "progress range" << begin << end;
       
  1186         rangeBegin = begin;
       
  1187         rangeEnd = end;
       
  1188     }
       
  1189 
       
  1190     void progress(int progress)
       
  1191     {
       
  1192 //        qDebug() << "progress" << progress;
       
  1193         reportedProgress.insert(progress);
       
  1194     }
       
  1195 public:
       
  1196     bool finishedCalled;
       
  1197     bool canceledCalled;
       
  1198     QSet<int> results;
       
  1199     int rangeBegin;
       
  1200     int rangeEnd;
       
  1201     QSet<int> reportedProgress;
       
  1202 };
       
  1203 
       
  1204 void tst_QFuture::pause()
       
  1205 {
       
  1206     QFutureInterface<void> Interface;
       
  1207 
       
  1208     Interface.reportStarted();
       
  1209     QFuture<void> f = Interface.future();
       
  1210 
       
  1211     QVERIFY(Interface.isPaused() == false);
       
  1212     f.pause();
       
  1213     QVERIFY(Interface.isPaused() == true);
       
  1214     f.resume();
       
  1215     QVERIFY(Interface.isPaused() == false);
       
  1216     f.togglePaused();
       
  1217     QVERIFY(Interface.isPaused() == true);
       
  1218     f.togglePaused();
       
  1219     QVERIFY(Interface.isPaused() == false);
       
  1220 
       
  1221     Interface.reportFinished();
       
  1222 }
       
  1223 
       
  1224 const int resultCount = 1000;
       
  1225 
       
  1226 class ResultObject : public QObject
       
  1227 {
       
  1228 Q_OBJECT
       
  1229 public slots:
       
  1230     void resultReady(int)
       
  1231     {
       
  1232 
       
  1233     }
       
  1234 public:
       
  1235 };
       
  1236 
       
  1237 // Test that that the isPaused() on future result interface returns true
       
  1238 // if we report a lot of results that are not handled.
       
  1239 void tst_QFuture::throttling()
       
  1240 {
       
  1241     {
       
  1242         QFutureInterface<void> i;
       
  1243 
       
  1244         i.reportStarted();
       
  1245         QFuture<void> f = i.future();
       
  1246 
       
  1247         QVERIFY(i.isThrottled() == false);
       
  1248 
       
  1249         i.setThrottled(true);
       
  1250         QVERIFY(i.isThrottled());
       
  1251 
       
  1252         i.setThrottled(false);
       
  1253         QVERIFY(i.isThrottled() == false);
       
  1254 
       
  1255         i.setThrottled(true);
       
  1256         QVERIFY(i.isThrottled());
       
  1257 
       
  1258         i.reportFinished();
       
  1259     }
       
  1260 /*
       
  1261     QFutureInterface<int> *Interface = new QFutureInterface<int>();
       
  1262     Interface.reportStarted();
       
  1263     QFuture<int> f =  QFuture<int>(Interface);
       
  1264 
       
  1265     ResultObject object;
       
  1266     f.connectTo(ThrottledResultReadyAtSignal, &object, SLOT(resultReady(int)), Qt::DirectConnection);
       
  1267 
       
  1268     for (int i = 0; i < 100; ++i)
       
  1269         Interface.reportResult(&i);
       
  1270 
       
  1271     QVERIFY(Interface.isPaused() == true);
       
  1272 
       
  1273     // read the results, this should resume the task.
       
  1274     for (int i = 0; i < 100; ++i)
       
  1275         f.throttledResult(i);
       
  1276 
       
  1277     QVERIFY(Interface.isPaused() == false);
       
  1278     Interface.reportFinished();
       
  1279 */
       
  1280 }
       
  1281 
       
  1282 void tst_QFuture::voidConversions()
       
  1283 {
       
  1284     QFutureInterface<int> iface;
       
  1285     iface.reportStarted();
       
  1286 
       
  1287     QFuture<int> intFuture(&iface);
       
  1288 
       
  1289     int value = 10;
       
  1290     iface.reportFinished(&value);
       
  1291 
       
  1292     QFuture<void> voidFuture(intFuture);
       
  1293     voidFuture = intFuture;
       
  1294 
       
  1295     QVERIFY(voidFuture == intFuture);
       
  1296 }
       
  1297 
       
  1298 
       
  1299 #ifndef QT_NO_EXCEPTIONS
       
  1300 
       
  1301 QFuture<void> createExceptionFuture()
       
  1302 {
       
  1303     QFutureInterface<void> i;
       
  1304     i.reportStarted();
       
  1305     QFuture<void> f = i.future();
       
  1306 
       
  1307     Exception e;
       
  1308     i.reportException(e);
       
  1309     i.reportFinished();
       
  1310     return f;
       
  1311 }
       
  1312 
       
  1313 QFuture<int> createExceptionResultFuture()
       
  1314 {
       
  1315     QFutureInterface<int> i;
       
  1316     i.reportStarted();
       
  1317     QFuture<int> f = i.future();
       
  1318     int r = 0;
       
  1319     i.reportResult(r);
       
  1320 
       
  1321     Exception e;
       
  1322     i.reportException(e);
       
  1323     i.reportFinished();
       
  1324     return f;
       
  1325 }
       
  1326 
       
  1327 class DerivedException : public Exception
       
  1328 {
       
  1329 public:
       
  1330     void raise() const { throw *this; }
       
  1331     Exception *clone() const { return new DerivedException(*this); }
       
  1332 };
       
  1333 
       
  1334 QFuture<void> createDerivedExceptionFuture()
       
  1335 {
       
  1336     QFutureInterface<void> i;
       
  1337     i.reportStarted();
       
  1338     QFuture<void> f = i.future();
       
  1339 
       
  1340     DerivedException e;
       
  1341     i.reportException(e);
       
  1342     i.reportFinished();
       
  1343     return f;
       
  1344 }
       
  1345 
       
  1346 void tst_QFuture::exceptions()
       
  1347 {
       
  1348 
       
  1349 // test throwing from waitForFinished
       
  1350 {
       
  1351     QFuture<void> f = createExceptionFuture();
       
  1352     bool caught = false;
       
  1353     try {
       
  1354         f.waitForFinished();
       
  1355     } catch (Exception &) {
       
  1356         caught = true;
       
  1357     }
       
  1358     QVERIFY(caught);
       
  1359 }
       
  1360 
       
  1361 // test result()
       
  1362 {
       
  1363     QFuture<int> f = createExceptionResultFuture();
       
  1364     bool caught = false;
       
  1365     try {
       
  1366         f.result();
       
  1367     } catch (Exception &) {
       
  1368         caught = true;
       
  1369     }
       
  1370     QVERIFY(caught);
       
  1371 }
       
  1372 
       
  1373 // test result() and destroy
       
  1374 {
       
  1375     bool caught = false;
       
  1376     try {
       
  1377         createExceptionResultFuture().result();
       
  1378     } catch (Exception &) {
       
  1379         caught = true;
       
  1380     }
       
  1381     QVERIFY(caught);
       
  1382 }
       
  1383 
       
  1384 // test results()
       
  1385 {
       
  1386     QFuture<int> f = createExceptionResultFuture();
       
  1387     bool caught = false;
       
  1388     try {
       
  1389         f.results();
       
  1390     } catch (Exception &) {
       
  1391         caught = true;
       
  1392     }
       
  1393     QVERIFY(caught);
       
  1394 }
       
  1395 
       
  1396 // test foreach
       
  1397 {
       
  1398     QFuture<int> f = createExceptionResultFuture();
       
  1399     bool caught = false;
       
  1400     try {
       
  1401         foreach (int e, f.results()) {
       
  1402             Q_UNUSED(e);
       
  1403             QFAIL("did not get exception");
       
  1404         }
       
  1405     } catch (Exception &) {
       
  1406         caught = true;
       
  1407     }
       
  1408     QVERIFY(caught);
       
  1409 }
       
  1410 
       
  1411 // catch derived exceptions
       
  1412 {
       
  1413     bool caught = false;
       
  1414     try {
       
  1415         createDerivedExceptionFuture().waitForFinished();
       
  1416     } catch (Exception &) {
       
  1417         caught = true;
       
  1418     }
       
  1419     QVERIFY(caught);
       
  1420 }
       
  1421 
       
  1422 {
       
  1423     bool caught = false;
       
  1424     try {
       
  1425         createDerivedExceptionFuture().waitForFinished();
       
  1426     } catch (DerivedException &) {
       
  1427         caught = true;
       
  1428     }
       
  1429     QVERIFY(caught);
       
  1430 }
       
  1431 
       
  1432 }
       
  1433 
       
  1434 #endif // QT_NO_EXCEPTIONS
       
  1435 
       
  1436 #include "tst_qfuture.moc"
       
  1437 
       
  1438 #else
       
  1439 QTEST_NOOP_MAIN
       
  1440 #endif