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 | |
33 | using namespace QtPrivate; |
34 | |
35 | struct ResultStoreInt : ResultStoreBase |
36 | { |
37 | ~ResultStoreInt() { clear<int>(); } |
38 | }; |
39 | |
40 | class tst_QtConcurrentResultStore : public QObject |
41 | { |
42 | Q_OBJECT |
43 | public slots: |
44 | void init(); |
45 | private 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(); |
56 | private: |
57 | int int0; |
58 | int int1; |
59 | int int2; |
60 | QVector<int> vec0; |
61 | QVector<int> vec1; |
62 | }; |
63 | |
64 | void 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 | |
73 | void tst_QtConcurrentResultStore::construction() |
74 | { |
75 | ResultStoreBase store; |
76 | QCOMPARE(store.count(), 0); |
77 | } |
78 | |
79 | void 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 | |
107 | void 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 | |
155 | void 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 | |
188 | void 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 | |
220 | void 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 | |
245 | void 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 | |
314 | void 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 | |
359 | void 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 | |
397 | void 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 | |
496 | QTEST_MAIN(tst_QtConcurrentResultStore) |
497 | #include "tst_qresultstore.moc" |
498 | |