289 QCOMPARE(values[1].size(), 20); |
290 QCOMPARE(values[1].size(), 20); |
290 QCOMPARE(values.size(), 2); |
291 QCOMPARE(values.size(), 2); |
291 } |
292 } |
292 } |
293 } |
293 |
294 |
|
295 struct MyBase |
|
296 { |
|
297 MyBase() |
|
298 : data(this) |
|
299 , isCopy(false) |
|
300 { |
|
301 ++liveCount; |
|
302 } |
|
303 |
|
304 MyBase(MyBase const &) |
|
305 : data(this) |
|
306 , isCopy(true) |
|
307 { |
|
308 ++copyCount; |
|
309 ++liveCount; |
|
310 } |
|
311 |
|
312 MyBase & operator=(MyBase const &) |
|
313 { |
|
314 if (!isCopy) { |
|
315 isCopy = true; |
|
316 ++copyCount; |
|
317 } else { |
|
318 ++errorCount; |
|
319 } |
|
320 |
|
321 return *this; |
|
322 } |
|
323 |
|
324 ~MyBase() |
|
325 { |
|
326 if (isCopy) { |
|
327 if (!copyCount) |
|
328 ++errorCount; |
|
329 else |
|
330 --copyCount; |
|
331 } |
|
332 |
|
333 if (!liveCount) |
|
334 ++errorCount; |
|
335 else |
|
336 --liveCount; |
|
337 } |
|
338 |
|
339 bool hasMoved() const |
|
340 { |
|
341 return this != data; |
|
342 } |
|
343 |
|
344 protected: |
|
345 MyBase const * const data; |
|
346 bool isCopy; |
|
347 |
|
348 public: |
|
349 static int errorCount; |
|
350 static int liveCount; |
|
351 static int copyCount; |
|
352 }; |
|
353 |
|
354 int MyBase::errorCount = 0; |
|
355 int MyBase::liveCount = 0; |
|
356 int MyBase::copyCount = 0; |
|
357 |
|
358 struct MyPrimitive |
|
359 : MyBase |
|
360 { |
|
361 MyPrimitive() |
|
362 { |
|
363 ++errorCount; |
|
364 } |
|
365 |
|
366 ~MyPrimitive() |
|
367 { |
|
368 ++errorCount; |
|
369 } |
|
370 |
|
371 MyPrimitive(MyPrimitive const &other) |
|
372 : MyBase(other) |
|
373 { |
|
374 ++errorCount; |
|
375 } |
|
376 }; |
|
377 |
|
378 struct MyMovable |
|
379 : MyBase |
|
380 { |
|
381 }; |
|
382 |
|
383 struct MyComplex |
|
384 : MyBase |
|
385 { |
|
386 }; |
|
387 |
|
388 QT_BEGIN_NAMESPACE |
|
389 |
|
390 Q_DECLARE_TYPEINFO(MyPrimitive, Q_PRIMITIVE_TYPE); |
|
391 Q_DECLARE_TYPEINFO(MyMovable, Q_MOVABLE_TYPE); |
|
392 Q_DECLARE_TYPEINFO(MyComplex, Q_COMPLEX_TYPE); |
|
393 |
|
394 QT_END_NAMESPACE |
|
395 |
|
396 bool QTBUG10978_proceed = true; |
|
397 |
|
398 template <class T, int PreAlloc> |
|
399 int countMoved(QVarLengthArray<T, PreAlloc> const &c) |
|
400 { |
|
401 int result = 0; |
|
402 for (int i = 0; i < c.size(); ++i) |
|
403 if (c[i].hasMoved()) |
|
404 ++result; |
|
405 |
|
406 return result; |
|
407 } |
|
408 |
|
409 template <class T> |
|
410 void QTBUG10978_test() |
|
411 { |
|
412 QTBUG10978_proceed = false; |
|
413 |
|
414 typedef QVarLengthArray<T, 16> Container; |
|
415 enum { |
|
416 isStatic = QTypeInfo<T>::isStatic, |
|
417 isComplex = QTypeInfo<T>::isComplex, |
|
418 |
|
419 isPrimitive = !isComplex && !isStatic, |
|
420 isMovable = !isStatic |
|
421 }; |
|
422 |
|
423 // Constructors |
|
424 Container a; |
|
425 QCOMPARE( MyBase::liveCount, 0 ); |
|
426 QCOMPARE( MyBase::copyCount, 0 ); |
|
427 |
|
428 QVERIFY( a.capacity() >= 16 ); |
|
429 QCOMPARE( a.size(), 0 ); |
|
430 |
|
431 Container b_real(8); |
|
432 Container const &b = b_real; |
|
433 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 8 ); |
|
434 QCOMPARE( MyBase::copyCount, 0 ); |
|
435 |
|
436 QVERIFY( b.capacity() >= 16 ); |
|
437 QCOMPARE( b.size(), 8 ); |
|
438 |
|
439 // Assignment |
|
440 a = b; |
|
441 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 16 ); |
|
442 QCOMPARE( MyBase::copyCount, isComplex ? 8 : 0 ); |
|
443 QVERIFY( a.capacity() >= 16 ); |
|
444 QCOMPARE( a.size(), 8 ); |
|
445 |
|
446 QVERIFY( b.capacity() >= 16 ); |
|
447 QCOMPARE( b.size(), 8 ); |
|
448 |
|
449 // append |
|
450 a.append(b.data(), b.size()); |
|
451 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 24 ); |
|
452 QCOMPARE( MyBase::copyCount, isComplex ? 16 : 0 ); |
|
453 |
|
454 QVERIFY( a.capacity() >= 16 ); |
|
455 QCOMPARE( a.size(), 16 ); |
|
456 |
|
457 QVERIFY( b.capacity() >= 16 ); |
|
458 QCOMPARE( b.size(), 8 ); |
|
459 |
|
460 // removeLast |
|
461 a.removeLast(); |
|
462 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 23 ); |
|
463 QCOMPARE( MyBase::copyCount, isComplex ? 15 : 0 ); |
|
464 |
|
465 QVERIFY( a.capacity() >= 16 ); |
|
466 QCOMPARE( a.size(), 15 ); |
|
467 |
|
468 QVERIFY( b.capacity() >= 16 ); |
|
469 QCOMPARE( b.size(), 8 ); |
|
470 |
|
471 // Movable types |
|
472 const int capacity = a.capacity(); |
|
473 if (!isPrimitive) |
|
474 QCOMPARE( countMoved(a), 0 ); |
|
475 |
|
476 // Reserve, no re-allocation |
|
477 a.reserve(capacity); |
|
478 if (!isPrimitive) |
|
479 QCOMPARE( countMoved(a), 0 ); |
|
480 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 23 ); |
|
481 QCOMPARE( MyBase::copyCount, isComplex ? 15 : 0 ); |
|
482 |
|
483 QCOMPARE( a.capacity(), capacity ); |
|
484 QCOMPARE( a.size(), 15 ); |
|
485 |
|
486 QVERIFY( b.capacity() >= 16 ); |
|
487 QCOMPARE( b.size(), 8 ); |
|
488 |
|
489 // Reserve, force re-allocation |
|
490 a.reserve(capacity * 2); |
|
491 if (!isPrimitive) |
|
492 QCOMPARE( countMoved(a), isMovable ? 15 : 0 ); |
|
493 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 23 ); |
|
494 QCOMPARE( MyBase::copyCount, isComplex ? 15 : 0 ); |
|
495 |
|
496 QVERIFY( a.capacity() >= capacity * 2 ); |
|
497 QCOMPARE( a.size(), 15 ); |
|
498 |
|
499 QVERIFY( b.capacity() >= 16 ); |
|
500 QCOMPARE( b.size(), 8 ); |
|
501 |
|
502 // resize, grow |
|
503 a.resize(40); |
|
504 if (!isPrimitive) |
|
505 QCOMPARE( countMoved(a), isMovable ? 15 : 0 ); |
|
506 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 48 ); |
|
507 QCOMPARE( MyBase::copyCount, isComplex ? 15 : 0 ); |
|
508 |
|
509 QVERIFY( a.capacity() >= a.size() ); |
|
510 QCOMPARE( a.size(), 40 ); |
|
511 |
|
512 QVERIFY( b.capacity() >= 16 ); |
|
513 QCOMPARE( b.size(), 8 ); |
|
514 |
|
515 // Copy constructor, allocate |
|
516 { |
|
517 Container c(a); |
|
518 if (!isPrimitive) |
|
519 QCOMPARE( countMoved(c), 0 ); |
|
520 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 88 ); |
|
521 QCOMPARE( MyBase::copyCount, isComplex ? 55 : 0 ); |
|
522 |
|
523 QVERIFY( a.capacity() >= a.size() ); |
|
524 QCOMPARE( a.size(), 40 ); |
|
525 |
|
526 QVERIFY( b.capacity() >= 16 ); |
|
527 QCOMPARE( b.size(), 8 ); |
|
528 |
|
529 QVERIFY( c.capacity() >= 40 ); |
|
530 QCOMPARE( c.size(), 40 ); |
|
531 } |
|
532 |
|
533 // resize, shrink |
|
534 a.resize(10); |
|
535 if (!isPrimitive) |
|
536 QCOMPARE( countMoved(a), isMovable ? 10 : 0 ); |
|
537 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 18 ); |
|
538 QCOMPARE( MyBase::copyCount, isComplex ? 10 : 0 ); |
|
539 |
|
540 QVERIFY( a.capacity() >= a.size() ); |
|
541 QCOMPARE( a.size(), 10 ); |
|
542 |
|
543 QVERIFY( b.capacity() >= 16 ); |
|
544 QCOMPARE( b.size(), 8 ); |
|
545 |
|
546 // Copy constructor, don't allocate |
|
547 { |
|
548 Container c(a); |
|
549 if (!isPrimitive) |
|
550 QCOMPARE( countMoved(c), 0 ); |
|
551 QCOMPARE( MyBase::liveCount, isPrimitive ? 0 : 28 ); |
|
552 QCOMPARE( MyBase::copyCount, isComplex ? 20 : 0 ); |
|
553 |
|
554 QVERIFY( a.capacity() >= a.size() ); |
|
555 QCOMPARE( a.size(), 10 ); |
|
556 |
|
557 QVERIFY( b.capacity() >= 16 ); |
|
558 QCOMPARE( b.size(), 8 ); |
|
559 |
|
560 QVERIFY( c.capacity() >= 16 ); |
|
561 QCOMPARE( c.size(), 10 ); |
|
562 } |
|
563 |
|
564 a.clear(); |
|
565 QCOMPARE( a.size(), 0 ); |
|
566 |
|
567 b_real.clear(); |
|
568 QCOMPARE( b.size(), 0 ); |
|
569 |
|
570 QCOMPARE(MyBase::errorCount, 0); |
|
571 QCOMPARE(MyBase::liveCount, 0); |
|
572 |
|
573 // All done |
|
574 QTBUG10978_proceed = true; |
|
575 } |
|
576 |
|
577 void tst_QVarLengthArray::QTBUG10978_realloc() |
|
578 { |
|
579 QTBUG10978_test<MyBase>(); |
|
580 QVERIFY(QTBUG10978_proceed); |
|
581 |
|
582 QTBUG10978_test<MyPrimitive>(); |
|
583 QVERIFY(QTBUG10978_proceed); |
|
584 |
|
585 QTBUG10978_test<MyMovable>(); |
|
586 QVERIFY(QTBUG10978_proceed); |
|
587 |
|
588 QTBUG10978_test<MyComplex>(); |
|
589 QVERIFY(QTBUG10978_proceed); |
|
590 } |
|
591 |
294 QTEST_APPLESS_MAIN(tst_QVarLengthArray) |
592 QTEST_APPLESS_MAIN(tst_QVarLengthArray) |
295 #include "tst_qvarlengtharray.moc" |
593 #include "tst_qvarlengtharray.moc" |