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
30#include <QtTest/QtTest>
31#include <QList>
32
33template <typename T, class MemoryLayout>
34class is_qlist_array_memory_layout {
35 struct No { char c; };
36 struct Yes { No n[2]; };
37 Q_STATIC_ASSERT(sizeof(No) != sizeof(Yes));
38 static No check(...);
39 static Yes check(MemoryLayout);
40public:
41 enum { value = sizeof(check(typename QList<T>::MemoryLayout())) == sizeof(Yes) };
42};
43
44struct Movable {
45 Movable(char input = 'j')
46 : i(input)
47 , state(Constructed)
48 {
49 ++liveCount;
50 }
51 Movable(const Movable &other)
52 : i(other.i)
53 , state(Constructed)
54 {
55 check(state1: other.state, state2: Constructed);
56 ++liveCount;
57 }
58
59 ~Movable()
60 {
61 check(state1: state, state2: Constructed);
62 i = 0;
63 --liveCount;
64 state = Destructed;
65 }
66
67 bool operator ==(const Movable &other) const
68 {
69 check(state1: state, state2: Constructed);
70 check(state1: other.state, state2: Constructed);
71 return i == other.i;
72 }
73
74 bool operator<(const Movable &other) const
75 {
76 check(state1: state, state2: Constructed);
77 check(state1: other.state, state2: Constructed);
78 return i < other.i;
79 }
80
81 Movable &operator=(const Movable &other)
82 {
83 check(state1: state, state2: Constructed);
84 check(state1: other.state, state2: Constructed);
85 i = other.i;
86 return *this;
87 }
88 char i;
89
90 static int getLiveCount() { return liveCount; }
91private:
92 static int liveCount;
93
94 enum State { Constructed = 106, Destructed = 110 };
95 uchar state;
96
97 static void check(const uchar state1, const uchar state2)
98 {
99 QCOMPARE(state1, state2);
100 }
101};
102
103Q_STATIC_ASSERT(sizeof(Movable) < sizeof(void*));
104
105int Movable::liveCount = 0;
106
107QT_BEGIN_NAMESPACE
108Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
109QT_END_NAMESPACE
110
111Q_DECLARE_METATYPE(Movable);
112
113int qHash(const Movable& movable)
114{
115 return qHash(key: movable.i);
116}
117
118struct Optimal
119{
120 Optimal(char input = 'j')
121 : i(input),
122 state(Constructed)
123 {
124 ++liveCount;
125 }
126 Optimal(const Optimal &other)
127 : i(other.i),
128 state(Constructed)
129 {
130 check(state1: other.state, state2: Constructed);
131 ++liveCount;
132 }
133
134 ~Optimal()
135 {
136 check(state1: state, state2: Constructed);
137 i = 0;
138 --liveCount;
139 state = Destructed;
140 }
141
142 bool operator ==(const Optimal &other) const
143 {
144 check(state1: state, state2: Constructed);
145 check(state1: other.state, state2: Constructed);
146 return i == other.i;
147 }
148
149 bool operator<(const Optimal &other) const
150 {
151 check(state1: state, state2: Constructed);
152 check(state1: other.state, state2: Constructed);
153 return i < other.i;
154 }
155
156 Optimal &operator=(const Optimal &other)
157 {
158 check(state1: state, state2: Constructed);
159 check(state1: other.state, state2: Constructed);
160 i = other.i;
161 return *this;
162 }
163 char i;
164
165 static int getLiveCount() { return liveCount; }
166private:
167 static int liveCount;
168
169 enum State { Constructed = 106, Destructed = 110 };
170 uchar state;
171 char padding[sizeof(void*) - 2];
172
173 static void check(const uchar state1, const uchar state2)
174 {
175 QCOMPARE(state1, state2);
176 }
177};
178
179Q_STATIC_ASSERT(sizeof(Optimal) == sizeof(void*));
180
181int Optimal::liveCount = 0;
182
183QT_BEGIN_NAMESPACE
184Q_DECLARE_TYPEINFO(Optimal, Q_MOVABLE_TYPE);
185QT_END_NAMESPACE
186
187Q_DECLARE_METATYPE(Optimal);
188
189int qHash(const Optimal& key)
190{
191 return qHash(key: key.i);
192}
193
194struct Complex
195{
196 Complex(int val = 0)
197 : value(val)
198 , checkSum(this)
199 {
200 ++liveCount;
201 }
202
203 Complex(Complex const &other)
204 : value(other.value)
205 , checkSum(this)
206 {
207 ++liveCount;
208 }
209
210 Complex &operator=(Complex const &other)
211 {
212 check(); other.check();
213
214 value = other.value;
215 return *this;
216 }
217
218 ~Complex()
219 {
220 --liveCount;
221 check();
222 }
223
224 operator int() const { return value; }
225
226 bool operator==(Complex const &other) const
227 {
228 check(); other.check();
229 return value == other.value;
230 }
231
232 bool operator<(Complex const &other) const
233 {
234 check(); other.check();
235 return value < other.value;
236 }
237
238 void check() const
239 {
240 QVERIFY(this == checkSum);
241 }
242
243 static int getLiveCount() { return liveCount; }
244private:
245 static int liveCount;
246
247 int value;
248 void *checkSum;
249};
250
251int Complex::liveCount = 0;
252
253Q_DECLARE_METATYPE(Complex);
254
255// Tests depend on the fact that:
256Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic);
257Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex);
258Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic);
259Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex);
260Q_STATIC_ASSERT(!QTypeInfo<Optimal>::isStatic);
261Q_STATIC_ASSERT(QTypeInfo<Optimal>::isComplex);
262Q_STATIC_ASSERT(QTypeInfo<Complex>::isStatic);
263Q_STATIC_ASSERT(QTypeInfo<Complex>::isComplex);
264// iow:
265Q_STATIC_ASSERT(( is_qlist_array_memory_layout<int, QListData::NotIndirectLayout> ::value));
266Q_STATIC_ASSERT((!is_qlist_array_memory_layout<int, QListData::IndirectLayout> ::value));
267
268Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::InlineWithPaddingLayout> ::value));
269Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::NotArrayCompatibleLayout>::value));
270Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Optimal, QListData::NotIndirectLayout> ::value));
271Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Optimal, QListData::ArrayCompatibleLayout> ::value));
272Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::IndirectLayout> ::value));
273
274Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::InlineWithPaddingLayout> ::value));
275Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::NotArrayCompatibleLayout>::value));
276Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::NotIndirectLayout> ::value));
277Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Movable, QListData::ArrayCompatibleLayout> ::value));
278Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Movable, QListData::IndirectLayout> ::value));
279
280Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::InlineWithPaddingLayout> ::value));
281Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Complex, QListData::NotArrayCompatibleLayout>::value));
282Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::NotIndirectLayout> ::value));
283Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::ArrayCompatibleLayout> ::value));
284Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Complex, QListData::IndirectLayout> ::value));
285
286class tst_QList : public QObject
287{
288 Q_OBJECT
289
290private slots:
291 void lengthOptimal() const;
292 void lengthMovable() const;
293 void lengthComplex() const;
294 void lengthSignature() const;
295 void appendOptimal() const;
296 void appendMovable() const;
297 void appendComplex() const;
298 void prepend() const;
299 void midOptimal() const;
300 void midMovable() const;
301 void midComplex() const;
302 void atOptimal() const;
303 void atMovable() const;
304 void atComplex() const;
305 void firstOptimal() const;
306 void firstMovable() const;
307 void firstComplex() const;
308 void lastOptimal() const;
309 void lastMovable() const;
310 void lastComplex() const;
311 void constFirst() const;
312 void constLast() const;
313 void cpp17ctad() const;
314 void beginOptimal() const;
315 void beginMovable() const;
316 void beginComplex() const;
317 void endOptimal() const;
318 void endMovable() const;
319 void endComplex() const;
320 void containsOptimal() const;
321 void containsMovable() const;
322 void containsComplex() const;
323 void countOptimal() const;
324 void countMovable() const;
325 void countComplex() const;
326 void emptyOptimal() const;
327 void emptyMovable() const;
328 void emptyComplex() const;
329 void endsWithOptimal() const;
330 void endsWithMovable() const;
331 void endsWithComplex() const;
332 void lastIndexOfOptimal() const;
333 void lastIndexOfMovable() const;
334 void lastIndexOfComplex() const;
335 void moveOptimal() const;
336 void moveMovable() const;
337 void moveComplex() const;
338 void removeAllOptimal() const;
339 void removeAllMovable() const;
340 void removeAllComplex() const;
341 void removeAtOptimal() const;
342 void removeAtMovable() const;
343 void removeAtComplex() const;
344 void removeOneOptimal() const;
345 void removeOneMovable() const;
346 void removeOneComplex() const;
347 void replaceOptimal() const;
348 void replaceMovable() const;
349 void replaceComplex() const;
350 void reverseIteratorsOptimal() const;
351 void reverseIteratorsMovable() const;
352 void reverseIteratorsComplex() const;
353 void startsWithOptimal() const;
354 void startsWithMovable() const;
355 void startsWithComplex() const;
356 void swapOptimal() const;
357 void swapMovable() const;
358 void swapComplex() const;
359 void takeAtOptimal() const;
360 void takeAtMovable() const;
361 void takeAtComplex() const;
362 void takeFirstOptimal() const;
363 void takeFirstMovable() const;
364 void takeFirstComplex() const;
365 void takeLastOptimal() const;
366 void takeLastMovable() const;
367 void takeLastComplex() const;
368#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
369 void toSetOptimal() const;
370 void toSetMovable() const;
371 void toSetComplex() const;
372 void toStdListOptimal() const;
373 void toStdListMovable() const;
374 void toStdListComplex() const;
375#endif
376 void toVectorOptimal() const;
377 void toVectorMovable() const;
378 void toVectorComplex() const;
379 void valueOptimal() const;
380 void valueMovable() const;
381 void valueComplex() const;
382
383 void testOperatorsOptimal() const;
384 void testOperatorsMovable() const;
385 void testOperatorsComplex() const;
386 void testSTLIteratorsOptimal() const;
387 void testSTLIteratorsMovable() const;
388 void testSTLIteratorsComplex() const;
389
390 void initializeList() const;
391
392 void constSharedNullOptimal() const;
393 void constSharedNullMovable() const;
394 void constSharedNullComplex() const;
395 void setSharableInt_data() const;
396 void setSharableInt() const;
397 void setSharableComplex_data() const;
398 void setSharableComplex() const;
399 void eraseValidIteratorsOnSharedList() const;
400 void insertWithValidIteratorsOnSharedList() const;
401
402 void qhashOptimal() const { qhash<Optimal>(); }
403 void qhashMovable() const { qhash<Movable>(); }
404 void qhashComplex() const { qhash<Complex>(); }
405 void reserve() const;
406private:
407 template<typename T> void length() const;
408 template<typename T> void append() const;
409 template<typename T> void mid() const;
410 template<typename T> void at() const;
411 template<typename T> void first() const;
412 template<typename T> void last() const;
413 template<typename T> void begin() const;
414 template<typename T> void end() const;
415 template<typename T> void contains() const;
416 template<typename T> void count() const;
417 template<typename T> void empty() const;
418 template<typename T> void endsWith() const;
419 template<typename T> void lastIndexOf() const;
420 template<typename T> void move() const;
421 template<typename T> void qhash() const;
422 template<typename T> void removeAll() const;
423 template<typename T> void removeAt() const;
424 template<typename T> void removeOne() const;
425 template<typename T> void replace() const;
426 template<typename T> void reverseIterators() const;
427 template<typename T> void startsWith() const;
428 template<typename T> void swap() const;
429 template<typename T> void takeAt() const;
430 template<typename T> void takeFirst() const;
431 template<typename T> void takeLast() const;
432#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
433 template<typename T> void toSet() const;
434 template<typename T> void toStdList() const;
435#endif
436 template<typename T> void toVector() const;
437 template<typename T> void value() const;
438
439 template<typename T> void testOperators() const;
440 template<typename T> void testSTLIterators() const;
441
442 template<typename T> void constSharedNull() const;
443
444 int dummyForGuard;
445};
446
447template<typename T> struct SimpleValue
448{
449 static T at(int index)
450 {
451 return values[index % maxSize];
452 }
453 static const uint maxSize = 7;
454 static const T values[maxSize];
455};
456
457template<>
458const Optimal SimpleValue<Optimal>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
459template<>
460const Movable SimpleValue<Movable>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
461template<>
462const Complex SimpleValue<Complex>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
463
464// Make some macros for the tests to use in order to be slightly more readable...
465#define T_FOO SimpleValue<T>::at(0)
466#define T_BAR SimpleValue<T>::at(1)
467#define T_BAZ SimpleValue<T>::at(2)
468#define T_CAT SimpleValue<T>::at(3)
469#define T_DOG SimpleValue<T>::at(4)
470#define T_BLAH SimpleValue<T>::at(5)
471#define T_WEEE SimpleValue<T>::at(6)
472
473template<typename T>
474void tst_QList::length() const
475{
476 /* Empty list. */
477 {
478 const QList<T> list;
479 QCOMPARE(list.length(), 0);
480 }
481
482 /* One entry. */
483 {
484 QList<T> list;
485 list.append(T_FOO);
486 QCOMPARE(list.length(), 1);
487 }
488
489 /* Two entries. */
490 {
491 QList<T> list;
492 list.append(T_FOO);
493 list.append(T_BAR);
494 QCOMPARE(list.length(), 2);
495 }
496
497 /* Three entries. */
498 {
499 QList<T> list;
500 list.append(T_FOO);
501 list.append(T_BAR);
502 list.append(T_BAZ);
503 QCOMPARE(list.length(), 3);
504 }
505}
506
507void tst_QList::lengthOptimal() const
508{
509 const int liveCount = Optimal::getLiveCount();
510 length<Optimal>();
511 QCOMPARE(liveCount, Optimal::getLiveCount());
512}
513
514void tst_QList::lengthMovable() const
515{
516 const int liveCount = Movable::getLiveCount();
517 length<Movable>();
518 QCOMPARE(liveCount, Movable::getLiveCount());
519}
520
521void tst_QList::lengthComplex() const
522{
523 const int liveCount = Complex::getLiveCount();
524 length<Complex>();
525 QCOMPARE(liveCount, Complex::getLiveCount());
526}
527
528void tst_QList::lengthSignature() const
529{
530 /* Constness. */
531 {
532 const QList<int> list;
533 /* The function should be const. */
534 list.length();
535 }
536}
537
538template<typename T>
539void tst_QList::append() const
540{
541 /* test append(const QList<T> &) function */
542 T one(T_FOO);
543 T two(T_BAR);
544 T three(T_BAZ);
545 T four(T_CAT);
546 QList<T> list1;
547 QList<T> list2;
548 QList<T> listTotal;
549 list1.append(one);
550 list1.append(two);
551 list2.append(three);
552 list2.append(four);
553 list1.append(list2);
554 listTotal.append(one);
555 listTotal.append(two);
556 listTotal.append(three);
557 listTotal.append(four);
558 QCOMPARE(list1, listTotal);
559}
560
561void tst_QList::appendOptimal() const
562{
563 const int liveCount = Optimal::getLiveCount();
564 append<Optimal>();
565 QCOMPARE(liveCount, Optimal::getLiveCount());
566}
567
568void tst_QList::appendMovable() const
569{
570 const int liveCount = Movable::getLiveCount();
571 append<Movable>();
572 QCOMPARE(liveCount, Movable::getLiveCount());
573}
574
575void tst_QList::appendComplex() const
576{
577 const int liveCount = Complex::getLiveCount();
578 append<Complex>();
579 QCOMPARE(liveCount, Complex::getLiveCount());
580}
581
582void tst_QList::prepend() const
583{
584 QList<int *> list;
585 int *t1 = new int(0);
586 list.prepend(t: t1);
587 QVERIFY(list.size() == 1);
588 QVERIFY(list.at(0) == t1);
589 int *t2 = new int(0);
590 list.prepend(t: t2);
591 QVERIFY(list.size() == 2);
592 QVERIFY(list.at(0) == t2);
593 QVERIFY(list.at(1) == t1);
594 int *t3 = new int(0);
595 list.prepend(t: t3);
596 QVERIFY(list.size() == 3);
597 QVERIFY(list.at(0) == t3);
598 QVERIFY(list.at(1) == t2);
599 QVERIFY(list.at(2) == t1);
600 list.removeAll(t: t2);
601 delete t2;
602 QVERIFY(list.size() == 2);
603 QVERIFY(list.at(0) == t3);
604 QVERIFY(list.at(1) == t1);
605 int *t4 = new int(0);
606 list.prepend(t: t4);
607 QVERIFY(list.size() == 3);
608 QVERIFY(list.at(0) == t4);
609 QVERIFY(list.at(1) == t3);
610 QVERIFY(list.at(2) == t1);
611 qDeleteAll(c: list);
612 list.clear();
613}
614
615template<typename T>
616void tst_QList::mid() const
617{
618 QList<T> list;
619 list << T_FOO << T_BAR << T_BAZ << T_CAT << T_DOG << T_BLAH << T_WEEE;
620
621 QCOMPARE(list.mid(3, 3),
622 QList<T>() << T_CAT << T_DOG << T_BLAH);
623
624 QList<T> list1;
625 QCOMPARE(list1.mid(1, 1).length(), 0);
626}
627
628void tst_QList::midOptimal() const
629{
630 const int liveCount = Optimal::getLiveCount();
631 mid<Optimal>();
632 QCOMPARE(liveCount, Optimal::getLiveCount());
633}
634
635void tst_QList::midMovable() const
636{
637 const int liveCount = Movable::getLiveCount();
638 mid<Movable>();
639 QCOMPARE(liveCount, Movable::getLiveCount());
640}
641
642void tst_QList::midComplex() const
643{
644 const int liveCount = Complex::getLiveCount();
645 mid<Complex>();
646 QCOMPARE(liveCount, Complex::getLiveCount());
647}
648
649template<typename T>
650void tst_QList::at() const
651{
652 // test at() and make sure it functions correctly with some simple list manipulation.
653 QList<T> list;
654
655 // create a list
656 list << T_FOO << T_BAR << T_BAZ;
657 QVERIFY(list.size() == 3);
658 QCOMPARE(list.at(0), T_FOO);
659 QCOMPARE(list.at(1), T_BAR);
660 QCOMPARE(list.at(2), T_BAZ);
661
662 // append an item
663 list << T_CAT;
664 QVERIFY(list.size() == 4);
665 QCOMPARE(list.at(0), T_FOO);
666 QCOMPARE(list.at(1), T_BAR);
667 QCOMPARE(list.at(2), T_BAZ);
668 QCOMPARE(list.at(3), T_CAT);
669
670 // remove an item
671 list.removeAt(1);
672 QVERIFY(list.size() == 3);
673 QCOMPARE(list.at(0), T_FOO);
674 QCOMPARE(list.at(1), T_BAZ);
675 QCOMPARE(list.at(2), T_CAT);
676}
677
678void tst_QList::atOptimal() const
679{
680 const int liveCount = Optimal::getLiveCount();
681 at<Optimal>();
682 QCOMPARE(liveCount, Optimal::getLiveCount());
683}
684
685void tst_QList::atMovable() const
686{
687 const int liveCount = Movable::getLiveCount();
688 at<Movable>();
689 QCOMPARE(liveCount, Movable::getLiveCount());
690}
691
692void tst_QList::atComplex() const
693{
694 const int liveCount = Complex::getLiveCount();
695 at<Complex>();
696 QCOMPARE(liveCount, Complex::getLiveCount());
697}
698
699template<typename T>
700void tst_QList::first() const
701{
702 QList<T> list;
703 list << T_FOO << T_BAR;
704
705 QCOMPARE(list.first(), T_FOO);
706
707 // remove an item, make sure it still works
708 list.pop_front();
709 QVERIFY(list.size() == 1);
710 QCOMPARE(list.first(), T_BAR);
711}
712
713void tst_QList::firstOptimal() const
714{
715 const int liveCount = Optimal::getLiveCount();
716 first<Optimal>();
717 QCOMPARE(liveCount, Optimal::getLiveCount());
718}
719
720void tst_QList::firstMovable() const
721{
722 const int liveCount = Movable::getLiveCount();
723 first<Movable>();
724 QCOMPARE(liveCount, Movable::getLiveCount());
725}
726
727void tst_QList::firstComplex() const
728{
729 const int liveCount = Complex::getLiveCount();
730 first<Complex>();
731 QCOMPARE(liveCount, Complex::getLiveCount());
732}
733
734void tst_QList::constFirst() const
735{
736 // Based on tst_QVector::constFirst()
737 QList<int> list;
738 list << 69 << 42 << 3;
739
740 // test it starts ok
741 QCOMPARE(list.constFirst(), 69);
742 QVERIFY(list.isDetached());
743
744 QList<int> listCopy = list;
745 QVERIFY(!list.isDetached());
746 QVERIFY(!listCopy.isDetached());
747 QVERIFY(list.isSharedWith(listCopy));
748 QVERIFY(listCopy.isSharedWith(list));
749
750 QCOMPARE(list.constFirst(), 69);
751 QCOMPARE(listCopy.constFirst(), 69);
752
753 QVERIFY(!list.isDetached());
754 QVERIFY(!listCopy.isDetached());
755 QVERIFY(list.isSharedWith(listCopy));
756 QVERIFY(listCopy.isSharedWith(list));
757
758 // test removal changes
759 list.removeAt(i: 0);
760 QVERIFY(list.isDetached());
761 QVERIFY(!list.isSharedWith(listCopy));
762 QCOMPARE(list.constFirst(), 42);
763 QCOMPARE(listCopy.constFirst(), 69);
764
765 listCopy = list;
766 QVERIFY(!list.isDetached());
767 QVERIFY(!listCopy.isDetached());
768 QVERIFY(list.isSharedWith(listCopy));
769 QVERIFY(listCopy.isSharedWith(list));
770
771 QCOMPARE(list.constFirst(), 42);
772 QCOMPARE(listCopy.constFirst(), 42);
773
774 QVERIFY(!list.isDetached());
775 QVERIFY(!listCopy.isDetached());
776 QVERIFY(list.isSharedWith(listCopy));
777 QVERIFY(listCopy.isSharedWith(list));
778
779 // test prepend changes
780 list.prepend(t: 23);
781 QVERIFY(list.isDetached());
782 QVERIFY(!list.isSharedWith(listCopy));
783 QCOMPARE(list.constFirst(), 23);
784 QCOMPARE(listCopy.constFirst(), 42);
785
786 listCopy = list;
787 QVERIFY(!list.isDetached());
788 QVERIFY(!listCopy.isDetached());
789 QVERIFY(list.isSharedWith(listCopy));
790 QVERIFY(listCopy.isSharedWith(list));
791
792 QCOMPARE(list.constFirst(), 23);
793 QCOMPARE(listCopy.constFirst(), 23);
794
795 QVERIFY(!list.isDetached());
796 QVERIFY(!listCopy.isDetached());
797 QVERIFY(list.isSharedWith(listCopy));
798 QVERIFY(listCopy.isSharedWith(list));
799}
800
801void tst_QList::constLast() const
802{
803 // Based on tst_QVector::constLast()
804 QList<int> list;
805 list << 69 << 42 << 3;
806
807 // test it starts ok
808 QCOMPARE(list.constLast(), 3);
809 QVERIFY(list.isDetached());
810
811 QList<int> listCopy = list;
812 QVERIFY(!list.isDetached());
813 QVERIFY(!listCopy.isDetached());
814 QVERIFY(list.isSharedWith(listCopy));
815 QVERIFY(listCopy.isSharedWith(list));
816
817 QCOMPARE(list.constLast(), 3);
818 QCOMPARE(listCopy.constLast(), 3);
819
820 QVERIFY(!list.isDetached());
821 QVERIFY(!listCopy.isDetached());
822 QVERIFY(list.isSharedWith(listCopy));
823 QVERIFY(listCopy.isSharedWith(list));
824
825 // test removal changes
826 list.removeLast();
827 QVERIFY(list.isDetached());
828 QVERIFY(!list.isSharedWith(listCopy));
829 QCOMPARE(list.constLast(), 42);
830 QCOMPARE(listCopy.constLast(), 3);
831
832 listCopy = list;
833 QVERIFY(!list.isDetached());
834 QVERIFY(!listCopy.isDetached());
835 QVERIFY(list.isSharedWith(listCopy));
836 QVERIFY(listCopy.isSharedWith(list));
837
838 QCOMPARE(list.constLast(), 42);
839 QCOMPARE(listCopy.constLast(), 42);
840
841 QVERIFY(!list.isDetached());
842 QVERIFY(!listCopy.isDetached());
843 QVERIFY(list.isSharedWith(listCopy));
844 QVERIFY(listCopy.isSharedWith(list));
845
846 // test prepend changes
847 list.append(t: 23);
848 QVERIFY(list.isDetached());
849 QVERIFY(!list.isSharedWith(listCopy));
850 QCOMPARE(list.constLast(), 23);
851 QCOMPARE(listCopy.constLast(), 42);
852
853 listCopy = list;
854 QVERIFY(!list.isDetached());
855 QVERIFY(!listCopy.isDetached());
856 QVERIFY(list.isSharedWith(listCopy));
857 QVERIFY(listCopy.isSharedWith(list));
858
859 QCOMPARE(list.constLast(), 23);
860 QCOMPARE(listCopy.constLast(), 23);
861
862 QVERIFY(!list.isDetached());
863 QVERIFY(!listCopy.isDetached());
864 QVERIFY(list.isSharedWith(listCopy));
865 QVERIFY(listCopy.isSharedWith(list));
866}
867
868void tst_QList::cpp17ctad() const
869{
870#ifdef __cpp_deduction_guides
871#define QVERIFY_IS_LIST_OF(obj, Type) \
872 QVERIFY2((std::is_same<decltype(obj), QList<Type>>::value), \
873 QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
874#define CHECK(Type, One, Two, Three) \
875 do { \
876 const Type v[] = {One, Two, Three}; \
877 QList v1 = {One, Two, Three}; \
878 QVERIFY_IS_LIST_OF(v1, Type); \
879 QList v2(v1.begin(), v1.end()); \
880 QVERIFY_IS_LIST_OF(v2, Type); \
881 QList v3(std::begin(v), std::end(v)); \
882 QVERIFY_IS_LIST_OF(v3, Type); \
883 } while (false) \
884 /*end*/
885 CHECK(int, 1, 2, 3);
886 CHECK(double, 1.0, 2.0, 3.0);
887 CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
888#undef QVERIFY_IS_LIST_OF
889#undef CHECK
890#else
891 QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
892#endif
893}
894
895template<typename T>
896void tst_QList::last() const
897{
898 QList<T> list;
899 list << T_FOO << T_BAR;
900
901 QCOMPARE(list.last(), T_BAR);
902
903 // remove an item, make sure it still works
904 list.pop_back();
905 QVERIFY(list.size() == 1);
906 QCOMPARE(list.last(), T_FOO);
907}
908
909void tst_QList::lastOptimal() const
910{
911 const int liveCount = Optimal::getLiveCount();
912 last<Optimal>();
913 QCOMPARE(liveCount, Optimal::getLiveCount());
914}
915
916void tst_QList::lastMovable() const
917{
918 const int liveCount = Movable::getLiveCount();
919 last<Movable>();
920 QCOMPARE(liveCount, Movable::getLiveCount());
921}
922
923void tst_QList::lastComplex() const
924{
925 const int liveCount = Complex::getLiveCount();
926 last<Complex>();
927 QCOMPARE(liveCount, Complex::getLiveCount());
928}
929
930template<typename T>
931void tst_QList::begin() const
932{
933 QList<T> list;
934 list << T_FOO << T_BAR;
935
936 QCOMPARE(*list.begin(), T_FOO);
937
938 // remove an item, make sure it still works
939 list.pop_front();
940 QVERIFY(list.size() == 1);
941 QCOMPARE(*list.begin(), T_BAR);
942}
943
944void tst_QList::beginOptimal() const
945{
946 const int liveCount = Optimal::getLiveCount();
947 begin<Optimal>();
948 QCOMPARE(liveCount, Optimal::getLiveCount());
949}
950
951void tst_QList::beginMovable() const
952{
953 const int liveCount = Movable::getLiveCount();
954 begin<Movable>();
955 QCOMPARE(liveCount, Movable::getLiveCount());
956}
957
958void tst_QList::beginComplex() const
959{
960 const int liveCount = Complex::getLiveCount();
961 begin<Complex>();
962 QCOMPARE(liveCount, Complex::getLiveCount());
963}
964
965template<typename T>
966void tst_QList::end() const
967{
968 QList<T> list;
969 list << T_FOO << T_BAR;
970
971 QCOMPARE(*--list.end(), T_BAR);
972
973 // remove an item, make sure it still works
974 list.pop_back();
975 QVERIFY(list.size() == 1);
976 QCOMPARE(*--list.end(), T_FOO);
977}
978
979void tst_QList::endOptimal() const
980{
981 const int liveCount = Optimal::getLiveCount();
982 end<Optimal>();
983 QCOMPARE(liveCount, Optimal::getLiveCount());
984}
985
986void tst_QList::endMovable() const
987{
988 const int liveCount = Movable::getLiveCount();
989 end<Movable>();
990 QCOMPARE(liveCount, Movable::getLiveCount());
991}
992
993void tst_QList::endComplex() const
994{
995 const int liveCount = Complex::getLiveCount();
996 end<Complex>();
997 QCOMPARE(liveCount, Complex::getLiveCount());
998}
999
1000template<typename T>
1001void tst_QList::contains() const
1002{
1003 QList<T> list;
1004 list << T_FOO << T_BAR << T_BAZ;
1005
1006 QVERIFY(list.contains(T_FOO));
1007 QVERIFY(list.contains(T_BLAH) != true);
1008
1009 // add it and make sure it matches
1010 list.append(T_BLAH);
1011 QVERIFY(list.contains(T_BLAH));
1012}
1013
1014void tst_QList::containsOptimal() const
1015{
1016 const int liveCount = Optimal::getLiveCount();
1017 contains<Optimal>();
1018 QCOMPARE(liveCount, Optimal::getLiveCount());
1019}
1020
1021void tst_QList::containsMovable() const
1022{
1023 const int liveCount = Movable::getLiveCount();
1024 contains<Movable>();
1025 QCOMPARE(liveCount, Movable::getLiveCount());
1026}
1027
1028void tst_QList::containsComplex() const
1029{
1030 const int liveCount = Complex::getLiveCount();
1031 contains<Complex>();
1032 QCOMPARE(liveCount, Complex::getLiveCount());
1033}
1034
1035template<typename T>
1036void tst_QList::count() const
1037{
1038 QList<T> list;
1039
1040 // starts empty
1041 QVERIFY(list.count() == 0);
1042
1043 // goes up
1044 list.append(T_FOO);
1045 QVERIFY(list.count() == 1);
1046
1047 // and up
1048 list.append(T_BAR);
1049 QVERIFY(list.count() == 2);
1050
1051 // and down
1052 list.pop_back();
1053 QVERIFY(list.count() == 1);
1054
1055 // and empty. :)
1056 list.pop_back();
1057 QVERIFY(list.count() == 0);
1058}
1059
1060void tst_QList::countOptimal() const
1061{
1062 const int liveCount = Optimal::getLiveCount();
1063 count<Optimal>();
1064 QCOMPARE(liveCount, Optimal::getLiveCount());
1065}
1066
1067void tst_QList::countMovable() const
1068{
1069 const int liveCount = Movable::getLiveCount();
1070 count<Movable>();
1071 QCOMPARE(liveCount, Movable::getLiveCount());
1072}
1073
1074void tst_QList::countComplex() const
1075{
1076 const int liveCount = Complex::getLiveCount();
1077 count<Complex>();
1078 QCOMPARE(liveCount, Complex::getLiveCount());
1079}
1080
1081template<typename T>
1082void tst_QList::empty() const
1083{
1084 QList<T> list;
1085
1086 // make sure it starts empty
1087 QVERIFY(list.empty());
1088
1089 // and doesn't stay empty
1090 list.append(T_FOO);
1091 QVERIFY(!list.empty());
1092
1093 // and goes back to being empty
1094 list.pop_back();
1095 QVERIFY(list.empty());
1096}
1097
1098void tst_QList::emptyOptimal() const
1099{
1100 const int liveCount = Optimal::getLiveCount();
1101 empty<Optimal>();
1102 QCOMPARE(liveCount, Optimal::getLiveCount());
1103}
1104
1105void tst_QList::emptyMovable() const
1106{
1107 const int liveCount = Movable::getLiveCount();
1108 empty<Movable>();
1109 QCOMPARE(liveCount, Movable::getLiveCount());
1110}
1111
1112void tst_QList::emptyComplex() const
1113{
1114 const int liveCount = Complex::getLiveCount();
1115 empty<Complex>();
1116 QCOMPARE(liveCount, Complex::getLiveCount());
1117}
1118
1119template<typename T>
1120void tst_QList::endsWith() const
1121{
1122 QList<T> list;
1123 list << T_FOO << T_BAR << T_BAZ;
1124
1125 // test it returns correctly in both cases
1126 QVERIFY(list.endsWith(T_BAZ));
1127 QVERIFY(!list.endsWith(T_BAR));
1128
1129 // remove an item and make sure the end item changes
1130 list.pop_back();
1131 QVERIFY(list.endsWith(T_BAR));
1132}
1133
1134void tst_QList::endsWithOptimal() const
1135{
1136 const int liveCount = Optimal::getLiveCount();
1137 endsWith<Optimal>();
1138 QCOMPARE(liveCount, Optimal::getLiveCount());
1139}
1140
1141void tst_QList::endsWithMovable() const
1142{
1143 const int liveCount = Movable::getLiveCount();
1144 endsWith<Movable>();
1145 QCOMPARE(liveCount, Movable::getLiveCount());
1146}
1147
1148void tst_QList::endsWithComplex() const
1149{
1150 const int liveCount = Complex::getLiveCount();
1151 endsWith<Complex>();
1152 QCOMPARE(liveCount, Complex::getLiveCount());
1153}
1154
1155template<typename T>
1156void tst_QList::lastIndexOf() const
1157{
1158 QList<T> list;
1159 list << T_FOO << T_BAR << T_BAZ;
1160
1161 // one instance of the target item
1162 QVERIFY(list.lastIndexOf(T_BAZ) == 2);
1163
1164 // shouldn't find this
1165 QVERIFY(list.lastIndexOf(T_WEEE) == -1);
1166
1167 // multiple instances
1168 list.append(T_BAZ);
1169 list.append(T_BAZ);
1170 QVERIFY(list.lastIndexOf(T_BAZ) == 4);
1171
1172 // search from the middle to find the last one
1173 QVERIFY(list.lastIndexOf(T_BAZ, 3) == 3);
1174
1175 // try to find none
1176 QVERIFY(list.lastIndexOf(T_BAZ, 1) == -1);
1177}
1178
1179void tst_QList::lastIndexOfOptimal() const
1180{
1181 const int liveCount = Optimal::getLiveCount();
1182 lastIndexOf<Optimal>();
1183 QCOMPARE(liveCount, Optimal::getLiveCount());
1184}
1185
1186void tst_QList::lastIndexOfMovable() const
1187{
1188 const int liveCount = Movable::getLiveCount();
1189 lastIndexOf<Movable>();
1190 QCOMPARE(liveCount, Movable::getLiveCount());
1191}
1192
1193void tst_QList::lastIndexOfComplex() const
1194{
1195 const int liveCount = Complex::getLiveCount();
1196 lastIndexOf<Complex>();
1197 QCOMPARE(liveCount, Complex::getLiveCount());
1198}
1199
1200template<typename T>
1201void tst_QList::move() const
1202{
1203 QList<T> list;
1204 list << T_FOO << T_BAR << T_BAZ;
1205
1206 // move an item
1207 list.move(0, list.count() - 1);
1208 QCOMPARE(list, QList<T>() << T_BAR << T_BAZ << T_FOO);
1209
1210 // move it back
1211 list.move(list.count() - 1, 0);
1212 QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
1213
1214 // move an item in the middle
1215 list.move(1, 0);
1216 QCOMPARE(list, QList<T>() << T_BAR << T_FOO << T_BAZ);
1217}
1218
1219void tst_QList::moveOptimal() const
1220{
1221 const int liveCount = Optimal::getLiveCount();
1222 move<Optimal>();
1223 QCOMPARE(liveCount, Optimal::getLiveCount());
1224}
1225
1226void tst_QList::moveMovable() const
1227{
1228 const int liveCount = Movable::getLiveCount();
1229 move<Movable>();
1230 QCOMPARE(liveCount, Movable::getLiveCount());
1231}
1232
1233void tst_QList::moveComplex() const
1234{
1235 const int liveCount = Complex::getLiveCount();
1236 move<Complex>();
1237 QCOMPARE(liveCount, Complex::getLiveCount());
1238}
1239
1240template<typename T>
1241void tst_QList::removeAll() const
1242{
1243 QList<T> list;
1244 list << T_FOO << T_BAR << T_BAZ;
1245
1246 // remove one instance
1247 list.removeAll(T_BAR);
1248 QCOMPARE(list, QList<T>() << T_FOO << T_BAZ);
1249
1250 // many instances
1251 list << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ;
1252 list.removeAll(T_BAR);
1253 QCOMPARE(list, QList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
1254
1255 // try remove something that doesn't exist
1256 list.removeAll(T_WEEE);
1257 QCOMPARE(list, QList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
1258}
1259
1260void tst_QList::removeAllOptimal() const
1261{
1262 const int liveCount = Optimal::getLiveCount();
1263 removeAll<Optimal>();
1264 QCOMPARE(liveCount, Optimal::getLiveCount());
1265}
1266
1267void tst_QList::removeAllMovable() const
1268{
1269 const int liveCount = Movable::getLiveCount();
1270 removeAll<Movable>();
1271 QCOMPARE(liveCount, Movable::getLiveCount());
1272}
1273
1274void tst_QList::removeAllComplex() const
1275{
1276 const int liveCount = Complex::getLiveCount();
1277 removeAll<Complex>();
1278 QCOMPARE(liveCount, Complex::getLiveCount());
1279}
1280
1281template<typename T>
1282void tst_QList::removeAt() const
1283{
1284 QList<T> list;
1285 list << T_FOO << T_BAR << T_BAZ;
1286
1287 // middle
1288 list.removeAt(1);
1289 QCOMPARE(list, QList<T>() << T_FOO << T_BAZ);
1290
1291 // start
1292 list.removeAt(0);
1293 QCOMPARE(list, QList<T>() << T_BAZ);
1294
1295 // final
1296 list.removeAt(0);
1297 QCOMPARE(list, QList<T>());
1298}
1299
1300void tst_QList::removeAtOptimal() const
1301{
1302 const int liveCount = Optimal::getLiveCount();
1303 removeAt<Optimal>();
1304 QCOMPARE(liveCount, Optimal::getLiveCount());
1305}
1306
1307void tst_QList::removeAtMovable() const
1308{
1309 const int liveCount = Movable::getLiveCount();
1310 removeAt<Movable>();
1311 QCOMPARE(liveCount, Movable::getLiveCount());
1312}
1313
1314void tst_QList::removeAtComplex() const
1315{
1316 const int liveCount = Complex::getLiveCount();
1317 removeAt<Complex>();
1318 QCOMPARE(liveCount, Complex::getLiveCount());
1319}
1320
1321template<typename T>
1322void tst_QList::removeOne() const
1323{
1324 QList<T> list;
1325 list << T_FOO << T_BAR << T_BAZ;
1326
1327 // middle
1328 list.removeOne(T_BAR);
1329 QCOMPARE(list, QList<T>() << T_FOO << T_BAZ);
1330
1331 // start
1332 list.removeOne(T_FOO);
1333 QCOMPARE(list, QList<T>() << T_BAZ);
1334
1335 // last
1336 list.removeOne(T_BAZ);
1337 QCOMPARE(list, QList<T>());
1338
1339 // make sure it really only removes one :)
1340 list << T_FOO << T_FOO;
1341 list.removeOne(T_FOO);
1342 QCOMPARE(list, QList<T>() << T_FOO);
1343
1344 // try remove something that doesn't exist
1345 list.removeOne(T_WEEE);
1346 QCOMPARE(list, QList<T>() << T_FOO);
1347}
1348
1349void tst_QList::removeOneOptimal() const
1350{
1351 const int liveCount = Optimal::getLiveCount();
1352 removeOne<Optimal>();
1353 QCOMPARE(liveCount, Optimal::getLiveCount());
1354}
1355
1356void tst_QList::removeOneMovable() const
1357{
1358 const int liveCount = Movable::getLiveCount();
1359 removeOne<Movable>();
1360 QCOMPARE(liveCount, Movable::getLiveCount());
1361}
1362
1363void tst_QList::removeOneComplex() const
1364{
1365 const int liveCount = Complex::getLiveCount();
1366 removeOne<Complex>();
1367 QCOMPARE(liveCount, Complex::getLiveCount());
1368}
1369
1370template<typename T>
1371void tst_QList::replace() const
1372{
1373 QList<T> list;
1374 list << T_FOO << T_BAR << T_BAZ;
1375
1376 // start
1377 list.replace(0, T_CAT);
1378 QCOMPARE(list, QList<T>() << T_CAT
1379 << T_BAR << T_BAZ);
1380
1381 // middle
1382 list.replace(1, T_DOG);
1383 QCOMPARE(list, QList<T>() << T_CAT
1384 << T_DOG << T_BAZ);
1385
1386 // end
1387 list.replace(2, T_BLAH);
1388 QCOMPARE(list, QList<T>() << T_CAT
1389 << T_DOG << T_BLAH);
1390}
1391
1392void tst_QList::replaceOptimal() const
1393{
1394 const int liveCount = Optimal::getLiveCount();
1395 replace<Optimal>();
1396 QCOMPARE(liveCount, Optimal::getLiveCount());
1397}
1398
1399void tst_QList::replaceMovable() const
1400{
1401 const int liveCount = Movable::getLiveCount();
1402 replace<Movable>();
1403 QCOMPARE(liveCount, Movable::getLiveCount());
1404}
1405
1406void tst_QList::replaceComplex() const
1407{
1408 const int liveCount = Complex::getLiveCount();
1409 replace<Complex>();
1410 QCOMPARE(liveCount, Complex::getLiveCount());
1411}
1412
1413template<typename T>
1414void tst_QList::reverseIterators() const
1415{
1416 QList<T> v;
1417 v << T_CAT << T_DOG << T_BLAH << T_BAZ;
1418 QList<T> vr = v;
1419 std::reverse(vr.begin(), vr.end());
1420 const QList<T> &cvr = vr;
1421 QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin()));
1422 QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin()));
1423 QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin()));
1424 QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin()));
1425 QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin()));
1426 QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin()));
1427}
1428
1429void tst_QList::reverseIteratorsOptimal() const
1430{
1431 const int liveCount = Optimal::getLiveCount();
1432 reverseIterators<Optimal>();
1433 QCOMPARE(liveCount, Optimal::getLiveCount());
1434}
1435
1436void tst_QList::reverseIteratorsMovable() const
1437{
1438 const int liveCount = Movable::getLiveCount();
1439 reverseIterators<Movable>();
1440 QCOMPARE(liveCount, Movable::getLiveCount());
1441}
1442
1443void tst_QList::reverseIteratorsComplex() const
1444{
1445 const int liveCount = Complex::getLiveCount();
1446 reverseIterators<Complex>();
1447 QCOMPARE(liveCount, Complex::getLiveCount());
1448}
1449
1450template<typename T>
1451void tst_QList::startsWith() const
1452{
1453 QList<T> list;
1454 list << T_FOO << T_BAR << T_BAZ;
1455
1456 // make sure it starts ok
1457 QVERIFY(list.startsWith(T_FOO));
1458
1459 // remove an item
1460 list.removeFirst();
1461 QVERIFY(list.startsWith(T_BAR));
1462}
1463
1464void tst_QList::startsWithOptimal() const
1465{
1466 const int liveCount = Optimal::getLiveCount();
1467 startsWith<Optimal>();
1468 QCOMPARE(liveCount, Optimal::getLiveCount());
1469}
1470
1471void tst_QList::startsWithMovable() const
1472{
1473 const int liveCount = Movable::getLiveCount();
1474 startsWith<Movable>();
1475 QCOMPARE(liveCount, Movable::getLiveCount());
1476}
1477
1478void tst_QList::startsWithComplex() const
1479{
1480 const int liveCount = Complex::getLiveCount();
1481 startsWith<Complex>();
1482 QCOMPARE(liveCount, Complex::getLiveCount());
1483}
1484
1485template<typename T>
1486void tst_QList::swap() const
1487{
1488 QList<T> list;
1489 list << T_FOO << T_BAR << T_BAZ;
1490
1491 // swap
1492 list.swapItemsAt(0, 2);
1493 QCOMPARE(list, QList<T>() << T_BAZ << T_BAR << T_FOO);
1494
1495 // swap again
1496 list.swapItemsAt(1, 2);
1497 QCOMPARE(list, QList<T>() << T_BAZ << T_FOO << T_BAR);
1498
1499 QList<T> list2;
1500 list2 << T_DOG << T_BLAH;
1501
1502 list.swap(list2);
1503 QCOMPARE(list, QList<T>() << T_DOG << T_BLAH);
1504 QCOMPARE(list2, QList<T>() << T_BAZ << T_FOO << T_BAR);
1505}
1506
1507void tst_QList::swapOptimal() const
1508{
1509 const int liveCount = Optimal::getLiveCount();
1510 swap<Optimal>();
1511 QCOMPARE(liveCount, Optimal::getLiveCount());
1512}
1513
1514void tst_QList::swapMovable() const
1515{
1516 const int liveCount = Movable::getLiveCount();
1517 swap<Movable>();
1518 QCOMPARE(liveCount, Movable::getLiveCount());
1519}
1520
1521void tst_QList::swapComplex() const
1522{
1523 const int liveCount = Complex::getLiveCount();
1524 swap<Complex>();
1525 QCOMPARE(liveCount, Complex::getLiveCount());
1526}
1527
1528template<typename T>
1529void tst_QList::takeAt() const
1530{
1531 QList<T> list;
1532 list << T_FOO << T_BAR << T_BAZ;
1533
1534 QCOMPARE(list.takeAt(0), T_FOO);
1535 QVERIFY(list.size() == 2);
1536 QCOMPARE(list.takeAt(1), T_BAZ);
1537 QVERIFY(list.size() == 1);
1538 QCOMPARE(list.takeAt(0), T_BAR);
1539 QVERIFY(list.size() == 0);
1540}
1541
1542void tst_QList::takeAtOptimal() const
1543{
1544 const int liveCount = Optimal::getLiveCount();
1545 takeAt<Optimal>();
1546 QCOMPARE(liveCount, Optimal::getLiveCount());
1547}
1548
1549void tst_QList::takeAtMovable() const
1550{
1551 const int liveCount = Movable::getLiveCount();
1552 takeAt<Movable>();
1553 QCOMPARE(liveCount, Movable::getLiveCount());
1554}
1555
1556void tst_QList::takeAtComplex() const
1557{
1558 const int liveCount = Complex::getLiveCount();
1559 takeAt<Complex>();
1560 QCOMPARE(liveCount, Complex::getLiveCount());
1561}
1562
1563template<typename T>
1564void tst_QList::takeFirst() const
1565{
1566 QList<T> list;
1567 list << T_FOO << T_BAR << T_BAZ;
1568
1569 QCOMPARE(list.takeFirst(), T_FOO);
1570 QVERIFY(list.size() == 2);
1571 QCOMPARE(list.takeFirst(), T_BAR);
1572 QVERIFY(list.size() == 1);
1573 QCOMPARE(list.takeFirst(), T_BAZ);
1574 QVERIFY(list.size() == 0);
1575}
1576
1577void tst_QList::takeFirstOptimal() const
1578{
1579 const int liveCount = Optimal::getLiveCount();
1580 takeFirst<Optimal>();
1581 QCOMPARE(liveCount, Optimal::getLiveCount());
1582}
1583
1584void tst_QList::takeFirstMovable() const
1585{
1586 const int liveCount = Movable::getLiveCount();
1587 takeFirst<Movable>();
1588 QCOMPARE(liveCount, Movable::getLiveCount());
1589}
1590
1591void tst_QList::takeFirstComplex() const
1592{
1593 const int liveCount = Complex::getLiveCount();
1594 takeFirst<Complex>();
1595 QCOMPARE(liveCount, Complex::getLiveCount());
1596}
1597
1598template<typename T>
1599void tst_QList::takeLast() const
1600{
1601 QList<T> list;
1602 list << T_FOO << T_BAR << T_BAZ;
1603
1604 QCOMPARE(list.takeLast(), T_BAZ);
1605 QCOMPARE(list.takeLast(), T_BAR);
1606 QCOMPARE(list.takeLast(), T_FOO);
1607}
1608
1609void tst_QList::takeLastOptimal() const
1610{
1611 const int liveCount = Optimal::getLiveCount();
1612 takeLast<Optimal>();
1613 QCOMPARE(liveCount, Optimal::getLiveCount());
1614}
1615
1616void tst_QList::takeLastMovable() const
1617{
1618 const int liveCount = Movable::getLiveCount();
1619 takeLast<Movable>();
1620 QCOMPARE(liveCount, Movable::getLiveCount());
1621}
1622
1623void tst_QList::takeLastComplex() const
1624{
1625 const int liveCount = Complex::getLiveCount();
1626 takeLast<Complex>();
1627 QCOMPARE(liveCount, Complex::getLiveCount());
1628}
1629
1630#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1631template<typename T>
1632void tst_QList::toSet() const
1633{
1634 QList<T> list;
1635 list << T_FOO << T_BAR << T_BAZ;
1636
1637 // no duplicates
1638 QCOMPARE(list.toSet(), QSet<T>() << T_FOO << T_BAR << T_BAZ);
1639 QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
1640
1641 // duplicates (is this more of a QSet test?)
1642 list << T_FOO << T_BAR << T_BAZ;
1643 QCOMPARE(list.toSet(), QSet<T>() << T_FOO << T_BAR << T_BAZ);
1644 QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ
1645 << T_FOO << T_BAR << T_BAZ);
1646}
1647
1648void tst_QList::toSetOptimal() const
1649{
1650 const int liveCount = Optimal::getLiveCount();
1651 toSet<Optimal>();
1652 QCOMPARE(liveCount, Optimal::getLiveCount());
1653}
1654
1655void tst_QList::toSetMovable() const
1656{
1657 const int liveCount = Movable::getLiveCount();
1658 toSet<Movable>();
1659 QCOMPARE(liveCount, Movable::getLiveCount());
1660}
1661
1662void tst_QList::toSetComplex() const
1663{
1664 const int liveCount = Complex::getLiveCount();
1665 toSet<Complex>();
1666 QCOMPARE(liveCount, Complex::getLiveCount());
1667}
1668
1669template<typename T>
1670void tst_QList::toStdList() const
1671{
1672 QList<T> list;
1673 list << T_FOO << T_BAR << T_BAZ;
1674
1675 // yuck.
1676 std::list<T> slist;
1677 slist.push_back(T_FOO);
1678 slist.push_back(T_BAR);
1679 slist.push_back(T_BAZ);
1680
1681 QCOMPARE(list.toStdList(), slist);
1682 QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
1683}
1684
1685void tst_QList::toStdListOptimal() const
1686{
1687 const int liveCount = Optimal::getLiveCount();
1688 toStdList<Optimal>();
1689 QCOMPARE(liveCount, Optimal::getLiveCount());
1690}
1691
1692void tst_QList::toStdListMovable() const
1693{
1694 const int liveCount = Movable::getLiveCount();
1695 toStdList<Movable>();
1696 QCOMPARE(liveCount, Movable::getLiveCount());
1697}
1698
1699void tst_QList::toStdListComplex() const
1700{
1701 const int liveCount = Complex::getLiveCount();
1702 toStdList<Complex>();
1703 QCOMPARE(liveCount, Complex::getLiveCount());
1704}
1705#endif
1706
1707template<typename T>
1708void tst_QList::toVector() const
1709{
1710 QList<T> list;
1711 list << T_FOO << T_BAR << T_BAZ;
1712
1713 QCOMPARE(list.toVector(), QVector<T>() << T_FOO << T_BAR << T_BAZ);
1714}
1715
1716void tst_QList::toVectorOptimal() const
1717{
1718 const int liveCount = Optimal::getLiveCount();
1719 toVector<Optimal>();
1720 QCOMPARE(liveCount, Optimal::getLiveCount());
1721}
1722
1723void tst_QList::toVectorMovable() const
1724{
1725 const int liveCount = Movable::getLiveCount();
1726 toVector<Movable>();
1727 QCOMPARE(liveCount, Movable::getLiveCount());
1728}
1729
1730void tst_QList::toVectorComplex() const
1731{
1732 const int liveCount = Complex::getLiveCount();
1733 toVector<Complex>();
1734 QCOMPARE(liveCount, Complex::getLiveCount());
1735}
1736
1737template<typename T>
1738void tst_QList::value() const
1739{
1740 QList<T> list;
1741 list << T_FOO << T_BAR << T_BAZ;
1742
1743 // test real values
1744 QCOMPARE(list.value(0), T_FOO);
1745 QCOMPARE(list.value(2), T_BAZ);
1746
1747 // test empty default
1748 QCOMPARE(list.value(3), T());
1749 QCOMPARE(list.value(-1), T());
1750
1751 // test defaults
1752 T defaultT(T_WEEE);
1753 QCOMPARE(list.value(-1, defaultT), defaultT);
1754 QCOMPARE(list.value(3, defaultT), defaultT);
1755}
1756
1757void tst_QList::valueOptimal() const
1758{
1759 const int liveCount = Optimal::getLiveCount();
1760 value<Optimal>();
1761 QCOMPARE(liveCount, Optimal::getLiveCount());
1762}
1763
1764void tst_QList::valueMovable() const
1765{
1766 const int liveCount = Movable::getLiveCount();
1767 value<Movable>();
1768 QCOMPARE(liveCount, Movable::getLiveCount());
1769}
1770
1771void tst_QList::valueComplex() const
1772{
1773 const int liveCount = Complex::getLiveCount();
1774 value<Complex>();
1775 QCOMPARE(liveCount, Complex::getLiveCount());
1776}
1777
1778template<typename T>
1779void tst_QList::testOperators() const
1780{
1781 QList<T> list;
1782 list << T_FOO << T_BAR << T_BAZ;
1783
1784 QList<T> listtwo;
1785 listtwo << T_FOO << T_BAR << T_BAZ;
1786
1787 // test equal
1788 QVERIFY(list == listtwo);
1789
1790 // not equal
1791 listtwo.append(T_CAT);
1792 QVERIFY(list != listtwo);
1793
1794 // +=
1795 list += listtwo;
1796 QVERIFY(list.size() == 7);
1797 QVERIFY(listtwo.size() == 4);
1798 QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ
1799 << T_FOO << T_BAR << T_BAZ << T_CAT);
1800
1801 // =
1802 list = listtwo;
1803 QCOMPARE(list, listtwo);
1804 QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ << T_CAT);
1805
1806 // []
1807 QCOMPARE(list[0], T_FOO);
1808 QCOMPARE(list[list.size() - 1], T_CAT);
1809
1810 // <, >, <=, >=
1811 QVERIFY(!(list < listtwo));
1812 QVERIFY(!(list > listtwo));
1813 QVERIFY( list <= listtwo);
1814 QVERIFY( list >= listtwo);
1815 listtwo.push_back(T_CAT);
1816 QVERIFY( list < listtwo);
1817 QVERIFY(!(list > listtwo));
1818 QVERIFY( list <= listtwo);
1819 QVERIFY(!(list >= listtwo));
1820 QVERIFY(listtwo > list);
1821 QVERIFY(listtwo >= list);
1822}
1823
1824void tst_QList::testOperatorsOptimal() const
1825{
1826 const int liveCount = Optimal::getLiveCount();
1827 testOperators<Optimal>();
1828 QCOMPARE(liveCount, Optimal::getLiveCount());
1829}
1830
1831void tst_QList::testOperatorsMovable() const
1832{
1833 const int liveCount = Movable::getLiveCount();
1834 testOperators<Movable>();
1835 QCOMPARE(liveCount, Movable::getLiveCount());
1836}
1837
1838void tst_QList::testOperatorsComplex() const
1839{
1840 const int liveCount = Complex::getLiveCount();
1841 testOperators<Complex>();
1842 QCOMPARE(liveCount, Complex::getLiveCount());
1843}
1844
1845template<typename T>
1846void tst_QList::testSTLIterators() const
1847{
1848 QList<T> list;
1849
1850 // create a list
1851 list << T_FOO << T_BAR << T_BAZ;
1852 typename QList<T>::iterator it = list.begin();
1853 QCOMPARE(*it, T_FOO); it++;
1854 QCOMPARE(*it, T_BAR); it++;
1855 QCOMPARE(*it, T_BAZ); it++;
1856 QCOMPARE(it, list.end()); it--;
1857
1858 // walk backwards
1859 QCOMPARE(*it, T_BAZ); it--;
1860 QCOMPARE(*it, T_BAR); it--;
1861 QCOMPARE(*it, T_FOO);
1862
1863 // test erase
1864 it = list.erase(it);
1865 QVERIFY(list.size() == 2);
1866 QCOMPARE(*it, T_BAR);
1867
1868 // test multiple erase
1869 it = list.erase(it, it + 2);
1870 QVERIFY(list.size() == 0);
1871 QCOMPARE(it, list.end());
1872
1873 // insert again
1874 it = list.insert(it, T_FOO);
1875 QVERIFY(list.size() == 1);
1876 QCOMPARE(*it, T_FOO);
1877
1878 // insert again
1879 it = list.insert(it, T_BAR);
1880 QVERIFY(list.size() == 2);
1881 QCOMPARE(*it++, T_BAR);
1882 QCOMPARE(*it, T_FOO);
1883}
1884
1885void tst_QList::testSTLIteratorsOptimal() const
1886{
1887 const int liveCount = Optimal::getLiveCount();
1888 testSTLIterators<Optimal>();
1889 QCOMPARE(liveCount, Optimal::getLiveCount());
1890}
1891
1892void tst_QList::testSTLIteratorsMovable() const
1893{
1894 const int liveCount = Movable::getLiveCount();
1895 testSTLIterators<Movable>();
1896 QCOMPARE(liveCount, Movable::getLiveCount());
1897}
1898
1899void tst_QList::testSTLIteratorsComplex() const
1900{
1901 const int liveCount = Complex::getLiveCount();
1902 testSTLIterators<Complex>();
1903 QCOMPARE(liveCount, Complex::getLiveCount());
1904}
1905
1906void tst_QList::initializeList() const
1907{
1908 QList<int> v1{2,3,4};
1909 QCOMPARE(v1, QList<int>() << 2 << 3 << 4);
1910 QCOMPARE(v1, (QList<int>{2,3,4}));
1911
1912 QList<QList<int>> v2{ v1, {1}, QList<int>(), {2,3,4} };
1913 QList<QList<int>> v3;
1914 v3 << v1 << (QList<int>() << 1) << QList<int>() << v1;
1915 QCOMPARE(v3, v2);
1916}
1917
1918template<typename T>
1919void tst_QList::constSharedNull() const
1920{
1921 QList<T> list2;
1922#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1923 QList<T> list1;
1924 list1.setSharable(false);
1925 QVERIFY(list1.isDetached());
1926
1927 list2.setSharable(true);
1928#endif
1929 QVERIFY(!list2.isDetached());
1930}
1931
1932void tst_QList::constSharedNullOptimal() const
1933{
1934 const int liveCount = Optimal::getLiveCount();
1935 constSharedNull<Optimal>();
1936 QCOMPARE(liveCount, Optimal::getLiveCount());
1937}
1938
1939void tst_QList::constSharedNullMovable() const
1940{
1941 const int liveCount = Movable::getLiveCount();
1942 constSharedNull<Movable>();
1943 QCOMPARE(liveCount, Movable::getLiveCount());
1944}
1945
1946void tst_QList::constSharedNullComplex() const
1947{
1948 const int liveCount = Complex::getLiveCount();
1949 constSharedNull<Complex>();
1950 QCOMPARE(liveCount, Complex::getLiveCount());
1951}
1952
1953template <class T>
1954void generateSetSharableData()
1955{
1956#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1957 QTest::addColumn<QList<T> >("list");
1958 QTest::addColumn<int>(name: "size");
1959
1960 QTest::newRow(dataTag: "null") << QList<T>() << 0;
1961 QTest::newRow(dataTag: "non-empty") << (QList<T>() << T(0) << T(1) << T(2) << T(3) << T(4)) << 5;
1962#endif
1963}
1964
1965template <class T>
1966void runSetSharableTest()
1967{
1968#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1969 QFETCH(QList<T>, list);
1970 QFETCH(int, size);
1971
1972 QVERIFY(!list.isDetached()); // Shared with QTest
1973
1974 list.setSharable(true);
1975
1976 QCOMPARE(list.size(), size);
1977
1978 {
1979 QList<T> copy(list);
1980 QVERIFY(!copy.isDetached());
1981 QVERIFY(copy.isSharedWith(list));
1982 }
1983
1984 list.setSharable(false);
1985 QVERIFY(list.isDetached() || list.isSharedWith(QList<T>()));
1986
1987 {
1988 QList<T> copy(list);
1989
1990 QVERIFY(copy.isDetached() || copy.isSharedWith(QList<T>()));
1991 QCOMPARE(copy.size(), size);
1992 QCOMPARE(copy, list);
1993 }
1994
1995 list.setSharable(true);
1996
1997 {
1998 QList<T> copy(list);
1999
2000 QVERIFY(!copy.isDetached());
2001 QVERIFY(copy.isSharedWith(list));
2002 }
2003
2004 for (int i = 0; i < list.size(); ++i)
2005 QCOMPARE(int(list[i]), i);
2006
2007 QCOMPARE(list.size(), size);
2008#endif
2009}
2010
2011void tst_QList::setSharableInt_data() const
2012{
2013 generateSetSharableData<int>();
2014}
2015
2016void tst_QList::setSharableComplex_data() const
2017{
2018 generateSetSharableData<Complex>();
2019}
2020
2021void tst_QList::setSharableInt() const
2022{
2023 runSetSharableTest<int>();
2024}
2025
2026void tst_QList::setSharableComplex() const
2027{
2028 runSetSharableTest<Complex>();
2029}
2030
2031void tst_QList::eraseValidIteratorsOnSharedList() const
2032{
2033 QList<int> a, b;
2034 a.push_back(t: 10);
2035 a.push_back(t: 20);
2036 a.push_back(t: 30);
2037 QList<int>::iterator i = a.begin();
2038 ++i;
2039 b = a;
2040 a.erase(it: i);
2041 QCOMPARE(b.size(), 3);
2042 QCOMPARE(a.size(), 2);
2043 QCOMPARE(a.at(0), 10);
2044 QCOMPARE(a.at(1), 30);
2045
2046 a.push_back(t: 40);
2047 a.push_back(t: 50);
2048 a.push_back(t: 60);
2049 QCOMPARE(a.size(), 5);
2050 i = a.begin();
2051 b = a;
2052 ++i;
2053 QList<int>::iterator j = i;
2054 ++j;
2055 ++j;
2056 a.erase(afirst: i, alast: j); // remove 3 elements
2057 QCOMPARE(b.size(), 5);
2058 QCOMPARE(a.size(), 3);
2059 QCOMPARE(a.at(0), 10);
2060 QCOMPARE(a.at(1), 50);
2061}
2062
2063void tst_QList::insertWithValidIteratorsOnSharedList() const
2064{
2065 QList<int> a, b;
2066 a.push_back(t: 10);
2067 a.push_back(t: 20);
2068 a.push_back(t: 30);
2069 QList<int>::iterator i = a.begin();
2070 ++i;
2071 b = a;
2072 a.insert(before: i, t: 15);
2073 QCOMPARE(a.size(), b.size() + 1);
2074 QCOMPARE(b.at(1), 20);
2075 QCOMPARE(a.at(1), 15);
2076}
2077
2078template <typename T>
2079void tst_QList::qhash() const
2080{
2081 QList<T> l1, l2;
2082 QCOMPARE(qHash(l1), qHash(l2));
2083 l1 << T_BAR;
2084 l2 << T_BAR;
2085 QCOMPARE(qHash(l1), qHash(l2));
2086}
2087
2088void tst_QList::reserve() const
2089{
2090 // Note:
2091 // This test depends on QList's current behavior that ints are stored in the array itself.
2092 // This test would not work for QList<Complex>.
2093 int capacity = 100;
2094 QList<int> list;
2095 list.reserve(alloc: capacity);
2096 list << 0;
2097 int *data = &list[0];
2098
2099 for (int i = 1; i < capacity; i++) {
2100 list << i;
2101 QCOMPARE(&list.at(0), data);
2102 }
2103
2104 QList<int> copy = list;
2105 list.reserve(alloc: capacity / 2);
2106 QCOMPARE(list.size(), capacity); // we didn't shrink the size!
2107
2108 copy = list;
2109 list.reserve(alloc: capacity * 2);
2110 QCOMPARE(list.size(), capacity);
2111 QVERIFY(&list.at(0) != data);
2112}
2113
2114QTEST_APPLESS_MAIN(tst_QList)
2115#include "tst_qlist.moc"
2116

source code of qtbase/tests/auto/corelib/tools/qlist/tst_qlist.cpp