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 <QLinkedList>
31
32#if QT_DEPRECATED_SINCE(5, 15)
33QT_WARNING_PUSH
34QT_WARNING_DISABLE_DEPRECATED
35
36struct Movable
37{
38 Movable(char input = 'j') : i(input), state(Constructed)
39 {
40 ++liveCount;
41 }
42 Movable(const Movable &other)
43 : i(other.i)
44 , state(Constructed)
45 {
46 check(state1: other.state, state2: Constructed);
47 ++liveCount;
48 }
49
50 ~Movable()
51 {
52 check(state1: state, state2: Constructed);
53 i = 0;
54 --liveCount;
55 state = Destructed;
56 }
57
58 bool operator ==(const Movable &other) const
59 {
60 check(state1: state, state2: Constructed);
61 check(state1: other.state, state2: Constructed);
62 return i == other.i;
63 }
64
65 Movable &operator=(const Movable &other)
66 {
67 check(state1: state, state2: Constructed);
68 check(state1: other.state, state2: Constructed);
69 i = other.i;
70 return *this;
71 }
72 char i;
73
74 static int getLiveCount() { return liveCount; }
75private:
76 static int liveCount;
77
78 enum State { Constructed = 106, Destructed = 110 };
79 State state;
80
81 static void check(const State state1, const State state2)
82 {
83 QCOMPARE(int(state1), int(state2));
84 }
85};
86
87int Movable::liveCount = 0;
88
89QT_BEGIN_NAMESPACE
90Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
91QT_END_NAMESPACE
92
93Q_DECLARE_METATYPE(Movable);
94
95Q_DECLARE_METATYPE(QLinkedList<int>);
96
97
98int qHash(const Movable& movable)
99{
100 return qHash(key: movable.i);
101}
102
103struct Complex
104{
105 Complex(int val = 0)
106 : value(val)
107 , checkSum(this)
108 {
109 ++liveCount;
110 }
111
112 Complex(Complex const &other)
113 : value(other.value)
114 , checkSum(this)
115 {
116 ++liveCount;
117 }
118
119 Complex &operator=(Complex const &other)
120 {
121 check(); other.check();
122
123 value = other.value;
124 return *this;
125 }
126
127 ~Complex()
128 {
129 --liveCount;
130 check();
131 }
132
133 operator int() const { return value; }
134
135 bool operator==(Complex const &other) const
136 {
137 check(); other.check();
138 return value == other.value;
139 }
140
141 void check() const
142 {
143 QVERIFY(this == checkSum);
144 }
145
146 static int getLiveCount() { return liveCount; }
147private:
148 static int liveCount;
149
150 int value;
151 void *checkSum;
152};
153
154int Complex::liveCount = 0;
155
156Q_DECLARE_METATYPE(Complex);
157
158// Tests depend on the fact that:
159Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic);
160Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex);
161Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic);
162Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex);
163Q_STATIC_ASSERT(QTypeInfo<Complex>::isStatic);
164Q_STATIC_ASSERT(QTypeInfo<Complex>::isComplex);
165
166class tst_QLinkedList : public QObject
167{
168 Q_OBJECT
169private slots:
170 void eraseValidIteratorsOnSharedList() const;
171 void insertWithIteratorsOnSharedList() const;
172 void lengthInt() const;
173 void lengthMovable() const;
174 void lengthComplex() const;
175 void lengthSignature() const;
176 void firstInt() const;
177 void firstMovable() const;
178 void firstComplex() const;
179 void lastInt() const;
180 void lastMovable() const;
181 void lastComplex() const;
182 void beginInt() const;
183 void beginMovable() const;
184 void beginComplex() const;
185 void endInt() const;
186 void endMovable() const;
187 void endComplex() const;
188 void containsInt() const;
189 void containsMovable() const;
190 void containsComplex() const;
191 void countInt() const;
192 void countMovable() const;
193 void countComplex() const;
194 void cpp17ctad() const;
195 void emptyInt() const;
196 void emptyMovable() const;
197 void emptyComplex() const;
198 void endsWithInt() const;
199 void endsWithMovable() const;
200 void endsWithComplex() const;
201 void removeAllInt() const;
202 void removeAllMovable() const;
203 void removeAllComplex() const;
204 void removeOneInt() const;
205 void removeOneMovable() const;
206 void removeOneComplex() const;
207 void reverseIterators() const;
208 void startsWithInt() const;
209 void startsWithMovable() const;
210 void startsWithComplex() const;
211 void takeFirstInt() const;
212 void takeFirstMovable() const;
213 void takeFirstComplex() const;
214 void takeLastInt() const;
215 void takeLastMovable() const;
216 void takeLastComplex() const;
217 void toStdListInt() const;
218 void toStdListMovable() const;
219 void toStdListComplex() const;
220 void testOperatorsInt() const;
221 void testOperatorsMovable() const;
222 void testOperatorsComplex() const;
223 void testSTLIteratorsInt() const;
224 void testSTLIteratorsMovable() const;
225 void testSTLIteratorsComplex() const;
226
227 void initializeList() const;
228
229 void constSharedNullInt() const;
230 void constSharedNullMovable() const;
231 void constSharedNullComplex() const;
232
233 void setSharableInt() const;
234private:
235 template<typename T> void length() const;
236 template<typename T> void first() const;
237 template<typename T> void last() const;
238 template<typename T> void begin() const;
239 template<typename T> void end() const;
240 template<typename T> void contains() const;
241 template<typename T> void count() const;
242 template<typename T> void empty() const;
243 template<typename T> void endsWith() const;
244 template<typename T> void move() const;
245 template<typename T> void removeAll() const;
246 template<typename T> void removeOne() const;
247 template<typename T> void startsWith() const;
248 template<typename T> void swap() const;
249 template<typename T> void takeFirst() const;
250 template<typename T> void takeLast() const;
251 template<typename T> void toStdList() const;
252 template<typename T> void value() const;
253
254 template<typename T> void testOperators() const;
255 template<typename T> void testSTLIterators() const;
256
257 template<typename T> void constSharedNull() const;
258
259 int dummyForGuard;
260};
261
262template<typename T> struct SimpleValue
263{
264 static T at(int index)
265 {
266 return values[index % maxSize];
267 }
268 static const uint maxSize = 7;
269 static const T values[maxSize];
270};
271
272template<>
273const int SimpleValue<int>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
274template<>
275const Movable SimpleValue<Movable>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
276template<>
277const Complex SimpleValue<Complex>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
278
279// Make some macros for the tests to use in order to be slightly more readable...
280#define T_FOO SimpleValue<T>::at(0)
281#define T_BAR SimpleValue<T>::at(1)
282#define T_BAZ SimpleValue<T>::at(2)
283#define T_CAT SimpleValue<T>::at(3)
284#define T_DOG SimpleValue<T>::at(4)
285#define T_BLAH SimpleValue<T>::at(5)
286#define T_WEEE SimpleValue<T>::at(6)
287
288template<typename T>
289void tst_QLinkedList::length() const
290{
291 /* Empty list. */
292 {
293 const QLinkedList<T> list;
294 QCOMPARE(list.size(), 0);
295 }
296
297 /* One entry. */
298 {
299 QLinkedList<T> list;
300 list.append(T_FOO);
301 QCOMPARE(list.size(), 1);
302 }
303
304 /* Two entries. */
305 {
306 QLinkedList<T> list;
307 list.append(T_FOO);
308 list.append(T_BAR);
309 QCOMPARE(list.size(), 2);
310 }
311
312 /* Three entries. */
313 {
314 QLinkedList<T> list;
315 list.append(T_FOO);
316 list.append(T_BAR);
317 list.append(T_BAZ);
318 QCOMPARE(list.size(), 3);
319 }
320}
321
322void tst_QLinkedList::eraseValidIteratorsOnSharedList() const
323{
324 QLinkedList<int> a, b;
325 a.append(t: 5);
326 a.append(t: 10);
327 a.append(t: 20);
328 a.append(t: 20);
329 a.append(t: 20);
330 a.append(t: 20);
331 a.append(t: 30);
332
333 QLinkedList<int>::iterator i = a.begin();
334 ++i;
335 ++i;
336 ++i;
337 b = a;
338 QLinkedList<int>::iterator r = a.erase(pos: i);
339 QCOMPARE(b.size(), 7);
340 QCOMPARE(a.size(), 6);
341 --r;
342 --r;
343 QCOMPARE(*r, 10); // Ensure that number 2 instance was removed;
344}
345
346void tst_QLinkedList::insertWithIteratorsOnSharedList() const
347{
348 QLinkedList<int> a, b;
349 a.append(t: 5);
350 a.append(t: 10);
351 a.append(t: 20);
352 QLinkedList<int>::iterator i = a.begin();
353 ++i;
354 ++i;
355 b = a;
356
357 QLinkedList<int>::iterator i2 = a.insert(before: i, t: 15);
358 QCOMPARE(b.size(), 3);
359 QCOMPARE(a.size(), 4);
360 --i2;
361 QCOMPARE(*i2, 10);
362}
363
364void tst_QLinkedList::lengthInt() const
365{
366 length<int>();
367}
368
369void tst_QLinkedList::lengthMovable() const
370{
371 const int liveCount = Movable::getLiveCount();
372 length<Movable>();
373 QCOMPARE(liveCount, Movable::getLiveCount());
374}
375
376void tst_QLinkedList::lengthComplex() const
377{
378 const int liveCount = Complex::getLiveCount();
379 length<Complex>();
380 QCOMPARE(liveCount, Complex::getLiveCount());
381}
382
383void tst_QLinkedList::lengthSignature() const
384{
385 /* Constness. */
386 {
387 const QLinkedList<int> list;
388 /* The function should be const. */
389 list.size();
390 }
391}
392
393template<typename T>
394void tst_QLinkedList::first() const
395{
396 QLinkedList<T> list;
397 list << T_FOO << T_BAR;
398
399 QCOMPARE(list.first(), T_FOO);
400
401 // remove an item, make sure it still works
402 list.pop_front();
403 QVERIFY(list.size() == 1);
404 QCOMPARE(list.first(), T_BAR);
405}
406
407void tst_QLinkedList::firstInt() const
408{
409 first<int>();
410}
411
412void tst_QLinkedList::firstMovable() const
413{
414 const int liveCount = Movable::getLiveCount();
415 first<Movable>();
416 QCOMPARE(liveCount, Movable::getLiveCount());
417}
418
419void tst_QLinkedList::firstComplex() const
420{
421 const int liveCount = Complex::getLiveCount();
422 first<Complex>();
423 QCOMPARE(liveCount, Complex::getLiveCount());
424}
425
426template<typename T>
427void tst_QLinkedList::last() const
428{
429 QLinkedList<T> list;
430 list << T_FOO << T_BAR;
431
432 QCOMPARE(list.last(), T_BAR);
433
434 // remove an item, make sure it still works
435 list.pop_back();
436 QVERIFY(list.size() == 1);
437 QCOMPARE(list.last(), T_FOO);
438}
439
440void tst_QLinkedList::lastInt() const
441{
442 last<int>();
443}
444
445void tst_QLinkedList::lastMovable() const
446{
447 const int liveCount = Movable::getLiveCount();
448 last<Movable>();
449 QCOMPARE(liveCount, Movable::getLiveCount());
450}
451
452void tst_QLinkedList::lastComplex() const
453{
454 const int liveCount = Complex::getLiveCount();
455 last<Complex>();
456 QCOMPARE(liveCount, Complex::getLiveCount());
457}
458
459template<typename T>
460void tst_QLinkedList::begin() const
461{
462 QLinkedList<T> list;
463 list << T_FOO << T_BAR;
464
465 QCOMPARE(*list.begin(), T_FOO);
466
467 // remove an item, make sure it still works
468 list.pop_front();
469 QVERIFY(list.size() == 1);
470 QCOMPARE(*list.begin(), T_BAR);
471}
472
473void tst_QLinkedList::beginInt() const
474{
475 begin<int>();
476}
477
478void tst_QLinkedList::beginMovable() const
479{
480 const int liveCount = Movable::getLiveCount();
481 begin<Movable>();
482 QCOMPARE(liveCount, Movable::getLiveCount());
483}
484
485void tst_QLinkedList::beginComplex() const
486{
487 const int liveCount = Complex::getLiveCount();
488 begin<Complex>();
489 QCOMPARE(liveCount, Complex::getLiveCount());
490}
491
492template<typename T>
493void tst_QLinkedList::end() const
494{
495 QLinkedList<T> list;
496 list << T_FOO << T_BAR;
497
498 QCOMPARE(*--list.end(), T_BAR);
499
500 // remove an item, make sure it still works
501 list.pop_back();
502 QVERIFY(list.size() == 1);
503 QCOMPARE(*--list.end(), T_FOO);
504}
505
506void tst_QLinkedList::endInt() const
507{
508 end<int>();
509}
510
511void tst_QLinkedList::endMovable() const
512{
513 const int liveCount = Movable::getLiveCount();
514 end<Movable>();
515 QCOMPARE(liveCount, Movable::getLiveCount());
516}
517
518void tst_QLinkedList::endComplex() const
519{
520 const int liveCount = Complex::getLiveCount();
521 end<Complex>();
522 QCOMPARE(liveCount, Complex::getLiveCount());
523}
524
525template<typename T>
526void tst_QLinkedList::contains() const
527{
528 QLinkedList<T> list;
529 list << T_FOO << T_BAR << T_BAZ;
530
531 QVERIFY(list.contains(T_FOO));
532 QVERIFY(list.contains(T_BLAH) != true);
533
534 // add it and make sure it matches
535 list.append(T_BLAH);
536 QVERIFY(list.contains(T_BLAH));
537}
538
539void tst_QLinkedList::containsInt() const
540{
541 contains<int>();
542}
543
544void tst_QLinkedList::containsMovable() const
545{
546 const int liveCount = Movable::getLiveCount();
547 contains<Movable>();
548 QCOMPARE(liveCount, Movable::getLiveCount());
549}
550
551void tst_QLinkedList::containsComplex() const
552{
553 const int liveCount = Complex::getLiveCount();
554 contains<Complex>();
555 QCOMPARE(liveCount, Complex::getLiveCount());
556}
557
558template<typename T>
559void tst_QLinkedList::count() const
560{
561 QLinkedList<T> list;
562
563 // starts empty
564 QVERIFY(list.count() == 0);
565
566 // goes up
567 list.append(T_FOO);
568 QVERIFY(list.count() == 1);
569
570 // and up
571 list.append(T_BAR);
572 QVERIFY(list.count() == 2);
573
574 // and down
575 list.pop_back();
576 QVERIFY(list.count() == 1);
577
578 // and empty. :)
579 list.pop_back();
580 QVERIFY(list.count() == 0);
581}
582
583void tst_QLinkedList::countInt() const
584{
585 count<int>();
586}
587
588void tst_QLinkedList::countMovable() const
589{
590 const int liveCount = Movable::getLiveCount();
591 count<Movable>();
592 QCOMPARE(liveCount, Movable::getLiveCount());
593}
594
595void tst_QLinkedList::countComplex() const
596{
597 const int liveCount = Complex::getLiveCount();
598 count<Complex>();
599 QCOMPARE(liveCount, Complex::getLiveCount());
600}
601
602void tst_QLinkedList::cpp17ctad() const
603{
604#ifdef __cpp_deduction_guides
605#define QVERIFY_IS_LIST_OF(obj, Type) \
606 QVERIFY2((std::is_same<decltype(obj), QLinkedList<Type>>::value), \
607 QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
608#define CHECK(Type, One, Two, Three) \
609 do { \
610 const Type v[] = {One, Two, Three}; \
611 QLinkedList v1 = {One, Two, Three}; \
612 QVERIFY_IS_LIST_OF(v1, Type); \
613 QLinkedList v2(v1.begin(), v1.end()); \
614 QVERIFY_IS_LIST_OF(v2, Type); \
615 QLinkedList v3(std::begin(v), std::end(v)); \
616 QVERIFY_IS_LIST_OF(v3, Type); \
617 } while (false) \
618 /*end*/
619 CHECK(int, 1, 2, 3);
620 CHECK(double, 1.0, 2.0, 3.0);
621 CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
622#undef QVERIFY_IS_LIST_OF
623#undef CHECK
624#else
625 QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
626#endif
627}
628
629template<typename T>
630void tst_QLinkedList::empty() const
631{
632 QLinkedList<T> list;
633
634 // make sure it starts empty
635 QVERIFY(list.empty());
636
637 // and doesn't stay empty
638 list.append(T_FOO);
639 QVERIFY(!list.empty());
640
641 // and goes back to being empty
642 list.pop_back();
643 QVERIFY(list.empty());
644}
645
646void tst_QLinkedList::emptyInt() const
647{
648 empty<int>();
649}
650
651void tst_QLinkedList::emptyMovable() const
652{
653 const int liveCount = Movable::getLiveCount();
654 empty<Movable>();
655 QCOMPARE(liveCount, Movable::getLiveCount());
656}
657
658void tst_QLinkedList::emptyComplex() const
659{
660 const int liveCount = Complex::getLiveCount();
661 empty<Complex>();
662 QCOMPARE(liveCount, Complex::getLiveCount());
663}
664
665template<typename T>
666void tst_QLinkedList::endsWith() const
667{
668 QLinkedList<T> list;
669 list << T_FOO << T_BAR << T_BAZ;
670
671 // test it returns correctly in both cases
672 QVERIFY(list.endsWith(T_BAZ));
673 QVERIFY(!list.endsWith(T_BAR));
674
675 // remove an item and make sure the end item changes
676 list.pop_back();
677 QVERIFY(list.endsWith(T_BAR));
678}
679
680void tst_QLinkedList::endsWithInt() const
681{
682 endsWith<int>();
683}
684
685void tst_QLinkedList::endsWithMovable() const
686{
687 const int liveCount = Movable::getLiveCount();
688 endsWith<Movable>();
689 QCOMPARE(liveCount, Movable::getLiveCount());
690}
691
692void tst_QLinkedList::endsWithComplex() const
693{
694 const int liveCount = Complex::getLiveCount();
695 endsWith<Complex>();
696 QCOMPARE(liveCount, Complex::getLiveCount());
697}
698
699template<typename T>
700void tst_QLinkedList::removeAll() const
701{
702 QLinkedList<T> list;
703 list << T_FOO << T_BAR << T_BAZ;
704
705 // remove one instance
706 list.removeAll(T_BAR);
707 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ);
708
709 // many instances
710 list << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ;
711 list.removeAll(T_BAR);
712 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
713
714 // try remove something that doesn't exist
715 list.removeAll(T_WEEE);
716 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
717}
718
719void tst_QLinkedList::removeAllInt() const
720{
721 removeAll<int>();
722}
723
724void tst_QLinkedList::removeAllMovable() const
725{
726 const int liveCount = Movable::getLiveCount();
727 removeAll<Movable>();
728 QCOMPARE(liveCount, Movable::getLiveCount());
729}
730
731void tst_QLinkedList::removeAllComplex() const
732{
733 const int liveCount = Complex::getLiveCount();
734 removeAll<Complex>();
735 QCOMPARE(liveCount, Complex::getLiveCount());
736}
737
738template<typename T>
739void tst_QLinkedList::removeOne() const
740{
741 QLinkedList<T> list;
742 list << T_FOO << T_BAR << T_BAZ;
743
744 // middle
745 list.removeOne(T_BAR);
746 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ);
747
748 // start
749 list.removeOne(T_FOO);
750 QCOMPARE(list, QLinkedList<T>() << T_BAZ);
751
752 // last
753 list.removeOne(T_BAZ);
754 QCOMPARE(list, QLinkedList<T>());
755
756 // make sure it really only removes one :)
757 list << T_FOO << T_FOO;
758 list.removeOne(T_FOO);
759 QCOMPARE(list, QLinkedList<T>() << T_FOO);
760
761 // try remove something that doesn't exist
762 list.removeOne(T_WEEE);
763 QCOMPARE(list, QLinkedList<T>() << T_FOO);
764}
765
766void tst_QLinkedList::removeOneInt() const
767{
768 removeOne<int>();
769}
770
771void tst_QLinkedList::removeOneMovable() const
772{
773 const int liveCount = Movable::getLiveCount();
774 removeOne<Movable>();
775 QCOMPARE(liveCount, Movable::getLiveCount());
776}
777
778void tst_QLinkedList::removeOneComplex() const
779{
780 const int liveCount = Complex::getLiveCount();
781 removeOne<Complex>();
782 QCOMPARE(liveCount, Complex::getLiveCount());
783}
784
785void tst_QLinkedList::reverseIterators() const
786{
787 QLinkedList<int> l;
788 l << 1 << 2 << 3 << 4;
789 QLinkedList<int> lr = l;
790 std::reverse(first: lr.begin(), last: lr.end());
791 const QLinkedList<int> &clr = lr;
792 QVERIFY(std::equal(l.begin(), l.end(), lr.rbegin()));
793 QVERIFY(std::equal(l.begin(), l.end(), lr.crbegin()));
794 QVERIFY(std::equal(l.begin(), l.end(), clr.rbegin()));
795 QVERIFY(std::equal(lr.rbegin(), lr.rend(), l.begin()));
796 QVERIFY(std::equal(lr.crbegin(), lr.crend(), l.begin()));
797 QVERIFY(std::equal(clr.rbegin(), clr.rend(), l.begin()));
798}
799
800template<typename T>
801void tst_QLinkedList::startsWith() const
802{
803 QLinkedList<T> list;
804 list << T_FOO << T_BAR << T_BAZ;
805
806 // make sure it starts ok
807 QVERIFY(list.startsWith(T_FOO));
808
809 // remove an item
810 list.removeFirst();
811 QVERIFY(list.startsWith(T_BAR));
812}
813
814void tst_QLinkedList::startsWithInt() const
815{
816 startsWith<int>();
817}
818
819void tst_QLinkedList::startsWithMovable() const
820{
821 const int liveCount = Movable::getLiveCount();
822 startsWith<Movable>();
823 QCOMPARE(liveCount, Movable::getLiveCount());
824}
825
826void tst_QLinkedList::startsWithComplex() const
827{
828 const int liveCount = Complex::getLiveCount();
829 startsWith<Complex>();
830 QCOMPARE(liveCount, Complex::getLiveCount());
831}
832
833template<typename T>
834void tst_QLinkedList::takeFirst() const
835{
836 QLinkedList<T> list;
837 list << T_FOO << T_BAR << T_BAZ;
838
839 QCOMPARE(list.takeFirst(), T_FOO);
840 QVERIFY(list.size() == 2);
841 QCOMPARE(list.takeFirst(), T_BAR);
842 QVERIFY(list.size() == 1);
843 QCOMPARE(list.takeFirst(), T_BAZ);
844 QVERIFY(list.size() == 0);
845}
846
847void tst_QLinkedList::takeFirstInt() const
848{
849 takeFirst<int>();
850}
851
852void tst_QLinkedList::takeFirstMovable() const
853{
854 const int liveCount = Movable::getLiveCount();
855 takeFirst<Movable>();
856 QCOMPARE(liveCount, Movable::getLiveCount());
857}
858
859void tst_QLinkedList::takeFirstComplex() const
860{
861 const int liveCount = Complex::getLiveCount();
862 takeFirst<Complex>();
863 QCOMPARE(liveCount, Complex::getLiveCount());
864}
865
866template<typename T>
867void tst_QLinkedList::takeLast() const
868{
869 QLinkedList<T> list;
870 list << T_FOO << T_BAR << T_BAZ;
871
872 QCOMPARE(list.takeLast(), T_BAZ);
873 QCOMPARE(list.takeLast(), T_BAR);
874 QCOMPARE(list.takeLast(), T_FOO);
875}
876
877void tst_QLinkedList::takeLastInt() const
878{
879 takeLast<int>();
880}
881
882void tst_QLinkedList::takeLastMovable() const
883{
884 const int liveCount = Movable::getLiveCount();
885 takeLast<Movable>();
886 QCOMPARE(liveCount, Movable::getLiveCount());
887}
888
889void tst_QLinkedList::takeLastComplex() const
890{
891 const int liveCount = Complex::getLiveCount();
892 takeLast<Complex>();
893 QCOMPARE(liveCount, Complex::getLiveCount());
894}
895
896template<typename T>
897void tst_QLinkedList::toStdList() const
898{
899 QLinkedList<T> list;
900 list << T_FOO << T_BAR << T_BAZ;
901
902 // yuck.
903 std::list<T> slist;
904 slist.push_back(T_FOO);
905 slist.push_back(T_BAR);
906 slist.push_back(T_BAZ);
907
908 QCOMPARE(list.toStdList(), slist);
909 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAR << T_BAZ);
910}
911
912void tst_QLinkedList::toStdListInt() const
913{
914 toStdList<int>();
915}
916
917void tst_QLinkedList::toStdListMovable() const
918{
919 const int liveCount = Movable::getLiveCount();
920 toStdList<Movable>();
921 QCOMPARE(liveCount, Movable::getLiveCount());
922}
923
924void tst_QLinkedList::toStdListComplex() const
925{
926 const int liveCount = Complex::getLiveCount();
927 toStdList<Complex>();
928 QCOMPARE(liveCount, Complex::getLiveCount());
929}
930
931template<typename T>
932void tst_QLinkedList::testOperators() const
933{
934 QLinkedList<T> list;
935 list << T_FOO << T_BAR << T_BAZ;
936
937 QLinkedList<T> listtwo;
938 listtwo << T_FOO << T_BAR << T_BAZ;
939
940 // test equal
941 QVERIFY(list == listtwo);
942
943 // not equal
944 listtwo.append(T_CAT);
945 QVERIFY(list != listtwo);
946
947 // +=
948 list += listtwo;
949 QVERIFY(list.size() == 7);
950 QVERIFY(listtwo.size() == 4);
951 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAR << T_BAZ
952 << T_FOO << T_BAR << T_BAZ << T_CAT);
953
954 // =
955 list = listtwo;
956 QCOMPARE(list, listtwo);
957 QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAR << T_BAZ << T_CAT);
958}
959
960void tst_QLinkedList::testOperatorsInt() const
961{
962 testOperators<int>();
963}
964
965void tst_QLinkedList::testOperatorsMovable() const
966{
967 const int liveCount = Movable::getLiveCount();
968 testOperators<Movable>();
969 QCOMPARE(liveCount, Movable::getLiveCount());
970}
971
972void tst_QLinkedList::testOperatorsComplex() const
973{
974 const int liveCount = Complex::getLiveCount();
975 testOperators<Complex>();
976 QCOMPARE(liveCount, Complex::getLiveCount());
977}
978
979template<typename T>
980void tst_QLinkedList::testSTLIterators() const
981{
982 QLinkedList<T> list;
983
984 // create a list
985 list << T_FOO << T_BAR << T_BAZ;
986 typename QLinkedList<T>::iterator it = list.begin();
987 QCOMPARE(*it, T_FOO); it++;
988 QCOMPARE(*it, T_BAR); it++;
989 QCOMPARE(*it, T_BAZ); it++;
990 QCOMPARE(it, list.end()); it--;
991
992 // walk backwards
993 QCOMPARE(*it, T_BAZ); it--;
994 QCOMPARE(*it, T_BAR); it--;
995 QCOMPARE(*it, T_FOO);
996
997 // test erase
998 it = list.erase(it);
999 QVERIFY(list.size() == 2);
1000 QCOMPARE(*it, T_BAR);
1001
1002 // test multiple erase
1003 it = list.erase(it, it + 2);
1004 QVERIFY(list.size() == 0);
1005 QCOMPARE(it, list.end());
1006
1007 // insert again
1008 it = list.insert(it, T_FOO);
1009 QVERIFY(list.size() == 1);
1010 QCOMPARE(*it, T_FOO);
1011
1012 // insert again
1013 it = list.insert(it, T_BAR);
1014 QVERIFY(list.size() == 2);
1015 QCOMPARE(*it++, T_BAR);
1016 QCOMPARE(*it, T_FOO);
1017}
1018
1019void tst_QLinkedList::testSTLIteratorsInt() const
1020{
1021 testSTLIterators<int>();
1022}
1023
1024void tst_QLinkedList::testSTLIteratorsMovable() const
1025{
1026 const int liveCount = Movable::getLiveCount();
1027 testSTLIterators<Movable>();
1028 QCOMPARE(liveCount, Movable::getLiveCount());
1029}
1030
1031void tst_QLinkedList::testSTLIteratorsComplex() const
1032{
1033 const int liveCount = Complex::getLiveCount();
1034 testSTLIterators<Complex>();
1035 QCOMPARE(liveCount, Complex::getLiveCount());
1036}
1037
1038void tst_QLinkedList::initializeList() const
1039{
1040 QLinkedList<int> v1 { 2, 3, 4 };
1041 QCOMPARE(v1, QLinkedList<int>() << 2 << 3 << 4);
1042 QCOMPARE(v1, (QLinkedList<int> { 2, 3, 4}));
1043
1044 QLinkedList<QLinkedList<int>> v2{ v1, { 1 }, QLinkedList<int>(), { 2, 3, 4 } };
1045 QLinkedList<QLinkedList<int>> v3;
1046 v3 << v1 << (QLinkedList<int>() << 1) << QLinkedList<int>() << v1;
1047 QCOMPARE(v3, v2);
1048}
1049
1050
1051template<typename T>
1052void tst_QLinkedList::constSharedNull() const
1053{
1054 QLinkedList<T> list2;
1055#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1056 QLinkedList<T> list1;
1057 list1.setSharable(false);
1058 QVERIFY(list1.isDetached());
1059
1060 list2.setSharable(true);
1061#endif
1062 QVERIFY(!list2.isDetached());
1063}
1064
1065void tst_QLinkedList::constSharedNullInt() const
1066{
1067 constSharedNull<int>();
1068}
1069
1070void tst_QLinkedList::constSharedNullMovable() const
1071{
1072 const int liveCount = Movable::getLiveCount();
1073 constSharedNull<Movable>();
1074 QCOMPARE(liveCount, Movable::getLiveCount());
1075}
1076
1077void tst_QLinkedList::constSharedNullComplex() const
1078{
1079 const int liveCount = Complex::getLiveCount();
1080 constSharedNull<Complex>();
1081 QCOMPARE(liveCount, Complex::getLiveCount());
1082}
1083
1084
1085void tst_QLinkedList::setSharableInt() const
1086{
1087#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1088 QLinkedList<int> orglist;
1089 orglist << 0 << 1 << 2 << 3 << 4 << 5;
1090 int size = 6;
1091
1092 QLinkedList<int> list;
1093 list = orglist;
1094
1095 QVERIFY(!list.isDetached());
1096 list.setSharable(true);
1097
1098 QCOMPARE(list.size(), size);
1099
1100 {
1101 QLinkedList<int> copy(list);
1102 QVERIFY(!copy.isDetached());
1103 QVERIFY(copy.isSharedWith(list));
1104 }
1105
1106 list.setSharable(false);
1107 QVERIFY(list.isDetached() || list.isSharedWith(QLinkedList<int>()));
1108
1109 {
1110 QLinkedList<int> copy(list);
1111
1112 QVERIFY(copy.isDetached() || copy.isSharedWith(QLinkedList<int>()));
1113 QCOMPARE(copy.size(), size);
1114 QCOMPARE(copy, list);
1115 }
1116
1117 list.setSharable(true);
1118
1119 {
1120 QLinkedList<int> copy(list);
1121
1122 QVERIFY(!copy.isDetached());
1123 QVERIFY(copy.isSharedWith(list));
1124 }
1125
1126 QLinkedList<int>::const_iterator it = list.constBegin();
1127 for (int i = 0; i < list.size(); ++i) {
1128 QCOMPARE(int(*it), i);
1129 ++it;
1130 }
1131
1132 QCOMPARE(list.size(), size);
1133#endif
1134}
1135
1136QT_WARNING_POP
1137#else
1138class tst_QLinkedList : public QObject
1139{
1140 Q_OBJECT
1141private slots:
1142 void initTestCase() { QSKIP("Deprecated APIs are disabled, skipping this test."); }
1143};
1144
1145#endif // QT_DEPRECATED_SINCE(5, 15)
1146
1147QTEST_APPLESS_MAIN(tst_QLinkedList)
1148#include "tst_qlinkedlist.moc"
1149

source code of qtbase/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp