1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module 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 | #include <private/qframeallocator_p.h> |
31 | #include <private/qframeallocator_p_p.h> |
32 | |
33 | class tst_QFrameAllocator : public QObject |
34 | { |
35 | Q_OBJECT |
36 | public: |
37 | tst_QFrameAllocator() : QObject() {} |
38 | ~tst_QFrameAllocator() {} |
39 | |
40 | struct small |
41 | { |
42 | char c; |
43 | }; |
44 | |
45 | struct medium |
46 | { |
47 | int a, b, c; |
48 | }; |
49 | |
50 | struct big |
51 | { |
52 | int t[8]; |
53 | }; |
54 | |
55 | struct huge |
56 | { |
57 | int t[64]; |
58 | }; |
59 | |
60 | struct composed |
61 | { |
62 | QVector<int> vec; |
63 | QList<int> list; |
64 | int t; |
65 | }; |
66 | |
67 | struct subclass : public composed |
68 | { |
69 | float toto; |
70 | // add some more data to force the subclass into a different bucket |
71 | char data[32]; |
72 | }; |
73 | |
74 | private slots: |
75 | |
76 | void initQFrameChunk(); |
77 | void singleAllocationQFrameChunk(); |
78 | void qvectorAllocationQFrameChunk(); |
79 | void multipleAllocationQFrameChunk(); |
80 | void overflowAllocationQFrameChunk(); |
81 | void singleDeallocationQFrameChunk(); |
82 | void multipleDeallocationQFrameChunk(); |
83 | void containsCheckQFrameChunk(); |
84 | void clearQFrameChunk(); |
85 | void initQFixedFrameAllocator(); |
86 | void allocateQFixedFrameAllocator(); |
87 | void deallocateQFixedFrameAllocator(); |
88 | void checkFragmentationQFixedFrameAllocator(); |
89 | void clearQFixedFrameAllocator(); |
90 | void initQFrameAllocator(); |
91 | void allocateWithQFrameAllocator(); |
92 | void deallocateWithQFrameAllocator(); |
93 | void testAllocationComposedValues(); |
94 | void allocateSubclass(); |
95 | void deallocateSubclass(); |
96 | void clearQFrameAllocator(); |
97 | void isEmptyQFrameAllocator(); |
98 | void subclassPointerClearing(); |
99 | void allocateWithRawMemoryDeallocate(); |
100 | void allocateDeallocateRawMemory(); |
101 | }; |
102 | |
103 | void tst_QFrameAllocator::initQFrameChunk() |
104 | { |
105 | Qt3DCore::QFrameChunk c; |
106 | |
107 | c.init(blockSize: 16, blocks: 12); |
108 | |
109 | QVERIFY(c.m_blocksAvailable == c.m_maxBlocksAvailable); |
110 | QCOMPARE(c.m_blocksAvailable, (uchar)12); |
111 | QCOMPARE(c.m_firstAvailableBlock, (uchar)0); |
112 | QVERIFY(c.m_data != nullptr); |
113 | QVERIFY(c.isEmpty()); |
114 | |
115 | for (int i = 0; i < 12; i++) { |
116 | QCOMPARE(c.m_data[i * 16], (uchar)(i + 1)); |
117 | } |
118 | } |
119 | |
120 | void tst_QFrameAllocator::singleAllocationQFrameChunk() |
121 | { |
122 | Qt3DCore::QFrameChunk c; |
123 | |
124 | c.init(blockSize: 16, blocks: 12); |
125 | |
126 | void *ptr = c.allocate(blockSize: 16); |
127 | |
128 | QVERIFY(c.contains(ptr, 16)); |
129 | QVERIFY(!c.isEmpty()); |
130 | QCOMPARE(c.m_blocksAvailable, (uchar)(c.m_maxBlocksAvailable - 1)); |
131 | QVERIFY(ptr != nullptr); |
132 | QCOMPARE(c.m_firstAvailableBlock, (uchar)1); |
133 | QCOMPARE(*((uchar*)ptr), (uchar)1); |
134 | } |
135 | |
136 | void tst_QFrameAllocator::qvectorAllocationQFrameChunk() |
137 | { |
138 | Qt3DCore::QFrameChunk c; |
139 | |
140 | c.init(blockSize: 16, blocks: 12); |
141 | |
142 | QVector<int> *v = nullptr; |
143 | |
144 | QVERIFY(sizeof(v) < 16); |
145 | v = static_cast<QVector<int> *>(c.allocate(blockSize: 16)); |
146 | QVERIFY(v != nullptr); |
147 | new (v) QVector<int>(); |
148 | for (int i = 0; i < 1024; i++) |
149 | v->append(t: i); |
150 | } |
151 | |
152 | void tst_QFrameAllocator::multipleAllocationQFrameChunk() |
153 | { |
154 | Qt3DCore::QFrameChunk c; |
155 | |
156 | c.init(blockSize: 16, blocks: 12); |
157 | |
158 | QList<void *> ptrs; |
159 | for (int i = 0; i < 6; i++) { |
160 | ptrs << c.allocate(blockSize: 16); |
161 | } |
162 | |
163 | QCOMPARE(c.m_maxBlocksAvailable, (uchar)12); |
164 | QCOMPARE(c.m_blocksAvailable, (uchar)6); |
165 | QCOMPARE(c.m_firstAvailableBlock, (uchar)6); |
166 | QVERIFY(!c.isEmpty()); |
167 | for (int i = 0; i < 6; i++) { |
168 | QVERIFY(ptrs.at(i) != nullptr); |
169 | QCOMPARE(*((uchar*)ptrs.at(i)), (uchar)(i + 1)); |
170 | } |
171 | } |
172 | |
173 | void tst_QFrameAllocator::overflowAllocationQFrameChunk() |
174 | { |
175 | Qt3DCore::QFrameChunk c; |
176 | |
177 | c.init(blockSize: 16, blocks: 12); |
178 | |
179 | QList<void *> ptrs; |
180 | for (int i = 0; i < 15; i++) { |
181 | ptrs << c.allocate(blockSize: 16); |
182 | } |
183 | |
184 | QCOMPARE(c.m_maxBlocksAvailable, (uchar)12); |
185 | QCOMPARE(c.m_blocksAvailable,(uchar) 0); |
186 | QCOMPARE(c.m_firstAvailableBlock, (uchar)12); |
187 | QVERIFY(!c.isEmpty()); |
188 | for (int i = 0; i < 15; i++) { |
189 | if (i < 12) { |
190 | QVERIFY(ptrs.at(i) != nullptr); |
191 | QCOMPARE(*((uchar*)ptrs.at(i)), (uchar)(i + 1)); |
192 | } |
193 | else { |
194 | QVERIFY(ptrs.at(i) == nullptr); |
195 | } |
196 | } |
197 | } |
198 | |
199 | void tst_QFrameAllocator::singleDeallocationQFrameChunk() |
200 | { |
201 | Qt3DCore::QFrameChunk c; |
202 | |
203 | c.init(blockSize: 16, blocks: 12); |
204 | |
205 | void *ptr = c.allocate(blockSize: 16); |
206 | |
207 | c.deallocate(p: ptr, blockSize: 16); |
208 | |
209 | QVERIFY(c.m_blocksAvailable == c.m_maxBlocksAvailable); |
210 | QCOMPARE(c.m_blocksAvailable, (uchar)12); |
211 | QCOMPARE(c.m_firstAvailableBlock, (uchar)0); |
212 | QVERIFY(c.m_data != nullptr); |
213 | QVERIFY(c.isEmpty()); |
214 | |
215 | for (int i = 0; i < 12; i++) { |
216 | QCOMPARE(c.m_data[i * 16], (uchar)(i + 1)); |
217 | } |
218 | } |
219 | |
220 | void tst_QFrameAllocator::multipleDeallocationQFrameChunk() |
221 | { |
222 | Qt3DCore::QFrameChunk c; |
223 | |
224 | c.init(blockSize: 16, blocks: 12); |
225 | |
226 | QList<void *> ptrs; |
227 | for (int i = 0; i < 6; i++) { |
228 | ptrs << c.allocate(blockSize: 16); |
229 | } |
230 | |
231 | // Free half |
232 | |
233 | for (int i = 0; i < 6; i++) { |
234 | c.deallocate(p: ptrs.at(i), blockSize: 16); |
235 | QCOMPARE(c.m_firstAvailableBlock, (uchar)(i)); |
236 | } |
237 | |
238 | QVERIFY(c.m_blocksAvailable == c.m_maxBlocksAvailable); |
239 | QCOMPARE(c.m_blocksAvailable, (uchar)12); |
240 | QVERIFY(c.m_data != nullptr); |
241 | QVERIFY(c.isEmpty()); |
242 | |
243 | // Refill all |
244 | ptrs.clear(); |
245 | for (int i = 0; i < 12; i++) { |
246 | void *ptr = c.allocate(blockSize: 16); |
247 | ptrs << ptr; |
248 | QVERIFY(ptr != nullptr); |
249 | } |
250 | QVERIFY(!c.isEmpty()); |
251 | |
252 | // Free all |
253 | for (int i = 0; i < 12; i++) { |
254 | c.deallocate(p: ptrs.at(i), blockSize: 16); |
255 | } |
256 | QVERIFY(c.isEmpty()); |
257 | |
258 | // Refill all |
259 | ptrs.clear(); |
260 | |
261 | for (int i = 0; i < 12; i++) { |
262 | void *ptr = c.allocate(blockSize: 16); |
263 | ptrs << ptr; |
264 | QVERIFY(ptr != nullptr); |
265 | } |
266 | |
267 | // Free all in non linear behavior |
268 | for (int i = 0; i < 6; i++) { |
269 | c.deallocate(p: ptrs.takeLast(), blockSize: 16); |
270 | c.deallocate(p: ptrs.takeFirst(), blockSize: 16); |
271 | } |
272 | QVERIFY(c.isEmpty()); |
273 | |
274 | // Refill all |
275 | ptrs.clear(); |
276 | for (int i = 0; i < 12; i++) { |
277 | void *ptr = c.allocate(blockSize: 16); |
278 | ptrs << ptr; |
279 | QVERIFY(ptr != nullptr); |
280 | } |
281 | QVERIFY(!c.isEmpty()); |
282 | } |
283 | |
284 | void tst_QFrameAllocator::containsCheckQFrameChunk() |
285 | { |
286 | Qt3DCore::QFrameChunk c; |
287 | Qt3DCore::QFrameChunk c2; |
288 | |
289 | c.init(blockSize: 16, blocks: 12); |
290 | c2.init(blockSize: 16, blocks: 12); |
291 | |
292 | QList<void *> ptrs; |
293 | for (int i = 0; i < 6; i++) { |
294 | ptrs << c.allocate(blockSize: 16); |
295 | } |
296 | |
297 | QVERIFY(!c.contains((void *)(quintptr)0xffffffff, 16)); |
298 | QVERIFY(!c2.contains((void *)(quintptr)0xffffffff, 16)); |
299 | QVERIFY(c.contains(ptrs.first(), 16)); |
300 | QVERIFY(!c2.contains(ptrs.first(), 16)); |
301 | QVERIFY(c.contains(ptrs.last(), 16)); |
302 | QVERIFY(!c2.contains(ptrs.last(), 16)); |
303 | |
304 | for (int i = 0; i < 6; i++) { |
305 | ptrs << c2.allocate(blockSize: 16); |
306 | } |
307 | |
308 | QVERIFY(!c.contains((void *)(quintptr)0xffffffff, 16)); |
309 | QVERIFY(!c.contains(ptrs.last(), 16)); |
310 | QVERIFY(c.contains(ptrs.first(), 16)); |
311 | QVERIFY(c2.contains(ptrs.last(), 16)); |
312 | QVERIFY(!c2.contains(ptrs.first(), 16)); |
313 | } |
314 | |
315 | void tst_QFrameAllocator::clearQFrameChunk() |
316 | { |
317 | Qt3DCore::QFrameChunk c; |
318 | |
319 | c.init(blockSize: 16, blocks: 12); |
320 | QList<void *> ptrs; |
321 | for (int i = 0; i < 6; i++) { |
322 | ptrs << c.allocate(blockSize: 16); |
323 | } |
324 | QVERIFY(!c.isEmpty()); |
325 | c.clear(blockSize: 16, blocks: 12); |
326 | QVERIFY(c.isEmpty()); |
327 | QCOMPARE(c.m_blocksAvailable, c.m_maxBlocksAvailable); |
328 | QCOMPARE(c.m_firstAvailableBlock, (uchar)0); |
329 | |
330 | for (int i = 0; i < 12; i++) { |
331 | QCOMPARE(c.m_data[i * 16], (uchar)(i + 1)); |
332 | } |
333 | } |
334 | |
335 | void tst_QFrameAllocator::initQFixedFrameAllocator() |
336 | { |
337 | Qt3DCore::QFixedFrameAllocator f; |
338 | |
339 | f.init(blockSize: 4); |
340 | |
341 | QCOMPARE(f.chunkCount(), 0); |
342 | QCOMPARE(f.pageSize(), (uchar)128); |
343 | } |
344 | |
345 | void tst_QFrameAllocator::allocateQFixedFrameAllocator() |
346 | { |
347 | Qt3DCore::QFixedFrameAllocator f; |
348 | |
349 | f.init(blockSize: 4, pageSize: 128); |
350 | |
351 | QList<void *> ptrs; |
352 | |
353 | // Fill 1 chunck |
354 | for (int i = 0; i < 128; i++) { |
355 | void *ptr = f.allocate(); |
356 | QVERIFY(ptr != nullptr); |
357 | ptrs << ptr; |
358 | } |
359 | QCOMPARE(f.chunkCount(), 1); |
360 | // Fill half of chunk 2 |
361 | for (int i = 0; i < 64; i++) { |
362 | void *ptr = f.allocate(); |
363 | QVERIFY(ptr != nullptr); |
364 | ptrs << ptr; |
365 | } |
366 | // Free chunk 2 |
367 | QCOMPARE(f.chunkCount(), 2); |
368 | for (int i = 0; i < 64; i++) { |
369 | f.deallocate(ptr: ptrs.takeLast()); |
370 | } |
371 | // Allocate 2 chunks worth of data which should create a single new chunk |
372 | // as chunk 2 is empty |
373 | QCOMPARE(f.chunkCount(), 2); |
374 | |
375 | for (int i = 0; i < 256; i++) { |
376 | void *ptr = f.allocate(); |
377 | QVERIFY(ptr != nullptr); |
378 | ptrs << ptr; |
379 | } |
380 | QCOMPARE(f.chunkCount(), 3); |
381 | } |
382 | |
383 | void tst_QFrameAllocator::deallocateQFixedFrameAllocator() |
384 | { |
385 | Qt3DCore::QFixedFrameAllocator f; |
386 | |
387 | f.init(blockSize: 4); |
388 | |
389 | QList<void *> ptrs; |
390 | |
391 | for (int i = 0; i < 128; i++) { |
392 | void *ptr = f.allocate(); |
393 | QVERIFY(ptr != nullptr); |
394 | ptrs << ptr; |
395 | } |
396 | QCOMPARE(f.chunkCount(), 1); |
397 | for (int i = 0; i < 64; i++) { |
398 | void *ptr = f.allocate(); |
399 | QVERIFY(ptr != nullptr); |
400 | ptrs << ptr; |
401 | } |
402 | QCOMPARE(f.chunkCount(), 2); |
403 | for (int i = 0; i < 64; i++) { |
404 | f.deallocate(ptr: ptrs.takeLast()); |
405 | } |
406 | QCOMPARE(f.chunkCount(), 2); |
407 | f.trim(); |
408 | QCOMPARE(f.chunkCount(), 1); |
409 | |
410 | for (int i = 0; i < 64; i++) { |
411 | f.deallocate(ptr: ptrs.takeFirst()); |
412 | } |
413 | QCOMPARE(f.chunkCount(), 1); |
414 | for (int i = 0; i < 36; i++) { |
415 | void *ptr = f.allocate(); |
416 | QVERIFY(ptr != nullptr); |
417 | ptrs << ptr; |
418 | } |
419 | QCOMPARE(f.chunkCount(), 1); |
420 | } |
421 | |
422 | void tst_QFrameAllocator::checkFragmentationQFixedFrameAllocator() |
423 | { |
424 | Qt3DCore::QFixedFrameAllocator f; |
425 | |
426 | f.init(blockSize: 4); |
427 | |
428 | QList<void *> ptrs; |
429 | |
430 | for (int i = 0; i < 256; i++) { |
431 | void *ptr = f.allocate(); |
432 | QVERIFY(ptr != nullptr); |
433 | ptrs << ptr; |
434 | } |
435 | |
436 | QCOMPARE(f.chunkCount(), 2); |
437 | |
438 | for (int i = 0; i < 64; i++) { |
439 | f.deallocate(ptr: ptrs.takeFirst()); |
440 | } |
441 | |
442 | QCOMPARE(f.chunkCount(), 2); |
443 | |
444 | for (int i = 0; i < 64; i++) { |
445 | void *ptr = f.allocate(); |
446 | QVERIFY(ptr != nullptr); |
447 | ptrs << ptr; |
448 | } |
449 | QCOMPARE(f.chunkCount(), 2); |
450 | } |
451 | |
452 | void tst_QFrameAllocator::clearQFixedFrameAllocator() |
453 | { |
454 | Qt3DCore::QFixedFrameAllocator f; |
455 | |
456 | f.init(blockSize: 16); |
457 | |
458 | QList<void *> ptrs; |
459 | |
460 | for (int i = 0; i < 256; i++) { |
461 | void *ptr = f.allocate(); |
462 | QVERIFY(ptr != nullptr); |
463 | ptrs << ptr; |
464 | } |
465 | QCOMPARE(f.chunkCount(), 2); |
466 | |
467 | f.clear(); |
468 | QCOMPARE(f.chunkCount(), 2); |
469 | |
470 | for (int i = 0; i < 256; i++) { |
471 | void *ptr = f.allocate(); |
472 | QVERIFY(ptr != nullptr); |
473 | ptrs << ptr; |
474 | } |
475 | QCOMPARE(f.chunkCount(), 2); |
476 | } |
477 | |
478 | void tst_QFrameAllocator::initQFrameAllocator() |
479 | { |
480 | Qt3DCore::QFrameAllocator f(4, 4); |
481 | QCOMPARE(f.allocatorPoolSize(), 1); |
482 | |
483 | |
484 | Qt3DCore::QFrameAllocator f2(32, 4); |
485 | QCOMPARE(f2.allocatorPoolSize(), 8); |
486 | } |
487 | |
488 | void tst_QFrameAllocator::allocateWithQFrameAllocator() |
489 | { |
490 | Qt3DCore::QFrameAllocator f2(256, 4); |
491 | QCOMPARE(f2.allocatorPoolSize(), 256 / 4); |
492 | |
493 | QVERIFY(f2.allocate<small>()); |
494 | QVERIFY(f2.allocate<medium>()); |
495 | QVERIFY(f2.allocate<big>()); |
496 | QVERIFY(f2.allocate<huge>()); |
497 | |
498 | QList<medium *> mediums; |
499 | for (int i = 0; i < 800; i++) { |
500 | medium *m = f2.allocate<medium>(); |
501 | QVERIFY(m); |
502 | m->a = i; |
503 | m->b = 800; |
504 | m->c = m->b - m->a; |
505 | mediums.append(t: m); |
506 | } |
507 | QCOMPARE(mediums.size(), 800); |
508 | for (int i = 0; i < 800; i++) { |
509 | medium *m = mediums.at(i); |
510 | QCOMPARE(m->a, i); |
511 | QCOMPARE(m->b, 800); |
512 | QCOMPARE(m->c, m->b - m->a); |
513 | } |
514 | |
515 | QList<huge *> huges; |
516 | for (int i = 0; i < 250; i++) { |
517 | huge *m = f2.allocate<huge>(); |
518 | QCOMPARE((int)(sizeof(m->t) / sizeof(int)), 64); |
519 | for (int j = 0; j < 64; j++) |
520 | m->t[j] = i * j; |
521 | huges.append(t: m); |
522 | } |
523 | for (int i = 0; i < 250; i++) { |
524 | huge *m = huges.at(i); |
525 | for (int j = 0; j < 64; j++) |
526 | QCOMPARE(m->t[j], i * j); |
527 | } |
528 | } |
529 | |
530 | void tst_QFrameAllocator::deallocateWithQFrameAllocator() |
531 | { |
532 | Qt3DCore::QFrameAllocator f2(256, 4); |
533 | QCOMPARE(f2.allocatorPoolSize(), 256 / 4); |
534 | |
535 | small *s = f2.allocate<small>(); |
536 | QVERIFY(s); |
537 | medium *m = f2.allocate<medium>(); |
538 | QVERIFY(m); |
539 | big *b = f2.allocate<big>(); |
540 | QVERIFY(b); |
541 | huge *h = f2.allocate<huge>(); |
542 | QVERIFY(h); |
543 | |
544 | f2.deallocate(ptr: s); |
545 | f2.deallocate(ptr: m); |
546 | f2.deallocate(ptr: b); |
547 | f2.deallocate(ptr: h); |
548 | } |
549 | |
550 | void tst_QFrameAllocator::testAllocationComposedValues() |
551 | { |
552 | Qt3DCore::QFrameAllocator f(128, 32); |
553 | |
554 | composed t; |
555 | |
556 | QVector<int> *v = f.allocate<QVector<int> >(); |
557 | |
558 | QVERIFY(v); |
559 | |
560 | for (int i = 0; i < 10; i++) |
561 | v->append(t: 2); |
562 | |
563 | |
564 | for (int i = 0; i < 100; i++) { |
565 | t.vec.append(t: i); |
566 | t.list.append(t: i); |
567 | } |
568 | |
569 | composed *composedValues[30]; |
570 | |
571 | for (auto &v : composedValues) { |
572 | v = f.allocate<composed>(); |
573 | QVERIFY(v); |
574 | for (int j = 0; j < 100; j++) { |
575 | v->vec.append(t: j); |
576 | v->list.append(t: j); |
577 | v->t = 100; |
578 | } |
579 | } |
580 | |
581 | for (composed *c : composedValues) { |
582 | QCOMPARE(c->vec.size(), 100); |
583 | QCOMPARE(c->list.size(), 100); |
584 | QCOMPARE(c->t, 100); |
585 | |
586 | for (int j = 0; j < 100; j++) { |
587 | QCOMPARE(c->vec.at(j), j); |
588 | QCOMPARE(c->list.at(j), j); |
589 | } |
590 | } |
591 | } |
592 | |
593 | void tst_QFrameAllocator::allocateSubclass() |
594 | { |
595 | Qt3DCore::QFrameAllocator f(128, 32); |
596 | |
597 | QList<composed *> composeds; |
598 | |
599 | for (int i = 0; i < 256; i++) { |
600 | // Allocate a composed object of size subclass |
601 | // c is actually a subclass |
602 | composed *c = static_cast<composed*>(f.allocateRawMemory(size: sizeof(subclass))); |
603 | composeds << c; |
604 | } |
605 | |
606 | QCOMPARE(composeds.count(), 256); |
607 | |
608 | for (composed *c : qAsConst(t&: composeds)) { |
609 | subclass *s = static_cast<subclass *>(c); |
610 | s->toto = 2586.0f; |
611 | } |
612 | |
613 | for (int i = 0; i < 256; i++) { |
614 | subclass *s = static_cast<subclass *>(composeds.takeLast()); |
615 | QVERIFY(s->toto == 2586.0f); |
616 | } |
617 | } |
618 | |
619 | void tst_QFrameAllocator::deallocateSubclass() |
620 | { |
621 | Qt3DCore::QFrameAllocator f(128, 32); |
622 | |
623 | |
624 | const int NUM_ITEMS = 256; |
625 | QVector<void *> allocated(NUM_ITEMS); |
626 | uint chunkCount = 0; |
627 | |
628 | for (int l = 0; l < 6; l++) { |
629 | |
630 | for (int i = 0; i < NUM_ITEMS; i++) { |
631 | // Allocate a composed object of size subclass |
632 | // c is actually a subclass |
633 | allocated[i] = f.allocateRawMemory(size: sizeof(subclass)); |
634 | } |
635 | |
636 | if (!chunkCount) |
637 | chunkCount = f.totalChunkCount(); |
638 | else |
639 | QCOMPARE(chunkCount, f.totalChunkCount()); |
640 | |
641 | for (int i = 0; i < NUM_ITEMS; i++) { |
642 | f.deallocateRawMemory(ptr: allocated[i], size: sizeof(subclass)); |
643 | } |
644 | } |
645 | |
646 | } |
647 | |
648 | void tst_QFrameAllocator::clearQFrameAllocator() |
649 | { |
650 | Qt3DCore::QFrameAllocator f(128, 32); |
651 | |
652 | for (int i = 0; i < 256; i++) { |
653 | f.allocate<composed>(); |
654 | } |
655 | uint chunkCount = f.totalChunkCount(); |
656 | f.clear(); |
657 | QCOMPARE(chunkCount, f.totalChunkCount()); |
658 | |
659 | for (int i = 0; i < 256; i++) { |
660 | QList<composed *> composeds; |
661 | for (int j = 0; j < 256; j++) { |
662 | composed *c = f.allocate<composed>(); |
663 | c ->t = i * j; |
664 | composeds << c; |
665 | } |
666 | QCOMPARE(chunkCount, f.totalChunkCount()); |
667 | for (int j = 0; j < 256; j++) { |
668 | QCOMPARE(composeds.at(j)->t, i * j); |
669 | } |
670 | f.clear(); |
671 | QCOMPARE(chunkCount, f.totalChunkCount()); |
672 | } |
673 | } |
674 | |
675 | void tst_QFrameAllocator::isEmptyQFrameAllocator() |
676 | { |
677 | // GIVEN |
678 | Qt3DCore::QFrameAllocator f(128, 32); |
679 | |
680 | |
681 | // WHEN |
682 | for (int i = 0; i < 256; ++i) |
683 | f.allocate<composed>(); |
684 | // THEN |
685 | QVERIFY(!f.isEmpty()); |
686 | |
687 | // WHEN |
688 | f.clear(); |
689 | // THEN |
690 | QVERIFY(f.isEmpty()); |
691 | |
692 | for (int i = 0; i < 256; ++i) { |
693 | |
694 | // GIVEN |
695 | QVector<composed *> composeds; |
696 | for (int j = 0; j < 256; ++j) { |
697 | composed *c = f.allocate<composed>(); |
698 | c ->t = i * j; |
699 | composeds << c; |
700 | } |
701 | // THEN |
702 | QVERIFY(!f.isEmpty()); |
703 | |
704 | // WHEN |
705 | for (int j = 0; j < 256; ++j) |
706 | f.deallocate(ptr: composeds.takeAt(i: 0)); |
707 | // THEN |
708 | QVERIFY(f.isEmpty()); |
709 | } |
710 | } |
711 | |
712 | void tst_QFrameAllocator::subclassPointerClearing() |
713 | { |
714 | // GIVEN |
715 | Qt3DCore::QFrameAllocator f(128, 32); |
716 | QVector<composed *> data; |
717 | |
718 | // WHEN |
719 | for (int i = 0; i < 32; ++i) { |
720 | composed *c = (i % 2 == 0) ? f.allocate<composed>() : f.allocate<subclass>(); |
721 | data.append(t: c); |
722 | } |
723 | // THEN |
724 | QVERIFY(!f.isEmpty()); |
725 | |
726 | // WHEN |
727 | for (int j = 0; j < 32; ++j) { |
728 | if ((j % 2 == 0)) |
729 | f.deallocate<composed>(ptr: data.takeAt(i: 0)); |
730 | else |
731 | f.deallocate<subclass>(ptr: static_cast<subclass *>(data.takeAt(i: 0))); |
732 | } |
733 | |
734 | // THEN |
735 | QVERIFY(f.isEmpty()); |
736 | } |
737 | |
738 | void tst_QFrameAllocator::allocateWithRawMemoryDeallocate() |
739 | { |
740 | // GIVEN |
741 | Qt3DCore::QFrameAllocator f(128, 32); |
742 | subclass *s = static_cast<subclass *>(f.allocateRawMemory(size: sizeof(subclass))); |
743 | new (s) subclass(); |
744 | |
745 | // WHEN |
746 | f.deallocate(ptr: s); |
747 | |
748 | // THEN |
749 | QVERIFY(f.isEmpty()); |
750 | } |
751 | |
752 | void tst_QFrameAllocator::allocateDeallocateRawMemory() |
753 | { |
754 | // GIVEN |
755 | Qt3DCore::QFrameAllocator f(128, 32); |
756 | subclass *s = f.allocate<subclass>(); |
757 | |
758 | // WHEN |
759 | f.deallocateRawMemory(ptr: s, size: sizeof(subclass)); |
760 | |
761 | // THEN |
762 | QVERIFY(f.isEmpty()); |
763 | } |
764 | |
765 | QTEST_APPLESS_MAIN(tst_QFrameAllocator) |
766 | |
767 | #include "tst_qframeallocator.moc" |
768 | |