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#include <QAtomicInt>
31#include <QThread>
32#include <QSemaphore>
33#include <qvector.h>
34
35struct Movable {
36 Movable(char input = 'j')
37 : i(input)
38 , that(this)
39 , state(Constructed)
40 {
41 counter.fetchAndAddRelaxed(valueToAdd: 1);
42 }
43 Movable(const Movable &other)
44 : i(other.i)
45 , that(this)
46 , state(Constructed)
47 {
48 check(state1: other.state, state2: Constructed);
49 counter.fetchAndAddRelaxed(valueToAdd: 1);
50 }
51 Movable(Movable &&other)
52 : i(other.i)
53 , that(other.that)
54 , state(Constructed)
55 {
56 check(state1: other.state, state2: Constructed);
57 counter.fetchAndAddRelaxed(valueToAdd: 1);
58 other.that = nullptr;
59 }
60
61 ~Movable()
62 {
63 check(state1: state, state2: Constructed);
64 i = 0;
65 counter.fetchAndAddRelaxed(valueToAdd: -1);
66 state = Destructed;
67 }
68
69 bool operator ==(const Movable &other) const
70 {
71 check(state1: state, state2: Constructed);
72 check(state1: other.state, state2: Constructed);
73 return i == other.i;
74 }
75
76 Movable &operator=(const Movable &other)
77 {
78 check(state1: state, state2: Constructed);
79 check(state1: other.state, state2: Constructed);
80 i = other.i;
81 that = this;
82 return *this;
83 }
84 Movable &operator=(Movable &&other)
85 {
86 check(state1: state, state2: Constructed);
87 check(state1: other.state, state2: Constructed);
88 i = other.i;
89 that = other.that;
90 other.that = nullptr;
91 return *this;
92 }
93 bool wasConstructedAt(const Movable *other) const
94 {
95 return that == other;
96 }
97 char i;
98 static QAtomicInt counter;
99private:
100 Movable *that; // used to check if an instance was moved
101
102 enum State { Constructed = 106, Destructed = 110 };
103 State state;
104
105 static void check(const State state1, const State state2)
106 {
107 QCOMPARE(state1, state2);
108 }
109};
110
111inline uint qHash(const Movable &key, uint seed = 0) { return qHash(key: key.i, seed); }
112
113QAtomicInt Movable::counter = 0;
114QT_BEGIN_NAMESPACE
115Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
116QT_END_NAMESPACE
117Q_DECLARE_METATYPE(Movable);
118
119struct Custom {
120 Custom(char input = 'j')
121 : i(input)
122 , that(this)
123 , state(Constructed)
124 {
125 counter.fetchAndAddRelaxed(valueToAdd: 1);
126 }
127 Custom(const Custom &other)
128 : that(this)
129 , state(Constructed)
130 {
131 check(c: &other);
132 counter.fetchAndAddRelaxed(valueToAdd: 1);
133 this->i = other.i;
134 }
135 ~Custom()
136 {
137 check(c: this);
138 i = 0;
139 counter.fetchAndAddRelaxed(valueToAdd: -1);
140 state = Destructed;
141 }
142
143 bool operator ==(const Custom &other) const
144 {
145 check(c: &other);
146 check(c: this);
147 return i == other.i;
148 }
149
150 bool operator<(const Custom &other) const
151 {
152 check(c: &other);
153 check(c: this);
154 return i < other.i;
155 }
156
157 Custom &operator=(const Custom &other)
158 {
159 check(c: &other);
160 check(c: this);
161 i = other.i;
162 return *this;
163 }
164 static QAtomicInt counter;
165
166 char i; // used to identify orgin of an instance
167private:
168 Custom *that; // used to check if an instance was moved
169
170 enum State { Constructed = 106, Destructed = 110 };
171 State state;
172
173 static void check(const Custom *c)
174 {
175 // check if c object has been moved
176 QCOMPARE(c, c->that);
177 QCOMPARE(c->state, Constructed);
178 }
179};
180QAtomicInt Custom::counter = 0;
181
182inline uint qHash(const Custom &key, uint seed = 0) { return qHash(key: key.i, seed); }
183
184Q_DECLARE_METATYPE(Custom);
185
186// Similar to Custom but not default-constructible and has move constructor and assignment
187struct NonDefaultConstructible {
188 NonDefaultConstructible() = delete;
189 NonDefaultConstructible(char input)
190 : i(input)
191 , that(this)
192 , state(Constructed)
193 {
194 counter.fetchAndAddRelaxed(valueToAdd: 1);
195 }
196 NonDefaultConstructible(const NonDefaultConstructible &other)
197 : i(other.i)
198 , that(this)
199 , state(Constructed)
200 {
201 check(c: &other);
202 counter.fetchAndAddRelaxed(valueToAdd: 1);
203 }
204 NonDefaultConstructible(NonDefaultConstructible &&other)
205 : i(other.i)
206 , that(this)
207 , state(Constructed)
208 {
209 check(c: &other);
210 other.state = MovedFrom;
211 counter.fetchAndAddRelaxed(valueToAdd: 1);
212 }
213 ~NonDefaultConstructible()
214 {
215 check(c: this, movedOk: true);
216 i = 0;
217 counter.fetchAndAddRelaxed(valueToAdd: -1);
218 state = Destructed;
219 }
220
221 bool operator==(const NonDefaultConstructible &other) const
222 {
223 check(c: &other);
224 check(c: this);
225 return i == other.i;
226 }
227
228 bool operator<(const NonDefaultConstructible &other) const
229 {
230 check(c: &other);
231 check(c: this);
232 return i < other.i;
233 }
234
235 NonDefaultConstructible &operator=(const NonDefaultConstructible &other)
236 {
237 check(c: &other);
238 check(c: this, movedOk: true);
239 i = other.i;
240 state = Constructed;
241 return *this;
242 }
243
244 NonDefaultConstructible &operator=(NonDefaultConstructible &&other)
245 {
246 check(c: &other);
247 check(c: this, movedOk: true);
248 i = other.i;
249 state = Constructed;
250 other.state = MovedFrom;
251 return *this;
252 }
253 static QAtomicInt counter;
254
255 char i; // used to identify origin of an instance
256private:
257 NonDefaultConstructible *that; // used to catch copying using mem{cpy,move}()
258
259 enum State { Constructed = 106, Destructed = 110, MovedFrom = 120 };
260 State state;
261
262 static void check(const NonDefaultConstructible *c, bool movedOk = false)
263 {
264 // check if c object has been moved incorrectly
265 QCOMPARE(c, c->that);
266 if (!movedOk || c->state != MovedFrom)
267 QCOMPARE(c->state, Constructed);
268 }
269};
270QAtomicInt NonDefaultConstructible::counter = 0;
271
272inline uint qHash(const NonDefaultConstructible &key, uint seed = 0) { return qHash(key: key.i, seed); }
273
274// tests depends on the fact that:
275Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic);
276Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex);
277Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic);
278Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex);
279Q_STATIC_ASSERT(QTypeInfo<Custom>::isStatic);
280Q_STATIC_ASSERT(QTypeInfo<Custom>::isComplex);
281Q_STATIC_ASSERT(QTypeInfo<NonDefaultConstructible>::isStatic);
282Q_STATIC_ASSERT(QTypeInfo<NonDefaultConstructible>::isComplex);
283
284
285class tst_QVector : public QObject
286{
287 Q_OBJECT
288private slots:
289 void constructors_empty() const;
290 void constructors_emptyReserveZero() const;
291 void constructors_emptyReserve() const;
292 void constructors_reserveAndInitialize() const;
293 void copyConstructorInt() const;
294 void copyConstructorMovable() const;
295 void copyConstructorCustom() const;
296 void assignmentInt() const;
297 void assignmentMovable() const;
298 void assignmentCustom() const;
299 void assignFromInitializerListInt() const;
300 void assignFromInitializerListMovable() const;
301 void assignFromInitializerListCustom() const;
302 void addInt() const;
303 void addMovable() const;
304 void addCustom() const;
305 void appendInt() const;
306 void appendMovable() const;
307 void appendCustom() const;
308 void appendRvalue() const;
309 void at() const;
310 void capacityInt() const;
311 void capacityMovable() const;
312 void capacityCustom() const;
313 void clearInt() const;
314 void clearMovable() const;
315 void clearCustom() const;
316 void constData() const;
317 void constFirst() const;
318 void constLast() const;
319 void contains() const;
320 void countInt() const;
321 void countMovable() const;
322 void countCustom() const;
323 void cpp17ctad() const;
324 void data() const;
325 void emptyInt() const;
326 void emptyMovable() const;
327 void emptyCustom() const;
328 void endsWith() const;
329 void eraseEmptyInt() const;
330 void eraseEmptyMovable() const;
331 void eraseEmptyCustom() const;
332 void eraseEmptyReservedInt() const;
333 void eraseEmptyReservedMovable() const;
334 void eraseEmptyReservedCustom() const;
335 void eraseInt() const;
336 void eraseIntShared() const;
337 void eraseMovable() const;
338 void eraseMovableShared() const;
339 void eraseCustom() const;
340 void eraseCustomShared() const;
341 void eraseReservedInt() const;
342 void eraseReservedMovable() const;
343 void eraseReservedCustom() const;
344 void fillInt() const;
345 void fillMovable() const;
346 void fillCustom() const;
347 void fillDetaches() const;
348 void first() const;
349 void fromListInt() const;
350 void fromListMovable() const;
351 void fromListCustom() const;
352 void indexOf() const;
353 void insertInt() const;
354 void insertMovable() const;
355 void insertCustom() const;
356 void insertNonDefaultConstructible() const;
357 void isEmpty() const;
358 void last() const;
359 void lastIndexOf() const;
360 void mid() const;
361 void moveInt() const;
362 void moveMovable() const;
363 void moveCustom() const;
364 void prependInt() const;
365 void prependMovable() const;
366 void prependCustom() const;
367 void prependNonDefaultConstructible() const;
368 void qhashInt() const { qhash<int>(); }
369 void qhashMovable() const { qhash<Movable>(); }
370 void qhashCustom() const { qhash<Custom>(); }
371 void removeAllWithAlias() const;
372 void removeInt() const;
373 void removeMovable() const;
374 void removeCustom() const;
375 void removeFirstLast() const;
376 void resizePOD_data() const;
377 void resizePOD() const;
378 void resizeComplexMovable_data() const;
379 void resizeComplexMovable() const;
380 void resizeComplex_data() const;
381 void resizeComplex() const;
382 void resizeCtorAndDtor() const;
383 void reverseIterators() const;
384 void sizeInt() const;
385 void sizeMovable() const;
386 void sizeCustom() const;
387 void startsWith() const;
388 void swapInt() const;
389 void swapMovable() const;
390 void swapCustom() const;
391 void toList() const;
392#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
393 void fromStdVector() const;
394 void toStdVector() const;
395#endif
396 void value() const;
397
398 void testOperators() const;
399
400 void reserve();
401 void reserveZero();
402 void reallocAfterCopy_data();
403 void reallocAfterCopy();
404 void initializeListInt();
405 void initializeListMovable();
406 void initializeListCustom();
407
408 void const_shared_null();
409#if 1
410 // ### Qt6 remove this section
411 void setSharableInt_data();
412 void setSharableInt();
413 void setSharableMovable_data();
414 void setSharableMovable();
415 void setSharableCustom_data();
416 void setSharableCustom();
417#endif
418
419 void detachInt() const;
420 void detachMovable() const;
421 void detachCustom() const;
422 void detachThreadSafetyInt() const;
423 void detachThreadSafetyMovable() const;
424 void detachThreadSafetyCustom() const;
425
426 void insertMove() const;
427
428 void swapItemsAt() const;
429
430private:
431 template<typename T> void copyConstructor() const;
432 template<typename T> void add() const;
433 template<typename T> void append() const;
434 template<typename T> void assignFromInitializerList() const;
435 template<typename T> void capacity() const;
436 template<typename T> void clear() const;
437 template<typename T> void count() const;
438 template<typename T> void empty() const;
439 template<typename T> void eraseEmpty() const;
440 template<typename T> void eraseEmptyReserved() const;
441 template<typename T> void erase(bool shared) const;
442 template<typename T> void eraseReserved() const;
443 template<typename T> void fill() const;
444 template<typename T> void fromList() const;
445 template<typename T> void insert() const;
446 template<typename T> void qhash() const;
447 template<typename T> void move() const;
448 template<typename T> void prepend() const;
449 template<typename T> void remove() const;
450 template<typename T> void size() const;
451 template<typename T> void swap() const;
452 template<typename T> void initializeList();
453 template<typename T> void setSharable_data() const;
454 template<typename T> void setSharable() const;
455 template<typename T> void detach() const;
456 template<typename T> void detachThreadSafety() const;
457};
458
459
460template<typename T> struct SimpleValue
461{
462 static T at(int index)
463 {
464 return Values[index % MaxIndex];
465 }
466
467 static QVector<T> vector(int size)
468 {
469 QVector<T> ret;
470 for (int i = 0; i < size; i++)
471 ret.append(at(index: i));
472 return ret;
473 }
474
475 static const uint MaxIndex = 6;
476 static const T Values[MaxIndex];
477};
478
479template<>
480const int SimpleValue<int>::Values[] = { 110, 105, 101, 114, 111, 98 };
481template<>
482const Movable SimpleValue<Movable>::Values[] = { 110, 105, 101, 114, 111, 98 };
483template<>
484const Custom SimpleValue<Custom>::Values[] = { 110, 105, 101, 114, 111, 98 };
485template<>
486const NonDefaultConstructible SimpleValue<NonDefaultConstructible>::Values[] =
487 { 110, 105, 101, 114, 111, 98 };
488
489
490// Make some macros for the tests to use in order to be slightly more readable...
491#define T_FOO SimpleValue<T>::at(0)
492#define T_BAR SimpleValue<T>::at(1)
493#define T_BAZ SimpleValue<T>::at(2)
494#define T_CAT SimpleValue<T>::at(3)
495#define T_DOG SimpleValue<T>::at(4)
496#define T_BLAH SimpleValue<T>::at(5)
497
498void tst_QVector::constructors_empty() const
499{
500 QVector<int> emptyInt;
501 QVector<Movable> emptyMovable;
502 QVector<Custom> emptyCustom;
503}
504
505void tst_QVector::constructors_emptyReserveZero() const
506{
507 QVector<int> emptyInt(0);
508 QVector<Movable> emptyMovable(0);
509 QVector<Custom> emptyCustom(0);
510}
511
512void tst_QVector::constructors_emptyReserve() const
513{
514 // pre-reserve capacity
515 QVector<int> myInt(5);
516 QVERIFY(myInt.capacity() == 5);
517 QVector<Movable> myMovable(5);
518 QVERIFY(myMovable.capacity() == 5);
519 QVector<Custom> myCustom(4);
520 QVERIFY(myCustom.capacity() == 4);
521}
522
523void tst_QVector::constructors_reserveAndInitialize() const
524{
525 // default-initialise items
526
527 QVector<int> myInt(5, 42);
528 QVERIFY(myInt.capacity() == 5);
529 foreach (int meaningoflife, myInt) {
530 QCOMPARE(meaningoflife, 42);
531 }
532
533 QVector<QString> myString(5, QString::fromLatin1(str: "c++"));
534 QVERIFY(myString.capacity() == 5);
535 // make sure all items are initialised ok
536 foreach (QString meaningoflife, myString) {
537 QCOMPARE(meaningoflife, QString::fromLatin1("c++"));
538 }
539
540 QVector<Custom> myCustom(5, Custom('n'));
541 QVERIFY(myCustom.capacity() == 5);
542 // make sure all items are initialised ok
543 foreach (Custom meaningoflife, myCustom) {
544 QCOMPARE(meaningoflife.i, 'n');
545 }
546}
547
548template<typename T>
549void tst_QVector::copyConstructor() const
550{
551 T value1(SimpleValue<T>::at(0));
552 T value2(SimpleValue<T>::at(1));
553 T value3(SimpleValue<T>::at(2));
554 T value4(SimpleValue<T>::at(3));
555 {
556 QVector<T> v1;
557 QVector<T> v2(v1);
558 QCOMPARE(v1, v2);
559 }
560 {
561 QVector<T> v1;
562 v1 << value1 << value2 << value3 << value4;
563 QVector<T> v2(v1);
564 QCOMPARE(v1, v2);
565 }
566#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
567 // ### Qt6 remove this section
568 {
569 QVector<T> v1;
570 v1.setSharable(false);
571 QVector<T> v2(v1);
572 QVERIFY(!v1.isSharedWith(v2));
573 QCOMPARE(v1, v2);
574 }
575 {
576 QVector<T> v1;
577 v1 << value1 << value2 << value3 << value4;
578 v1.setSharable(false);
579 QVector<T> v2(v1);
580 QVERIFY(!v1.isSharedWith(v2));
581 QCOMPARE(v1, v2);
582 }
583#endif
584}
585
586void tst_QVector::copyConstructorInt() const
587{
588 copyConstructor<int>();
589}
590
591void tst_QVector::copyConstructorMovable() const
592{
593 const int instancesCount = Movable::counter.loadAcquire();
594 copyConstructor<Movable>();
595 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
596}
597
598void tst_QVector::copyConstructorCustom() const
599{
600 const int instancesCount = Custom::counter.loadAcquire();
601 copyConstructor<Custom>();
602 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
603}
604
605template <class T>
606static inline void testAssignment()
607{
608 QVector<T> v1(5);
609 QCOMPARE(v1.size(), 5);
610 QVERIFY(v1.isDetached());
611
612 QVector<T> v2(7);
613 QCOMPARE(v2.size(), 7);
614 QVERIFY(v2.isDetached());
615
616 QVERIFY(!v1.isSharedWith(v2));
617
618 v1 = v2;
619
620 QVERIFY(!v1.isDetached());
621 QVERIFY(!v2.isDetached());
622 QVERIFY(v1.isSharedWith(v2));
623
624 const void *const data1 = v1.constData();
625 const void *const data2 = v2.constData();
626
627 QCOMPARE(data1, data2);
628
629 v1.clear();
630
631 QVERIFY(v2.isDetached());
632 QVERIFY(!v1.isSharedWith(v2));
633 QCOMPARE((void *)v2.constData(), data2);
634}
635
636void tst_QVector::assignmentInt() const
637{
638 testAssignment<int>();
639}
640
641void tst_QVector::assignmentMovable() const
642{
643 testAssignment<Movable>();
644}
645
646void tst_QVector::assignmentCustom() const
647{
648 testAssignment<Custom>();
649}
650
651template<typename T>
652void tst_QVector::assignFromInitializerList() const
653{
654 T val1(SimpleValue<T>::at(1));
655 T val2(SimpleValue<T>::at(2));
656 T val3(SimpleValue<T>::at(3));
657
658 QVector<T> v1 = {val1, val2, val3};
659 QCOMPARE(v1, QVector<T>() << val1 << val2 << val3);
660 QCOMPARE(v1, (QVector<T> {val1, val2, val3}));
661
662 v1 = {};
663 QCOMPARE(v1.size(), 0);
664}
665
666void tst_QVector::assignFromInitializerListInt() const
667{
668 assignFromInitializerList<int>();
669}
670
671void tst_QVector::assignFromInitializerListMovable() const
672{
673 const int instancesCount = Movable::counter.loadAcquire();
674 assignFromInitializerList<Movable>();
675 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
676}
677
678void tst_QVector::assignFromInitializerListCustom() const
679{
680 const int instancesCount = Custom::counter.loadAcquire();
681 assignFromInitializerList<Custom>();
682 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
683}
684
685template<typename T>
686void tst_QVector::add() const
687{
688 {
689 QVector<T> empty1;
690 QVector<T> empty2;
691 QVERIFY((empty1 + empty2).isEmpty());
692 empty1 += empty2;
693 QVERIFY(empty1.isEmpty());
694 QVERIFY(empty2.isEmpty());
695 }
696 {
697 QVector<T> v(12);
698 QVector<T> empty;
699 QCOMPARE((v + empty), v);
700 v += empty;
701 QVERIFY(!v.isEmpty());
702 QCOMPARE(v.size(), 12);
703 QVERIFY(empty.isEmpty());
704 }
705 {
706 QVector<T> v1(12);
707 QVector<T> v2;
708 v2 += v1;
709 QVERIFY(!v1.isEmpty());
710 QCOMPARE(v1.size(), 12);
711 QVERIFY(!v2.isEmpty());
712 QCOMPARE(v2.size(), 12);
713 }
714}
715
716void tst_QVector::addInt() const
717{
718 add<int>();
719}
720
721void tst_QVector::addMovable() const
722{
723 const int instancesCount = Movable::counter.loadAcquire();
724 add<Movable>();
725 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
726}
727
728void tst_QVector::addCustom() const
729{
730 const int instancesCount = Custom::counter.loadAcquire();
731 add<Custom>();
732 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
733}
734
735template<typename T>
736void tst_QVector::append() const
737{
738 {
739 QVector<T> myvec;
740 myvec.append(SimpleValue<T>::at(0));
741 QVERIFY(myvec.size() == 1);
742 myvec.append(SimpleValue<T>::at(1));
743 QVERIFY(myvec.size() == 2);
744 myvec.append(SimpleValue<T>::at(2));
745 QVERIFY(myvec.size() == 3);
746
747 QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(0)
748 << SimpleValue<T>::at(1)
749 << SimpleValue<T>::at(2));
750 }
751 {
752 QVector<T> v(2);
753 v.append(SimpleValue<T>::at(0));
754 QVERIFY(v.size() == 3);
755 QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0));
756 }
757 {
758 QVector<T> v(2);
759 v.reserve(12);
760 v.append(SimpleValue<T>::at(0));
761 QVERIFY(v.size() == 3);
762 QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0));
763 }
764#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
765 // ### Qt6 remove this section
766 {
767 QVector<T> v(2);
768 v.reserve(12);
769 v.setSharable(false);
770 v.append(SimpleValue<T>::at(0));
771 QVERIFY(v.size() == 3);
772 QCOMPARE(v.last(), SimpleValue<T>::at(0));
773 }
774#endif
775 {
776 QVector<int> v;
777 v << 1 << 2 << 3;
778 QVector<int> x;
779 x << 4 << 5 << 6;
780 v.append(l: x);
781
782 QVector<int> combined;
783 combined << 1 << 2 << 3 << 4 << 5 << 6;
784
785 QCOMPARE(v, combined);
786 }
787}
788
789void tst_QVector::appendInt() const
790{
791 append<int>();
792}
793
794void tst_QVector::appendMovable() const
795{
796 const int instancesCount = Movable::counter.loadAcquire();
797 append<Movable>();
798 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
799}
800
801void tst_QVector::appendCustom() const
802{
803 const int instancesCount = Custom::counter.loadAcquire();
804 append<Custom>();
805 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
806}
807
808void tst_QVector::appendRvalue() const
809{
810 QVector<QString> v;
811 v.append(t: "hello");
812 QString world = "world";
813 v.append(t: std::move(world));
814 QVERIFY(world.isEmpty());
815 QCOMPARE(v.front(), QString("hello"));
816 QCOMPARE(v.back(), QString("world"));
817}
818
819void tst_QVector::at() const
820{
821 QVector<QString> myvec;
822 myvec << "foo" << "bar" << "baz";
823
824 QVERIFY(myvec.size() == 3);
825 QCOMPARE(myvec.at(0), QLatin1String("foo"));
826 QCOMPARE(myvec.at(1), QLatin1String("bar"));
827 QCOMPARE(myvec.at(2), QLatin1String("baz"));
828
829 // append an item
830 myvec << "hello";
831 QVERIFY(myvec.size() == 4);
832 QCOMPARE(myvec.at(0), QLatin1String("foo"));
833 QCOMPARE(myvec.at(1), QLatin1String("bar"));
834 QCOMPARE(myvec.at(2), QLatin1String("baz"));
835 QCOMPARE(myvec.at(3), QLatin1String("hello"));
836
837 // remove an item
838 myvec.remove(i: 1);
839 QVERIFY(myvec.size() == 3);
840 QCOMPARE(myvec.at(0), QLatin1String("foo"));
841 QCOMPARE(myvec.at(1), QLatin1String("baz"));
842 QCOMPARE(myvec.at(2), QLatin1String("hello"));
843}
844
845template<typename T>
846void tst_QVector::capacity() const
847{
848 QVector<T> myvec;
849
850 // TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a
851 // few items isn't an entirely unforseeable possibility.
852 QVERIFY(myvec.capacity() == 0);
853
854 // test it gets a size
855 myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
856 QVERIFY(myvec.capacity() >= 3);
857
858 // make sure it grows ok
859 myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
860 QVERIFY(myvec.capacity() >= 6);
861 // let's try squeeze a bit
862 myvec.remove(3);
863 myvec.remove(3);
864 myvec.remove(3);
865 // TODO: is this a safe assumption? presumably it won't release memory until shrink(), but can we asser that is true?
866 QVERIFY(myvec.capacity() >= 6);
867 myvec.squeeze();
868 QVERIFY(myvec.capacity() >= 3);
869
870 myvec.remove(0);
871 myvec.remove(0);
872 myvec.remove(0);
873 // TODO: as above note
874 QVERIFY(myvec.capacity() >= 3);
875 myvec.squeeze();
876 QVERIFY(myvec.capacity() == 0);
877}
878
879void tst_QVector::capacityInt() const
880{
881 capacity<int>();
882}
883
884void tst_QVector::capacityMovable() const
885{
886 const int instancesCount = Movable::counter.loadAcquire();
887 capacity<Movable>();
888 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
889}
890
891void tst_QVector::capacityCustom() const
892{
893 const int instancesCount = Custom::counter.loadAcquire();
894 capacity<Custom>();
895 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
896}
897
898template<typename T>
899void tst_QVector::clear() const
900{
901 QVector<T> myvec;
902 myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
903
904 const auto oldCapacity = myvec.capacity();
905 QCOMPARE(myvec.size(), 3);
906 myvec.clear();
907 QCOMPARE(myvec.size(), 0);
908 QCOMPARE(myvec.capacity(), oldCapacity);
909}
910
911void tst_QVector::clearInt() const
912{
913 clear<int>();
914}
915
916void tst_QVector::clearMovable() const
917{
918 const int instancesCount = Movable::counter.loadAcquire();
919 clear<Movable>();
920 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
921}
922
923void tst_QVector::clearCustom() const
924{
925 const int instancesCount = Custom::counter.loadAcquire();
926 clear<Custom>();
927 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
928}
929
930void tst_QVector::constData() const
931{
932 int arr[] = { 42, 43, 44 };
933 QVector<int> myvec;
934 myvec << 42 << 43 << 44;
935
936 QVERIFY(memcmp(myvec.constData(), reinterpret_cast<const int *>(&arr), sizeof(int) * 3) == 0);
937}
938
939void tst_QVector::contains() const
940{
941 QVector<QString> myvec;
942 myvec << "aaa" << "bbb" << "ccc";
943
944 QVERIFY(myvec.contains(QLatin1String("aaa")));
945 QVERIFY(myvec.contains(QLatin1String("bbb")));
946 QVERIFY(myvec.contains(QLatin1String("ccc")));
947 QVERIFY(!myvec.contains(QLatin1String("I don't exist")));
948
949 // add it and make sure it does :)
950 myvec.append(t: QLatin1String("I don't exist"));
951 QVERIFY(myvec.contains(QLatin1String("I don't exist")));
952}
953
954template<typename T>
955void tst_QVector::count() const
956{
957 // total size
958 {
959 // zero size
960 QVector<T> myvec;
961 QVERIFY(myvec.count() == 0);
962
963 // grow
964 myvec.append(SimpleValue<T>::at(0));
965 QVERIFY(myvec.count() == 1);
966 myvec.append(SimpleValue<T>::at(1));
967 QVERIFY(myvec.count() == 2);
968
969 // shrink
970 myvec.remove(0);
971 QVERIFY(myvec.count() == 1);
972 myvec.remove(0);
973 QVERIFY(myvec.count() == 0);
974 }
975
976 // count of items
977 {
978 QVector<T> myvec;
979 myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
980
981 // initial tests
982 QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1);
983 QVERIFY(myvec.count(SimpleValue<T>::at(3)) == 0);
984
985 // grow
986 myvec.append(SimpleValue<T>::at(0));
987 QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 2);
988
989 // shrink
990 myvec.remove(0);
991 QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1);
992 }
993}
994
995void tst_QVector::countInt() const
996{
997 count<int>();
998}
999
1000void tst_QVector::countMovable() const
1001{
1002 const int instancesCount = Movable::counter.loadAcquire();
1003 count<Movable>();
1004 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1005}
1006
1007void tst_QVector::countCustom() const
1008{
1009 const int instancesCount = Custom::counter.loadAcquire();
1010 count<Custom>();
1011 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1012}
1013
1014void tst_QVector::cpp17ctad() const
1015{
1016#ifdef __cpp_deduction_guides
1017#define QVERIFY_IS_VECTOR_OF(obj, Type) \
1018 QVERIFY2((std::is_same<decltype(obj), QVector<Type>>::value), \
1019 QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
1020#define CHECK(Type, One, Two, Three) \
1021 do { \
1022 const Type v[] = {One, Two, Three}; \
1023 QVector v1 = {One, Two, Three}; \
1024 QVERIFY_IS_VECTOR_OF(v1, Type); \
1025 QVector v2(v1.begin(), v1.end()); \
1026 QVERIFY_IS_VECTOR_OF(v2, Type); \
1027 QVector v3(std::begin(v), std::end(v)); \
1028 QVERIFY_IS_VECTOR_OF(v3, Type); \
1029 } while (false) \
1030 /*end*/
1031 CHECK(int, 1, 2, 3);
1032 CHECK(double, 1.0, 2.0, 3.0);
1033 CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
1034#undef QVERIFY_IS_VECTOR_OF
1035#undef CHECK
1036#else
1037 QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
1038#endif
1039}
1040
1041void tst_QVector::data() const
1042{
1043 QVector<int> myvec;
1044 myvec << 42 << 43 << 44;
1045
1046 // make sure it starts off ok
1047 QCOMPARE(*(myvec.data() + 1), 43);
1048
1049 // alter it
1050 *(myvec.data() + 1) = 69;
1051
1052 // check it altered
1053 QCOMPARE(*(myvec.data() + 1), 69);
1054
1055 int arr[] = { 42, 69, 44 };
1056 QVERIFY(memcmp(myvec.data(), reinterpret_cast<int *>(&arr), sizeof(int) * 3) == 0);
1057}
1058
1059template<typename T>
1060void tst_QVector::empty() const
1061{
1062 QVector<T> myvec;
1063
1064 // starts empty
1065 QVERIFY(myvec.empty());
1066
1067 // not empty
1068 myvec.append(SimpleValue<T>::at(2));
1069 QVERIFY(!myvec.empty());
1070
1071 // empty again
1072 myvec.remove(0);
1073 QVERIFY(myvec.empty());
1074}
1075
1076void tst_QVector::emptyInt() const
1077{
1078 empty<int>();
1079}
1080
1081void tst_QVector::emptyMovable() const
1082{
1083 const int instancesCount = Movable::counter.loadAcquire();
1084 empty<Movable>();
1085 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1086}
1087
1088void tst_QVector::emptyCustom() const
1089{
1090 const int instancesCount = Custom::counter.loadAcquire();
1091 empty<Custom>();
1092 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1093}
1094
1095void tst_QVector::endsWith() const
1096{
1097 QVector<int> myvec;
1098
1099 // empty vector
1100 QVERIFY(!myvec.endsWith(1));
1101
1102 // add the one, should work
1103 myvec.append(t: 1);
1104 QVERIFY(myvec.endsWith(1));
1105
1106 // add something else, fails now
1107 myvec.append(t: 3);
1108 QVERIFY(!myvec.endsWith(1));
1109
1110 // remove it again :)
1111 myvec.remove(i: 1);
1112 QVERIFY(myvec.endsWith(1));
1113}
1114
1115template<typename T>
1116void tst_QVector::eraseEmpty() const
1117{
1118 {
1119 QVector<T> v;
1120 v.erase(v.begin(), v.end());
1121 QCOMPARE(v.size(), 0);
1122 }
1123#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1124 // ### Qt6 remove this section
1125 {
1126 QVector<T> v;
1127 v.setSharable(false);
1128 v.erase(v.begin(), v.end());
1129 QCOMPARE(v.size(), 0);
1130 }
1131#endif
1132}
1133
1134void tst_QVector::eraseEmptyInt() const
1135{
1136 eraseEmpty<int>();
1137}
1138
1139void tst_QVector::eraseEmptyMovable() const
1140{
1141 const int instancesCount = Movable::counter.loadAcquire();
1142 eraseEmpty<Movable>();
1143 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1144}
1145
1146void tst_QVector::eraseEmptyCustom() const
1147{
1148 const int instancesCount = Custom::counter.loadAcquire();
1149 eraseEmpty<Custom>();
1150 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1151}
1152
1153template<typename T>
1154void tst_QVector::eraseEmptyReserved() const
1155{
1156 {
1157 QVector<T> v;
1158 v.reserve(10);
1159 v.erase(v.begin(), v.end());
1160 QCOMPARE(v.size(), 0);
1161 }
1162#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1163 // ### Qt6 remove this section
1164 {
1165 QVector<T> v;
1166 v.reserve(10);
1167 v.setSharable(false);
1168 v.erase(v.begin(), v.end());
1169 QCOMPARE(v.size(), 0);
1170 }
1171#endif
1172}
1173
1174void tst_QVector::eraseEmptyReservedInt() const
1175{
1176 eraseEmptyReserved<int>();
1177}
1178
1179void tst_QVector::eraseEmptyReservedMovable() const
1180{
1181 const int instancesCount = Movable::counter.loadAcquire();
1182 eraseEmptyReserved<Movable>();
1183 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1184}
1185
1186void tst_QVector::eraseEmptyReservedCustom() const
1187{
1188 const int instancesCount = Custom::counter.loadAcquire();
1189 eraseEmptyReserved<Custom>();
1190 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1191}
1192
1193template<typename T>
1194struct SharedVectorChecker
1195{
1196 SharedVectorChecker(const QVector<T> &original, bool doCopyVector)
1197 : originalSize(-1),
1198 copy(0)
1199 {
1200 if (doCopyVector) {
1201 originalSize = original.size();
1202 copy = new QVector<T>(original);
1203 // this is unlikely to fail, but if the check in the destructor fails it's good to know that
1204 // we were still alright here.
1205 QCOMPARE(originalSize, copy->size());
1206 }
1207 }
1208
1209 ~SharedVectorChecker()
1210 {
1211 if (copy)
1212 QCOMPARE(copy->size(), originalSize);
1213 delete copy;
1214 }
1215
1216 int originalSize;
1217 QVector<T> *copy;
1218};
1219
1220template<typename T>
1221void tst_QVector::erase(bool shared) const
1222{
1223 // note: remove() is actually more efficient, and more dangerous, because it uses the non-detaching
1224 // begin() / end() internally. you can also use constBegin() and constEnd() with erase(), but only
1225 // using reinterpret_cast... because both iterator types are really just pointers.
1226 // so we use a mix of erase() and remove() to cover more cases.
1227 {
1228 QVector<T> v = SimpleValue<T>::vector(12);
1229 SharedVectorChecker<T> svc(v, shared);
1230 v.erase(v.begin());
1231 QCOMPARE(v.size(), 11);
1232 for (int i = 0; i < 11; i++)
1233 QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1));
1234 v.erase(v.begin(), v.end());
1235 QCOMPARE(v.size(), 0);
1236 if (shared)
1237 QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1238 }
1239 {
1240 QVector<T> v = SimpleValue<T>::vector(12);
1241 SharedVectorChecker<T> svc(v, shared);
1242 v.remove(1);
1243 QCOMPARE(v.size(), 11);
1244 QCOMPARE(v.at(0), SimpleValue<T>::at(0));
1245 for (int i = 1; i < 11; i++)
1246 QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1));
1247 v.erase(v.begin() + 1, v.end());
1248 QCOMPARE(v.size(), 1);
1249 QCOMPARE(v.at(0), SimpleValue<T>::at(0));
1250 if (shared)
1251 QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1252 }
1253 {
1254 QVector<T> v = SimpleValue<T>::vector(12);
1255 SharedVectorChecker<T> svc(v, shared);
1256 v.erase(v.begin(), v.end() - 1);
1257 QCOMPARE(v.size(), 1);
1258 QCOMPARE(v.at(0), SimpleValue<T>::at(11));
1259 if (shared)
1260 QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1261 }
1262 {
1263 QVector<T> v = SimpleValue<T>::vector(12);
1264 SharedVectorChecker<T> svc(v, shared);
1265 v.remove(5);
1266 QCOMPARE(v.size(), 11);
1267 for (int i = 0; i < 5; i++)
1268 QCOMPARE(v.at(i), SimpleValue<T>::at(i));
1269 for (int i = 5; i < 11; i++)
1270 QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1));
1271 v.erase(v.begin() + 1, v.end() - 1);
1272 QCOMPARE(v.at(0), SimpleValue<T>::at(0));
1273 QCOMPARE(v.at(1), SimpleValue<T>::at(11));
1274 QCOMPARE(v.size(), 2);
1275 if (shared)
1276 QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1277 }
1278#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1279 // ### Qt6 remove this section
1280 {
1281 QVector<T> v = SimpleValue<T>::vector(10);
1282 SharedVectorChecker<T> svc(v, shared);
1283 v.setSharable(false);
1284 SharedVectorChecker<T> svc2(v, shared);
1285 v.erase(v.begin() + 3);
1286 QCOMPARE(v.size(), 9);
1287 v.erase(v.begin(), v.end() - 1);
1288 QCOMPARE(v.size(), 1);
1289 if (shared)
1290 QCOMPARE(SimpleValue<T>::vector(10), *svc.copy);
1291 }
1292#endif
1293}
1294
1295void tst_QVector::eraseInt() const
1296{
1297 erase<int>(shared: false);
1298}
1299
1300void tst_QVector::eraseIntShared() const
1301{
1302 erase<int>(shared: true);
1303}
1304
1305void tst_QVector::eraseMovable() const
1306{
1307 const int instancesCount = Movable::counter.loadAcquire();
1308 erase<Movable>(shared: false);
1309 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1310}
1311
1312void tst_QVector::eraseMovableShared() const
1313{
1314 const int instancesCount = Movable::counter.loadAcquire();
1315 erase<Movable>(shared: true);
1316 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1317}
1318
1319void tst_QVector::eraseCustom() const
1320{
1321 const int instancesCount = Custom::counter.loadAcquire();
1322 erase<Custom>(shared: false);
1323 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1324}
1325
1326void tst_QVector::eraseCustomShared() const
1327{
1328 const int instancesCount = Custom::counter.loadAcquire();
1329 erase<Custom>(shared: true);
1330 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1331}
1332
1333template<typename T> void tst_QVector::eraseReserved() const
1334{
1335 {
1336 QVector<T> v(12);
1337 v.reserve(16);
1338 v.erase(v.begin());
1339 QCOMPARE(v.size(), 11);
1340 v.erase(v.begin(), v.end());
1341 QCOMPARE(v.size(), 0);
1342 }
1343 {
1344 QVector<T> v(12);
1345 v.reserve(16);
1346 v.erase(v.begin() + 1);
1347 QCOMPARE(v.size(), 11);
1348 v.erase(v.begin() + 1, v.end());
1349 QCOMPARE(v.size(), 1);
1350 }
1351 {
1352 QVector<T> v(12);
1353 v.reserve(16);
1354 v.erase(v.begin(), v.end() - 1);
1355 QCOMPARE(v.size(), 1);
1356 }
1357 {
1358 QVector<T> v(12);
1359 v.reserve(16);
1360 v.erase(v.begin() + 5);
1361 QCOMPARE(v.size(), 11);
1362 v.erase(v.begin() + 1, v.end() - 1);
1363 QCOMPARE(v.size(), 2);
1364 }
1365#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1366 // ### Qt6 remove this section
1367 {
1368 QVector<T> v(10);
1369 v.reserve(16);
1370 v.setSharable(false);
1371 v.erase(v.begin() + 3);
1372 QCOMPARE(v.size(), 9);
1373 v.erase(v.begin(), v.end() - 1);
1374 QCOMPARE(v.size(), 1);
1375 }
1376#endif
1377}
1378
1379void tst_QVector::eraseReservedInt() const
1380{
1381 eraseReserved<int>();
1382}
1383
1384void tst_QVector::eraseReservedMovable() const
1385{
1386 const int instancesCount = Movable::counter.loadAcquire();
1387 eraseReserved<Movable>();
1388 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1389}
1390
1391void tst_QVector::eraseReservedCustom() const
1392{
1393 const int instancesCount = Custom::counter.loadAcquire();
1394 eraseReserved<Custom>();
1395 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1396}
1397
1398template<typename T>
1399void tst_QVector::fill() const
1400{
1401 QVector<T> myvec;
1402
1403 // resize
1404 myvec.resize(5);
1405 myvec.fill(SimpleValue<T>::at(1));
1406 QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(1) << SimpleValue<T>::at(1)
1407 << SimpleValue<T>::at(1) << SimpleValue<T>::at(1)
1408 << SimpleValue<T>::at(1));
1409
1410 // make sure it can resize itself too
1411 myvec.fill(SimpleValue<T>::at(2), 10);
1412 QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
1413 << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
1414 << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
1415 << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
1416 << SimpleValue<T>::at(2) << SimpleValue<T>::at(2));
1417}
1418
1419void tst_QVector::fillInt() const
1420{
1421 fill<int>();
1422}
1423
1424void tst_QVector::fillMovable() const
1425{
1426 const int instancesCount = Movable::counter.loadAcquire();
1427 fill<Movable>();
1428 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1429}
1430
1431void tst_QVector::fillCustom() const
1432{
1433 const int instancesCount = Custom::counter.loadAcquire();
1434 fill<Custom>();
1435 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1436}
1437
1438void tst_QVector::fillDetaches() const
1439{
1440 QVector<int> test = { 1, 2, 3 };
1441 QVector<int> copy = test;
1442 copy.fill(from: 42);
1443
1444 QCOMPARE(test, QVector<int>({1, 2, 3}));
1445 QCOMPARE(copy, QVector<int>({42, 42, 42}));
1446}
1447
1448void tst_QVector::first() const
1449{
1450 QVector<int> myvec;
1451 myvec << 69 << 42 << 3;
1452
1453 // test it starts ok
1454 QCOMPARE(myvec.first(), 69);
1455 QCOMPARE(myvec.constFirst(), 69);
1456
1457 // test removal changes
1458 myvec.remove(i: 0);
1459 QCOMPARE(myvec.first(), 42);
1460 QCOMPARE(myvec.constFirst(), 42);
1461
1462 // test prepend changes
1463 myvec.prepend(t: 23);
1464 QCOMPARE(myvec.first(), 23);
1465 QCOMPARE(myvec.constFirst(), 23);
1466}
1467
1468void tst_QVector::constFirst() const
1469{
1470 QVector<int> myvec;
1471 myvec << 69 << 42 << 3;
1472
1473 // test it starts ok
1474 QCOMPARE(myvec.constFirst(), 69);
1475 QVERIFY(myvec.isDetached());
1476
1477 QVector<int> myvecCopy = myvec;
1478 QVERIFY(!myvec.isDetached());
1479 QVERIFY(!myvecCopy.isDetached());
1480 QVERIFY(myvec.isSharedWith(myvecCopy));
1481 QVERIFY(myvecCopy.isSharedWith(myvec));
1482
1483 QCOMPARE(myvec.constFirst(), 69);
1484 QCOMPARE(myvecCopy.constFirst(), 69);
1485
1486 QVERIFY(!myvec.isDetached());
1487 QVERIFY(!myvecCopy.isDetached());
1488 QVERIFY(myvec.isSharedWith(myvecCopy));
1489 QVERIFY(myvecCopy.isSharedWith(myvec));
1490
1491 // test removal changes
1492 myvec.remove(i: 0);
1493 QVERIFY(myvec.isDetached());
1494 QVERIFY(!myvec.isSharedWith(myvecCopy));
1495 QCOMPARE(myvec.constFirst(), 42);
1496 QCOMPARE(myvecCopy.constFirst(), 69);
1497
1498 myvecCopy = myvec;
1499 QVERIFY(!myvec.isDetached());
1500 QVERIFY(!myvecCopy.isDetached());
1501 QVERIFY(myvec.isSharedWith(myvecCopy));
1502 QVERIFY(myvecCopy.isSharedWith(myvec));
1503
1504 QCOMPARE(myvec.constFirst(), 42);
1505 QCOMPARE(myvecCopy.constFirst(), 42);
1506
1507 QVERIFY(!myvec.isDetached());
1508 QVERIFY(!myvecCopy.isDetached());
1509 QVERIFY(myvec.isSharedWith(myvecCopy));
1510 QVERIFY(myvecCopy.isSharedWith(myvec));
1511
1512 // test prepend changes
1513 myvec.prepend(t: 23);
1514 QVERIFY(myvec.isDetached());
1515 QVERIFY(!myvec.isSharedWith(myvecCopy));
1516 QCOMPARE(myvec.constFirst(), 23);
1517 QCOMPARE(myvecCopy.constFirst(), 42);
1518
1519 myvecCopy = myvec;
1520 QVERIFY(!myvec.isDetached());
1521 QVERIFY(!myvecCopy.isDetached());
1522 QVERIFY(myvec.isSharedWith(myvecCopy));
1523 QVERIFY(myvecCopy.isSharedWith(myvec));
1524
1525 QCOMPARE(myvec.constFirst(), 23);
1526 QCOMPARE(myvecCopy.constFirst(), 23);
1527
1528 QVERIFY(!myvec.isDetached());
1529 QVERIFY(!myvecCopy.isDetached());
1530 QVERIFY(myvec.isSharedWith(myvecCopy));
1531 QVERIFY(myvecCopy.isSharedWith(myvec));
1532}
1533
1534
1535template<typename T>
1536void tst_QVector::fromList() const
1537{
1538 QList<T> list;
1539 list << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3);
1540
1541 QVector<T> myvec;
1542 myvec = QVector<T>::fromList(list);
1543
1544 // test it worked ok
1545 QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3));
1546 QCOMPARE(list, QList<T>() << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3));
1547}
1548
1549void tst_QVector::fromListInt() const
1550{
1551 fromList<int>();
1552}
1553
1554void tst_QVector::fromListMovable() const
1555{
1556 const int instancesCount = Movable::counter.loadAcquire();
1557 fromList<Movable>();
1558 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1559}
1560
1561void tst_QVector::fromListCustom() const
1562{
1563 const int instancesCount = Custom::counter.loadAcquire();
1564 fromList<Custom>();
1565 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1566}
1567
1568#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1569void tst_QVector::fromStdVector() const
1570{
1571 // stl = :(
1572 std::vector<QString> svec;
1573 svec.push_back(x: QLatin1String("aaa"));
1574 svec.push_back(x: QLatin1String("bbb"));
1575 svec.push_back(x: QLatin1String("ninjas"));
1576 svec.push_back(x: QLatin1String("pirates"));
1577 QVector<QString> myvec = QVector<QString>::fromStdVector(vector: svec);
1578
1579 // test it converts ok
1580 QCOMPARE(myvec, QVector<QString>() << "aaa" << "bbb" << "ninjas" << "pirates");
1581}
1582#endif
1583
1584void tst_QVector::indexOf() const
1585{
1586 QVector<QString> myvec;
1587 myvec << "A" << "B" << "C" << "B" << "A";
1588
1589 QVERIFY(myvec.indexOf("B") == 1);
1590 QVERIFY(myvec.indexOf("B", 1) == 1);
1591 QVERIFY(myvec.indexOf("B", 2) == 3);
1592 QVERIFY(myvec.indexOf("X") == -1);
1593 QVERIFY(myvec.indexOf("X", 2) == -1);
1594
1595 // add an X
1596 myvec << "X";
1597 QVERIFY(myvec.indexOf("X") == 5);
1598 QVERIFY(myvec.indexOf("X", 5) == 5);
1599 QVERIFY(myvec.indexOf("X", 6) == -1);
1600
1601 // remove first A
1602 myvec.remove(i: 0);
1603 QVERIFY(myvec.indexOf("A") == 3);
1604 QVERIFY(myvec.indexOf("A", 3) == 3);
1605 QVERIFY(myvec.indexOf("A", 4) == -1);
1606}
1607
1608template <typename T>
1609void tst_QVector::insert() const
1610{
1611 QVector<T> myvec;
1612 const T
1613 tA = SimpleValue<T>::at(0),
1614 tB = SimpleValue<T>::at(1),
1615 tC = SimpleValue<T>::at(2),
1616 tX = SimpleValue<T>::at(3),
1617 tZ = SimpleValue<T>::at(4),
1618 tT = SimpleValue<T>::at(5),
1619 ti = SimpleValue<T>::at(6);
1620 myvec << tA << tB << tC;
1621 QVector<T> myvec2 = myvec;
1622
1623 // first position
1624 QCOMPARE(myvec.at(0), tA);
1625 myvec.insert(0, tX);
1626 QCOMPARE(myvec.at(0), tX);
1627 QCOMPARE(myvec.at(1), tA);
1628
1629 QCOMPARE(myvec2.at(0), tA);
1630 myvec2.insert(myvec2.begin(), tX);
1631 QCOMPARE(myvec2.at(0), tX);
1632 QCOMPARE(myvec2.at(1), tA);
1633
1634 // middle
1635 myvec.insert(1, tZ);
1636 QCOMPARE(myvec.at(0), tX);
1637 QCOMPARE(myvec.at(1), tZ);
1638 QCOMPARE(myvec.at(2), tA);
1639
1640 myvec2.insert(myvec2.begin() + 1, tZ);
1641 QCOMPARE(myvec2.at(0), tX);
1642 QCOMPARE(myvec2.at(1), tZ);
1643 QCOMPARE(myvec2.at(2), tA);
1644
1645 // end
1646 myvec.insert(5, tT);
1647 QCOMPARE(myvec.at(5), tT);
1648 QCOMPARE(myvec.at(4), tC);
1649
1650 myvec2.insert(myvec2.end(), tT);
1651 QCOMPARE(myvec2.at(5), tT);
1652 QCOMPARE(myvec2.at(4), tC);
1653
1654 // insert a lot of garbage in the middle
1655 myvec.insert(2, 2, ti);
1656 QCOMPARE(myvec, QVector<T>() << tX << tZ << ti << ti
1657 << tA << tB << tC << tT);
1658
1659 myvec2.insert(myvec2.begin() + 2, 2, ti);
1660 QCOMPARE(myvec2, myvec);
1661
1662 // insert from references to the same container:
1663 myvec.insert(0, 1, myvec[5]); // inserts tB
1664 myvec2.insert(0, 1, myvec2[5]); // inserts tB
1665 QCOMPARE(myvec, QVector<T>() << tB << tX << tZ << ti << ti
1666 << tA << tB << tC << tT);
1667 QCOMPARE(myvec2, myvec);
1668
1669 myvec.insert(0, 1, const_cast<const QVector<T>&>(myvec)[0]); // inserts tB
1670 myvec2.insert(0, 1, const_cast<const QVector<T>&>(myvec2)[0]); // inserts tB
1671 QCOMPARE(myvec, QVector<T>() << tB << tB << tX << tZ << ti << ti
1672 << tA << tB << tC << tT);
1673 QCOMPARE(myvec2, myvec);
1674}
1675
1676void tst_QVector::insertInt() const
1677{
1678 insert<int>();
1679}
1680
1681void tst_QVector::insertMovable() const
1682{
1683 insert<Movable>();
1684}
1685
1686void tst_QVector::insertCustom() const
1687{
1688 insert<Custom>();
1689}
1690
1691void tst_QVector::insertNonDefaultConstructible() const
1692{
1693 insert<NonDefaultConstructible>();
1694}
1695
1696void tst_QVector::isEmpty() const
1697{
1698 QVector<QString> myvec;
1699
1700 // starts ok
1701 QVERIFY(myvec.isEmpty());
1702
1703 // not empty now
1704 myvec.append(t: QLatin1String("hello there"));
1705 QVERIFY(!myvec.isEmpty());
1706
1707 // empty again
1708 myvec.remove(i: 0);
1709 QVERIFY(myvec.isEmpty());
1710}
1711
1712void tst_QVector::last() const
1713{
1714 QVector<QString> myvec;
1715 myvec << "A" << "B" << "C";
1716
1717 // test starts ok
1718 QCOMPARE(myvec.last(), QLatin1String("C"));
1719 QCOMPARE(myvec.constLast(), QLatin1String("C"));
1720
1721 // test it changes ok
1722 myvec.append(t: QLatin1String("X"));
1723 QCOMPARE(myvec.last(), QLatin1String("X"));
1724 QCOMPARE(myvec.constLast(), QLatin1String("X"));
1725
1726 // and remove again
1727 myvec.remove(i: 3);
1728 QCOMPARE(myvec.last(), QLatin1String("C"));
1729 QCOMPARE(myvec.constLast(), QLatin1String("C"));
1730}
1731
1732void tst_QVector::constLast() const
1733{
1734 QVector<int> myvec;
1735 myvec << 69 << 42 << 3;
1736
1737 // test it starts ok
1738 QCOMPARE(myvec.constLast(), 3);
1739 QVERIFY(myvec.isDetached());
1740
1741 QVector<int> myvecCopy = myvec;
1742 QVERIFY(!myvec.isDetached());
1743 QVERIFY(!myvecCopy.isDetached());
1744 QVERIFY(myvec.isSharedWith(myvecCopy));
1745 QVERIFY(myvecCopy.isSharedWith(myvec));
1746
1747 QCOMPARE(myvec.constLast(), 3);
1748 QCOMPARE(myvecCopy.constLast(), 3);
1749
1750 QVERIFY(!myvec.isDetached());
1751 QVERIFY(!myvecCopy.isDetached());
1752 QVERIFY(myvec.isSharedWith(myvecCopy));
1753 QVERIFY(myvecCopy.isSharedWith(myvec));
1754
1755 // test removal changes
1756 myvec.removeLast();
1757 QVERIFY(myvec.isDetached());
1758 QVERIFY(!myvec.isSharedWith(myvecCopy));
1759 QCOMPARE(myvec.constLast(), 42);
1760 QCOMPARE(myvecCopy.constLast(), 3);
1761
1762 myvecCopy = myvec;
1763 QVERIFY(!myvec.isDetached());
1764 QVERIFY(!myvecCopy.isDetached());
1765 QVERIFY(myvec.isSharedWith(myvecCopy));
1766 QVERIFY(myvecCopy.isSharedWith(myvec));
1767
1768 QCOMPARE(myvec.constLast(), 42);
1769 QCOMPARE(myvecCopy.constLast(), 42);
1770
1771 QVERIFY(!myvec.isDetached());
1772 QVERIFY(!myvecCopy.isDetached());
1773 QVERIFY(myvec.isSharedWith(myvecCopy));
1774 QVERIFY(myvecCopy.isSharedWith(myvec));
1775
1776 // test prepend changes
1777 myvec.append(t: 23);
1778 QVERIFY(myvec.isDetached());
1779 QVERIFY(!myvec.isSharedWith(myvecCopy));
1780 QCOMPARE(myvec.constLast(), 23);
1781 QCOMPARE(myvecCopy.constLast(), 42);
1782
1783 myvecCopy = myvec;
1784 QVERIFY(!myvec.isDetached());
1785 QVERIFY(!myvecCopy.isDetached());
1786 QVERIFY(myvec.isSharedWith(myvecCopy));
1787 QVERIFY(myvecCopy.isSharedWith(myvec));
1788
1789 QCOMPARE(myvec.constLast(), 23);
1790 QCOMPARE(myvecCopy.constLast(), 23);
1791
1792 QVERIFY(!myvec.isDetached());
1793 QVERIFY(!myvecCopy.isDetached());
1794 QVERIFY(myvec.isSharedWith(myvecCopy));
1795 QVERIFY(myvecCopy.isSharedWith(myvec));
1796}
1797
1798void tst_QVector::lastIndexOf() const
1799{
1800 QVector<QString> myvec;
1801 myvec << "A" << "B" << "C" << "B" << "A";
1802
1803 QVERIFY(myvec.lastIndexOf("B") == 3);
1804 QVERIFY(myvec.lastIndexOf("B", 2) == 1);
1805 QVERIFY(myvec.lastIndexOf("X") == -1);
1806 QVERIFY(myvec.lastIndexOf("X", 2) == -1);
1807
1808 // add an X
1809 myvec << "X";
1810 QVERIFY(myvec.lastIndexOf("X") == 5);
1811 QVERIFY(myvec.lastIndexOf("X", 5) == 5);
1812 QVERIFY(myvec.lastIndexOf("X", 3) == -1);
1813
1814 // remove first A
1815 myvec.remove(i: 0);
1816 QVERIFY(myvec.lastIndexOf("A") == 3);
1817 QVERIFY(myvec.lastIndexOf("A", 3) == 3);
1818 QVERIFY(myvec.lastIndexOf("A", 2) == -1);
1819}
1820
1821void tst_QVector::mid() const
1822{
1823 QVector<QString> list;
1824 list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty";
1825
1826 QCOMPARE(list.mid(3, 3), QVector<QString>() << "bak" << "buck" << "hello");
1827 QCOMPARE(list.mid(6, 10), QVector<QString>() << "kitty");
1828 QCOMPARE(list.mid(-1, 20), list);
1829 QCOMPARE(list.mid(4), QVector<QString>() << "buck" << "hello" << "kitty");
1830}
1831
1832template <typename T>
1833void tst_QVector::qhash() const
1834{
1835 QVector<T> l1, l2;
1836 QCOMPARE(qHash(l1), qHash(l2));
1837 l1 << SimpleValue<T>::at(0);
1838 l2 << SimpleValue<T>::at(0);
1839 QCOMPARE(qHash(l1), qHash(l2));
1840}
1841
1842template <typename T>
1843void tst_QVector::move() const
1844{
1845 QVector<T> list;
1846 list << T_FOO << T_BAR << T_BAZ;
1847
1848 // move an item
1849 list.move(0, list.count() - 1);
1850 QCOMPARE(list, QVector<T>() << T_BAR << T_BAZ << T_FOO);
1851
1852 // move it back
1853 list.move(list.count() - 1, 0);
1854 QCOMPARE(list, QVector<T>() << T_FOO << T_BAR << T_BAZ);
1855
1856 // move an item in the middle
1857 list.move(1, 0);
1858 QCOMPARE(list, QVector<T>() << T_BAR << T_FOO << T_BAZ);
1859}
1860
1861void tst_QVector::moveInt() const
1862{
1863 move<int>();
1864}
1865
1866void tst_QVector::moveMovable() const
1867{
1868 const int instancesCount = Movable::counter.loadAcquire();
1869 move<Movable>();
1870 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1871}
1872
1873void tst_QVector::moveCustom() const
1874{
1875 const int instancesCount = Custom::counter.loadAcquire();
1876 move<Custom>();
1877 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1878}
1879
1880template<typename T>
1881void tst_QVector::prepend() const
1882{
1883 QVector<T> myvec;
1884 T val1 = SimpleValue<T>::at(0);
1885 T val2 = SimpleValue<T>::at(1);
1886 T val3 = SimpleValue<T>::at(2);
1887 T val4 = SimpleValue<T>::at(3);
1888 T val5 = SimpleValue<T>::at(4);
1889 myvec << val1 << val2 << val3;
1890
1891 // starts ok
1892 QVERIFY(myvec.size() == 3);
1893 QCOMPARE(myvec.at(0), val1);
1894
1895 // add something
1896 myvec.prepend(val4);
1897 QCOMPARE(myvec.at(0), val4);
1898 QCOMPARE(myvec.at(1), val1);
1899 QVERIFY(myvec.size() == 4);
1900
1901 // something else
1902 myvec.prepend(val5);
1903 QCOMPARE(myvec.at(0), val5);
1904 QCOMPARE(myvec.at(1), val4);
1905 QCOMPARE(myvec.at(2), val1);
1906 QVERIFY(myvec.size() == 5);
1907
1908 // clear and prepend to an empty vector
1909 myvec.clear();
1910 QVERIFY(myvec.size() == 0);
1911 myvec.prepend(val5);
1912 QVERIFY(myvec.size() == 1);
1913 QCOMPARE(myvec.at(0), val5);
1914}
1915
1916void tst_QVector::prependInt() const
1917{
1918 prepend<int>();
1919}
1920
1921void tst_QVector::prependMovable() const
1922{
1923 const int instancesCount = Movable::counter.loadAcquire();
1924 prepend<Movable>();
1925 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1926}
1927
1928void tst_QVector::prependCustom() const
1929{
1930 const int instancesCount = Custom::counter.loadAcquire();
1931 prepend<Custom>();
1932 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
1933}
1934
1935void tst_QVector::prependNonDefaultConstructible() const
1936{
1937 const int instancesCount = NonDefaultConstructible::counter.loadAcquire();
1938 prepend<NonDefaultConstructible>();
1939 QCOMPARE(instancesCount, NonDefaultConstructible::counter.loadAcquire());
1940}
1941
1942void tst_QVector::removeAllWithAlias() const
1943{
1944 QVector<QString> strings;
1945 strings << "One" << "Two" << "Three" << "One" /* must be distinct, but equal */;
1946 QCOMPARE(strings.removeAll(strings.front()), 2); // will trigger asan/ubsan
1947}
1948
1949template<typename T>
1950void tst_QVector::remove() const
1951{
1952 QVector<T> myvec;
1953 T val1 = SimpleValue<T>::at(1);
1954 T val2 = SimpleValue<T>::at(2);
1955 T val3 = SimpleValue<T>::at(3);
1956 T val4 = SimpleValue<T>::at(4);
1957 myvec << val1 << val2 << val3;
1958 myvec << val1 << val2 << val3;
1959 myvec << val1 << val2 << val3;
1960 // remove middle
1961 myvec.remove(1);
1962 QCOMPARE(myvec, QVector<T>() << val1 << val3 << val1 << val2 << val3 << val1 << val2 << val3);
1963
1964 // removeOne()
1965 QVERIFY(!myvec.removeOne(val4));
1966 QVERIFY(myvec.removeOne(val2));
1967 QCOMPARE(myvec, QVector<T>() << val1 << val3 << val1 << val3 << val1 << val2 << val3);
1968
1969 QVector<T> myvecCopy = myvec;
1970 QVERIFY(myvecCopy.isSharedWith(myvec));
1971 // removeAll()
1972 QCOMPARE(myvec.removeAll(val4), 0);
1973 QVERIFY(myvecCopy.isSharedWith(myvec));
1974 QCOMPARE(myvec.removeAll(val1), 3);
1975 QVERIFY(!myvecCopy.isSharedWith(myvec));
1976 QCOMPARE(myvec, QVector<T>() << val3 << val3 << val2 << val3);
1977 myvecCopy = myvec;
1978 QVERIFY(myvecCopy.isSharedWith(myvec));
1979 QCOMPARE(myvec.removeAll(val2), 1);
1980 QVERIFY(!myvecCopy.isSharedWith(myvec));
1981 QCOMPARE(myvec, QVector<T>() << val3 << val3 << val3);
1982
1983 // remove rest
1984 myvec.remove(0, 3);
1985 QCOMPARE(myvec, QVector<T>());
1986}
1987
1988void tst_QVector::removeInt() const
1989{
1990 remove<int>();
1991}
1992
1993void tst_QVector::removeMovable() const
1994{
1995 const int instancesCount = Movable::counter.loadAcquire();
1996 remove<Movable>();
1997 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
1998}
1999
2000void tst_QVector::removeCustom() const
2001{
2002 const int instancesCount = Custom::counter.loadAcquire();
2003 remove<Custom>();
2004 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
2005}
2006
2007struct RemoveLastTestClass
2008{
2009 RemoveLastTestClass() { other = 0; deleted = false; }
2010 RemoveLastTestClass *other;
2011 bool deleted;
2012 ~RemoveLastTestClass()
2013 {
2014 deleted = true;
2015 if (other)
2016 other->other = 0;
2017 }
2018};
2019
2020void tst_QVector::removeFirstLast() const
2021{
2022 // pop_pack - pop_front
2023 QVector<int> t, t2;
2024 t.append(t: 1);
2025 t.append(t: 2);
2026 t.append(t: 3);
2027 t.append(t: 4);
2028 t2 = t;
2029 t.pop_front();
2030 QCOMPARE(t.size(), 3);
2031 QCOMPARE(t.at(0), 2);
2032 t.pop_back();
2033 QCOMPARE(t.size(), 2);
2034 QCOMPARE(t.at(0), 2);
2035 QCOMPARE(t.at(1), 3);
2036
2037 // takefirst - takeLast
2038 int n1 = t2.takeLast();
2039 QCOMPARE(t2.size(), 3);
2040 QCOMPARE(n1, 4);
2041 QCOMPARE(t2.at(0), 1);
2042 QCOMPARE(t2.at(2), 3);
2043 n1 = t2.takeFirst();
2044 QCOMPARE(t2.size(), 2);
2045 QCOMPARE(n1, 1);
2046 QCOMPARE(t2.at(0), 2);
2047 QCOMPARE(t2.at(1), 3);
2048
2049 // remove first
2050 QVector<int> x, y;
2051 x.append(t: 1);
2052 x.append(t: 2);
2053 y = x;
2054 x.removeFirst();
2055 QCOMPARE(x.size(), 1);
2056 QCOMPARE(y.size(), 2);
2057 QCOMPARE(x.at(0), 2);
2058
2059 // remove Last
2060 QVector<RemoveLastTestClass> v;
2061 v.resize(asize: 2);
2062 v[0].other = &(v[1]);
2063 v[1].other = &(v[0]);
2064 // Check dtor - complex type
2065 QVERIFY(v.at(0).other != 0);
2066 v.removeLast();
2067 QVERIFY(v.at(0).other == 0);
2068 QCOMPARE(v.at(0).deleted, false);
2069 // check iterator
2070 int count = 0;
2071 for (QVector<RemoveLastTestClass>::const_iterator i = v.constBegin(); i != v.constEnd(); ++i) {
2072 ++count;
2073 QVERIFY(i->other == 0);
2074 QCOMPARE(i->deleted, false);
2075 }
2076 // Check size
2077 QCOMPARE(count, 1);
2078 QCOMPARE(v.size(), 1);
2079 v.removeLast();
2080 QCOMPARE(v.size(), 0);
2081 // Check if we do correct realloc
2082 QVector<int> v2, v3;
2083 v2.append(t: 1);
2084 v2.append(t: 2);
2085 v3 = v2; // shared
2086 v2.removeLast();
2087 QCOMPARE(v2.size(), 1);
2088 QCOMPARE(v3.size(), 2);
2089 QCOMPARE(v2.at(0), 1);
2090 QCOMPARE(v3.at(0), 1);
2091 QCOMPARE(v3.at(1), 2);
2092
2093 // Remove last with shared
2094 QVector<int> z1, z2;
2095 z1.append(t: 9);
2096 z2 = z1;
2097 z1.removeLast();
2098 QCOMPARE(z1.size(), 0);
2099 QCOMPARE(z2.size(), 1);
2100 QCOMPARE(z2.at(0), 9);
2101}
2102
2103
2104void tst_QVector::resizePOD_data() const
2105{
2106 QTest::addColumn<QVector<int> >(name: "vector");
2107 QTest::addColumn<int>(name: "size");
2108
2109 QVERIFY(!QTypeInfo<int>::isComplex);
2110 QVERIFY(!QTypeInfo<int>::isStatic);
2111
2112 QVector<int> null;
2113 QVector<int> empty(0, 5);
2114 QVector<int> emptyReserved;
2115 QVector<int> nonEmpty;
2116 QVector<int> nonEmptyReserved;
2117
2118 emptyReserved.reserve(asize: 10);
2119 nonEmptyReserved.reserve(asize: 15);
2120 nonEmpty << 0 << 1 << 2 << 3 << 4;
2121 nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6;
2122 QVERIFY(emptyReserved.capacity() >= 10);
2123 QVERIFY(nonEmptyReserved.capacity() >= 15);
2124
2125 QTest::newRow(dataTag: "null") << null << 10;
2126 QTest::newRow(dataTag: "empty") << empty << 10;
2127 QTest::newRow(dataTag: "emptyReserved") << emptyReserved << 10;
2128 QTest::newRow(dataTag: "nonEmpty") << nonEmpty << 10;
2129 QTest::newRow(dataTag: "nonEmptyReserved") << nonEmptyReserved << 10;
2130
2131#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
2132 // ### Qt6 remove this section
2133 QVector<int> nullNotShared;
2134 QVector<int> emptyNotShared(0, 5);
2135 QVector<int> emptyReservedNotShared;
2136 QVector<int> nonEmptyNotShared;
2137 QVector<int> nonEmptyReservedNotShared;
2138
2139 emptyReservedNotShared.reserve(asize: 10);
2140 nonEmptyReservedNotShared.reserve(asize: 15);
2141 nonEmptyNotShared << 0 << 1 << 2 << 3 << 4;
2142 nonEmptyReservedNotShared << 0 << 1 << 2 << 3 << 4 << 5 << 6;
2143 QVERIFY(emptyReservedNotShared.capacity() >= 10);
2144 QVERIFY(nonEmptyReservedNotShared.capacity() >= 15);
2145
2146 emptyNotShared.setSharable(false);
2147 emptyReservedNotShared.setSharable(false);
2148 nonEmptyNotShared.setSharable(false);
2149 nonEmptyReservedNotShared.setSharable(false);
2150
2151 QTest::newRow(dataTag: "nullNotShared") << nullNotShared << 10;
2152 QTest::newRow(dataTag: "emptyNotShared") << emptyNotShared << 10;
2153 QTest::newRow(dataTag: "emptyReservedNotShared") << emptyReservedNotShared << 10;
2154 QTest::newRow(dataTag: "nonEmptyNotShared") << nonEmptyNotShared << 10;
2155 QTest::newRow(dataTag: "nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10;
2156#endif
2157}
2158
2159void tst_QVector::resizePOD() const
2160{
2161 QFETCH(QVector<int>, vector);
2162 QFETCH(int, size);
2163
2164 const int oldSize = vector.size();
2165
2166 vector.resize(asize: size);
2167 QCOMPARE(vector.size(), size);
2168 QVERIFY(vector.capacity() >= size);
2169 for (int i = oldSize; i < size; ++i)
2170 QVERIFY(vector[i] == 0); // check initialization
2171
2172 const int capacity = vector.capacity();
2173
2174 vector.clear();
2175 QCOMPARE(vector.size(), 0);
2176 QVERIFY(vector.capacity() <= capacity);
2177}
2178
2179void tst_QVector::resizeComplexMovable_data() const
2180{
2181 QTest::addColumn<QVector<Movable> >(name: "vector");
2182 QTest::addColumn<int>(name: "size");
2183
2184 QVERIFY(QTypeInfo<Movable>::isComplex);
2185 QVERIFY(!QTypeInfo<Movable>::isStatic);
2186
2187 QVector<Movable> null;
2188 QVector<Movable> empty(0, 'Q');
2189 QVector<Movable> emptyReserved;
2190 QVector<Movable> nonEmpty;
2191 QVector<Movable> nonEmptyReserved;
2192
2193 emptyReserved.reserve(asize: 10);
2194 nonEmptyReserved.reserve(asize: 15);
2195 nonEmpty << '0' << '1' << '2' << '3' << '4';
2196 nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2197 QVERIFY(emptyReserved.capacity() >= 10);
2198 QVERIFY(nonEmptyReserved.capacity() >= 15);
2199
2200 QTest::newRow(dataTag: "null") << null << 10;
2201 QTest::newRow(dataTag: "empty") << empty << 10;
2202 QTest::newRow(dataTag: "emptyReserved") << emptyReserved << 10;
2203 QTest::newRow(dataTag: "nonEmpty") << nonEmpty << 10;
2204 QTest::newRow(dataTag: "nonEmptyReserved") << nonEmptyReserved << 10;
2205
2206#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
2207 // ### Qt6 remove this section
2208 QVector<Movable> nullNotShared;
2209 QVector<Movable> emptyNotShared(0, 'Q');
2210 QVector<Movable> emptyReservedNotShared;
2211 QVector<Movable> nonEmptyNotShared;
2212 QVector<Movable> nonEmptyReservedNotShared;
2213
2214 emptyReservedNotShared.reserve(asize: 10);
2215 nonEmptyReservedNotShared.reserve(asize: 15);
2216 nonEmptyNotShared << '0' << '1' << '2' << '3' << '4';
2217 nonEmptyReservedNotShared << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2218 QVERIFY(emptyReservedNotShared.capacity() >= 10);
2219 QVERIFY(nonEmptyReservedNotShared.capacity() >= 15);
2220
2221 emptyNotShared.setSharable(false);
2222 emptyReservedNotShared.setSharable(false);
2223 nonEmptyNotShared.setSharable(false);
2224 nonEmptyReservedNotShared.setSharable(false);
2225
2226 QTest::newRow(dataTag: "nullNotShared") << nullNotShared << 10;
2227 QTest::newRow(dataTag: "emptyNotShared") << emptyNotShared << 10;
2228 QTest::newRow(dataTag: "emptyReservedNotShared") << emptyReservedNotShared << 10;
2229 QTest::newRow(dataTag: "nonEmptyNotShared") << nonEmptyNotShared << 10;
2230 QTest::newRow(dataTag: "nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10;
2231#endif
2232}
2233
2234void tst_QVector::resizeComplexMovable() const
2235{
2236 const int items = Movable::counter.loadAcquire();
2237 {
2238 QFETCH(QVector<Movable>, vector);
2239 QFETCH(int, size);
2240
2241 const int oldSize = vector.size();
2242
2243 vector.resize(asize: size);
2244 QCOMPARE(vector.size(), size);
2245 QVERIFY(vector.capacity() >= size);
2246 for (int i = oldSize; i < size; ++i)
2247 QVERIFY(vector[i] == 'j'); // check initialization
2248
2249 const int capacity = vector.capacity();
2250
2251 vector.resize(asize: 0);
2252 QCOMPARE(vector.size(), 0);
2253 QVERIFY(vector.capacity() <= capacity);
2254 }
2255 QCOMPARE(items, Movable::counter.loadAcquire());
2256}
2257
2258void tst_QVector::resizeComplex_data() const
2259{
2260 QTest::addColumn<QVector<Custom> >(name: "vector");
2261 QTest::addColumn<int>(name: "size");
2262
2263 QVERIFY(QTypeInfo<Custom>::isComplex);
2264 QVERIFY(QTypeInfo<Custom>::isStatic);
2265
2266 QVector<Custom> null;
2267 QVector<Custom> empty(0, '0');
2268 QVector<Custom> emptyReserved;
2269 QVector<Custom> nonEmpty;
2270 QVector<Custom> nonEmptyReserved;
2271
2272 emptyReserved.reserve(asize: 10);
2273 nonEmptyReserved.reserve(asize: 15);
2274 nonEmpty << '0' << '1' << '2' << '3' << '4';
2275 nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2276 QVERIFY(emptyReserved.capacity() >= 10);
2277 QVERIFY(nonEmptyReserved.capacity() >= 15);
2278
2279 QTest::newRow(dataTag: "null") << null << 10;
2280 QTest::newRow(dataTag: "empty") << empty << 10;
2281 QTest::newRow(dataTag: "emptyReserved") << emptyReserved << 10;
2282 QTest::newRow(dataTag: "nonEmpty") << nonEmpty << 10;
2283 QTest::newRow(dataTag: "nonEmptyReserved") << nonEmptyReserved << 10;
2284
2285#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
2286 // ### Qt6 remove this section
2287 QVector<Custom> nullNotShared;
2288 QVector<Custom> emptyNotShared(0, '0');
2289 QVector<Custom> emptyReservedNotShared;
2290 QVector<Custom> nonEmptyNotShared;
2291 QVector<Custom> nonEmptyReservedNotShared;
2292
2293 emptyReservedNotShared.reserve(asize: 10);
2294 nonEmptyReservedNotShared.reserve(asize: 15);
2295 nonEmptyNotShared << '0' << '1' << '2' << '3' << '4';
2296 nonEmptyReservedNotShared << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2297 QVERIFY(emptyReservedNotShared.capacity() >= 10);
2298 QVERIFY(nonEmptyReservedNotShared.capacity() >= 15);
2299
2300 emptyNotShared.setSharable(false);
2301 emptyReservedNotShared.setSharable(false);
2302 nonEmptyNotShared.setSharable(false);
2303 nonEmptyReservedNotShared.setSharable(false);
2304
2305 QTest::newRow(dataTag: "nullNotShared") << nullNotShared << 10;
2306 QTest::newRow(dataTag: "emptyNotShared") << emptyNotShared << 10;
2307 QTest::newRow(dataTag: "emptyReservedNotShared") << emptyReservedNotShared << 10;
2308 QTest::newRow(dataTag: "nonEmptyNotShared") << nonEmptyNotShared << 10;
2309 QTest::newRow(dataTag: "nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10;
2310#endif
2311}
2312
2313void tst_QVector::resizeComplex() const
2314{
2315 const int items = Custom::counter.loadAcquire();
2316 {
2317 QFETCH(QVector<Custom>, vector);
2318 QFETCH(int, size);
2319
2320 int oldSize = vector.size();
2321 vector.resize(asize: size);
2322 QCOMPARE(vector.size(), size);
2323 QVERIFY(vector.capacity() >= size);
2324 for (int i = oldSize; i < size; ++i)
2325 QVERIFY(vector[i].i == 'j'); // check default initialization
2326
2327 const int capacity = vector.capacity();
2328
2329 vector.resize(asize: 0);
2330 QCOMPARE(vector.size(), 0);
2331 QVERIFY(vector.isEmpty());
2332 QVERIFY(vector.capacity() <= capacity);
2333 }
2334 QCOMPARE(Custom::counter.loadAcquire(), items);
2335}
2336
2337void tst_QVector::resizeCtorAndDtor() const
2338{
2339 const int items = Custom::counter.loadAcquire();
2340 {
2341 QVector<Custom> null;
2342 QVector<Custom> empty(0, '0');
2343 QVector<Custom> emptyReserved;
2344 QVector<Custom> nonEmpty;
2345 QVector<Custom> nonEmptyReserved;
2346
2347 emptyReserved.reserve(asize: 10);
2348 nonEmptyReserved.reserve(asize: 15);
2349 nonEmpty << '0' << '1' << '2' << '3' << '4';
2350 nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2351 QVERIFY(emptyReserved.capacity() >= 10);
2352 QVERIFY(nonEmptyReserved.capacity() >= 15);
2353
2354 // start playing with vectors
2355 null.resize(asize: 21);
2356 nonEmpty.resize(asize: 2);
2357 emptyReserved.resize(asize: 0);
2358 nonEmpty.resize(asize: 0);
2359 nonEmptyReserved.resize(asize: 2);
2360 }
2361 QCOMPARE(Custom::counter.loadAcquire(), items);
2362}
2363
2364void tst_QVector::reverseIterators() const
2365{
2366 QVector<int> v;
2367 v << 1 << 2 << 3 << 4;
2368 QVector<int> vr = v;
2369 std::reverse(first: vr.begin(), last: vr.end());
2370 const QVector<int> &cvr = vr;
2371 QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin()));
2372 QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin()));
2373 QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin()));
2374 QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin()));
2375 QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin()));
2376 QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin()));
2377}
2378
2379template<typename T>
2380void tst_QVector::size() const
2381{
2382 // zero size
2383 QVector<T> myvec;
2384 QVERIFY(myvec.size() == 0);
2385
2386 // grow
2387 myvec.append(SimpleValue<T>::at(0));
2388 QVERIFY(myvec.size() == 1);
2389 myvec.append(SimpleValue<T>::at(1));
2390 QVERIFY(myvec.size() == 2);
2391
2392 // shrink
2393 myvec.remove(0);
2394 QVERIFY(myvec.size() == 1);
2395 myvec.remove(0);
2396 QVERIFY(myvec.size() == 0);
2397}
2398
2399void tst_QVector::sizeInt() const
2400{
2401 size<int>();
2402}
2403
2404void tst_QVector::sizeMovable() const
2405{
2406 const int instancesCount = Movable::counter.loadAcquire();
2407 size<Movable>();
2408 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
2409}
2410
2411void tst_QVector::sizeCustom() const
2412{
2413 const int instancesCount = Custom::counter.loadAcquire();
2414 size<Custom>();
2415 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
2416}
2417
2418// ::squeeze() is tested in ::capacity().
2419
2420void tst_QVector::startsWith() const
2421{
2422 QVector<int> myvec;
2423
2424 // empty vector
2425 QVERIFY(!myvec.startsWith(1));
2426
2427 // add the one, should work
2428 myvec.prepend(t: 1);
2429 QVERIFY(myvec.startsWith(1));
2430
2431 // add something else, fails now
2432 myvec.prepend(t: 3);
2433 QVERIFY(!myvec.startsWith(1));
2434
2435 // remove it again :)
2436 myvec.remove(i: 0);
2437 QVERIFY(myvec.startsWith(1));
2438}
2439
2440template<typename T>
2441void tst_QVector::swap() const
2442{
2443 QVector<T> v1, v2;
2444 T val1 = SimpleValue<T>::at(0);
2445 T val2 = SimpleValue<T>::at(1);
2446 T val3 = SimpleValue<T>::at(2);
2447 T val4 = SimpleValue<T>::at(3);
2448 T val5 = SimpleValue<T>::at(4);
2449 T val6 = SimpleValue<T>::at(5);
2450 v1 << val1 << val2 << val3;
2451 v2 << val4 << val5 << val6;
2452
2453 v1.swap(v2);
2454 QCOMPARE(v1,QVector<T>() << val4 << val5 << val6);
2455 QCOMPARE(v2,QVector<T>() << val1 << val2 << val3);
2456}
2457
2458void tst_QVector::swapInt() const
2459{
2460 swap<int>();
2461}
2462
2463void tst_QVector::swapMovable() const
2464{
2465 const int instancesCount = Movable::counter.loadAcquire();
2466 swap<Movable>();
2467 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
2468}
2469
2470void tst_QVector::swapCustom() const
2471{
2472 const int instancesCount = Custom::counter.loadAcquire();
2473 swap<Custom>();
2474 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
2475}
2476
2477void tst_QVector::toList() const
2478{
2479 QVector<QString> myvec;
2480 myvec << "A" << "B" << "C";
2481
2482 // make sure it converts and doesn't modify the original vector
2483 QCOMPARE(myvec.toList(), QList<QString>() << "A" << "B" << "C");
2484 QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
2485}
2486
2487#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2488void tst_QVector::toStdVector() const
2489{
2490 QVector<QString> myvec;
2491 myvec << "A" << "B" << "C";
2492
2493 std::vector<QString> svec = myvec.toStdVector();
2494 QCOMPARE(svec.at(0), QLatin1String("A"));
2495 QCOMPARE(svec.at(1), QLatin1String("B"));
2496 QCOMPARE(svec.at(2), QLatin1String("C"));
2497
2498 QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
2499}
2500#endif
2501
2502void tst_QVector::value() const
2503{
2504 QVector<QString> myvec;
2505 myvec << "A" << "B" << "C";
2506
2507 // valid calls
2508 QCOMPARE(myvec.value(0), QLatin1String("A"));
2509 QCOMPARE(myvec.value(1), QLatin1String("B"));
2510 QCOMPARE(myvec.value(2), QLatin1String("C"));
2511
2512 // default calls
2513 QCOMPARE(myvec.value(-1), QString());
2514 QCOMPARE(myvec.value(3), QString());
2515
2516 // test calls with a provided default, valid calls
2517 QCOMPARE(myvec.value(0, QLatin1String("default")), QLatin1String("A"));
2518 QCOMPARE(myvec.value(1, QLatin1String("default")), QLatin1String("B"));
2519 QCOMPARE(myvec.value(2, QLatin1String("default")), QLatin1String("C"));
2520
2521 // test calls with a provided default that will return the default
2522 QCOMPARE(myvec.value(-1, QLatin1String("default")), QLatin1String("default"));
2523 QCOMPARE(myvec.value(3, QLatin1String("default")), QLatin1String("default"));
2524}
2525
2526void tst_QVector::testOperators() const
2527{
2528 QVector<QString> myvec;
2529 myvec << "A" << "B" << "C";
2530 QVector<QString> myvectwo;
2531 myvectwo << "D" << "E" << "F";
2532 QVector<QString> combined;
2533 combined << "A" << "B" << "C" << "D" << "E" << "F";
2534
2535 // !=
2536 QVERIFY(myvec != myvectwo);
2537
2538 // +
2539 QCOMPARE(myvec + myvectwo, combined);
2540 QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
2541 QCOMPARE(myvectwo, QVector<QString>() << "D" << "E" << "F");
2542
2543 // +=
2544 myvec += myvectwo;
2545 QCOMPARE(myvec, combined);
2546
2547 // ==
2548 QVERIFY(myvec == combined);
2549
2550 // <, >, <=, >=
2551 QVERIFY(!(myvec < combined));
2552 QVERIFY(!(myvec > combined));
2553 QVERIFY( myvec <= combined);
2554 QVERIFY( myvec >= combined);
2555 combined.push_back(t: "G");
2556 QVERIFY( myvec < combined);
2557 QVERIFY(!(myvec > combined));
2558 QVERIFY( myvec <= combined);
2559 QVERIFY(!(myvec >= combined));
2560 QVERIFY(combined > myvec);
2561 QVERIFY(combined >= myvec);
2562
2563 // []
2564 QCOMPARE(myvec[0], QLatin1String("A"));
2565 QCOMPARE(myvec[1], QLatin1String("B"));
2566 QCOMPARE(myvec[2], QLatin1String("C"));
2567 QCOMPARE(myvec[3], QLatin1String("D"));
2568 QCOMPARE(myvec[4], QLatin1String("E"));
2569 QCOMPARE(myvec[5], QLatin1String("F"));
2570}
2571
2572
2573int fooCtor;
2574int fooDtor;
2575
2576struct Foo
2577{
2578 int *p;
2579
2580 Foo() { p = new int; ++fooCtor; }
2581 Foo(const Foo &other) { Q_UNUSED(other); p = new int; ++fooCtor; }
2582
2583 void operator=(const Foo & /* other */) { }
2584
2585 ~Foo() { delete p; ++fooDtor; }
2586};
2587
2588void tst_QVector::reserve()
2589{
2590 fooCtor = 0;
2591 fooDtor = 0;
2592 {
2593 QVector<Foo> a;
2594 a.resize(asize: 2);
2595 QCOMPARE(fooCtor, 2);
2596 QVector<Foo> b(a);
2597 b.reserve(asize: 1);
2598 QCOMPARE(b.size(), a.size());
2599 QCOMPARE(fooDtor, 0);
2600 }
2601 QCOMPARE(fooCtor, fooDtor);
2602}
2603
2604// This is a regression test for QTBUG-51758
2605void tst_QVector::reserveZero()
2606{
2607 QVector<int> vec;
2608 vec.detach();
2609 vec.reserve(asize: 0); // should not crash
2610 QCOMPARE(vec.size(), 0);
2611 QCOMPARE(vec.capacity(), 0);
2612 vec.squeeze();
2613 QCOMPARE(vec.size(), 0);
2614 QCOMPARE(vec.capacity(), 0);
2615 vec.reserve(asize: -1);
2616 QCOMPARE(vec.size(), 0);
2617 QCOMPARE(vec.capacity(), 0);
2618 vec.append(t: 42);
2619 QCOMPARE(vec.size(), 1);
2620 QVERIFY(vec.capacity() >= 1);
2621}
2622
2623// This is a regression test for QTBUG-11763, where memory would be reallocated
2624// soon after copying a QVector.
2625void tst_QVector::reallocAfterCopy_data()
2626{
2627 QTest::addColumn<int>(name: "capacity");
2628 QTest::addColumn<int>(name: "fill_size");
2629 QTest::addColumn<int>(name: "func_id");
2630 QTest::addColumn<int>(name: "result1");
2631 QTest::addColumn<int>(name: "result2");
2632 QTest::addColumn<int>(name: "result3");
2633 QTest::addColumn<int>(name: "result4");
2634
2635 int result1, result2, result3, result4;
2636 int fill_size;
2637 for (int i = 70; i <= 100; i += 10) {
2638 const QByteArray prefix = "reallocAfterCopy:" + QByteArray::number(i) + ',';
2639 fill_size = i - 20;
2640 for (int j = 0; j <= 3; j++) {
2641 if (j == 0) { // append
2642 result1 = i;
2643 result2 = i;
2644 result3 = i - 19;
2645 result4 = i - 20;
2646 } else if (j == 1) { // insert(0)
2647 result1 = i;
2648 result2 = i;
2649 result3 = i - 19;
2650 result4 = i - 20;
2651 } else if (j == 2) { // insert(20)
2652 result1 = i;
2653 result2 = i;
2654 result3 = i - 19;
2655 result4 = i - 20;
2656 } else if (j == 3) { // insert(0, 10)
2657 result1 = i;
2658 result2 = i;
2659 result3 = i - 10;
2660 result4 = i - 20;
2661 }
2662 QTest::newRow(dataTag: (prefix + QByteArray::number(j)).constData())
2663 << i << fill_size << j << result1 << result2 << result3 << result4;
2664 }
2665 }
2666}
2667
2668void tst_QVector::reallocAfterCopy()
2669{
2670 QFETCH(int, capacity);
2671 QFETCH(int, fill_size);
2672 QFETCH(int, func_id);
2673 QFETCH(int, result1);
2674 QFETCH(int, result2);
2675 QFETCH(int, result3);
2676 QFETCH(int, result4);
2677
2678 QVector<qreal> v1;
2679 QVector<qreal> v2;
2680
2681 v1.reserve(asize: capacity);
2682 v1.resize(asize: 0);
2683 v1.fill(from: qreal(1.0), asize: fill_size);
2684
2685 v2 = v1;
2686
2687 // no need to test begin() and end(), there is a detach() in them
2688 if (func_id == 0) {
2689 v1.append(t: qreal(1.0)); //push_back is same as append
2690 } else if (func_id == 1) {
2691 v1.insert(i: 0, t: qreal(1.0)); //push_front is same as prepend, insert(0)
2692 } else if (func_id == 2) {
2693 v1.insert(i: 20, t: qreal(1.0));
2694 } else if (func_id == 3) {
2695 v1.insert(i: 0, n: 10, t: qreal(1.0));
2696 }
2697
2698 QCOMPARE(v1.capacity(), result1);
2699 QCOMPARE(v2.capacity(), result2);
2700 QCOMPARE(v1.size(), result3);
2701 QCOMPARE(v2.size(), result4);
2702}
2703
2704template<typename T>
2705void tst_QVector::initializeList()
2706{
2707 T val1(SimpleValue<T>::at(1));
2708 T val2(SimpleValue<T>::at(2));
2709 T val3(SimpleValue<T>::at(3));
2710 T val4(SimpleValue<T>::at(4));
2711
2712 QVector<T> v1 {val1, val2, val3};
2713 QCOMPARE(v1, QVector<T>() << val1 << val2 << val3);
2714 QCOMPARE(v1, (QVector<T> {val1, val2, val3}));
2715
2716 QVector<QVector<T>> v2{ v1, {val4}, QVector<T>(), {val1, val2, val3} };
2717 QVector<QVector<T>> v3;
2718 v3 << v1 << (QVector<T>() << val4) << QVector<T>() << v1;
2719 QCOMPARE(v3, v2);
2720
2721 QVector<T> v4({});
2722 QCOMPARE(v4.size(), 0);
2723}
2724
2725void tst_QVector::initializeListInt()
2726{
2727 initializeList<int>();
2728}
2729
2730void tst_QVector::initializeListMovable()
2731{
2732 const int instancesCount = Movable::counter.loadAcquire();
2733 initializeList<Movable>();
2734 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
2735}
2736
2737void tst_QVector::initializeListCustom()
2738{
2739 const int instancesCount = Custom::counter.loadAcquire();
2740 initializeList<Custom>();
2741 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
2742}
2743
2744void tst_QVector::const_shared_null()
2745{
2746 QVector<int> v2;
2747#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
2748 // ### Qt6 remove this section
2749 QVector<int> v1;
2750 v1.setSharable(false);
2751 QVERIFY(v1.isDetached());
2752
2753 v2.setSharable(true);
2754#endif
2755 QVERIFY(!v2.isDetached());
2756}
2757
2758#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
2759// ### Qt6 remove this section
2760template<typename T>
2761void tst_QVector::setSharable_data() const
2762{
2763 QTest::addColumn<QVector<T> >("vector");
2764 QTest::addColumn<int>(name: "size");
2765 QTest::addColumn<int>(name: "capacity");
2766 QTest::addColumn<bool>(name: "isCapacityReserved");
2767
2768 QVector<T> null;
2769 QVector<T> empty(0, SimpleValue<T>::at(1));
2770 QVector<T> emptyReserved;
2771 QVector<T> nonEmpty;
2772 QVector<T> nonEmptyReserved;
2773
2774 emptyReserved.reserve(10);
2775 nonEmptyReserved.reserve(15);
2776
2777 nonEmpty << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3) << SimpleValue<T>::at(4);
2778 nonEmptyReserved << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3) << SimpleValue<T>::at(4) << SimpleValue<T>::at(5) << SimpleValue<T>::at(6);
2779
2780 QVERIFY(emptyReserved.capacity() >= 10);
2781 QVERIFY(nonEmptyReserved.capacity() >= 15);
2782
2783 QTest::newRow(dataTag: "null") << null << 0 << 0 << false;
2784 QTest::newRow(dataTag: "empty") << empty << 0 << 0 << false;
2785 QTest::newRow(dataTag: "empty, Reserved") << emptyReserved << 0 << 10 << true;
2786 QTest::newRow(dataTag: "non-empty") << nonEmpty << 5 << 0 << false;
2787 QTest::newRow(dataTag: "non-empty, Reserved") << nonEmptyReserved << 7 << 15 << true;
2788}
2789
2790template<typename T>
2791void tst_QVector::setSharable() const
2792{
2793 QFETCH(QVector<T>, vector);
2794 QFETCH(int, size);
2795 QFETCH(int, capacity);
2796 QFETCH(bool, isCapacityReserved);
2797
2798 QVERIFY(!vector.isDetached()); // Shared with QTest
2799
2800 vector.setSharable(true);
2801
2802 QCOMPARE(vector.size(), size);
2803 if (isCapacityReserved)
2804 QVERIFY2(vector.capacity() >= capacity,
2805 qPrintable(QString("Capacity is %1, expected at least %2.")
2806 .arg(vector.capacity())
2807 .arg(capacity)));
2808
2809 {
2810 QVector<T> copy(vector);
2811
2812 QVERIFY(!copy.isDetached());
2813 QVERIFY(copy.isSharedWith(vector));
2814 }
2815
2816 vector.setSharable(false);
2817 QVERIFY(vector.isDetached() || vector.isSharedWith(QVector<T>()));
2818
2819 {
2820 QVector<T> copy(vector);
2821
2822 QVERIFY(copy.isDetached() || copy.isEmpty() || copy.isSharedWith(QVector<T>()));
2823 QCOMPARE(copy.size(), size);
2824 if (isCapacityReserved)
2825 QVERIFY2(copy.capacity() >= capacity,
2826 qPrintable(QString("Capacity is %1, expected at least %2.")
2827 .arg(copy.capacity())
2828 .arg(capacity)));
2829 QCOMPARE(copy, vector);
2830 }
2831
2832 vector.setSharable(true);
2833
2834 {
2835 QVector<T> copy(vector);
2836
2837 QVERIFY(!copy.isDetached());
2838 QVERIFY(copy.isSharedWith(vector));
2839 }
2840
2841 for (int i = 0; i < vector.size(); ++i)
2842 QCOMPARE(vector[i], SimpleValue<T>::at(i));
2843
2844 QCOMPARE(vector.size(), size);
2845 if (isCapacityReserved)
2846 QVERIFY2(vector.capacity() >= capacity,
2847 qPrintable(QString("Capacity is %1, expected at least %2.")
2848 .arg(vector.capacity())
2849 .arg(capacity)));
2850}
2851#else
2852template<typename T> void tst_QVector::setSharable_data() const
2853{
2854}
2855
2856template<typename T> void tst_QVector::setSharable() const
2857{
2858}
2859#endif
2860
2861void tst_QVector::setSharableInt_data()
2862{
2863 setSharable_data<int>();
2864}
2865
2866void tst_QVector::setSharableMovable_data()
2867{
2868 setSharable_data<Movable>();
2869}
2870
2871void tst_QVector::setSharableCustom_data()
2872{
2873 setSharable_data<Custom>();
2874}
2875
2876void tst_QVector::setSharableInt()
2877{
2878 setSharable<int>();
2879}
2880
2881void tst_QVector::setSharableMovable()
2882{
2883 const int instancesCount = Movable::counter.loadAcquire();
2884 setSharable<Movable>();
2885 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
2886}
2887
2888void tst_QVector::setSharableCustom()
2889{
2890 const int instancesCount = Custom::counter.loadAcquire();
2891 setSharable<Custom>();
2892 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
2893}
2894
2895template<typename T>
2896void tst_QVector::detach() const
2897{
2898 {
2899 // detach an empty vector
2900 QVector<T> v;
2901 v.detach();
2902 QVERIFY(v.isDetached());
2903 QCOMPARE(v.size(), 0);
2904 QCOMPARE(v.capacity(), 0);
2905 }
2906 {
2907 // detach an empty referenced vector
2908 QVector<T> v;
2909 QVector<T> ref(v);
2910 QVERIFY(!v.isDetached());
2911 v.detach();
2912 QVERIFY(v.isDetached());
2913 QCOMPARE(v.size(), 0);
2914 QCOMPARE(v.capacity(), 0);
2915 }
2916 {
2917 // detach a not empty referenced vector
2918 QVector<T> v(31);
2919 QVector<T> ref(v);
2920 QVERIFY(!v.isDetached());
2921 v.detach();
2922 QVERIFY(v.isDetached());
2923 QCOMPARE(v.size(), 31);
2924 QCOMPARE(v.capacity(), 31);
2925 }
2926 {
2927 // detach a not empty vector
2928 QVector<T> v(31);
2929 QVERIFY(v.isDetached());
2930 v.detach(); // detaching a detached vector
2931 QVERIFY(v.isDetached());
2932 QCOMPARE(v.size(), 31);
2933 QCOMPARE(v.capacity(), 31);
2934 }
2935 {
2936 // detach a not empty vector with preallocated space
2937 QVector<T> v(3);
2938 v.reserve(8);
2939 QVector<T> ref(v);
2940 QVERIFY(!v.isDetached());
2941 v.detach();
2942 QVERIFY(v.isDetached());
2943 QCOMPARE(v.size(), 3);
2944 QCOMPARE(v.capacity(), 8);
2945 }
2946 {
2947 // detach a not empty vector with preallocated space
2948 QVector<T> v(3);
2949 v.reserve(8);
2950 QVERIFY(v.isDetached());
2951 v.detach(); // detaching a detached vector
2952 QVERIFY(v.isDetached());
2953 QCOMPARE(v.size(), 3);
2954 QCOMPARE(v.capacity(), 8);
2955 }
2956 {
2957 // detach a not empty, initialized vector
2958 QVector<T> v(7, SimpleValue<T>::at(1));
2959 QVector<T> ref(v);
2960 QVERIFY(!v.isDetached());
2961 v.detach();
2962 QVERIFY(v.isDetached());
2963 QCOMPARE(v.size(), 7);
2964 for (int i = 0; i < v.size(); ++i)
2965 QCOMPARE(v[i], SimpleValue<T>::at(1));
2966 }
2967 {
2968 // detach a not empty, initialized vector
2969 QVector<T> v(7, SimpleValue<T>::at(2));
2970 QVERIFY(v.isDetached());
2971 v.detach(); // detaching a detached vector
2972 QVERIFY(v.isDetached());
2973 QCOMPARE(v.size(), 7);
2974 for (int i = 0; i < v.size(); ++i)
2975 QCOMPARE(v[i], SimpleValue<T>::at(2));
2976 }
2977 {
2978 // detach a not empty, initialized vector with preallocated space
2979 QVector<T> v(7, SimpleValue<T>::at(3));
2980 v.reserve(31);
2981 QVector<T> ref(v);
2982 QVERIFY(!v.isDetached());
2983 v.detach();
2984 QVERIFY(v.isDetached());
2985 QCOMPARE(v.size(), 7);
2986 QCOMPARE(v.capacity(), 31);
2987 for (int i = 0; i < v.size(); ++i)
2988 QCOMPARE(v[i], SimpleValue<T>::at(3));
2989 }
2990}
2991
2992void tst_QVector::detachInt() const
2993{
2994 detach<int>();
2995}
2996
2997void tst_QVector::detachMovable() const
2998{
2999 const int instancesCount = Movable::counter.loadAcquire();
3000 detach<Movable>();
3001 QCOMPARE(instancesCount, Movable::counter.loadAcquire());
3002}
3003
3004void tst_QVector::detachCustom() const
3005{
3006 const int instancesCount = Custom::counter.loadAcquire();
3007 detach<Custom>();
3008 QCOMPARE(instancesCount, Custom::counter.loadAcquire());
3009}
3010
3011static QAtomicPointer<QVector<int> > detachThreadSafetyDataInt;
3012static QAtomicPointer<QVector<Movable> > detachThreadSafetyDataMovable;
3013static QAtomicPointer<QVector<Custom> > detachThreadSafetyDataCustom;
3014
3015template<typename T> QAtomicPointer<QVector<T> > *detachThreadSafetyData();
3016template<> QAtomicPointer<QVector<int> > *detachThreadSafetyData() { return &detachThreadSafetyDataInt; }
3017template<> QAtomicPointer<QVector<Movable> > *detachThreadSafetyData() { return &detachThreadSafetyDataMovable; }
3018template<> QAtomicPointer<QVector<Custom> > *detachThreadSafetyData() { return &detachThreadSafetyDataCustom; }
3019
3020static QSemaphore detachThreadSafetyLock;
3021
3022template<typename T>
3023void tst_QVector::detachThreadSafety() const
3024{
3025 delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(new QVector<T>(SimpleValue<T>::vector(400)));
3026
3027 static const uint threadsCount = 5;
3028
3029 struct : QThread {
3030 void run() override
3031 {
3032 QVector<T> copy(*detachThreadSafetyData<T>()->loadRelaxed());
3033 QVERIFY(!copy.isDetached());
3034 detachThreadSafetyLock.release();
3035 detachThreadSafetyLock.acquire(n: 100);
3036 copy.detach();
3037 }
3038 } threads[threadsCount];
3039
3040 for (uint i = 0; i < threadsCount; ++i)
3041 threads[i].start();
3042 QThread::yieldCurrentThread();
3043 detachThreadSafetyLock.acquire(n: threadsCount);
3044
3045 // destroy static original data
3046 delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(0);
3047
3048 QVERIFY(threadsCount < 100);
3049 detachThreadSafetyLock.release(n: threadsCount * 100);
3050 QThread::yieldCurrentThread();
3051
3052 for (uint i = 0; i < threadsCount; ++i)
3053 threads[i].wait();
3054}
3055
3056void tst_QVector::detachThreadSafetyInt() const
3057{
3058 for (uint i = 0; i < 128; ++i)
3059 detachThreadSafety<int>();
3060}
3061
3062void tst_QVector::detachThreadSafetyMovable() const
3063{
3064 const int instancesCount = Movable::counter.loadAcquire();
3065 for (uint i = 0; i < 128; ++i) {
3066 detachThreadSafety<Movable>();
3067 QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
3068 }
3069}
3070
3071void tst_QVector::detachThreadSafetyCustom() const
3072{
3073 const int instancesCount = Custom::counter.loadAcquire();
3074 for (uint i = 0; i < 128; ++i) {
3075 detachThreadSafety<Custom>();
3076 QCOMPARE(Custom::counter.loadAcquire(), instancesCount);
3077 }
3078}
3079
3080void tst_QVector::insertMove() const
3081{
3082 const int instancesCount = Movable::counter.loadAcquire();
3083 {
3084 QVector<Movable> vec;
3085 vec.reserve(asize: 7);
3086 Movable m0;
3087 Movable m1;
3088 Movable m2;
3089 Movable m3;
3090 Movable m4;
3091 Movable m5;
3092 Movable m6;
3093
3094 vec.append(t: std::move(m3));
3095 QVERIFY(m3.wasConstructedAt(nullptr));
3096 QVERIFY(vec.at(0).wasConstructedAt(&m3));
3097 vec.push_back(t: std::move(m4));
3098 QVERIFY(m4.wasConstructedAt(nullptr));
3099 QVERIFY(vec.at(0).wasConstructedAt(&m3));
3100 QVERIFY(vec.at(1).wasConstructedAt(&m4));
3101 vec.prepend(t: std::move(m1));
3102 QVERIFY(m1.wasConstructedAt(nullptr));
3103 QVERIFY(vec.at(0).wasConstructedAt(&m1));
3104 QVERIFY(vec.at(1).wasConstructedAt(&m3));
3105 QVERIFY(vec.at(2).wasConstructedAt(&m4));
3106 vec.insert(i: 1, t: std::move(m2));
3107 QVERIFY(m2.wasConstructedAt(nullptr));
3108 QVERIFY(vec.at(0).wasConstructedAt(&m1));
3109 QVERIFY(vec.at(1).wasConstructedAt(&m2));
3110 QVERIFY(vec.at(2).wasConstructedAt(&m3));
3111 QVERIFY(vec.at(3).wasConstructedAt(&m4));
3112 vec += std::move(m5);
3113 QVERIFY(m5.wasConstructedAt(nullptr));
3114 QVERIFY(vec.at(0).wasConstructedAt(&m1));
3115 QVERIFY(vec.at(1).wasConstructedAt(&m2));
3116 QVERIFY(vec.at(2).wasConstructedAt(&m3));
3117 QVERIFY(vec.at(3).wasConstructedAt(&m4));
3118 QVERIFY(vec.at(4).wasConstructedAt(&m5));
3119 vec << std::move(m6);
3120 QVERIFY(m6.wasConstructedAt(nullptr));
3121 QVERIFY(vec.at(0).wasConstructedAt(&m1));
3122 QVERIFY(vec.at(1).wasConstructedAt(&m2));
3123 QVERIFY(vec.at(2).wasConstructedAt(&m3));
3124 QVERIFY(vec.at(3).wasConstructedAt(&m4));
3125 QVERIFY(vec.at(4).wasConstructedAt(&m5));
3126 QVERIFY(vec.at(5).wasConstructedAt(&m6));
3127 vec.push_front(t: std::move(m0));
3128 QVERIFY(m0.wasConstructedAt(nullptr));
3129 QVERIFY(vec.at(0).wasConstructedAt(&m0));
3130 QVERIFY(vec.at(1).wasConstructedAt(&m1));
3131 QVERIFY(vec.at(2).wasConstructedAt(&m2));
3132 QVERIFY(vec.at(3).wasConstructedAt(&m3));
3133 QVERIFY(vec.at(4).wasConstructedAt(&m4));
3134 QVERIFY(vec.at(5).wasConstructedAt(&m5));
3135 QVERIFY(vec.at(6).wasConstructedAt(&m6));
3136
3137 QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14);
3138 }
3139 QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
3140}
3141
3142void tst_QVector::swapItemsAt() const
3143{
3144 QVector<int> v;
3145 v << 0 << 1 << 2 << 3;
3146
3147 v.swapItemsAt(i: 0, j: 2);
3148 QCOMPARE(v.at(0), 2);
3149 QCOMPARE(v.at(2), 0);
3150
3151 auto copy = v;
3152 copy.swapItemsAt(i: 0, j: 2);
3153 QCOMPARE(v.at(0), 2);
3154 QCOMPARE(v.at(2), 0);
3155 QCOMPARE(copy.at(0), 0);
3156 QCOMPARE(copy.at(2), 2);
3157}
3158
3159QTEST_MAIN(tst_QVector)
3160#include "tst_qvector.moc"
3161

source code of qtbase/tests/auto/corelib/tools/qvector/tst_qvector.cpp