1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30
31#include <qresultstore.h>
32
33using namespace QtPrivate;
34
35struct ResultStoreInt : ResultStoreBase
36{
37 ~ResultStoreInt() { clear<int>(); }
38};
39
40class tst_QtConcurrentResultStore : public QObject
41{
42 Q_OBJECT
43public slots:
44 void init();
45private slots:
46 void construction();
47 void iterators();
48 void addResult();
49 void addResults();
50 void resultIndex();
51 void resultAt();
52 void contains();
53 void filterMode();
54 void addCanceledResult();
55 void count();
56private:
57 int int0;
58 int int1;
59 int int2;
60 QVector<int> vec0;
61 QVector<int> vec1;
62};
63
64void tst_QtConcurrentResultStore::init()
65{
66 int0 = 0;
67 int1 = 1;
68 int2 = 2;
69 vec0 = QVector<int>() << 2 << 3;
70 vec1 = QVector<int>() << 4 << 5;
71}
72
73void tst_QtConcurrentResultStore::construction()
74{
75 ResultStoreBase store;
76 QCOMPARE(store.count(), 0);
77}
78
79void tst_QtConcurrentResultStore::iterators()
80{
81 {
82 ResultStoreBase store;
83 QCOMPARE(store.begin(), store.end());
84 QCOMPARE(store.resultAt(0), store.end());
85 QCOMPARE(store.resultAt(1), store.end());
86 }
87 {
88 ResultStoreInt storebase;
89 storebase.addResult(index: -1, result: &int0); // note to self: adding a pointer to the stack here is ok since
90 storebase.addResult(index: 1, result: &int1); // ResultStoreBase does not take ownership, only ResultStore<> does.
91 ResultIteratorBase it = storebase.begin();
92 QCOMPARE(it.resultIndex(), 0);
93 QCOMPARE(it, storebase.begin());
94 QVERIFY(it != storebase.end());
95
96 ++it;
97 QCOMPARE(it.resultIndex(), 1);
98 QVERIFY(it != storebase.begin());
99 QVERIFY(it != storebase.end());
100
101 ++it;
102 QVERIFY(it != storebase.begin());
103 QCOMPARE(it, storebase.end());
104 }
105}
106
107void tst_QtConcurrentResultStore::addResult()
108{
109 {
110 // test addResult return value
111 ResultStoreInt store;
112 store.setFilterMode(true);
113
114 QCOMPARE(store.addResult(0, &int0), 0);
115 QCOMPARE(store.count(), 1); // result 0 becomes available
116 QCOMPARE(store.contains(0), true);
117
118 QCOMPARE(store.addResult(2, &int0), 2);
119 QCOMPARE(store.count(), 1);
120 QCOMPARE(store.contains(2), false);
121
122 QCOMPARE(store.addCanceledResult(1), 1);
123 QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available
124
125 QCOMPARE(store.contains(0), true);
126 QCOMPARE(store.contains(1), true);
127 QCOMPARE(store.contains(2), false);
128
129 QCOMPARE(store.addResult(3, &int0), 3);
130 QCOMPARE(store.count(), 3);
131 QCOMPARE(store.contains(2), true);
132
133 QCOMPARE(store.addResult(6, &int0), 6);
134 QCOMPARE(store.count(), 3);
135 QCOMPARE(store.addResult(7, &int0), 7);
136 QCOMPARE(store.count(), 3);
137 QCOMPARE(store.contains(3), false);
138
139 QCOMPARE(store.addCanceledResult(4), 4);
140 QCOMPARE(store.addCanceledResult(5), 5);
141 QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available
142
143 QCOMPARE(store.contains(3), true);
144 QCOMPARE(store.contains(4), true);
145
146 QCOMPARE(store.addResult(8, &int0), 8);
147 QCOMPARE(store.contains(5), true);
148 QCOMPARE(store.count(), 6);
149
150 QCOMPARE(store.contains(6), false);
151 QCOMPARE(store.contains(7), false);
152 }
153}
154
155void tst_QtConcurrentResultStore::addResults()
156{
157 ResultStoreInt store;
158 store.addResults(index: -1, results: &vec0);
159 store.addResults(index: -1, results: &vec1);
160 ResultIteratorBase it = store.begin();
161 QCOMPARE(it.resultIndex(), 0);
162 QCOMPARE(it, store.begin());
163 QVERIFY(it != store.end());
164
165 ++it;
166 QCOMPARE(it.resultIndex(), 1);
167 QVERIFY(it != store.begin());
168 QVERIFY(it != store.end());
169
170 ++it;
171 QCOMPARE(it.resultIndex(), 2);
172
173 ++it;
174 QCOMPARE(it.resultIndex(), 3);
175
176 ++it;
177 QCOMPARE(it, store.end());
178
179 QVector<int> empty;
180 const auto countBefore = store.count();
181 QCOMPARE(store.addResults(countBefore, &empty), -1);
182 QCOMPARE(store.count(), countBefore);
183
184 QCOMPARE(store.addResults(countBefore, &vec1), countBefore);
185 QCOMPARE(store.count(), countBefore + vec1.size());
186}
187
188void tst_QtConcurrentResultStore::resultIndex()
189{
190 ResultStoreInt store;
191 store.addResult(index: -1, result: &int0);
192 store.addResults(index: -1, results: &vec0);
193 store.addResult(index: -1, result: &int1);
194
195 ResultIteratorBase it = store.begin();
196 QCOMPARE(it.resultIndex(), 0);
197 QVERIFY(it == store.begin());
198 QVERIFY(it != store.end());
199
200 ++it;
201 QCOMPARE(it.resultIndex(), 1);
202 QVERIFY(it != store.begin());
203 QVERIFY(it != store.end());
204
205 ++it;
206 QCOMPARE(it.resultIndex(), 2);
207 QVERIFY(it != store.end());
208 ++it;
209 QCOMPARE(it.resultIndex(), 3);
210 QVERIFY(it != store.end());
211 ++it;
212 QVERIFY(it == store.end());
213
214 QCOMPARE(store.resultAt(0).value<int>(), int0);
215 QCOMPARE(store.resultAt(1).value<int>(), vec0[0]);
216 QCOMPARE(store.resultAt(2).value<int>(), vec0[1]);
217 QCOMPARE(store.resultAt(3).value<int>(), int1);
218}
219
220void tst_QtConcurrentResultStore::resultAt()
221{
222 {
223 ResultStoreInt store;
224 store.addResult(index: -1, result: &int0);
225 store.addResults(index: -1, results: &vec0);
226 store.addResult(index: 200, result: &int1);
227
228 QCOMPARE(store.resultAt(0).value<int>(), int0);
229 QCOMPARE(store.resultAt(1).value<int>(), vec0[0]);
230 QCOMPARE(store.resultAt(2).value<int>(), vec0[1]);
231 QCOMPARE(store.resultAt(200).value<int>(), int1);
232 }
233 {
234 ResultStoreInt store;
235 store.addResult(index: 1, result: &int1);
236 store.addResult(index: 0, result: &int0);
237 store.addResult(index: -1, result: &int2);
238
239 QCOMPARE(store.resultAt(0).value<int>(), int0);
240 QCOMPARE(store.resultAt(1).value<int>(), int1);
241 QCOMPARE(store.resultAt(2).value<int>(), int2);
242 }
243}
244
245void tst_QtConcurrentResultStore::contains()
246{
247 {
248 ResultStoreInt store;
249 QCOMPARE(store.contains(0), false);
250 QCOMPARE(store.contains(1), false);
251 QCOMPARE(store.contains(INT_MAX), false);
252 store.addResult(index: 1, result: &int1);
253 QVERIFY(store.contains(int1));
254 store.addResult(index: 0, result: &int0);
255 QVERIFY(store.contains(int0));
256 store.addResult(index: -1, result: &int2);
257 QVERIFY(store.contains(int2));
258 }
259 {
260 ResultStoreInt store;
261 store.addResult(index: 1, result: &int0);
262 store.addResult(index: 3, result: &int0);
263 store.addResults(index: 6, results: &vec0);
264 QCOMPARE(store.contains(0), false);
265 QCOMPARE(store.contains(1), true);
266 QCOMPARE(store.contains(2), false);
267 QCOMPARE(store.contains(3), true);
268 QCOMPARE(store.contains(4), false);
269 QCOMPARE(store.contains(5), false);
270 QCOMPARE(store.contains(6), true);
271 QCOMPARE(store.contains(7), true);
272 }
273
274 {
275 ResultStoreInt store;
276 store.setFilterMode(true);
277 store.addResult(index: 1, result: &int0);
278 store.addResult(index: 3, result: &int0);
279 store.addResults(index: 6, results: &vec0);
280 QCOMPARE(store.contains(0), false);
281 QCOMPARE(store.contains(1), false);
282 QCOMPARE(store.contains(2), false);
283 QCOMPARE(store.contains(3), false);
284 QCOMPARE(store.contains(4), false);
285 QCOMPARE(store.contains(5), false);
286 QCOMPARE(store.contains(6), false);
287 QCOMPARE(store.contains(7), false);
288
289 store.addCanceledResult(index: 0);
290 store.addCanceledResult(index: 2);
291 store.addCanceledResults<int>(index: 4, count: 2);
292
293 QCOMPARE(store.contains(0), true);
294 QCOMPARE(store.contains(1), true);
295 QCOMPARE(store.contains(2), true);
296 QCOMPARE(store.contains(3), true);
297 QCOMPARE(store.contains(4), false);
298 QCOMPARE(store.contains(5), false);
299 QCOMPARE(store.contains(6), false);
300 QCOMPARE(store.contains(7), false);
301 }
302 {
303 ResultStoreInt store;
304 store.setFilterMode(true);
305 store.addCanceledResult(index: 0);
306 QCOMPARE(store.contains(0), false);
307
308 store.addResult(index: 1, result: &int0);
309 QCOMPARE(store.contains(0), true);
310 QCOMPARE(store.contains(1), false);
311 }
312}
313
314void tst_QtConcurrentResultStore::filterMode()
315{
316 // Test filter mode, where "gaps" in the result array aren't allowed.
317 ResultStoreInt store;
318 QCOMPARE(store.filterMode(), false);
319 store.setFilterMode(true);
320 QVERIFY(store.filterMode());
321
322 store.addResult(index: 0, result: &int0);
323 QCOMPARE(store.contains(0), true);
324
325 store.addResult(index: 2, result: &int2); // add result at index 2
326 QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet.
327
328 store.addResult(index: 1, result: &int1);
329 QCOMPARE(store.contains(1), true);
330 QCOMPARE(store.contains(2), true); // 2 should be visible now.
331
332 store.addResult(index: 4, result: &int0);
333 store.addResult(index: 5, result: &int0);
334 store.addResult(index: 7, result: &int0);
335 QCOMPARE(store.contains(4), false);
336 QCOMPARE(store.contains(5), false);
337 QCOMPARE(store.contains(7), false);
338
339 store.addResult(index: 3, result: &int0); // adding 3 makes 4 and 5 visible
340 QCOMPARE(store.contains(4), true);
341 QCOMPARE(store.contains(5), true);
342 QCOMPARE(store.contains(7), false);
343
344 store.addResult(index: 6, result: &int0); // adding 6 makes 7 visible
345
346 QCOMPARE(store.contains(6), true);
347 QCOMPARE(store.contains(7), true);
348 QCOMPARE(store.contains(8), false);
349
350 QVector<int> empty;
351 const auto countBefore = store.count();
352 QCOMPARE(store.addResults(countBefore, &empty), -1);
353 QCOMPARE(store.count(), countBefore);
354
355 QCOMPARE(store.addResult(countBefore, &int2), countBefore);
356 QCOMPARE(store.count(), countBefore + 1);
357}
358
359void tst_QtConcurrentResultStore::addCanceledResult()
360{
361 // test canceled results
362 ResultStoreInt store;
363 store.setFilterMode(true);
364
365 store.addResult(index: 0, result: &int0);
366 QCOMPARE(store.contains(0), true);
367
368 store.addResult(index: 2, result: &int0);
369 QCOMPARE(store.contains(2), false);
370
371 store.addCanceledResult(index: 1); // report no result at 1
372
373 QCOMPARE(store.contains(0), true);
374 QCOMPARE(store.contains(1), true); // 2 gets renamed to 1
375 QCOMPARE(store.contains(2), false);
376
377 store.addResult(index: 3, result: &int0);
378 QCOMPARE(store.contains(2), true); //3 gets renamed to 2
379
380 store.addResult(index: 6, result: &int0);
381 store.addResult(index: 7, result: &int0);
382 QCOMPARE(store.contains(3), false);
383
384 store.addCanceledResult(index: 4);
385 store.addCanceledResult(index: 5);
386
387 QCOMPARE(store.contains(3), true); //6 gets renamed to 3
388 QCOMPARE(store.contains(4), true); //7 gets renamed to 4
389
390 store.addResult(index: 8, result: &int0);
391 QCOMPARE(store.contains(5), true); //8 gets renamed to 4
392
393 QCOMPARE(store.contains(6), false);
394 QCOMPARE(store.contains(7), false);
395}
396
397void tst_QtConcurrentResultStore::count()
398{
399 {
400 // test resultCount in non-filtered mode. It should always be possible
401 // to iterate through the results 0 to resultCount.
402 ResultStoreInt store;
403 store.addResult(index: 0, result: &int0);
404
405 QCOMPARE(store.count(), 1);
406
407 store.addResult(index: 2, result: &int0);
408
409 QCOMPARE(store.count(), 1);
410
411 store.addResult(index: 1, result: &int0);
412 QCOMPARE(store.count(), 3);
413 }
414
415 {
416 ResultStoreInt store;
417 store.addResult(index: 2, result: &int0);
418 QCOMPARE(store.count(), 0);
419
420 store.addResult(index: 1, result: &int0);
421 QCOMPARE(store.count(), 0);
422
423 store.addResult(index: 0, result: &int0);
424 QCOMPARE(store.count(), 3);
425 }
426
427 {
428 ResultStoreInt store;
429 store.addResults(index: 2, results: &vec1);
430 QCOMPARE(store.count(), 0);
431
432 store.addResult(index: 1, result: &int0);
433 QCOMPARE(store.count(), 0);
434
435 store.addResult(index: 0, result: &int0);
436 QCOMPARE(store.count(), 4);
437 }
438
439 {
440 ResultStoreInt store;
441 store.addResults(index: 2, results: &vec1);
442 QCOMPARE(store.count(), 0);
443
444 store.addResults(index: 0, results: &vec0);
445 QCOMPARE(store.count(), 4);
446 }
447 {
448 ResultStoreInt store;
449 store.addResults(index: 3, results: &vec1);
450 QCOMPARE(store.count(), 0);
451
452 store.addResults(index: 0, results: &vec0);
453 QCOMPARE(store.count(), 2);
454
455 store.addResult(index: 2, result: &int0);
456 QCOMPARE(store.count(), 5);
457 }
458
459 {
460 ResultStoreInt store;
461 store.setFilterMode(true);
462 store.addResults(index: 3, results: &vec1);
463 QCOMPARE(store.count(), 0);
464
465 store.addResults(index: 0, results: &vec0);
466 QCOMPARE(store.count(), 2);
467
468 store.addCanceledResult(index: 2);
469 QCOMPARE(store.count(), 4);
470 }
471
472 {
473 ResultStoreInt store;
474 store.setFilterMode(true);
475 store.addResults(index: 3, results: &vec1);
476 QCOMPARE(store.count(), 0);
477
478 store.addCanceledResults<int>(index: 0, count: 3);
479 QCOMPARE(store.count(), 2);
480 }
481
482 {
483 ResultStoreInt store;
484 store.setFilterMode(true);
485 store.addResults(index: 3, results: &vec1);
486 QCOMPARE(store.count(), 0);
487
488 store.addCanceledResults<int>(index: 0, count: 3);
489 QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1
490
491 store.addResult(index: 5, result: &int0);
492 QCOMPARE(store.count(), 3);// result 5 becomes available at index 2
493 }
494}
495
496QTEST_MAIN(tst_QtConcurrentResultStore)
497#include "tst_qresultstore.moc"
498

source code of qtbase/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp