|
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 |