QtBase  v6.3.1
tst_qlist.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 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 <QTest>
30 #include <QAtomicInt>
31 #include <QThread>
32 #include <QSemaphore>
33 #include <QScopedValueRollback>
34 #include <qlist.h>
35 
36 
37 #if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11)
38 # if __has_include(<concepts>)
39 # include <concepts>
40 # if defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L
41  static_assert(std::contiguous_iterator<QList<int>::iterator>);
42  static_assert(std::contiguous_iterator<QList<int>::const_iterator>);
43 # endif
44 # endif
45 # if __has_include(<ranges>)
46 # include <ranges>
47 # if defined(__cpp_lib_ranges)
48  namespace rns = std::ranges;
49 
50  static_assert(rns::contiguous_range<QList<int>>);
51  static_assert(rns::contiguous_range<const QList<int>>);
52 # endif
53 # endif
54 #endif
55 
56 struct Movable {
57  Movable(char input = 'j')
58  : i(input)
59  , that(this)
60  , state(Constructed)
61  {
62  counter.fetchAndAddRelaxed(1);
63  }
65  : i(other.i)
66  , that(this)
67  , state(Constructed)
68  {
69  check(other.state, Constructed);
70  counter.fetchAndAddRelaxed(1);
71  }
73  : i(other.i)
74  , that(other.that)
75  , state(Constructed)
76  {
77  check(other.state, Constructed);
78  counter.fetchAndAddRelaxed(1);
79  other.that = nullptr;
80  }
81 
83  {
84  check(state, Constructed);
85  i = 0;
86  counter.fetchAndAddRelaxed(-1);
87  state = Destructed;
88  }
89 
90  bool operator ==(const Movable &other) const
91  {
92  check(state, Constructed);
93  check(other.state, Constructed);
94  return i == other.i;
95  }
96 
98  {
99  check(state, Constructed);
100  check(other.state, Constructed);
101  i = other.i;
102  that = this;
103  return *this;
104  }
106  {
107  check(state, Constructed);
108  check(other.state, Constructed);
109  i = other.i;
110  that = other.that;
111  other.that = nullptr;
112  return *this;
113  }
114  bool wasConstructedAt(const Movable *other) const
115  {
116  return that == other;
117  }
118  char i;
120 private:
121  Movable *that; // used to check if an instance was moved
122 
123  enum State { Constructed = 106, Destructed = 110 };
124  State state;
125 
126  static void check(const State state1, const State state2)
127  {
128  QCOMPARE(int(state1), int(state2));
129  }
130 };
131 
132 inline size_t qHash(const Movable &key, size_t seed = 0) { return qHash(key.i, seed); }
133 
139 
140 struct Custom {
141  Custom(char input = 'j')
142  : i(input)
143  , that(this)
144  , state(Constructed)
145  {
146  counter.fetchAndAddRelaxed(1);
147  }
149  : that(this)
150  , state(Constructed)
151  {
152  check(&other);
153  counter.fetchAndAddRelaxed(1);
154  this->i = other.i;
155  }
157  {
158  check(this);
159  i = 0;
160  counter.fetchAndAddRelaxed(-1);
161  state = Destructed;
162  QVERIFY(heapData.use_count() > 0); // otherwise it's double free
163  }
164 
165  bool operator ==(const Custom &other) const
166  {
167  check(&other);
168  check(this);
169  return i == other.i;
170  }
171 
172  bool operator<(const Custom &other) const
173  {
174  check(&other);
175  check(this);
176  return i < other.i;
177  }
178 
180  {
181  check(&other);
182  check(this);
183  i = other.i;
184  return *this;
185  }
187 
188  char i; // used to identify orgin of an instance
189 private:
190  Custom *that; // used to check if an instance was moved
191  // shared_ptr triggers ASan/LSan and can track if double free happens, which
192  // is convenient to ensure there's no malfunctioning QList APIs
193  std::shared_ptr<int> heapData = std::shared_ptr<int>(new int(42));
194 
195  enum State { Constructed = 106, Destructed = 110 };
196  State state;
197 
198  static void check(const Custom *c)
199  {
200  // check if c object has been moved
201  QCOMPARE(c, c->that);
202  QCOMPARE(int(c->state), int(Constructed));
203  }
204 };
206 
207 inline size_t qHash(const Custom &key, size_t seed = 0) { return qHash(key.i, seed); }
208 
210 
211 // tests depends on the fact that:
212 static_assert(QTypeInfo<int>::isRelocatable);
213 static_assert(!QTypeInfo<int>::isComplex);
214 static_assert(QTypeInfo<Movable>::isRelocatable);
215 static_assert(QTypeInfo<Movable>::isComplex);
216 static_assert(!QTypeInfo<Custom>::isRelocatable);
217 static_assert(QTypeInfo<Custom>::isComplex);
218 
219 // leak checking utility:
220 template<typename T>
222 {
224  LeakChecker() : instancesCount(T::counter.loadAcquire()) { }
226 };
227 template<> struct LeakChecker<int>{};
228 template<> struct LeakChecker<QString>{};
229 #define TST_QLIST_CHECK_LEAKS(Type) \
230  LeakChecker<Type> checker; \
231  Q_UNUSED(checker);
232 
233 class tst_QList : public QObject
234 {
235  Q_OBJECT
236 
237 private slots:
238  void constructors_empty() const;
239  void constructors_emptyReserveZero() const;
240  void constructors_emptyReserve() const;
241  void constructors_reserveAndInitialize() const;
242  void copyConstructorInt() const { copyConstructor<int>(); }
243  void copyConstructorMovable() const { copyConstructor<Movable>(); }
244  void copyConstructorCustom() const { copyConstructor<Custom>(); }
245  void assignmentInt() const { testAssignment<int>(); }
246  void assignmentMovable() const { testAssignment<Movable>(); }
247  void assignmentCustom() const { testAssignment<Custom>(); }
248  void assignFromInitializerListInt() const { assignFromInitializerList<int>(); }
249  void assignFromInitializerListMovable() const { assignFromInitializerList<Movable>(); }
250  void assignFromInitializerListCustom() const { assignFromInitializerList<Custom>(); }
251  void addInt() const { add<int>(); }
252  void addMovable() const { add<Movable>(); }
253  void addCustom() const { add<Custom>(); }
254  void appendInt() const { append<int>(); }
255  void appendMovable() const { append<Movable>(); }
256  void appendCustom() const { append<Custom>(); }
257  void appendRvalue() const;
258  void appendList() const;
259  void at() const;
260  void capacityInt() const { capacity<int>(); }
261  void capacityMovable() const { capacity<Movable>(); }
262  void capacityCustom() const { capacity<Custom>(); }
263  void clearInt() const { clear<int>(); }
264  void clearMovable() const { clear<Movable>(); }
265  void clearCustom() const { clear<Custom>(); }
266  void constData() const;
267  void constFirst() const;
268  void constLast() const;
269  void contains() const;
270  void countInt() const { count<int>(); }
271  void countMovable() const { count<Movable>(); }
272  void countCustom() const { count<Custom>(); }
273  void cpp17ctad() const;
274  void data() const;
275  void emptyInt() const { empty<int>(); }
276  void emptyMovable() const { empty<Movable>(); }
277  void emptyCustom() const { empty<Custom>(); }
278  void endsWith() const;
279  void eraseEmptyInt() const { eraseEmpty<int>(); }
280  void eraseEmptyMovable() const { eraseEmpty<Movable>(); }
281  void eraseEmptyCustom() const { eraseEmpty<Custom>(); }
282  void eraseEmptyReservedInt() const { eraseEmptyReserved<int>(); }
283  void eraseEmptyReservedMovable() const { eraseEmptyReserved<Movable>(); }
284  void eraseEmptyReservedCustom() const { eraseEmptyReserved<Custom>(); }
285  void eraseInt() const { erase<int>(false); }
286  void eraseIntShared() const { erase<int>(true); }
287  void eraseMovable() const { erase<Movable>(false); }
288  void eraseMovableShared() const { erase<Movable>(true); }
289  void eraseCustom() const { erase<Custom>(false); }
290  void eraseCustomShared() const { erase<Custom>(true); }
291  void eraseReservedInt() const { eraseReserved<int>(); }
292  void eraseReservedMovable() const { eraseReserved<Movable>(); }
293  void eraseReservedCustom() const { eraseReserved<Custom>(); }
294  void fillInt() const { fill<int>(); }
295  void fillMovable() const { fill<Movable>(); }
296  void fillCustom() const { fill<Custom>(); }
297  void fillDetachInt() const { fillDetach<int>(); }
298  void fillDetachMovable() const { fillDetach<Movable>(); }
299  void fillDetachCustom() const { fillDetach<Custom>(); }
300  void first() const;
301  void fromListInt() const { fromList<int>(); }
302  void fromListMovable() const { fromList<Movable>(); }
303  void fromListCustom() const { fromList<Custom>(); }
304  void indexOf() const;
305  void insertInt() const { insert<int>(); }
306  void insertMovable() const { insert<Movable>(); }
307  void insertCustom() const { insert<Custom>(); }
308  void insertZeroCount_data();
309  void insertZeroCount() const;
310  void isEmpty() const;
311  void last() const;
312  void lastIndexOf() const;
313  void mid() const;
314  void sliced() const;
315  void moveInt() const { move<int>(); }
316  void moveMovable() const { move<Movable>(); }
317  void moveCustom() const { move<Custom>(); }
318  void prependInt() const { prepend<int>(); }
319  void prependMovable() const { prepend<Movable>(); }
320  void prependCustom() const { prepend<Custom>(); }
321  void prependRvalue() const;
322  void qhashInt() const { qhash<int>(); }
323  void qhashMovable() const { qhash<Movable>(); }
324  void qhashCustom() const { qhash<Custom>(); }
325  void removeAllWithAlias() const;
326  void removeInt() const { remove<int>(); }
327  void removeMovable() const { remove<Movable>(); }
328  void removeCustom() const { remove<Custom>(); }
329  void removeFirstLast() const;
330  void resizePOD_data() const;
331  void resizePOD() const;
332  void resizeComplexMovable_data() const;
333  void resizeComplexMovable() const;
334  void resizeComplex_data() const;
335  void resizeComplex() const;
336  void resizeCtorAndDtor() const;
337  void resizeToZero() const;
338  void resizeToTheSameSize_data();
339  void resizeToTheSameSize() const;
340  void iterators() const;
341  void constIterators() const;
342  void reverseIterators() const;
343  void sizeInt() const { size<int>(); }
344  void sizeMovable() const { size<Movable>(); }
345  void sizeCustom() const { size<Custom>(); }
346  void startsWith() const;
347  void swapInt() const { swap<int>(); }
348  void swapMovable() const { swap<Movable>(); }
349  void swapCustom() const { swap<Custom>(); }
350  void toList() const;
351 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
352  void fromStdVector() const;
353  void toStdVector() const;
354 #endif
355  void value() const;
356  void testOperators() const;
357  void reserve();
358  void reserveZero();
359  void initializeListInt() { initializeList<int>(); }
360  void initializeListMovable() { initializeList<Movable>(); }
361  void initializeListCustom() { initializeList<Custom>(); }
362  void const_shared_null();
363  void detachInt() const { detach<int>(); }
364  void detachMovable() const { detach<Movable>(); }
365  void detachCustom() const { detach<Custom>(); }
366  void detachThreadSafetyInt() const;
367  void detachThreadSafetyMovable() const;
368  void detachThreadSafetyCustom() const;
369  void insertMove() const;
370  void swapItemsAt() const;
371  void emplaceInt() { emplaceImpl<int>(); }
372  void emplaceCustom() { emplaceImpl<Custom>(); }
373  void emplaceMovable() { emplaceImpl<Movable>(); }
374  void emplaceConsistentWithStdVectorInt() { emplaceConsistentWithStdVectorImpl<int>(); }
375  void emplaceConsistentWithStdVectorCustom() { emplaceConsistentWithStdVectorImpl<Custom>(); }
376  void emplaceConsistentWithStdVectorMovable() { emplaceConsistentWithStdVectorImpl<Movable>(); }
377  void emplaceConsistentWithStdVectorQString() { emplaceConsistentWithStdVectorImpl<QString>(); }
378  void emplaceReturnsIterator();
379  void emplaceFront() const;
380  void emplaceFrontReturnsRef() const;
381  void emplaceBack();
382  void emplaceBackReturnsRef();
383  void emplaceWithElementFromTheSameContainer();
384  void emplaceWithElementFromTheSameContainer_data();
385  void replaceInt() const { replace<int>(); }
386  void replaceCustom() const { replace<Custom>(); }
387  void replaceMovable() const { replace<Movable>(); }
388  void fromReadOnlyData() const;
389  void reallocateCustomAlignedType_qtbug90359() const;
390  void reinsertToBeginInt_qtbug91360() const { reinsertToBegin<int>(); }
391  void reinsertToBeginMovable_qtbug91360() const { reinsertToBegin<Movable>(); }
392  void reinsertToBeginCustom_qtbug91360() const { reinsertToBegin<Custom>(); }
393  void reinsertToEndInt_qtbug91360() const { reinsertToEnd<int>(); }
394  void reinsertToEndMovable_qtbug91360() const { reinsertToEnd<Movable>(); }
395  void reinsertToEndCustom_qtbug91360() const { reinsertToEnd<Custom>(); }
396  void reinsertRangeToEndInt_qtbug91360() const { reinsertRangeToEnd<int>(); }
397  void reinsertRangeToEndMovable_qtbug91360() const { reinsertRangeToEnd<Movable>(); }
398  void reinsertRangeToEndCustom_qtbug91360() const { reinsertRangeToEnd<Custom>(); }
399  // QList reference stability tests:
400  void stability_reserveInt() const { stability_reserve<int>(); }
401  void stability_reserveMovable() const { stability_reserve<Movable>(); }
402  void stability_reserveCustom() const { stability_reserve<Custom>(); }
403  void stability_eraseInt() const { stability_erase<int>(); }
404  void stability_eraseMovable() const { stability_erase<Movable>(); }
405  void stability_eraseCustom() const { stability_erase<Custom>(); }
406  void stability_appendInt() const { stability_append<int>(); }
407  void stability_appendMovable() const { stability_append<Movable>(); }
408  void stability_appendCustom() const { stability_append<Custom>(); }
409  void stability_insertElementInt() const { stability_insertElement<int>(); }
410  void stability_insertElementMovable() const { stability_insertElement<Movable>(); }
411  void stability_insertElementCustom() const { stability_insertElement<Custom>(); }
412  void stability_emplaceInt() const { stability_emplace<int>(); }
413  void stability_emplaceMovable() const { stability_emplace<Movable>(); }
414  void stability_emplaceCustom() const { stability_emplace<Custom>(); }
415  void stability_resizeInt() const { stability_resize<int>(); }
416  void stability_resizeMovable() const { stability_resize<Movable>(); }
417  void stability_resizeCustom() const { stability_resize<Custom>(); }
418 
419 private:
420  template<typename T> void copyConstructor() const;
421  template<typename T> void testAssignment() const;
422  template<typename T> void add() const;
423  template<typename T> void append() const;
424  template<typename T> void assignFromInitializerList() const;
425  template<typename T> void capacity() const;
426  template<typename T> void clear() const;
427  template<typename T> void count() const;
428  template<typename T> void empty() const;
429  template<typename T> void eraseEmpty() const;
430  template<typename T> void eraseEmptyReserved() const;
431  template<typename T> void erase(bool shared) const;
432  template<typename T> void eraseReserved() const;
433  template<typename T> void fill() const;
434  template<typename T> void fillDetach() const;
435  template<typename T> void fromList() const;
436  template<typename T> void insert() const;
437  template<typename T> void qhash() const;
438  template<typename T> void move() const;
439  template<typename T> void prepend() const;
440  template<typename T> void remove() const;
441  template<typename T> void size() const;
442  template<typename T> void swap() const;
443  template<typename T> void initializeList();
444  template<typename T> void detach() const;
445  template<typename T> void detachThreadSafety() const;
446  template<typename T> void emplaceImpl() const;
447  template<typename T> void emplaceConsistentWithStdVectorImpl() const;
448  template<typename T> void replace() const;
449  template<typename T, typename Reinsert>
450  void reinsert(Reinsert op) const;
451  template<typename T>
452  void reinsertToBegin() const
453  {
454  reinsert<T>([](QList<T> &list) {
455  list.prepend(list.back());
456  list.removeLast();
457  });
458  }
459  template<typename T>
460  void reinsertToEnd() const
461  {
462  reinsert<T>([](QList<T> &list) {
463  list.append(list.front());
464  list.removeFirst();
465  });
466  }
467  template<typename T>
468  void reinsertRangeToEnd() const
469  {
470  reinsert<T>([](QList<T> &list) {
471  list.append(list.begin(), list.begin() + 1);
472  list.removeFirst();
473  });
474  }
475  template<typename T>
476  void stability_reserve() const;
477  template<typename T>
478  void stability_erase() const;
479  template<typename T>
480  void stability_append() const;
481  template<typename T, typename Insert>
482  void stability_insert(Insert op) const;
483  template<typename T>
484  void stability_resize() const;
485 
486  template<typename T>
487  void stability_insertElement() const
488  {
489  stability_insert<T>(
490  [](QList<T> &list, int pos, const T &value) { list.insert(pos, 1, value); });
491  }
492  template<typename T>
493  void stability_emplace() const
494  {
495  stability_insert<T>(
496  [](QList<T> &list, int pos, const T &value) { list.emplace(pos, value); });
497  }
498 };
499 
500 
501 template<typename T> struct SimpleValue
502 {
503  static T at(int index)
504  {
505  return Values[index % MaxIndex];
506  }
507 
508  static QList<T> vector(int size)
509  {
510  QList<T> ret;
511  for (int i = 0; i < size; i++)
512  ret.append(at(i));
513  return ret;
514  }
515 
516  static const uint MaxIndex = 6;
517  static const T Values[MaxIndex];
518 };
519 
520 template<>
521 const int SimpleValue<int>::Values[] = { 110, 105, 101, 114, 111, 98 };
522 template<>
523 const Movable SimpleValue<Movable>::Values[] = { 110, 105, 101, 114, 111, 98 };
524 template<>
525 const Custom SimpleValue<Custom>::Values[] = { 110, 105, 101, 114, 111, 98 };
526 
527 // Make some macros for the tests to use in order to be slightly more readable...
528 #define T_FOO SimpleValue<T>::at(0)
529 #define T_BAR SimpleValue<T>::at(1)
530 #define T_BAZ SimpleValue<T>::at(2)
531 #define T_CAT SimpleValue<T>::at(3)
532 #define T_DOG SimpleValue<T>::at(4)
533 #define T_BLAH SimpleValue<T>::at(5)
534 
535 // returns a pair of QList<T> and QList<T *>
536 template<typename It>
537 decltype(auto) qlistCopyAndReferenceFromRange(It first, It last)
538 {
539  using T = typename std::iterator_traits<It>::value_type;
540  QList<T> copy(first, last);
542  for (; first != last; ++first)
543  reference.append(std::addressof(*first));
544  return std::make_pair(copy, reference);
545 }
546 
547 void tst_QList::constructors_empty() const
548 {
549  QList<int> emptyInt;
550  QList<Movable> emptyMovable;
551  QList<Custom> emptyCustom;
552 }
553 
554 void tst_QList::constructors_emptyReserveZero() const
555 {
556  QList<int> emptyInt(0);
557  QList<Movable> emptyMovable(0);
558  QList<Custom> emptyCustom(0);
559 }
560 
561 void tst_QList::constructors_emptyReserve() const
562 {
563  // pre-reserve capacity
564  QList<int> myInt(5);
565  QVERIFY(myInt.capacity() == 5);
566  QList<Movable> myMovable(5);
567  QVERIFY(myMovable.capacity() == 5);
568  QList<Custom> myCustom(4);
569  QVERIFY(myCustom.capacity() == 4);
570 }
571 
572 void tst_QList::constructors_reserveAndInitialize() const
573 {
574  // default-initialise items
575 
576  QList<int> myInt(5, 42);
577  QVERIFY(myInt.capacity() == 5);
578  foreach (int meaningoflife, myInt) {
579  QCOMPARE(meaningoflife, 42);
580  }
581 
582  QList<QString> myString(5, QString::fromLatin1("c++"));
583  QVERIFY(myString.capacity() == 5);
584  // make sure all items are initialised ok
585  foreach (QString meaningoflife, myString) {
586  QCOMPARE(meaningoflife, QString::fromLatin1("c++"));
587  }
588 
589  QList<Custom> myCustom(5, Custom('n'));
590  QVERIFY(myCustom.capacity() == 5);
591  // make sure all items are initialised ok
592  foreach (Custom meaningoflife, myCustom) {
593  QCOMPARE(meaningoflife.i, 'n');
594  }
595 }
596 
597 template<typename T>
598 void tst_QList::copyConstructor() const
599 {
601 
602  T value1(SimpleValue<T>::at(0));
603  T value2(SimpleValue<T>::at(1));
604  T value3(SimpleValue<T>::at(2));
605  T value4(SimpleValue<T>::at(3));
606  {
607  QList<T> v1;
608  QList<T> v2(v1);
609  QCOMPARE(v1, v2);
610  }
611  {
612  QList<T> v1;
613  v1 << value1 << value2 << value3 << value4;
614  QList<T> v2(v1);
615  QCOMPARE(v1, v2);
616  }
617 }
618 
619 template<typename T>
620 void tst_QList::testAssignment() const
621 {
623 
624  QList<T> v1(5);
625  QCOMPARE(v1.size(), 5);
626  QVERIFY(v1.isDetached());
627 
628  QList<T> v2(7);
629  QCOMPARE(v2.size(), 7);
630  QVERIFY(v2.isDetached());
631 
632  QVERIFY(!v1.isSharedWith(v2));
633 
634  v1 = v2;
635 
636  QVERIFY(!v1.isDetached());
637  QVERIFY(!v2.isDetached());
638  QVERIFY(v1.isSharedWith(v2));
639 
640  const void *const data1 = v1.constData();
641  const void *const data2 = v2.constData();
642 
643  QCOMPARE(data1, data2);
644 
645  v1.clear();
646 
647  QVERIFY(v2.isDetached());
648  QVERIFY(!v1.isSharedWith(v2));
649  QCOMPARE((void *)v2.constData(), data2);
650 }
651 
652 template<typename T>
653 void tst_QList::assignFromInitializerList() const
654 {
656 
657  T val1(SimpleValue<T>::at(1));
658  T val2(SimpleValue<T>::at(2));
659  T val3(SimpleValue<T>::at(3));
660 
661  QList<T> v1 = {val1, val2, val3};
662  QCOMPARE(v1, QList<T>() << val1 << val2 << val3);
663  QCOMPARE(v1, (QList<T> {val1, val2, val3}));
664 
665  v1 = {};
666  QCOMPARE(v1.size(), 0);
667 }
668 
669 template<typename T>
670 void tst_QList::add() const
671 {
673 
674  {
675  QList<T> empty1;
676  QList<T> empty2;
677  QVERIFY((empty1 + empty2).isEmpty());
678  empty1 += empty2;
679  QVERIFY(empty1.isEmpty());
680  QVERIFY(empty2.isEmpty());
681  }
682  {
683  QList<T> v(12);
684  QList<T> empty;
685  QCOMPARE((v + empty), v);
686  v += empty;
687  QVERIFY(!v.isEmpty());
688  QCOMPARE(v.size(), 12);
689  QVERIFY(empty.isEmpty());
690  }
691  {
692  QList<T> v1(12);
693  QList<T> v2;
694  v2 += v1;
695  QVERIFY(!v1.isEmpty());
696  QCOMPARE(v1.size(), 12);
697  QVERIFY(!v2.isEmpty());
698  QCOMPARE(v2.size(), 12);
699  }
700 }
701 
702 template<typename T>
703 void tst_QList::append() const
704 {
706 
707  {
708  QList<T> myvec;
709  myvec.append(SimpleValue<T>::at(0));
710  QVERIFY(myvec.size() == 1);
711  myvec.append(SimpleValue<T>::at(1));
712  QVERIFY(myvec.size() == 2);
713  myvec.append(SimpleValue<T>::at(2));
714  QVERIFY(myvec.size() == 3);
715 
716  QCOMPARE(myvec, QList<T>() << SimpleValue<T>::at(0)
717  << SimpleValue<T>::at(1)
718  << SimpleValue<T>::at(2));
719  }
720  {
721  QList<T> v(2);
722  v.append(SimpleValue<T>::at(0));
723  QVERIFY(v.size() == 3);
724  QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0));
725  }
726  {
727  QList<T> v(2);
728  v.reserve(12);
729  v.append(SimpleValue<T>::at(0));
730  QVERIFY(v.size() == 3);
731  QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0));
732  }
733  {
734  QList<int> v;
735  v << 1 << 2 << 3;
736  QList<int> x;
737  x << 4 << 5 << 6;
738  v.append(x);
739 
740  QList<int> combined;
741  combined << 1 << 2 << 3 << 4 << 5 << 6;
742 
743  QCOMPARE(v, combined);
744  }
745  {
746  const QList<T> otherVec { SimpleValue<T>::at(0),
749  SimpleValue<T>::at(3) };
750  QList<T> myvec;
751  myvec.append(otherVec.cbegin(), otherVec.cbegin() + 3);
752  QCOMPARE(myvec.size(), 3);
753  QCOMPARE(myvec, QList<T>() << SimpleValue<T>::at(0)
754  << SimpleValue<T>::at(1)
755  << SimpleValue<T>::at(2));
756  }
757  {
758  QList<T> emptyVec;
759  QList<T> otherEmptyVec;
760 
761  emptyVec.append(otherEmptyVec);
762 
763  QVERIFY(emptyVec.isEmpty());
764  QVERIFY(!emptyVec.isDetached());
765  QVERIFY(!otherEmptyVec.isDetached());
766  }
767  {
769  QList<T> emptyVec;
770 
771  myvec.append(emptyVec);
772  QVERIFY(emptyVec.isEmpty());
773  QVERIFY(!emptyVec.isDetached());
775  }
776 }
777 
778 void tst_QList::appendRvalue() const
779 {
781  v.append("hello");
782  QString world = "world";
783  v.append(std::move(world));
784  QCOMPARE(v.front(), QString("hello"));
785  QCOMPARE(v.back(), QString("world"));
786 
787  // check append rvalue to empty list
788  QList<QString> myvec;
789  QString test = "test";
790  myvec.append(std::move(test));
791  QCOMPARE(myvec.size(), 1);
792  QCOMPARE(myvec.front(), QString("test"));
793 }
794 
795 struct ConstructionCounted
796 {
797  ConstructionCounted(int i) : i(i) { }
799  : i(other.i), copies(other.copies), moves(other.moves + 1)
800  {
801  // set to some easily noticeable values
802  other.i = -64;
803  other.copies = -64;
804  other.moves = -64;
805  }
807  {
808  i = other.i;
809  copies = other.copies;
810  moves = other.moves + 1;
811  // set to some easily noticeable values
812  other.i = -64;
813  other.copies = -64;
814  other.moves = -64;
815  return *this;
816  }
818  : i(other.i), copies(other.copies + 1), moves(other.moves)
819  {
820  }
822  {
823  i = other.i;
824  copies = other.copies + 1;
825  moves = other.moves;
826  return *this;
827  }
828  ~ConstructionCounted() = default;
829 
830  friend bool operator==(const ConstructionCounted &lhs, const ConstructionCounted &rhs)
831  {
832  return lhs.i == rhs.i;
833  }
834 
836 
837  int i;
838  int copies = 0;
839  int moves = 0;
840 };
842 namespace QTest {
844 {
845  char *str = new char[5];
846  qsnprintf(str, 4, "%d", cc.i);
847  return str;
848 }
849 }
851 
852 void tst_QList::appendList() const
853 {
854  // By const-ref
855  {
856  QList<int> v1 = { 1, 2, 3, 4 };
857  QList<int> v2 = { 5, 6, 7, 8 };
858  v1.append(v2);
859  QCOMPARE(v2.size(), 4);
860  QCOMPARE(v1.size(), 8);
861  QList<int> expected = { 1, 2, 3, 4, 5, 6, 7, 8 };
862  QCOMPARE(v1, expected);
863 
864  QList<int> doubleExpected = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
865  // append self to self
866  v1.append(v1);
867  QCOMPARE(v1.size(), 16);
868  QCOMPARE(v1, doubleExpected);
869  v1.resize(8);
870 
871  // append to self, but was shared
872  QList v1_2(v1);
873  v1.append(v1);
874  QCOMPARE(v1_2.size(), 8);
875  QCOMPARE(v1_2, expected);
876  QCOMPARE(v1.size(), 16);
877  QCOMPARE(v1, doubleExpected);
878  v1.resize(8);
879 
880  // append empty
881  QList<int> v3;
882  v1.append(v3);
883 
884  // append to empty
885  QList<int> v4;
886  v4.append(v1);
887  QCOMPARE(v4, expected);
888 
889  v1 = { 1, 2, 3, 4 };
890  // Using operators
891  // <<
892  QList<int> v5;
893  v5 << v1 << v2;
894  QCOMPARE(v5, expected);
895 
896  // +=
897  QList<int> v6;
898  v6 += v1;
899  v6 += v2;
900  QCOMPARE(v6, expected);
901 
902  // +
903  QCOMPARE(v1 + v2, expected);
904  }
905  // By move
906  {
907  QList<ConstructionCounted> v1 = { 1, 2, 3, 4 };
908  // Sanity check
909  QCOMPARE(v1.at(3).moves, 0);
910  QCOMPARE(v1.at(3).copies, 1); // because of initializer list
911 
912  QList<ConstructionCounted> v2 = { 5, 6, 7, 8 };
913  v1.append(std::move(v2));
914  QCOMPARE(v1.size(), 8);
915  QList<ConstructionCounted> expected = { 1, 2, 3, 4, 5, 6, 7, 8 };
916  QCOMPARE(v1, expected);
917  QCOMPARE(v1.at(0).copies, 1);
918  QCOMPARE(v1.at(0).moves, 1);
919 
920  QCOMPARE(v1.at(4).copies, 1); // was v2.at(0)
921  QCOMPARE(v1.at(4).moves, 1);
922 
923  // append move from empty
925  v1.append(std::move(v3));
926  QCOMPARE(v1.size(), 8);
927  QCOMPARE(v1, expected);
928 
929  for (qsizetype i = 0; i < v1.size(); ++i) {
930  const auto &counter = v1.at(i);
931  QCOMPARE(counter.copies, 1);
932  QCOMPARE(counter.moves, 1);
933  }
934 
935  // append move to empty
937  v4.reserve(64);
938  v4.append(std::move(v1));
939  QCOMPARE(v4.size(), 8);
940  QCOMPARE(v4, expected);
941 
942  for (qsizetype i = 0; i < v4.size(); ++i) {
943  const auto &counter = v4.at(i);
944  QCOMPARE(counter.copies, 1);
945  QCOMPARE(counter.moves, 2);
946  }
947 
948  QVERIFY(v4.capacity() >= 64);
949 
950  v1.swap(v4); // swap back...
951 
952  // append move from shared
953  QList<ConstructionCounted> v5 = { 1, 2, 3, 4 };
955  v1.append(std::move(v5_2));
956  QCOMPARE(v1.size(), 12);
957  QList<ConstructionCounted> expectedTwelve = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4 };
958  QCOMPARE(v1, expectedTwelve);
959  QCOMPARE(v5.size(), 4);
960  QList<ConstructionCounted> expectedFour = { 1, 2, 3, 4 };
961  QCOMPARE(v5, expectedFour);
962 
963  QCOMPARE(v5.at(0).copies, 1); // from constructing with std::initializer_list
964  QCOMPARE(v5.at(0).moves, 0);
965 
966  // Using operators
967  // <<
969  v6 << (QList<ConstructionCounted>() << 1 << 2);
970  v6 << (QList<ConstructionCounted>() << 3 << 4);
971  QCOMPARE(v6, expectedFour);
972  QCOMPARE(v6.at(0).copies, 1);
973  QCOMPARE(v6.at(0).moves, 3);
974 
975  // +=
977  v7 += (QList<ConstructionCounted>() << 1 << 2);
978  v7 += (QList<ConstructionCounted>() << 3 << 4);
979  QCOMPARE(v7, expectedFour);
980 
981  // +
983  QCOMPARE(v8 + (QList<ConstructionCounted>() << 1 << 2 << 3 << 4), expectedFour);
984  v8 = { 1, 2 };
985  QCOMPARE(v8 + (QList<ConstructionCounted>() << 3 << 4), expectedFour);
986  }
987 }
988 
989 void tst_QList::at() const
990 {
991  QList<QString> myvec;
992  myvec << "foo" << "bar" << "baz";
993 
994  QVERIFY(myvec.size() == 3);
995  QCOMPARE(myvec.at(0), QLatin1String("foo"));
996  QCOMPARE(myvec.at(1), QLatin1String("bar"));
997  QCOMPARE(myvec.at(2), QLatin1String("baz"));
998 
999  // append an item
1000  myvec << "hello";
1001  QVERIFY(myvec.size() == 4);
1002  QCOMPARE(myvec.at(0), QLatin1String("foo"));
1003  QCOMPARE(myvec.at(1), QLatin1String("bar"));
1004  QCOMPARE(myvec.at(2), QLatin1String("baz"));
1005  QCOMPARE(myvec.at(3), QLatin1String("hello"));
1006 
1007  // remove an item
1008  myvec.remove(1);
1009  QVERIFY(myvec.size() == 3);
1010  QCOMPARE(myvec.at(0), QLatin1String("foo"));
1011  QCOMPARE(myvec.at(1), QLatin1String("baz"));
1012  QCOMPARE(myvec.at(2), QLatin1String("hello"));
1013 }
1014 
1015 template<typename T>
1016 void tst_QList::capacity() const
1017 {
1019 
1020  QList<T> myvec;
1021 
1022  // TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a
1023  // few items isn't an entirely unforseeable possibility.
1024  QVERIFY(myvec.capacity() == 0);
1025  QVERIFY(!myvec.isDetached());
1026 
1027  // test it gets a size
1029  QVERIFY(myvec.capacity() >= 3);
1030 
1031  // make sure it grows ok
1033  QVERIFY(myvec.capacity() >= 6);
1034  // let's try squeeze a bit
1035  myvec.remove(3);
1036  myvec.remove(3);
1037  myvec.remove(3);
1038  myvec.squeeze();
1039  QVERIFY(myvec.capacity() >= 3);
1040 
1041  myvec.remove(0);
1042  myvec.remove(0);
1043  myvec.remove(0);
1044  myvec.squeeze();
1045  QVERIFY(myvec.capacity() == 0);
1046 }
1047 
1048 template<typename T>
1049 void tst_QList::clear() const
1050 {
1052 
1053  QList<T> myvec;
1054  myvec.clear();
1055  QVERIFY(!myvec.isDetached());
1056 
1058 
1059  const auto oldCapacity = myvec.capacity();
1060  QCOMPARE(myvec.size(), 3);
1061  myvec.clear();
1062  QCOMPARE(myvec.size(), 0);
1063  QCOMPARE(myvec.capacity(), oldCapacity);
1064 }
1065 
1066 void tst_QList::constData() const
1067 {
1068  int arr[] = { 42, 43, 44 };
1069  QList<int> myvec;
1070  QCOMPARE(myvec.constData(), nullptr);
1071  QVERIFY(!myvec.isDetached());
1072 
1073  myvec << 42 << 43 << 44;
1074 
1075  QCOMPARE(memcmp(myvec.constData(), reinterpret_cast<const int *>(&arr), sizeof(int) * 3), 0);
1076 }
1077 
1078 void tst_QList::contains() const
1079 {
1080  QList<QString> myvec;
1081 
1082  QVERIFY(!myvec.contains(QLatin1String("test")));
1083  QVERIFY(!myvec.isDetached());
1084 
1085  myvec << "aaa" << "bbb" << "ccc";
1086 
1087  QVERIFY(myvec.contains(QLatin1String("aaa")));
1088  QVERIFY(myvec.contains(QLatin1String("bbb")));
1089  QVERIFY(myvec.contains(QLatin1String("ccc")));
1090  QVERIFY(!myvec.contains(QLatin1String("I don't exist")));
1091 
1092  // add it and make sure it does :)
1093  myvec.append(QLatin1String("I don't exist"));
1094  QVERIFY(myvec.contains(QLatin1String("I don't exist")));
1095 }
1096 
1097 template<typename T>
1098 void tst_QList::count() const
1099 {
1101 
1102  // total size
1103  {
1104  // zero size
1105  QList<T> myvec;
1106  QVERIFY(myvec.count() == 0);
1107  QVERIFY(!myvec.isDetached());
1108 
1109  // grow
1110  myvec.append(SimpleValue<T>::at(0));
1111  QVERIFY(myvec.count() == 1);
1112  myvec.append(SimpleValue<T>::at(1));
1113  QVERIFY(myvec.count() == 2);
1114 
1115  // shrink
1116  myvec.remove(0);
1117  QVERIFY(myvec.count() == 1);
1118  myvec.remove(0);
1119  QVERIFY(myvec.count() == 0);
1120  }
1121 
1122  // count of items
1123  {
1124  QList<T> myvec;
1125  QCOMPARE(myvec.count(SimpleValue<T>::at(0)), 0);
1126  QVERIFY(!myvec.isDetached());
1127 
1129 
1130  // initial tests
1131  QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1);
1132  QVERIFY(myvec.count(SimpleValue<T>::at(3)) == 0);
1133 
1134  // grow
1135  myvec.append(SimpleValue<T>::at(0));
1136  QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 2);
1137 
1138  // shrink
1139  myvec.remove(0);
1140  QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1);
1141  }
1142 }
1143 
1144 void tst_QList::cpp17ctad() const
1145 {
1146 #define QVERIFY_IS_VECTOR_OF(obj, Type) \
1147  QVERIFY2((std::is_same<decltype(obj), QList<Type>>::value), \
1148  QMetaType::fromType<decltype(obj)::value_type>().name())
1149 #define CHECK(Type, One, Two, Three) \
1150  do { \
1151  const Type v[] = {One, Two, Three}; \
1152  QList v1 = {One, Two, Three}; \
1153  QVERIFY_IS_VECTOR_OF(v1, Type); \
1154  QList v2(v1.begin(), v1.end()); \
1155  QVERIFY_IS_VECTOR_OF(v2, Type); \
1156  QList v3(std::begin(v), std::end(v)); \
1157  QVERIFY_IS_VECTOR_OF(v3, Type); \
1158  } while (false) \
1159  /*end*/
1160  CHECK(int, 1, 2, 3);
1161  CHECK(double, 1.0, 2.0, 3.0);
1162  CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
1163 #undef QVERIFY_IS_VECTOR_OF
1164 #undef CHECK
1165 }
1166 
1167 void tst_QList::data() const
1168 {
1169  QList<int> myvec;
1170  QCOMPARE(myvec.data(), nullptr);
1171 
1172  myvec << 42 << 43 << 44;
1173 
1174  // make sure it starts off ok
1175  QCOMPARE(*(myvec.data() + 1), 43);
1176 
1177  // alter it
1178  *(myvec.data() + 1) = 69;
1179 
1180  // check it altered
1181  QCOMPARE(*(myvec.data() + 1), 69);
1182 
1183  int arr[] = { 42, 69, 44 };
1184  QCOMPARE(memcmp(myvec.data(), reinterpret_cast<int *>(&arr), sizeof(int) * 3), 0);
1185 
1186  const QList<int> constVec = myvec;
1187  QCOMPARE(memcmp(constVec.data(), reinterpret_cast<const int *>(&arr), sizeof(int) * 3), 0);
1188  QVERIFY(!constVec.isDetached()); // const data() does not detach()
1189 }
1190 
1191 template<typename T>
1192 void tst_QList::empty() const
1193 {
1195 
1196  QList<T> myvec;
1197 
1198  // starts empty
1199  QVERIFY(myvec.empty());
1200  QVERIFY(!myvec.isDetached());
1201 
1202  // not empty
1203  myvec.append(SimpleValue<T>::at(2));
1204  QVERIFY(!myvec.empty());
1205 
1206  // empty again
1207  myvec.remove(0);
1208  QVERIFY(myvec.empty());
1209 }
1210 
1211 void tst_QList::endsWith() const
1212 {
1213  QList<int> myvec;
1214 
1215  // empty vector
1216  QVERIFY(!myvec.endsWith(1));
1217 
1218  // add the one, should work
1219  myvec.append(1);
1220  QVERIFY(myvec.endsWith(1));
1221 
1222  // add something else, fails now
1223  myvec.append(3);
1224  QVERIFY(!myvec.endsWith(1));
1225 
1226  // remove it again :)
1227  myvec.remove(1);
1228  QVERIFY(myvec.endsWith(1));
1229 }
1230 
1231 template<typename T>
1232 void tst_QList::eraseEmpty() const
1233 {
1235 
1236  QList<T> v;
1237  v.erase(v.begin(), v.end());
1238  QCOMPARE(v.size(), 0);
1239 }
1240 
1241 template<typename T>
1242 void tst_QList::eraseEmptyReserved() const
1243 {
1245 
1246  QList<T> v;
1247  v.reserve(10);
1248  v.erase(v.begin(), v.end());
1249  QCOMPARE(v.size(), 0);
1250 }
1251 
1252 template<typename T>
1254 {
1255  SharedVectorChecker(const QList<T> &original, bool doCopyVector)
1256  : originalSize(-1),
1257  copy(0)
1258  {
1259  if (doCopyVector) {
1260  originalSize = original.size();
1261  copy = new QList<T>(original);
1262  // this is unlikely to fail, but if the check in the destructor fails it's good to know that
1263  // we were still alright here.
1264  QCOMPARE(originalSize, copy->size());
1265  }
1266  }
1267 
1269  {
1270  if (copy)
1271  QCOMPARE(copy->size(), originalSize);
1272  delete copy;
1273  }
1274 
1277 };
1278 
1279 template<typename T>
1280 void tst_QList::erase(bool shared) const
1281 {
1283 
1284  // note: remove() is actually more efficient, and more dangerous, because it uses the
1285  // non-detaching begin() / end() internally. you can also use constBegin() and constEnd() with
1286  // erase(), but only using reinterpret_cast... because both iterator types are really just
1287  // pointers. so we use a mix of erase() and remove() to cover more cases.
1288  {
1290  SharedVectorChecker<T> svc(v, shared);
1291  v.erase(v.begin());
1292  QCOMPARE(v.size(), 11);
1293  for (int i = 0; i < 11; i++)
1294  QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1));
1295  v.erase(v.begin(), v.end());
1296  QCOMPARE(v.size(), 0);
1297  if (shared)
1299  }
1300  {
1302  SharedVectorChecker<T> svc(v, shared);
1303  v.remove(1);
1304  QCOMPARE(v.size(), 11);
1305  QCOMPARE(v.at(0), SimpleValue<T>::at(0));
1306  for (int i = 1; i < 11; i++)
1307  QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1));
1308  v.erase(v.begin() + 1, v.end());
1309  QCOMPARE(v.size(), 1);
1310  QCOMPARE(v.at(0), SimpleValue<T>::at(0));
1311  if (shared)
1312  QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1313  }
1314  {
1316  SharedVectorChecker<T> svc(v, shared);
1317  v.erase(v.begin(), v.end() - 1);
1318  QCOMPARE(v.size(), 1);
1319  QCOMPARE(v.at(0), SimpleValue<T>::at(11));
1320  if (shared)
1321  QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1322  }
1323  {
1325  SharedVectorChecker<T> svc(v, shared);
1326  v.remove(5);
1327  QCOMPARE(v.size(), 11);
1328  for (int i = 0; i < 5; i++)
1329  QCOMPARE(v.at(i), SimpleValue<T>::at(i));
1330  for (int i = 5; i < 11; i++)
1331  QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1));
1332  v.erase(v.begin() + 1, v.end() - 1);
1333  QCOMPARE(v.at(0), SimpleValue<T>::at(0));
1334  QCOMPARE(v.at(1), SimpleValue<T>::at(11));
1335  QCOMPARE(v.size(), 2);
1336  if (shared)
1337  QCOMPARE(SimpleValue<T>::vector(12), *svc.copy);
1338  }
1339 }
1340 
1341 template<typename T>
1342 void tst_QList::eraseReserved() const
1343 {
1345 
1346  {
1347  QList<T> v(12);
1348  v.reserve(16);
1349  v.erase(v.begin());
1350  QCOMPARE(v.size(), 11);
1351  v.erase(v.begin(), v.end());
1352  QCOMPARE(v.size(), 0);
1353  }
1354  {
1355  QList<T> v(12);
1356  v.reserve(16);
1357  v.erase(v.begin() + 1);
1358  QCOMPARE(v.size(), 11);
1359  v.erase(v.begin() + 1, v.end());
1360  QCOMPARE(v.size(), 1);
1361  }
1362  {
1363  QList<T> v(12);
1364  v.reserve(16);
1365  v.erase(v.begin(), v.end() - 1);
1366  QCOMPARE(v.size(), 1);
1367  }
1368  {
1369  QList<T> v(12);
1370  v.reserve(16);
1371  v.erase(v.begin() + 5);
1372  QCOMPARE(v.size(), 11);
1373  v.erase(v.begin() + 1, v.end() - 1);
1374  QCOMPARE(v.size(), 2);
1375  }
1376 }
1377 
1378 template<typename T>
1379 void tst_QList::fill() const
1380 {
1382 
1383  QList<T> myvec;
1384 
1385  // fill an empty list - it should resize
1386  myvec.fill(SimpleValue<T>::at(1), 2);
1388 
1389  // resize
1390  myvec.resize(5);
1391  myvec.fill(SimpleValue<T>::at(1));
1394  << SimpleValue<T>::at(1));
1395 
1396  // make sure it can resize itself too
1397  myvec.fill(SimpleValue<T>::at(2), 10);
1403 
1404  // make sure it can resize to smaller size as well
1405  myvec.fill(SimpleValue<T>::at(3), 2);
1407 }
1408 
1409 template<typename T>
1410 void tst_QList::fillDetach() const
1411 {
1413 
1414  // detaches to the same size
1415  {
1417  QList<T> copy = original;
1418  copy.fill(SimpleValue<T>::at(2));
1419 
1420  QCOMPARE(original,
1422  QCOMPARE(copy,
1424  }
1425 
1426  // detaches and grows in size
1427  {
1429  QList<T> copy = original;
1430  copy.fill(SimpleValue<T>::at(2), 5);
1431 
1432  QCOMPARE(original,
1434  QCOMPARE(copy,
1437  }
1438 
1439  // detaches and shrinks in size
1440  {
1442  QList<T> copy = original;
1443  copy.fill(SimpleValue<T>::at(2), 1);
1444 
1445  QCOMPARE(original,
1447  QCOMPARE(copy, QList<T>({ SimpleValue<T>::at(2) }));
1448  }
1449 }
1450 
1451 void tst_QList::first() const
1452 {
1453  QList<int> myvec;
1454  myvec << 69 << 42 << 3;
1455 
1456  // test it starts ok
1457  QCOMPARE(myvec.first(), 69);
1458  QCOMPARE(myvec.constFirst(), 69);
1459 
1460  // test removal changes
1461  myvec.remove(0);
1462  QCOMPARE(myvec.first(), 42);
1463  QCOMPARE(myvec.constFirst(), 42);
1464 
1465  // test prepend changes
1466  myvec.prepend(23);
1467  QCOMPARE(myvec.first(), 23);
1468  QCOMPARE(myvec.constFirst(), 23);
1469 
1470 
1472  QCOMPARE(myvec.first(0), QList<int>());
1473  QCOMPARE(myvec.first(1), (QList<int>{23}));
1474  QCOMPARE(myvec.first(2), (QList<int>{23, 42}));
1475  QCOMPARE(myvec.first(3), myvec);
1476 }
1477 
1478 void tst_QList::constFirst() const
1479 {
1480  QList<int> myvec;
1481  myvec << 69 << 42 << 3;
1482 
1483  // test it starts ok
1484  QCOMPARE(myvec.constFirst(), 69);
1485  QVERIFY(myvec.isDetached());
1486 
1487  QList<int> myvecCopy = myvec;
1488  QVERIFY(!myvec.isDetached());
1489  QVERIFY(!myvecCopy.isDetached());
1490  QVERIFY(myvec.isSharedWith(myvecCopy));
1491  QVERIFY(myvecCopy.isSharedWith(myvec));
1492 
1493  QCOMPARE(myvec.constFirst(), 69);
1494  QCOMPARE(myvecCopy.constFirst(), 69);
1495 
1496  QVERIFY(!myvec.isDetached());
1497  QVERIFY(!myvecCopy.isDetached());
1498  QVERIFY(myvec.isSharedWith(myvecCopy));
1499  QVERIFY(myvecCopy.isSharedWith(myvec));
1500 
1501  // test removal changes
1502  myvec.remove(0);
1503  QVERIFY(myvec.isDetached());
1504  QVERIFY(!myvec.isSharedWith(myvecCopy));
1505  QCOMPARE(myvec.constFirst(), 42);
1506  QCOMPARE(myvecCopy.constFirst(), 69);
1507 
1508  myvecCopy = myvec;
1509  QVERIFY(!myvec.isDetached());
1510  QVERIFY(!myvecCopy.isDetached());
1511  QVERIFY(myvec.isSharedWith(myvecCopy));
1512  QVERIFY(myvecCopy.isSharedWith(myvec));
1513 
1514  QCOMPARE(myvec.constFirst(), 42);
1515  QCOMPARE(myvecCopy.constFirst(), 42);
1516 
1517  QVERIFY(!myvec.isDetached());
1518  QVERIFY(!myvecCopy.isDetached());
1519  QVERIFY(myvec.isSharedWith(myvecCopy));
1520  QVERIFY(myvecCopy.isSharedWith(myvec));
1521 
1522  // test prepend changes
1523  myvec.prepend(23);
1524  QVERIFY(myvec.isDetached());
1525  QVERIFY(!myvec.isSharedWith(myvecCopy));
1526  QCOMPARE(myvec.constFirst(), 23);
1527  QCOMPARE(myvecCopy.constFirst(), 42);
1528 
1529  myvecCopy = myvec;
1530  QVERIFY(!myvec.isDetached());
1531  QVERIFY(!myvecCopy.isDetached());
1532  QVERIFY(myvec.isSharedWith(myvecCopy));
1533  QVERIFY(myvecCopy.isSharedWith(myvec));
1534 
1535  QCOMPARE(myvec.constFirst(), 23);
1536  QCOMPARE(myvecCopy.constFirst(), 23);
1537 
1538  QVERIFY(!myvec.isDetached());
1539  QVERIFY(!myvecCopy.isDetached());
1540  QVERIFY(myvec.isSharedWith(myvecCopy));
1541  QVERIFY(myvecCopy.isSharedWith(myvec));
1542 }
1543 
1544 
1545 template<typename T>
1546 void tst_QList::fromList() const
1547 {
1549 
1550  QList<T> list;
1552 
1553  QList<T> myvec;
1554  myvec = QList<T>::fromList(list);
1555 
1556  // test it worked ok
1559 }
1560 
1561 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1562 void tst_QList::fromStdVector() const
1563 {
1564  // stl = :(
1565  std::vector<QString> svec;
1566  svec.push_back(QLatin1String("aaa"));
1567  svec.push_back(QLatin1String("bbb"));
1568  svec.push_back(QLatin1String("ninjas"));
1569  svec.push_back(QLatin1String("pirates"));
1571 
1572  // test it converts ok
1573  QCOMPARE(myvec, QList<QString>() << "aaa" << "bbb" << "ninjas" << "pirates");
1574 }
1575 #endif
1576 
1577 void tst_QList::indexOf() const
1578 {
1579  QList<QString> myvec;
1580 
1581  QCOMPARE(myvec.indexOf("A"), -1);
1582  QCOMPARE(myvec.indexOf("A", 5), -1);
1583  QVERIFY(!myvec.isDetached());
1584 
1585  myvec << "A" << "B" << "C" << "B" << "A";
1586 
1587  QVERIFY(myvec.indexOf("B") == 1);
1588  QVERIFY(myvec.indexOf("B", 1) == 1);
1589  QVERIFY(myvec.indexOf("B", 2) == 3);
1590  QVERIFY(myvec.indexOf("X") == -1);
1591  QVERIFY(myvec.indexOf("X", 2) == -1);
1592 
1593  // add an X
1594  myvec << "X";
1595  QVERIFY(myvec.indexOf("X") == 5);
1596  QVERIFY(myvec.indexOf("X", 5) == 5);
1597  QVERIFY(myvec.indexOf("X", 6) == -1);
1598 
1599  // remove first A
1600  myvec.remove(0);
1601  QVERIFY(myvec.indexOf("A") == 3);
1602  QVERIFY(myvec.indexOf("A", 3) == 3);
1603  QVERIFY(myvec.indexOf("A", 4) == -1);
1604 }
1605 
1606 template <typename T>
1607 void tst_QList::insert() const
1608 {
1610 
1611  QList<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  QList<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, QList<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, QList<T>() << tB << tX << tZ << ti << ti
1666  << tA << tB << tC << tT);
1667  QCOMPARE(myvec2, myvec);
1668 
1669  myvec.insert(0, 1, const_cast<const QList<T>&>(myvec)[0]); // inserts tB
1670  myvec2.insert(0, 1, const_cast<const QList<T>&>(myvec2)[0]); // inserts tB
1671  QCOMPARE(myvec, QList<T>() << tB << tB << tX << tZ << ti << ti
1672  << tA << tB << tC << tT);
1673  QCOMPARE(myvec2, myvec);
1674 
1675  // Different insert() into empty list overloads
1676  {
1677  QList<T> myvec;
1678  auto it = myvec.insert(0, tA);
1679  QCOMPARE(myvec.size(), 1);
1680  QCOMPARE(myvec.front(), tA);
1681  QCOMPARE(it, myvec.begin());
1682  }
1683  {
1684  QList<T> myvec;
1685  auto it = myvec.insert(0, 3, tX);
1686  QCOMPARE(myvec.size(), 3);
1687  QCOMPARE(myvec, QList<T>({ tX, tX, tX }));
1688  QCOMPARE(it, myvec.begin());
1689  }
1690  {
1691  QList<T> myvec;
1692  auto it = myvec.insert(myvec.cbegin(), tA);
1693  QCOMPARE(myvec.size(), 1);
1694  QCOMPARE(myvec.front(), tA);
1695  QCOMPARE(it, myvec.begin());
1696  }
1697  {
1698  QList<T> myvec;
1699  auto it = myvec.insert(myvec.cbegin(), 3, tX);
1700  QCOMPARE(myvec.size(), 3);
1701  QCOMPARE(myvec, QList<T>({ tX, tX, tX }));
1702  QCOMPARE(it, myvec.begin());
1703  }
1704  {
1705  QList<QString> myvec;
1706  QString test = "test";
1707  auto it = myvec.insert(0, std::move(test));
1708  QCOMPARE(myvec.size(), 1);
1709  QCOMPARE(myvec.front(), u"test");
1710  QCOMPARE(it, myvec.begin());
1711  }
1712  {
1713  QList<QString> myvec;
1714  QString test = "test";
1715  auto it = myvec.insert(myvec.cbegin(), std::move(test));
1716  QCOMPARE(myvec.size(), 1);
1717  QCOMPARE(myvec.front(), u"test");
1718  QCOMPARE(it, myvec.begin());
1719  }
1720 }
1721 
1722 void tst_QList::insertZeroCount_data()
1723 {
1724  QTest::addColumn<int>("pos");
1725  QTest::newRow("0") << 0;
1726  QTest::newRow("1") << 1;
1727 }
1728 
1729 void tst_QList::insertZeroCount() const
1730 {
1731  QFETCH(int, pos);
1732  QList<int> x;
1733  x << 0 << 0;
1734  x.insert(pos, 0, 1);
1735  QCOMPARE(x[pos], 0);
1736  QList<int> y;
1737  y = x;
1738  y.insert(pos, 0, 2);
1739  QCOMPARE(y[pos], 0);
1740 }
1741 
1742 void tst_QList::isEmpty() const
1743 {
1744  QList<QString> myvec;
1745 
1746  // starts ok
1747  QVERIFY(myvec.isEmpty());
1748  QVERIFY(!myvec.isDetached());
1749 
1750  // not empty now
1751  myvec.append(QLatin1String("hello there"));
1752  QVERIFY(!myvec.isEmpty());
1753 
1754  // empty again
1755  myvec.remove(0);
1756  QVERIFY(myvec.isEmpty());
1757 }
1758 
1759 void tst_QList::last() const
1760 {
1761  QList<QString> myvec;
1762  myvec << "A" << "B" << "C";
1763 
1764  // test starts ok
1765  QCOMPARE(myvec.last(), QLatin1String("C"));
1766  QCOMPARE(myvec.constLast(), QLatin1String("C"));
1767 
1768  // test it changes ok
1769  myvec.append(QLatin1String("X"));
1770  QCOMPARE(myvec.last(), QLatin1String("X"));
1771  QCOMPARE(myvec.constLast(), QLatin1String("X"));
1772 
1773  // and remove again
1774  myvec.remove(3);
1775  QCOMPARE(myvec.last(), QLatin1String("C"));
1776  QCOMPARE(myvec.constLast(), QLatin1String("C"));
1777 
1778  QCOMPARE(QList<QString>().last(0), QList<QString>());
1779  QCOMPARE(myvec.last(0), QList<QString>());
1780  QCOMPARE(myvec.last(1), (QList<QString>{QLatin1String("C")}));
1781  QCOMPARE(myvec.last(2), (QList<QString>{QLatin1String("B"), QLatin1String("C")}));
1782  QCOMPARE(myvec.last(3), myvec);
1783 }
1784 
1785 void tst_QList::constLast() const
1786 {
1787  QList<int> myvec;
1788  myvec << 69 << 42 << 3;
1789 
1790  // test it starts ok
1791  QCOMPARE(myvec.constLast(), 3);
1792  QVERIFY(myvec.isDetached());
1793 
1794  QList<int> myvecCopy = myvec;
1795  QVERIFY(!myvec.isDetached());
1796  QVERIFY(!myvecCopy.isDetached());
1797  QVERIFY(myvec.isSharedWith(myvecCopy));
1798  QVERIFY(myvecCopy.isSharedWith(myvec));
1799 
1800  QCOMPARE(myvec.constLast(), 3);
1801  QCOMPARE(myvecCopy.constLast(), 3);
1802 
1803  QVERIFY(!myvec.isDetached());
1804  QVERIFY(!myvecCopy.isDetached());
1805  QVERIFY(myvec.isSharedWith(myvecCopy));
1806  QVERIFY(myvecCopy.isSharedWith(myvec));
1807 
1808  // test removal changes
1809  myvec.removeLast();
1810  QVERIFY(myvec.isDetached());
1811  QVERIFY(!myvec.isSharedWith(myvecCopy));
1812  QCOMPARE(myvec.constLast(), 42);
1813  QCOMPARE(myvecCopy.constLast(), 3);
1814 
1815  myvecCopy = myvec;
1816  QVERIFY(!myvec.isDetached());
1817  QVERIFY(!myvecCopy.isDetached());
1818  QVERIFY(myvec.isSharedWith(myvecCopy));
1819  QVERIFY(myvecCopy.isSharedWith(myvec));
1820 
1821  QCOMPARE(myvec.constLast(), 42);
1822  QCOMPARE(myvecCopy.constLast(), 42);
1823 
1824  QVERIFY(!myvec.isDetached());
1825  QVERIFY(!myvecCopy.isDetached());
1826  QVERIFY(myvec.isSharedWith(myvecCopy));
1827  QVERIFY(myvecCopy.isSharedWith(myvec));
1828 
1829  // test prepend changes
1830  myvec.append(23);
1831  QVERIFY(myvec.isDetached());
1832  QVERIFY(!myvec.isSharedWith(myvecCopy));
1833  QCOMPARE(myvec.constLast(), 23);
1834  QCOMPARE(myvecCopy.constLast(), 42);
1835 
1836  myvecCopy = myvec;
1837  QVERIFY(!myvec.isDetached());
1838  QVERIFY(!myvecCopy.isDetached());
1839  QVERIFY(myvec.isSharedWith(myvecCopy));
1840  QVERIFY(myvecCopy.isSharedWith(myvec));
1841 
1842  QCOMPARE(myvec.constLast(), 23);
1843  QCOMPARE(myvecCopy.constLast(), 23);
1844 
1845  QVERIFY(!myvec.isDetached());
1846  QVERIFY(!myvecCopy.isDetached());
1847  QVERIFY(myvec.isSharedWith(myvecCopy));
1848  QVERIFY(myvecCopy.isSharedWith(myvec));
1849 }
1850 
1851 void tst_QList::lastIndexOf() const
1852 {
1853  QList<QString> myvec;
1854 
1855  QCOMPARE(myvec.lastIndexOf("A"), -1);
1856  QCOMPARE(myvec.lastIndexOf("A", 5), -1);
1857  QVERIFY(!myvec.isDetached());
1858 
1859  myvec << "A" << "B" << "C" << "B" << "A";
1860 
1861  QVERIFY(myvec.lastIndexOf("B") == 3);
1862  QVERIFY(myvec.lastIndexOf("B", 2) == 1);
1863  QVERIFY(myvec.lastIndexOf("X") == -1);
1864  QVERIFY(myvec.lastIndexOf("X", 2) == -1);
1865 
1866  // add an X
1867  myvec << "X";
1868  QVERIFY(myvec.lastIndexOf("X") == 5);
1869  QVERIFY(myvec.lastIndexOf("X", 5) == 5);
1870  QVERIFY(myvec.lastIndexOf("X", 3) == -1);
1871 
1872  // remove first A
1873  myvec.remove(0);
1874  QVERIFY(myvec.lastIndexOf("A") == 3);
1875  QVERIFY(myvec.lastIndexOf("A", 3) == 3);
1876  QVERIFY(myvec.lastIndexOf("A", 2) == -1);
1877 }
1878 
1879 void tst_QList::mid() const
1880 {
1882 
1883  QCOMPARE(list.mid(4, 2), QList<QString>());
1884  QCOMPARE(list.mid(0, 3), QList<QString>());
1885  QCOMPARE(list.mid(-2, 3), QList<QString>());
1886  QVERIFY(!list.isDetached());
1887 
1888  list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty";
1889 
1890  QCOMPARE(list.mid(3, 3), QList<QString>() << "bak" << "buck" << "hello");
1891  QCOMPARE(list.mid(6, 10), QList<QString>() << "kitty");
1892  QCOMPARE(list.mid(-1, 20), list);
1893  QCOMPARE(list.mid(4), QList<QString>() << "buck" << "hello" << "kitty");
1894 }
1895 
1896 void tst_QList::sliced() const
1897 {
1899  list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty";
1900 
1901  QCOMPARE(QList<QString>().sliced(0), QList<QString>());
1902  QCOMPARE(QList<QString>().sliced(0, 0), QList<QString>());
1903  QCOMPARE(list.sliced(3, 3), QList<QString>() << "bak" << "buck" << "hello");
1904  QCOMPARE(list.sliced(3), QList<QString>() << "bak" << "buck" << "hello" << "kitty");
1905  QCOMPARE(list.sliced(6, 1), QList<QString>() << "kitty");
1906  QCOMPARE(list.sliced(6), QList<QString>() << "kitty");
1907  QCOMPARE(list.sliced(0, list.size()), list);
1908  QCOMPARE(list.sliced(0), list);
1909  QCOMPARE(list.sliced(4), QList<QString>() << "buck" << "hello" << "kitty");
1910 }
1911 
1912 template <typename T>
1913 void tst_QList::qhash() const
1914 {
1916 
1917  QList<T> l1, l2;
1918  QCOMPARE(qHash(l1), qHash(l2));
1921  QCOMPARE(qHash(l1), qHash(l2));
1922 }
1923 
1924 template <typename T>
1925 void tst_QList::move() const
1926 {
1928 
1929  QList<T> list;
1930  list << T_FOO << T_BAR << T_BAZ;
1931 
1932  // move an item
1933  list.move(0, list.count() - 1);
1934  QCOMPARE(list, QList<T>() << T_BAR << T_BAZ << T_FOO);
1935 
1936  // move it back
1937  list.move(list.count() - 1, 0);
1938  QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
1939 
1940  // move an item in the middle
1941  list.move(1, 0);
1942  QCOMPARE(list, QList<T>() << T_BAR << T_FOO << T_BAZ);
1943 }
1944 
1945 template<typename T>
1946 void tst_QList::prepend() const
1947 {
1949 
1950  QList<T> myvec;
1951 
1952  T val1 = SimpleValue<T>::at(0);
1953  T val2 = SimpleValue<T>::at(1);
1954  T val3 = SimpleValue<T>::at(2);
1955  T val4 = SimpleValue<T>::at(3);
1956  T val5 = SimpleValue<T>::at(4);
1957 
1958  // prepend to default-constructed empty list
1959  myvec.prepend(val1);
1960  QCOMPARE(myvec.size(), 1);
1961  QCOMPARE(myvec.at(0), val1);
1962  myvec.clear();
1963 
1964  myvec << val1 << val2 << val3;
1965 
1966  // starts ok
1967  QVERIFY(myvec.size() == 3);
1968  QCOMPARE(myvec.at(0), val1);
1969 
1970  // add something
1971  myvec.prepend(val4);
1972  QCOMPARE(myvec.at(0), val4);
1973  QCOMPARE(myvec.at(1), val1);
1974  QVERIFY(myvec.size() == 4);
1975 
1976  // something else
1977  myvec.prepend(val5);
1978  QCOMPARE(myvec.at(0), val5);
1979  QCOMPARE(myvec.at(1), val4);
1980  QCOMPARE(myvec.at(2), val1);
1981  QVERIFY(myvec.size() == 5);
1982 
1983  // clear and prepend to an empty vector
1984  myvec.clear();
1985  QVERIFY(myvec.size() == 0);
1986  myvec.prepend(val5);
1987  QVERIFY(myvec.size() == 1);
1988  QCOMPARE(myvec.at(0), val5);
1989 }
1990 
1991 void tst_QList::prependRvalue() const
1992 {
1993  QList<QString> myvec;
1994 
1995  QString hello = "hello";
1996  QString world = "world";
1997 
1998  myvec.prepend(std::move(world));
1999  QCOMPARE(myvec.size(), 1);
2000 
2001  myvec.prepend(std::move(hello));
2002  QCOMPARE(myvec.size(), 2);
2003  QCOMPARE(myvec, QList<QString>({ "hello", "world" }));
2004 }
2005 
2006 void tst_QList::removeAllWithAlias() const
2007 {
2009  strings << "One" << "Two" << "Three" << "One" /* must be distinct, but equal */;
2010  QCOMPARE(strings.removeAll(strings.front()), 2); // will trigger asan/ubsan
2011 }
2012 
2013 template<typename T>
2014 void tst_QList::remove() const
2015 {
2017 
2018  QList<T> myvec;
2019  T val1 = SimpleValue<T>::at(1);
2020  T val2 = SimpleValue<T>::at(2);
2021  T val3 = SimpleValue<T>::at(3);
2022  T val4 = SimpleValue<T>::at(4);
2023  T val5 = SimpleValue<T>::at(5);
2024 
2025  // some operations on empty list
2026  QVERIFY(!myvec.removeOne(val1));
2027  QCOMPARE(myvec.removeAll(val2), 0);
2028  auto count = myvec.removeIf([](const T&) { return true; });
2029  QCOMPARE(count, 0);
2030 
2031  myvec << val1 << val2 << val3 << val4;
2032  myvec << val1 << val2 << val3 << val4;
2033  myvec << val1 << val2 << val3 << val4;
2034  // remove by index
2035  myvec.remove(1);
2036  QCOMPARE(myvec, QList<T>({ val1, val3, val4, val1, val2, val3, val4, val1, val2, val3, val4 }));
2037  myvec.removeAt(6);
2038  QCOMPARE(myvec, QList<T>({ val1, val3, val4, val1, val2, val3, val1, val2, val3, val4 }));
2039 
2040  // removeOne()
2041  QVERIFY(!myvec.removeOne(val5));
2042  QVERIFY(myvec.removeOne(val2));
2043  QCOMPARE(myvec, QList<T>({ val1, val3, val4, val1, val3, val1, val2, val3, val4 }));
2044 
2045  QList<T> myvecCopy = myvec;
2046  QVERIFY(myvecCopy.isSharedWith(myvec));
2047  // removeAll()
2048  QCOMPARE(myvec.removeAll(val5), 0);
2049  QVERIFY(myvecCopy.isSharedWith(myvec));
2050  QCOMPARE(myvec.removeAll(val1), 3);
2051  QVERIFY(!myvecCopy.isSharedWith(myvec));
2052  QCOMPARE(myvec, QList<T>({ val3, val4, val3, val2, val3, val4 }));
2053  QCOMPARE(myvecCopy, QList<T>({ val1, val3, val4, val1, val3, val1, val2, val3, val4 }));
2054  myvecCopy = myvec;
2055  QVERIFY(myvecCopy.isSharedWith(myvec));
2056  QCOMPARE(myvec.removeAll(val2), 1);
2057  QVERIFY(!myvecCopy.isSharedWith(myvec));
2058  QCOMPARE(myvec, QList<T>({ val3, val4, val3, val3, val4 }));
2059  QCOMPARE(myvecCopy, QList<T>({ val3, val4, val3, val2, val3, val4 }));
2060 
2061  // removeIf
2062  count = myvec.removeIf([&val4](const T &val) { return val == val4; });
2063  QCOMPARE(count, 2);
2064  QCOMPARE(myvec, QList<T>({ val3, val3, val3 }));
2065 
2066  // remove rest
2067  myvec.remove(0, 3);
2068  QCOMPARE(myvec, QList<T>());
2069 }
2070 
2072 {
2073  RemoveLastTestClass() { other = 0; deleted = false; }
2075  bool deleted;
2077  {
2078  deleted = true;
2079  if (other)
2080  other->other = 0;
2081  }
2082 };
2083 
2084 void tst_QList::removeFirstLast() const
2085 {
2086  // pop_pack - pop_front
2087  QList<int> t, t2;
2088  t.append(1);
2089  t.append(2);
2090  t.append(3);
2091  t.append(4);
2092  t2 = t;
2093  t.pop_front();
2094  QCOMPARE(t.size(), 3);
2095  QCOMPARE(t.at(0), 2);
2096  t.pop_back();
2097  QCOMPARE(t.size(), 2);
2098  QCOMPARE(t.at(0), 2);
2099  QCOMPARE(t.at(1), 3);
2100 
2101  // takefirst - takeLast
2102  int n1 = t2.takeLast();
2103  QCOMPARE(t2.size(), 3);
2104  QCOMPARE(n1, 4);
2105  QCOMPARE(t2.at(0), 1);
2106  QCOMPARE(t2.at(2), 3);
2107  n1 = t2.takeFirst();
2108  QCOMPARE(t2.size(), 2);
2109  QCOMPARE(n1, 1);
2110  QCOMPARE(t2.at(0), 2);
2111  QCOMPARE(t2.at(1), 3);
2112 
2113  // remove first
2114  QList<int> x, y;
2115  x.append(1);
2116  x.append(2);
2117  y = x;
2118  x.removeFirst();
2119  QCOMPARE(x.size(), 1);
2120  QCOMPARE(y.size(), 2);
2121  QCOMPARE(x.at(0), 2);
2122 
2123  // remove Last
2125  v.resize(2);
2126  v[0].other = &(v[1]);
2127  v[1].other = &(v[0]);
2128  // Check dtor - complex type
2129  QVERIFY(v.at(0).other != 0);
2130  v.removeLast();
2131  QVERIFY(v.at(0).other == 0);
2132  QCOMPARE(v.at(0).deleted, false);
2133  // check iterator
2134  int count = 0;
2135  for (QList<RemoveLastTestClass>::const_iterator i = v.constBegin(); i != v.constEnd(); ++i) {
2136  ++count;
2137  QVERIFY(i->other == 0);
2138  QCOMPARE(i->deleted, false);
2139  }
2140  // Check size
2141  QCOMPARE(count, 1);
2142  QCOMPARE(v.size(), 1);
2143  v.removeLast();
2144  QCOMPARE(v.size(), 0);
2145  // Check if we do correct realloc
2146  QList<int> v2, v3;
2147  v2.append(1);
2148  v2.append(2);
2149  v3 = v2; // shared
2150  v2.removeLast();
2151  QCOMPARE(v2.size(), 1);
2152  QCOMPARE(v3.size(), 2);
2153  QCOMPARE(v2.at(0), 1);
2154  QCOMPARE(v3.at(0), 1);
2155  QCOMPARE(v3.at(1), 2);
2156 
2157  // Remove last with shared
2158  QList<int> z1, z2;
2159  z1.append(9);
2160  z2 = z1;
2161  z1.removeLast();
2162  QCOMPARE(z1.size(), 0);
2163  QCOMPARE(z2.size(), 1);
2164  QCOMPARE(z2.at(0), 9);
2165 }
2166 
2167 
2168 void tst_QList::resizePOD_data() const
2169 {
2170  QTest::addColumn<QList<int> >("vector");
2171  QTest::addColumn<int>("size");
2172 
2175 
2176  QList<int> null;
2177  QList<int> empty(0, 5);
2178  QList<int> emptyReserved;
2179  QList<int> nonEmpty;
2180  QList<int> nonEmptyReserved;
2181 
2182  emptyReserved.reserve(10);
2183  nonEmptyReserved.reserve(15);
2184  nonEmpty << 0 << 1 << 2 << 3 << 4;
2185  nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6;
2186  QVERIFY(emptyReserved.capacity() >= 10);
2187  QVERIFY(nonEmptyReserved.capacity() >= 15);
2188 
2189  QTest::newRow("null") << null << 10;
2190  QTest::newRow("null and 0 size") << null << 0;
2191  QTest::newRow("empty") << empty << 10;
2192  QTest::newRow("empty and 0 size") << empty << 0;
2193  QTest::newRow("emptyReserved") << emptyReserved << 10;
2194  QTest::newRow("nonEmpty") << nonEmpty << 10;
2195  QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10;
2196 }
2197 
2198 void tst_QList::resizePOD() const
2199 {
2201  QFETCH(int, size);
2202 
2203  const int oldSize = vector.size();
2204 
2205  vector.resize(size);
2206  QCOMPARE(vector.size(), size);
2207  QVERIFY(vector.capacity() >= size);
2208  if (vector.isEmpty())
2210 
2211  for (int i = oldSize; i < size; ++i)
2212  QVERIFY(vector[i] == 0); // check initialization
2213 
2214  const int capacity = vector.capacity();
2215 
2216  vector.clear();
2217  QCOMPARE(vector.size(), 0);
2218  QVERIFY(vector.capacity() <= capacity);
2219 }
2220 
2221 void tst_QList::resizeComplexMovable_data() const
2222 {
2223  QTest::addColumn<QList<Movable> >("vector");
2224  QTest::addColumn<int>("size");
2225 
2228 
2229  QList<Movable> null;
2230  QList<Movable> empty(0, 'Q');
2231  QList<Movable> emptyReserved;
2232  QList<Movable> nonEmpty;
2233  QList<Movable> nonEmptyReserved;
2234 
2235  emptyReserved.reserve(10);
2236  nonEmptyReserved.reserve(15);
2237  nonEmpty << '0' << '1' << '2' << '3' << '4';
2238  nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2239  QVERIFY(emptyReserved.capacity() >= 10);
2240  QVERIFY(nonEmptyReserved.capacity() >= 15);
2241 
2242  QTest::newRow("null") << null << 10;
2243  QTest::newRow("null and 0 size") << null << 0;
2244  QTest::newRow("empty") << empty << 10;
2245  QTest::newRow("empty and 0 size") << empty << 0;
2246  QTest::newRow("emptyReserved") << emptyReserved << 10;
2247  QTest::newRow("nonEmpty") << nonEmpty << 10;
2248  QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10;
2249 }
2250 
2251 void tst_QList::resizeComplexMovable() const
2252 {
2253  const int items = Movable::counter.loadAcquire();
2254  {
2256  QFETCH(int, size);
2257 
2258  const int oldSize = vector.size();
2259 
2260  vector.resize(size);
2261  QCOMPARE(vector.size(), size);
2262  QVERIFY(vector.capacity() >= size);
2263  if (vector.isEmpty())
2265  for (int i = oldSize; i < size; ++i)
2266  QVERIFY(vector[i] == 'j'); // check initialization
2267 
2268  const int capacity = vector.capacity();
2269 
2270  vector.resize(0);
2271  QCOMPARE(vector.size(), 0);
2272  QVERIFY(vector.capacity() <= capacity);
2273  }
2274  QCOMPARE(items, Movable::counter.loadAcquire());
2275 }
2276 
2277 void tst_QList::resizeComplex_data() const
2278 {
2279  QTest::addColumn<QList<Custom> >("vector");
2280  QTest::addColumn<int>("size");
2281 
2284 
2285  QList<Custom> null;
2286  QList<Custom> empty(0, '0');
2287  QList<Custom> emptyReserved;
2288  QList<Custom> nonEmpty;
2289  QList<Custom> nonEmptyReserved;
2290 
2291  emptyReserved.reserve(10);
2292  nonEmptyReserved.reserve(15);
2293  nonEmpty << '0' << '1' << '2' << '3' << '4';
2294  nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2295  QVERIFY(emptyReserved.capacity() >= 10);
2296  QVERIFY(nonEmptyReserved.capacity() >= 15);
2297 
2298  QTest::newRow("null") << null << 10;
2299  QTest::newRow("null and 0 size") << null << 0;
2300  QTest::newRow("empty") << empty << 10;
2301  QTest::newRow("empty and 0 size") << empty << 0;
2302  QTest::newRow("emptyReserved") << emptyReserved << 10;
2303  QTest::newRow("nonEmpty") << nonEmpty << 10;
2304  QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10;
2305 }
2306 
2307 void tst_QList::resizeComplex() const
2308 {
2309  const int items = Custom::counter.loadAcquire();
2310  {
2312  QFETCH(int, size);
2313 
2314  int oldSize = vector.size();
2315  vector.resize(size);
2316  QCOMPARE(vector.size(), size);
2317  QVERIFY(vector.capacity() >= size);
2318  if (vector.isEmpty())
2320  for (int i = oldSize; i < size; ++i)
2321  QVERIFY(vector[i].i == 'j'); // check default initialization
2322 
2323  const int capacity = vector.capacity();
2324 
2325  vector.resize(0);
2326  QCOMPARE(vector.size(), 0);
2327  QVERIFY(vector.isEmpty());
2328  QVERIFY(vector.capacity() <= capacity);
2329  }
2330  QCOMPARE(Custom::counter.loadAcquire(), items);
2331 }
2332 
2333 void tst_QList::resizeCtorAndDtor() const
2334 {
2335  const int items = Custom::counter.loadAcquire();
2336  {
2337  QList<Custom> null;
2338  QList<Custom> empty(0, '0');
2339  QList<Custom> emptyReserved;
2340  QList<Custom> nonEmpty;
2341  QList<Custom> nonEmptyReserved;
2342 
2343  emptyReserved.reserve(10);
2344  nonEmptyReserved.reserve(15);
2345  nonEmpty << '0' << '1' << '2' << '3' << '4';
2346  nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
2347  QVERIFY(emptyReserved.capacity() >= 10);
2348  QVERIFY(nonEmptyReserved.capacity() >= 15);
2349 
2350  // start playing with vectors
2351  null.resize(21);
2352  nonEmpty.resize(2);
2353  emptyReserved.resize(0);
2354  nonEmpty.resize(0);
2355  nonEmptyReserved.resize(2);
2356  }
2357  QCOMPARE(Custom::counter.loadAcquire(), items);
2358 }
2359 
2360 void tst_QList::resizeToZero() const
2361 {
2362  QList<int> x;
2363  QList<int> y;
2364  x << 1 << 2;
2365  y = x;
2366  y.resize(0);
2367  QCOMPARE(y.size(), 0);
2368  // grow back
2369  y.resize(x.size());
2370  QCOMPARE(y.size(), x.size());
2371  // default initialized
2372  QCOMPARE(y[0], 0);
2373  QCOMPARE(y[1], 0);
2374 }
2375 
2376 void tst_QList::resizeToTheSameSize_data()
2377 {
2378  QTest::addColumn<QList<int>>("x");
2379  QTest::newRow("size 2") << QList({ 1, 2 });
2380  QTest::newRow("size 0") << QList<int>();
2381 }
2382 
2383 void tst_QList::resizeToTheSameSize() const
2384 {
2385  QFETCH(QList<int>, x);
2386  QList<int> y;
2387  y = x;
2388  y.resize(x.size());
2389  QCOMPARE(y.size(), x.size());
2390 }
2391 
2392 void tst_QList::iterators() const
2393 {
2394  QList<int> v;
2395 
2396  QCOMPARE(v.begin(), v.end());
2397  QCOMPARE(v.rbegin(), v.rend());
2398 
2399  qsizetype idx = 0;
2400  for (; idx < 10; ++idx)
2401  v.push_back(idx);
2402 
2403  // stl-style iterators
2404  idx = 0;
2405  auto it = v.begin();
2406  QCOMPARE(*it, idx);
2407  // idx == 0
2408 
2409  std::advance(it, 7);
2410  idx += 7;
2411  QCOMPARE(*it, idx);
2412  // idx == 7
2413 
2414  it++;
2415  idx++;
2416  QCOMPARE(*it, idx);
2417  // idx == 8
2418 
2419  ++it;
2420  ++idx;
2421  QCOMPARE(*it, idx);
2422  // idx == 9
2423 
2424  std::advance(it, -3);
2425  idx -= 3;
2426  QCOMPARE(*it, idx);
2427  // idx == 6
2428 
2429  it--;
2430  idx--;
2431  QCOMPARE(*it, idx);
2432  // idx == 5
2433 
2434  --it;
2435  --idx;
2436  QCOMPARE(*it, idx);
2437  // idx == 4
2438 
2439  it = it + 1;
2440  idx = idx + 1;
2441  QCOMPARE(*it, idx);
2442  // idx == 5
2443 
2444  it = it + ptrdiff_t(1);
2445  idx = idx + 1;
2446  QCOMPARE(*it, idx);
2447  // idx == 6
2448 
2449  it = it + qsizetype(1);
2450  idx = idx + 1;
2451  QCOMPARE(*it, idx);
2452  // idx == 7
2453 
2454  it = it - qsizetype(1);
2455  idx = idx - 1;
2456  QCOMPARE(*it, idx);
2457  // idx == 6
2458 
2459  it = it - ptrdiff_t(1);
2460  idx = idx - 1;
2461  QCOMPARE(*it, idx);
2462  // idx == 5
2463 
2464  it = it - 1;
2465  idx = idx - 1;
2466  QCOMPARE(*it, idx);
2467  // idx == 4
2468 
2469  it -= 1;
2470  idx -= 1;
2471  QCOMPARE(*it, idx);
2472  // idx == 3
2473 
2474  it -= qsizetype(1);
2475  idx -= 1;
2476  QCOMPARE(*it, idx);
2477  // idx == 2
2478 
2479  it -= ptrdiff_t(1);
2480  idx -= 1;
2481  QCOMPARE(*it, idx);
2482  // idx == 1
2483 
2484  it += ptrdiff_t(1);
2485  idx += 1;
2486  QCOMPARE(*it, idx);
2487  // idx == 2
2488 
2489  it += qsizetype(1);
2490  idx += 1;
2491  QCOMPARE(*it, idx);
2492  // idx == 3
2493 
2494  it += 1;
2495  idx += 1;
2496  QCOMPARE(*it, idx);
2497  // idx == 4
2498 
2499  *it = idx + 1;
2500  QCOMPARE(*it, idx + 1);
2501  *it = idx;
2502 
2503  // stl-style reverse iterators
2504  idx = v.size() - 1;
2505  auto rit = v.rbegin();
2506  QCOMPARE(*rit, idx);
2507 
2508  *rit = idx + 1;
2509  QCOMPARE(*rit, idx + 1);
2510  *rit = idx;
2511 
2512  std::advance(rit, 5);
2513  idx -= 5;
2514  QCOMPARE(*rit, idx);
2515 
2516  ++rit;
2517  --idx;
2518  QCOMPARE(*rit, idx);
2519 
2520  rit++;
2521  idx--;
2522  QCOMPARE(*rit, idx);
2523 
2524  std::advance(rit, -4);
2525  idx += 4;
2526  QCOMPARE(*rit, idx);
2527 
2528  --rit;
2529  ++idx;
2530  QCOMPARE(*rit, idx);
2531 
2532  rit--;
2533  idx++;
2534  QCOMPARE(*rit, idx);
2535 }
2536 
2537 void tst_QList::constIterators() const
2538 {
2539  const QList<int> constEmptyList;
2540  QCOMPARE(constEmptyList.cbegin(), constEmptyList.cend());
2541  QCOMPARE(constEmptyList.begin(), constEmptyList.cbegin());
2542  QCOMPARE(constEmptyList.end(), constEmptyList.cend());
2543  QCOMPARE(constEmptyList.constBegin(), constEmptyList.constEnd());
2544  QCOMPARE(constEmptyList.constBegin(), constEmptyList.cbegin());
2545  QCOMPARE(constEmptyList.constEnd(), constEmptyList.cend());
2546  QVERIFY(!constEmptyList.isDetached());
2547 
2548  const QList<int> v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
2549 
2550  // stl-style iterators
2551  qsizetype idx = 0;
2552  auto it = v.cbegin();
2553  QCOMPARE(*it, idx);
2554  // idx == 0
2555 
2556  std::advance(it, 7);
2557  idx += 7;
2558  QCOMPARE(*it, idx);
2559  // idx == 7
2560 
2561  it++;
2562  idx++;
2563  QCOMPARE(*it, idx);
2564  // idx == 8
2565 
2566  ++it;
2567  ++idx;
2568  QCOMPARE(*it, idx);
2569  // idx == 9
2570 
2571  std::advance(it, -3);
2572  idx -= 3;
2573  QCOMPARE(*it, idx);
2574  // idx == 6
2575 
2576  it--;
2577  idx--;
2578  QCOMPARE(*it, idx);
2579  // idx == 5
2580 
2581  --it;
2582  --idx;
2583  QCOMPARE(*it, idx);
2584  // idx == 4
2585 
2586  it = it + 1;
2587  idx = idx + 1;
2588  QCOMPARE(*it, idx);
2589  // idx == 5
2590 
2591  it = it + ptrdiff_t(1);
2592  idx = idx + 1;
2593  QCOMPARE(*it, idx);
2594  // idx == 6
2595 
2596  it = it + qsizetype(1);
2597  idx = idx + 1;
2598  QCOMPARE(*it, idx);
2599  // idx == 7
2600 
2601  it = it - qsizetype(1);
2602  idx = idx - 1;
2603  QCOMPARE(*it, idx);
2604  // idx == 6
2605 
2606  it = it - ptrdiff_t(1);
2607  idx = idx - 1;
2608  QCOMPARE(*it, idx);
2609  // idx == 5
2610 
2611  it = it - 1;
2612  idx = idx - 1;
2613  QCOMPARE(*it, idx);
2614  // idx == 4
2615 
2616  it -= 1;
2617  idx -= 1;
2618  QCOMPARE(*it, idx);
2619  // idx == 3
2620 
2621  it -= qsizetype(1);
2622  idx -= 1;
2623  QCOMPARE(*it, idx);
2624  // idx == 2
2625 
2626  it -= ptrdiff_t(1);
2627  idx -= 1;
2628  QCOMPARE(*it, idx);
2629  // idx == 1
2630 
2631  it += ptrdiff_t(1);
2632  idx += 1;
2633  QCOMPARE(*it, idx);
2634  // idx == 2
2635 
2636  it += qsizetype(1);
2637  idx += 1;
2638  QCOMPARE(*it, idx);
2639  // idx == 3
2640 
2641  it += 1;
2642  idx += 1;
2643  QCOMPARE(*it, idx);
2644  // idx == 4
2645 
2646  // stl-style reverse iterators
2647  idx = v.size() - 1;
2648  auto rit = v.crbegin();
2649  QCOMPARE(*rit, idx);
2650 
2651  std::advance(rit, 5);
2652  idx -= 5;
2653  QCOMPARE(*rit, idx);
2654 
2655  ++rit;
2656  --idx;
2657  QCOMPARE(*rit, idx);
2658 
2659  rit++;
2660  idx--;
2661  QCOMPARE(*rit, idx);
2662 
2663  std::advance(rit, -4);
2664  idx += 4;
2665  QCOMPARE(*rit, idx);
2666 
2667  --rit;
2668  ++idx;
2669  QCOMPARE(*rit, idx);
2670 
2671  rit--;
2672  idx++;
2673  QCOMPARE(*rit, idx);
2674 }
2675 
2676 void tst_QList::reverseIterators() const
2677 {
2678  QList<int> v;
2679  v << 1 << 2 << 3 << 4;
2680  QList<int> vr = v;
2681  std::reverse(vr.begin(), vr.end());
2682  const QList<int> &cvr = vr;
2683  QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin()));
2684  QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin()));
2685  QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin()));
2686  QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin()));
2687  QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin()));
2688  QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin()));
2689 }
2690 
2691 template<typename T>
2692 void tst_QList::size() const
2693 {
2695 
2696  // also verify that length() is an alias to size()
2697 
2698  // zero size
2699  QList<T> myvec;
2700  QVERIFY(myvec.size() == 0);
2701  QCOMPARE(myvec.length(), myvec.size());
2702  QVERIFY(!myvec.isDetached());
2703 
2704  // grow
2705  myvec.append(SimpleValue<T>::at(0));
2706  QVERIFY(myvec.size() == 1);
2707  QCOMPARE(myvec.length(), myvec.size());
2708  myvec.append(SimpleValue<T>::at(1));
2709  QVERIFY(myvec.size() == 2);
2710  QCOMPARE(myvec.length(), myvec.size());
2711 
2712  // shrink
2713  myvec.remove(0);
2714  QVERIFY(myvec.size() == 1);
2715  QCOMPARE(myvec.length(), myvec.size());
2716  myvec.remove(0);
2717  QVERIFY(myvec.size() == 0);
2718  QCOMPARE(myvec.length(), myvec.size());
2719 }
2720 
2721 // ::squeeze() is tested in ::capacity().
2722 
2723 void tst_QList::startsWith() const
2724 {
2725  QList<int> myvec;
2726 
2727  // empty vector
2728  QVERIFY(!myvec.startsWith(1));
2729 
2730  // add the one, should work
2731  myvec.prepend(1);
2732  QVERIFY(myvec.startsWith(1));
2733 
2734  // add something else, fails now
2735  myvec.prepend(3);
2736  QVERIFY(!myvec.startsWith(1));
2737 
2738  // remove it again :)
2739  myvec.remove(0);
2740  QVERIFY(myvec.startsWith(1));
2741 }
2742 
2743 template<typename T>
2744 void tst_QList::swap() const
2745 {
2747 
2748  QList<T> v1, v2;
2749  T val1 = SimpleValue<T>::at(0);
2750  T val2 = SimpleValue<T>::at(1);
2751  T val3 = SimpleValue<T>::at(2);
2752  T val4 = SimpleValue<T>::at(3);
2753  T val5 = SimpleValue<T>::at(4);
2754  T val6 = SimpleValue<T>::at(5);
2755  v1 << val1 << val2 << val3;
2756  v2 << val4 << val5 << val6;
2757 
2758  v1.swap(v2);
2759  QCOMPARE(v1,QList<T>() << val4 << val5 << val6);
2760  QCOMPARE(v2,QList<T>() << val1 << val2 << val3);
2761 }
2762 
2763 void tst_QList::toList() const
2764 {
2765  QList<QString> myvec;
2766  myvec << "A" << "B" << "C";
2767 
2768  // make sure it converts and doesn't modify the original vector
2769  QCOMPARE(myvec.toList(), QList<QString>() << "A" << "B" << "C");
2770  QCOMPARE(myvec, QList<QString>() << "A" << "B" << "C");
2771 }
2772 
2773 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2774 void tst_QList::toStdVector() const
2775 {
2776  QList<QString> myvec;
2777  myvec << "A" << "B" << "C";
2778 
2779  std::vector<QString> svec = myvec.toStdVector();
2780  QCOMPARE(svec.at(0), QLatin1String("A"));
2781  QCOMPARE(svec.at(1), QLatin1String("B"));
2782  QCOMPARE(svec.at(2), QLatin1String("C"));
2783 
2784  QCOMPARE(myvec, QList<QString>() << "A" << "B" << "C");
2785 }
2786 #endif
2787 
2788 void tst_QList::value() const
2789 {
2790  QList<QString> myvec;
2791 
2792  QCOMPARE(myvec.value(1), QString());
2793  QCOMPARE(myvec.value(-1, QLatin1String("default")), QLatin1String("default"));
2794  QVERIFY(!myvec.isDetached());
2795 
2796  myvec << "A" << "B" << "C";
2797 
2798  // valid calls
2799  QCOMPARE(myvec.value(0), QLatin1String("A"));
2800  QCOMPARE(myvec.value(1), QLatin1String("B"));
2801  QCOMPARE(myvec.value(2), QLatin1String("C"));
2802 
2803  // default calls
2804  QCOMPARE(myvec.value(-1), QString());
2805  QCOMPARE(myvec.value(3), QString());
2806 
2807  // test calls with a provided default, valid calls
2808  QCOMPARE(myvec.value(0, QLatin1String("default")), QLatin1String("A"));
2809  QCOMPARE(myvec.value(1, QLatin1String("default")), QLatin1String("B"));
2810  QCOMPARE(myvec.value(2, QLatin1String("default")), QLatin1String("C"));
2811 
2812  // test calls with a provided default that will return the default
2813  QCOMPARE(myvec.value(-1, QLatin1String("default")), QLatin1String("default"));
2814  QCOMPARE(myvec.value(3, QLatin1String("default")), QLatin1String("default"));
2815 }
2816 
2817 void tst_QList::testOperators() const
2818 {
2819  QList<QString> myvec;
2820  myvec << "A" << "B" << "C";
2821  QList<QString> myvectwo;
2822  myvectwo << "D" << "E" << "F";
2823  QList<QString> combined;
2824  combined << "A" << "B" << "C" << "D" << "E" << "F";
2825 
2826  // !=
2827  QVERIFY(myvec != myvectwo);
2828 
2829  // +
2830  QCOMPARE(myvec + myvectwo, combined);
2831  QCOMPARE(myvec, QList<QString>() << "A" << "B" << "C");
2832  QCOMPARE(myvectwo, QList<QString>() << "D" << "E" << "F");
2833 
2834  // +=
2835  myvec += myvectwo;
2836  QCOMPARE(myvec, combined);
2837 
2838  // ==
2839  QVERIFY(myvec == combined);
2840 
2841  // <, >, <=, >=
2842  QVERIFY(!(myvec < combined));
2843  QVERIFY(!(myvec > combined));
2844  QVERIFY( myvec <= combined);
2845  QVERIFY( myvec >= combined);
2846  combined.push_back("G");
2847  QVERIFY( myvec < combined);
2848  QVERIFY(!(myvec > combined));
2849  QVERIFY( myvec <= combined);
2850  QVERIFY(!(myvec >= combined));
2851  QVERIFY(combined > myvec);
2852  QVERIFY(combined >= myvec);
2853 
2854  // []
2855  QCOMPARE(myvec[0], QLatin1String("A"));
2856  QCOMPARE(myvec[1], QLatin1String("B"));
2857  QCOMPARE(myvec[2], QLatin1String("C"));
2858  QCOMPARE(myvec[3], QLatin1String("D"));
2859  QCOMPARE(myvec[4], QLatin1String("E"));
2860  QCOMPARE(myvec[5], QLatin1String("F"));
2861 }
2862 
2863 
2866 
2867 struct Foo
2868 {
2869  int *p;
2870 
2871  Foo() { p = new int; ++fooCtor; }
2872  Foo(const Foo &other) { Q_UNUSED(other); p = new int; ++fooCtor; }
2873 
2874  void operator=(const Foo & /* other */) { }
2875 
2876  ~Foo() { delete p; ++fooDtor; }
2877 };
2878 
2879 void tst_QList::reserve()
2880 {
2881  fooCtor = 0;
2882  fooDtor = 0;
2883  {
2884  QList<Foo> a;
2885  a.resize(2);
2886  QCOMPARE(fooCtor, 2);
2887  QList<Foo> b(a);
2888  b.reserve(1);
2889  QCOMPARE(b.size(), a.size());
2890  QCOMPARE(fooDtor, 0);
2891  }
2893 }
2894 
2895 // This is a regression test for QTBUG-51758
2896 void tst_QList::reserveZero()
2897 {
2898  QList<int> vec;
2899  vec.detach();
2900  vec.reserve(0); // should not crash
2901  QCOMPARE(vec.size(), 0);
2902  QCOMPARE(vec.capacity(), 0);
2903  vec.squeeze();
2904  QCOMPARE(vec.size(), 0);
2905  QCOMPARE(vec.capacity(), 0);
2906  vec.reserve(-1);
2907  QCOMPARE(vec.size(), 0);
2908  QCOMPARE(vec.capacity(), 0);
2909  vec.append(42);
2910  QCOMPARE(vec.size(), 1);
2911  QVERIFY(vec.capacity() >= 1);
2912 
2913  QList<int> vec2;
2914  vec2.reserve(0); // should not crash either
2915  vec2.reserve(-1);
2916  vec2.squeeze();
2917  QCOMPARE(vec2.size(), 0);
2918  QCOMPARE(vec2.capacity(), 0);
2919  QVERIFY(!vec2.isDetached());
2920 }
2921 
2922 template<typename T>
2923 void tst_QList::initializeList()
2924 {
2926 
2927  T val1(SimpleValue<T>::at(1));
2928  T val2(SimpleValue<T>::at(2));
2929  T val3(SimpleValue<T>::at(3));
2930  T val4(SimpleValue<T>::at(4));
2931 
2932  QList<T> v1 {val1, val2, val3};
2933  QCOMPARE(v1, QList<T>() << val1 << val2 << val3);
2934  QCOMPARE(v1, (QList<T> {val1, val2, val3}));
2935 
2936  QList<QList<T>> v2{ v1, {val4}, QList<T>(), {val1, val2, val3} };
2937  QList<QList<T>> v3;
2938  v3 << v1 << (QList<T>() << val4) << QList<T>() << v1;
2939  QCOMPARE(v3, v2);
2940 
2941  QList<T> v4({});
2942  QCOMPARE(v4.size(), 0);
2943 }
2944 
2945 void tst_QList::const_shared_null()
2946 {
2947  QList<int> v2;
2948  QVERIFY(!v2.isDetached());
2949 }
2950 
2951 template<typename T>
2952 void tst_QList::detach() const
2953 {
2955 
2956  {
2957  // detach an empty vector
2958  QList<T> v;
2959  v.detach();
2960  QVERIFY(!v.isDetached());
2961  QCOMPARE(v.size(), 0);
2962  QCOMPARE(v.capacity(), 0);
2963  }
2964  {
2965  // detach an empty referenced vector
2966  QList<T> v;
2967  QList<T> ref(v);
2968  QVERIFY(!v.isDetached());
2969  v.detach();
2970  QVERIFY(!v.isDetached());
2971  QCOMPARE(v.size(), 0);
2972  QCOMPARE(v.capacity(), 0);
2973  }
2974  {
2975  // detach a not empty referenced vector
2976  QList<T> v(31);
2977  QList<T> ref(v);
2978  QVERIFY(!v.isDetached());
2979  v.detach();
2980  QVERIFY(v.isDetached());
2981  QCOMPARE(v.size(), 31);
2982  QCOMPARE(v.capacity(), 31);
2983  }
2984  {
2985  // detach a not empty vector
2986  QList<T> v(31);
2987  QVERIFY(v.isDetached());
2988  v.detach(); // detaching a detached vector
2989  QVERIFY(v.isDetached());
2990  QCOMPARE(v.size(), 31);
2991  QCOMPARE(v.capacity(), 31);
2992  }
2993  {
2994  // detach a not empty vector with preallocated space
2995  QList<T> v(3);
2996  v.reserve(8);
2997  QList<T> ref(v);
2998  QVERIFY(!v.isDetached());
2999  v.detach();
3000  QVERIFY(v.isDetached());
3001  QCOMPARE(v.size(), 3);
3002  QCOMPARE(v.capacity(), 8);
3003  }
3004  {
3005  // detach a not empty vector with preallocated space
3006  QList<T> v(3);
3007  v.reserve(8);
3008  QVERIFY(v.isDetached());
3009  v.detach(); // detaching a detached vector
3010  QVERIFY(v.isDetached());
3011  QCOMPARE(v.size(), 3);
3012  QCOMPARE(v.capacity(), 8);
3013  }
3014  {
3015  // detach a not empty, initialized vector
3016  QList<T> v(7, SimpleValue<T>::at(1));
3017  QList<T> ref(v);
3018  QVERIFY(!v.isDetached());
3019  v.detach();
3020  QVERIFY(v.isDetached());
3021  QCOMPARE(v.size(), 7);
3022  for (int i = 0; i < v.size(); ++i)
3024  }
3025  {
3026  // detach a not empty, initialized vector
3027  QList<T> v(7, SimpleValue<T>::at(2));
3028  QVERIFY(v.isDetached());
3029  v.detach(); // detaching a detached vector
3030  QVERIFY(v.isDetached());
3031  QCOMPARE(v.size(), 7);
3032  for (int i = 0; i < v.size(); ++i)
3034  }
3035  {
3036  // detach a not empty, initialized vector with preallocated space
3037  QList<T> v(7, SimpleValue<T>::at(3));
3038  v.reserve(31);
3039  QList<T> ref(v);
3040  QVERIFY(!v.isDetached());
3041  v.detach();
3042  QVERIFY(v.isDetached());
3043  QCOMPARE(v.size(), 7);
3044  QCOMPARE(v.capacity(), 31);
3045  for (int i = 0; i < v.size(); ++i)
3047  }
3048 }
3049 
3050 static QAtomicPointer<QList<int> > detachThreadSafetyDataInt;
3051 static QAtomicPointer<QList<Movable> > detachThreadSafetyDataMovable;
3052 static QAtomicPointer<QList<Custom> > detachThreadSafetyDataCustom;
3053 
3054 template<typename T> QAtomicPointer<QList<T> > *detachThreadSafetyData();
3055 template<> QAtomicPointer<QList<int> > *detachThreadSafetyData() { return &detachThreadSafetyDataInt; }
3056 template<> QAtomicPointer<QList<Movable> > *detachThreadSafetyData() { return &detachThreadSafetyDataMovable; }
3057 template<> QAtomicPointer<QList<Custom> > *detachThreadSafetyData() { return &detachThreadSafetyDataCustom; }
3058 
3059 static QSemaphore detachThreadSafetyLock;
3060 
3061 template<typename T>
3062 void tst_QList::detachThreadSafety() const
3063 {
3064  delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(new QList<T>(SimpleValue<T>::vector(400)));
3065 
3066  static const uint threadsCount = 5;
3067 
3068  struct : QThread {
3069  void run() override
3070  {
3071  QList<T> copy(*detachThreadSafetyData<T>()->loadRelaxed());
3072  QVERIFY(!copy.isDetached());
3073  detachThreadSafetyLock.release();
3074  detachThreadSafetyLock.acquire(100);
3075  copy.detach();
3076  }
3077  } threads[threadsCount];
3078 
3079  for (uint i = 0; i < threadsCount; ++i)
3080  threads[i].start();
3082  detachThreadSafetyLock.acquire(threadsCount);
3083 
3084  // destroy static original data
3085  delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(0);
3086 
3087  QVERIFY(threadsCount < 100);
3088  detachThreadSafetyLock.release(threadsCount * 100);
3090 
3091  for (uint i = 0; i < threadsCount; ++i)
3092  threads[i].wait();
3093 }
3094 
3095 void tst_QList::detachThreadSafetyInt() const
3096 {
3097  for (uint i = 0; i < 128; ++i)
3098  detachThreadSafety<int>();
3099 }
3100 
3101 void tst_QList::detachThreadSafetyMovable() const
3102 {
3103  const int instancesCount = Movable::counter.loadAcquire();
3104  for (uint i = 0; i < 128; ++i) {
3105  detachThreadSafety<Movable>();
3106  QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
3107  }
3108 }
3109 
3110 void tst_QList::detachThreadSafetyCustom() const
3111 {
3112  const int instancesCount = Custom::counter.loadAcquire();
3113  for (uint i = 0; i < 128; ++i) {
3114  detachThreadSafety<Custom>();
3115  QCOMPARE(Custom::counter.loadAcquire(), instancesCount);
3116  }
3117 }
3118 
3119 void tst_QList::insertMove() const
3120 {
3121  const int instancesCount = Movable::counter.loadAcquire();
3122  {
3124  vec.reserve(7);
3125  Movable m0;
3126  Movable m1;
3127  Movable m2;
3128  Movable m3;
3129  Movable m4;
3130  Movable m5;
3131  Movable m6;
3132 
3133  vec.append(std::move(m3));
3134  QVERIFY(m3.wasConstructedAt(nullptr));
3135  QVERIFY(vec.at(0).wasConstructedAt(&m3));
3136  vec.push_back(std::move(m4));
3137  QVERIFY(m4.wasConstructedAt(nullptr));
3138  QVERIFY(vec.at(0).wasConstructedAt(&m3));
3139  QVERIFY(vec.at(1).wasConstructedAt(&m4));
3140  vec.prepend(std::move(m1));
3141  QVERIFY(m1.wasConstructedAt(nullptr));
3142  QVERIFY(vec.at(0).wasConstructedAt(&m1));
3143  QVERIFY(vec.at(1).wasConstructedAt(&m3));
3144  QVERIFY(vec.at(2).wasConstructedAt(&m4));
3145  vec.insert(1, std::move(m2));
3146  QVERIFY(m2.wasConstructedAt(nullptr));
3147  QVERIFY(vec.at(0).wasConstructedAt(&m1));
3148  QVERIFY(vec.at(1).wasConstructedAt(&m2));
3149  QVERIFY(vec.at(2).wasConstructedAt(&m3));
3150  QVERIFY(vec.at(3).wasConstructedAt(&m4));
3151  vec += std::move(m5);
3152  QVERIFY(m5.wasConstructedAt(nullptr));
3153  QVERIFY(vec.at(0).wasConstructedAt(&m1));
3154  QVERIFY(vec.at(1).wasConstructedAt(&m2));
3155  QVERIFY(vec.at(2).wasConstructedAt(&m3));
3156  QVERIFY(vec.at(3).wasConstructedAt(&m4));
3157  QVERIFY(vec.at(4).wasConstructedAt(&m5));
3158  vec << std::move(m6);
3159  QVERIFY(m6.wasConstructedAt(nullptr));
3160  QVERIFY(vec.at(0).wasConstructedAt(&m1));
3161  QVERIFY(vec.at(1).wasConstructedAt(&m2));
3162  QVERIFY(vec.at(2).wasConstructedAt(&m3));
3163  QVERIFY(vec.at(3).wasConstructedAt(&m4));
3164  QVERIFY(vec.at(4).wasConstructedAt(&m5));
3165  QVERIFY(vec.at(5).wasConstructedAt(&m6));
3166  vec.push_front(std::move(m0));
3167  QVERIFY(m0.wasConstructedAt(nullptr));
3168  QVERIFY(vec.at(0).wasConstructedAt(&m0));
3169  QVERIFY(vec.at(1).wasConstructedAt(&m1));
3170  QVERIFY(vec.at(2).wasConstructedAt(&m2));
3171  QVERIFY(vec.at(3).wasConstructedAt(&m3));
3172  QVERIFY(vec.at(4).wasConstructedAt(&m4));
3173  QVERIFY(vec.at(5).wasConstructedAt(&m5));
3174  QVERIFY(vec.at(6).wasConstructedAt(&m6));
3175 
3176  QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14);
3177  }
3178  QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
3179 }
3180 
3181 void tst_QList::swapItemsAt() const
3182 {
3183  QList<int> v;
3184  v << 0 << 1 << 2 << 3;
3185 
3186  v.swapItemsAt(0, 2);
3187  QCOMPARE(v.at(0), 2);
3188  QCOMPARE(v.at(2), 0);
3189 
3190  auto copy = v;
3191  copy.swapItemsAt(0, 2);
3192  QCOMPARE(v.at(0), 2);
3193  QCOMPARE(v.at(2), 0);
3194  QCOMPARE(copy.at(0), 0);
3195  QCOMPARE(copy.at(2), 2);
3196 }
3197 
3198 void tst_QList::emplaceReturnsIterator()
3199 {
3201 
3202  vec.emplace(0, 'k')->i = 'p';
3203 
3204  QCOMPARE(vec[0].i, 'p');
3205 }
3206 
3207 void tst_QList::emplaceFront() const
3208 {
3210 
3212  vec.emplaceFront('b');
3214 
3215  vec.emplaceFront('a');
3217 
3218  QCOMPARE(vec, QList<Movable>({ 'a', 'b' }));
3219 }
3220 
3221 void tst_QList::emplaceFrontReturnsRef() const
3222 {
3224 
3225  QCOMPARE(vec.emplaceFront('c').i, 'c');
3226 
3227  vec.emplaceFront('b').i = 'a';
3228 
3229  QCOMPARE(vec.front().i, 'a');
3230 }
3231 
3232 void tst_QList::emplaceBack()
3233 {
3235 
3237 
3238  vec.emplaceBack('k');
3239 
3241 }
3242 
3243 void tst_QList::emplaceBackReturnsRef()
3244 {
3246 
3247  vec.emplaceBack('k').i = 'p';
3248 
3249  QCOMPARE(vec.at(0).i, 'p');
3250 }
3251 
3252 void tst_QList::emplaceWithElementFromTheSameContainer()
3253 {
3254  QFETCH(int, elementPos);
3255  QFETCH(int, insertPos);
3256  QFETCH(bool, doCopy);
3257 
3258  QList<QString> vec {"a", "b", "c", "d", "e"};
3259  const QString e = vec[elementPos];
3260 
3261  if (doCopy)
3262  vec.emplace(insertPos, vec[elementPos]);
3263  else
3264  vec.emplace(insertPos, std::move(vec[elementPos]));
3265 
3266  QCOMPARE(vec[insertPos], e);
3267 }
3268 
3269 void tst_QList::emplaceWithElementFromTheSameContainer_data()
3270 {
3271  QTest::addColumn<int>("elementPos");
3272  QTest::addColumn<int>("insertPos");
3273  QTest::addColumn<bool>("doCopy");
3274 
3275  for (int i = 0; i < 2; ++i) {
3276  const bool doCopy = i == 0;
3277  const char *opName = doCopy ? "copy" : "move";
3278 
3279  QTest::addRow("%s: begin -> end" , opName) << 0 << 5 << doCopy;
3280  QTest::addRow("%s: begin -> middle", opName) << 0 << 2 << doCopy;
3281  QTest::addRow("%s: middle -> begin" , opName) << 2 << 0 << doCopy;
3282  QTest::addRow("%s: middle -> end" , opName) << 2 << 5 << doCopy;
3283  QTest::addRow("%s: end -> middle", opName) << 4 << 2 << doCopy;
3284  QTest::addRow("%s: end -> begin" , opName) << 4 << 0 << doCopy;
3285  }
3286 }
3287 
3288 template<typename T>
3289 void tst_QList::emplaceImpl() const
3290 {
3292 
3293  QList<T> vec {'a', 'b', 'c', 'd'};
3294 
3295  vec.emplace(2, 'k');
3296 
3297  QCOMPARE(vec.size(), 5); // emplace adds new element
3298  QCOMPARE(vec[2], T('k'));
3299 
3300  vec.emplace(vec.end(), T('f'));
3301 
3302  QCOMPARE(vec.size(), 6);
3303  QCOMPARE(vec.back(), T('f'));
3304 
3305  // emplace() into empty container
3306  {
3307  QList<T> vec;
3308  vec.emplace(vec.begin(), 'a');
3309  QCOMPARE(vec.size(), 1);
3310  QCOMPARE(vec.front(), T('a'));
3311  }
3312  {
3313  QList<T> vec;
3314  vec.emplace(0, 'a');
3315  QCOMPARE(vec.size(), 1);
3316  QCOMPARE(vec.front(), T('a'));
3317  }
3318 }
3319 
3320 template <typename T>
3321 void tst_QList::replace() const
3322 {
3324 
3325  QList<T> vec { 'a', 'b', 'c', 'd' };
3326  T e = 'e';
3327  vec.replace(0, e);
3328  QCOMPARE(vec[0], T('e'));
3329 
3330  T f = 'f';
3331  vec.replace(2, std::move(f));
3332  QCOMPARE(vec[2], T('f'));
3333 }
3334 
3335 template <class T>
3336 static void vecEq(const QList<T> &qVec, const std::vector<T> &stdVec)
3337 {
3338  QCOMPARE(std::size_t(qVec.size()), stdVec.size());
3339  QVERIFY(std::equal(qVec.begin(), qVec.end(), stdVec.begin(), stdVec.end()));
3340 }
3341 
3342 template <class T>
3343 static void squeezeVec(QList<T> &qVec, std::vector<T> &stdVec)
3344 {
3345  qVec.squeeze();
3346  stdVec.shrink_to_fit();
3347 }
3348 
3349 template<typename T>
3350 void tst_QList::emplaceConsistentWithStdVectorImpl() const
3351 {
3353 
3354  // fast-patch to make QString work with the old logic
3355  const auto convert = [] (char i) {
3356  if constexpr (std::is_same_v<QString, T>) {
3357  return QChar(i);
3358  } else {
3359  return i;
3360  }
3361  };
3362 
3363  QList<T> qVec {convert('a'), convert('b'), convert('c'), convert('d'), convert('e')};
3364  std::vector<T> stdVec {convert('a'), convert('b'), convert('c'), convert('d'), convert('e')};
3365  vecEq(qVec, stdVec);
3366 
3367  qVec.emplaceBack(convert('f'));
3368  stdVec.emplace_back(convert('f'));
3369  vecEq(qVec, stdVec);
3370 
3371  qVec.emplace(3, convert('g'));
3372  stdVec.emplace(stdVec.begin() + 3, convert('g'));
3373  vecEq(qVec, stdVec);
3374 
3375  T t;
3376  // while QList is safe with regards to emplacing elements moved from itself, it's UB
3377  // for std::vector, so do the moving in two steps there.
3378  qVec.emplaceBack(std::move(qVec[0]));
3379  stdVec.emplace_back(std::move(t = std::move(stdVec[0])));
3380  vecEq(qVec, stdVec);
3381 
3382  squeezeVec(qVec, stdVec);
3383 
3384  qVec.emplaceBack(std::move(qVec[1]));
3385  stdVec.emplace_back(std::move(t = std::move(stdVec[1])));
3386  vecEq(qVec, stdVec);
3387 
3388  squeezeVec(qVec, stdVec);
3389 
3390  qVec.emplace(3, std::move(qVec[5]));
3391  stdVec.emplace(stdVec.begin() + 3, std::move(t = std::move(stdVec[5])));
3392 
3393  vecEq(qVec, stdVec);
3394 
3395  qVec.emplaceBack(qVec[3]);
3396  stdVec.emplace_back((t = stdVec[3]));
3397  vecEq(qVec, stdVec);
3398 
3399  squeezeVec(qVec, stdVec);
3400 
3401  qVec.emplaceBack(qVec[4]);
3402  stdVec.emplace_back((t = stdVec[4]));
3403  vecEq(qVec, stdVec);
3404 
3405  squeezeVec(qVec, stdVec);
3406 
3407  qVec.emplace(5, qVec[7]);
3408  stdVec.emplace(stdVec.begin() + 5, (t = stdVec[7]));
3409  vecEq(qVec, stdVec);
3410 }
3411 
3412 void tst_QList::fromReadOnlyData() const
3413 {
3414  {
3416  QCOMPARE(d.capacity(), 0);
3417  d.squeeze();
3418  QCOMPARE(d.capacity(), 0);
3419  QCOMPARE(d.size(), 10u + 1u);
3420  for (int i = 0; i < 10; ++i)
3421  QCOMPARE(d.data()[i], char('A' + i));
3422  }
3423 
3424  {
3425  // wchar_t is not necessarily 2-bytes
3427  QCOMPARE(d.size(), 10u + 1u);
3428  for (int i = 0; i < 10; ++i)
3429  QCOMPARE(d.data()[i], wchar_t('A' + i));
3430  QVERIFY(d.isDetached());
3431  }
3432 
3433  {
3434  const char data[] = "ABCDEFGHIJ";
3436 
3437  QVERIFY(v.constData() == data);
3438  QVERIFY(!v.isEmpty());
3439  QCOMPARE(v.size(), qsizetype(11));
3440  // v.capacity() is unspecified, for now
3441 
3442  QCOMPARE((void*)(v.constBegin() + v.size()).operator->(), (void*)v.constEnd().operator->());
3443 
3444  for (int i = 0; i < 10; ++i)
3445  QCOMPARE(v[i], char('A' + i));
3446  QCOMPARE(v[10], char('\0'));
3447  }
3448 
3449  {
3450  struct LiteralType {
3451  int value;
3452  constexpr LiteralType(int v = 0) : value(v) {}
3453  };
3454  const LiteralType literal[] = {LiteralType(0), LiteralType(1), LiteralType(2)};
3455 
3457  QCOMPARE(d.size(), 3);
3458  for (int i = 0; i < 3; ++i)
3459  QCOMPARE(d.data()[i].value, i);
3460  }
3461 }
3462 
3463 struct alignas(8) CustomAligned
3464 {
3465  qint64 v = 0;
3466  CustomAligned() = default;
3468  friend bool operator==(const CustomAligned &x, const CustomAligned &y) { return x.v == y.v; }
3469 };
3470 
3471 void tst_QList::reallocateCustomAlignedType_qtbug90359() const
3472 {
3473  // Note: a very special test that could only fail for specific alignments
3474  constexpr bool canFail = (alignof(QArrayData) == 4) && (sizeof(QArrayData) == 12);
3475  if constexpr (!canFail)
3476  qWarning() << "This test will always succeed on this system.";
3477  if constexpr (alignof(CustomAligned) > alignof(std::max_align_t))
3478  QSKIP("The codepaths tested here wouldn't be executed.");
3479 
3480  const QList<CustomAligned> expected({ 0, 1, 2, 3, 4, 5, 6 });
3481  QList<CustomAligned> actual;
3482  for (int i = 0; i < 7; ++i) {
3483  actual.append(i);
3484  QCOMPARE(actual.at(i), i);
3485  }
3486  QCOMPARE(actual, expected);
3487 }
3488 
3489 template<typename T, typename Reinsert>
3490 void tst_QList::reinsert(Reinsert op) const
3491 {
3493 
3494  QList<T> list(1);
3495  // this constant is big enough for the QList to stop reallocating, after
3496  // all, size is always less than 3
3497  const int maxIters = 128;
3498  for (int i = 0; i < maxIters; ++i) {
3499  op(list);
3500  }
3501 
3502  // if QList continues to grow, it's an error
3503  qsizetype capacity = list.capacity();
3504  for (int i = 0, enoughIters = int(capacity) * 2; i < enoughIters; ++i) {
3505  op(list);
3506  QCOMPARE(capacity, list.capacity());
3507  }
3508 }
3509 
3510 template<typename T>
3511 void tst_QList::stability_reserve() const
3512 {
3514 
3515  // NOTE: this test verifies that QList::constData() stays unchanged when
3516  // inserting as much as requested by the reserve. This is specifically
3517  // designed this way as in cases when QTypeInfo<T>::isRelocatable returns
3518  // true, reallocation might use fast ::realloc() path which may in theory
3519  // (and, actually, in practice) just expand the current memory area and thus
3520  // keep QList::constData() unchanged, which means checks like
3521  // QVERIFY(oldConstData != vec.constData()) are flaky. When
3522  // QTypeInfo<T>::isRelocatable returns false, constData() will always change
3523  // if a reallocation happens and this will fail the test. This should be
3524  // sufficient on its own to test the stability requirements.
3525 
3526  {
3527  QList<T> vec;
3528  vec.reserve(64);
3529  const T *ptr = vec.constData();
3530  vec.append(QList<T>(64));
3531  QCOMPARE(ptr, vec.constData());
3532  }
3533 
3534  {
3535  QList<T> vec;
3536  vec.prepend(SimpleValue<T>::at(0));
3537  vec.removeFirst();
3538  vec.reserve(64);
3539  const T *ptr = vec.constData();
3540  vec.append(QList<T>(64));
3541  QCOMPARE(ptr, vec.constData());
3542  }
3543 
3544  {
3545  QList<T> vec;
3546  const T *ptr = vec.constData();
3547  vec.reserve(vec.capacity());
3548  QCOMPARE(ptr, vec.constData());
3549  vec.append(QList<T>(vec.capacity()));
3550  QCOMPARE(ptr, vec.constData());
3551  }
3552 
3553  {
3554  QList<T> vec;
3555  vec.prepend(SimpleValue<T>::at(0));
3556  vec.removeFirst();
3557  vec.reserve(vec.capacity());
3558  const T *ptr = vec.constData();
3559  vec.append(QList<T>(vec.capacity()));
3560  QCOMPARE(ptr, vec.constData());
3561  }
3562 
3563  {
3564  QList<T> vec;
3565  vec.append(SimpleValue<T>::at(0));
3566  vec.reserve(64);
3567  const T *ptr = vec.constData();
3568  vec.append(QList<T>(64 - vec.size())); // 1 element is already in the container
3569  QCOMPARE(ptr, vec.constData());
3570  QCOMPARE(vec.size(), 64);
3571  QCOMPARE(vec.capacity(), 64);
3572  const qsizetype oldCapacity = vec.capacity();
3573  vec.append(SimpleValue<T>::at(1)); // will reallocate as this exceeds 64
3574  QVERIFY(oldCapacity < vec.capacity());
3575  }
3576 
3577  {
3578  QList<T> vec;
3579  vec.prepend(SimpleValue<T>::at(0));
3580  vec.reserve(64);
3581  const T *ptr = vec.constData();
3582  vec.append(QList<T>(64 - vec.size())); // 1 element is already in the container
3583  QCOMPARE(ptr, vec.constData());
3584  QCOMPARE(vec.size(), 64);
3585  QCOMPARE(vec.capacity(), 64);
3586  const qsizetype oldCapacity = vec.capacity();
3587  vec.append(SimpleValue<T>::at(1)); // will reallocate as this exceeds 64
3588  QVERIFY(oldCapacity < vec.capacity());
3589  }
3590 }
3591 
3592 template<typename T>
3593 void tst_QList::stability_erase() const
3594 {
3596 
3597  // invalidated: [pos, end())
3598  for (int pos = 1; pos < 10; ++pos) {
3599  QList<T> v(10);
3600  int k = 0;
3601  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3602  const auto ptr = v.constData();
3603 
3604  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.begin() + pos);
3605 
3606  v.remove(pos, 1);
3607  QVERIFY(ptr == v.constData());
3608  for (int i = 0; i < copy.size(); ++i)
3609  QCOMPARE(*reference[i], copy[i]);
3610  }
3611 
3612  // 0 is a special case, because all values get invalidated
3613  {
3614  QList<T> v(10);
3615  const auto ptr = v.constData();
3616  v.remove(0, 2);
3617  QVERIFY(ptr != v.constData()); // can do fast removal from begin()
3618  }
3619 
3620  // when erasing everything, leave the data pointer in place (not strictly
3621  // required, but this makes more sense in general)
3622  {
3623  QList<T> v(10);
3624  const auto ptr = v.constData();
3625  v.remove(0, v.size());
3626  QVERIFY(ptr == v.constData());
3627  }
3628 }
3629 
3630 template<typename T>
3631 void tst_QList::stability_append() const
3632 {
3634 
3635  {
3636  QList<T> v(10);
3637  int k = 0;
3638  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3640  v.append(src.begin(), src.end());
3641  QVERIFY(v.size() < v.capacity());
3642 
3643  for (int i = 0; i < v.capacity() - v.size(); ++i) {
3644  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end());
3645  v.append(SimpleValue<T>::at(i));
3646  for (int i = 0; i < copy.size(); ++i)
3647  QCOMPARE(*reference[i], copy[i]);
3648  }
3649  }
3650 
3651  {
3652  QList<T> v;
3653  v.reserve(10);
3654  const qsizetype capacity = v.capacity();
3655  const T *ptr = v.constData();
3656  v.prepend(SimpleValue<T>::at(0));
3657  // here we abuse the internal details of QList. since there's enough
3658  // free space, QList should've only rearranged the data in memory,
3659  // without reallocating.
3660  QCOMPARE(capacity, v.capacity()); // otherwise cannot rely on ptr
3661  const qsizetype freeSpaceAtBegin = v.constData() - ptr;
3662  const qsizetype freeSpaceAtEnd = v.capacity() - v.size() - freeSpaceAtBegin;
3663  QVERIFY(freeSpaceAtEnd > 0); // otherwise this test is useless
3664  QVERIFY(v.size() + freeSpaceAtBegin + freeSpaceAtEnd == v.capacity());
3665 
3666  for (int i = 0; i < freeSpaceAtEnd; ++i) {
3667  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end());
3669  v.append(src.begin(), src.end());
3670  for (int i = 0; i < copy.size(); ++i)
3671  QCOMPARE(*reference[i], copy[i]);
3672  }
3673  }
3674 }
3675 
3676 template<typename T, typename Insert>
3677 void tst_QList::stability_insert(Insert op) const
3678 {
3680 
3681  // invalidated: [pos, end())
3682  for (int pos = 1; pos <= 10; ++pos) {
3683  QList<T> v(10);
3684  int k = 0;
3685  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3686  v.append(SimpleValue<T>::at(0)); // causes growth
3687  v.removeLast();
3688  QCOMPARE(v.size(), 10);
3689  QVERIFY(v.size() < v.capacity());
3690 
3691  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.begin() + pos);
3692  op(v, pos, SimpleValue<T>::at(0));
3693  for (int i = 0; i < pos; ++i)
3694  QCOMPARE(*reference[i], copy[i]);
3695  }
3696 
3697  for (int pos = 1; pos <= 10; ++pos) {
3698  QList<T> v(10);
3699  int k = 0;
3700  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3701  v.prepend(SimpleValue<T>::at(0)); // causes growth and free space at begin > 0
3702  v.removeFirst();
3703  QCOMPARE(v.size(), 10);
3704  QVERIFY(v.size() < v.capacity());
3705 
3706  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.begin() + pos);
3707  op(v, pos, SimpleValue<T>::at(0));
3708  for (int i = 0; i < pos; ++i)
3709  QCOMPARE(*reference[i], copy[i]);
3710  }
3711 }
3712 
3713 template<typename T>
3714 void tst_QList::stability_resize() const
3715 {
3717 
3718  {
3719  QList<T> v(10);
3720  v.reserve(15);
3721  QVERIFY(v.size() < v.capacity());
3722  int k = 0;
3723  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3724  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end());
3725 
3726  v.resize(15);
3727  for (int i = 0; i < copy.size(); ++i)
3728  QCOMPARE(*reference[i], copy[i]);
3729  }
3730 
3731  {
3732  QList<T> v(10);
3733  int k = 0;
3734  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3735  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end());
3736 
3737  v.resize(10);
3738  for (int i = 0; i < 10; ++i)
3739  QCOMPARE(*reference[i], copy[i]);
3740  }
3741 
3742  {
3743  QList<T> v(10);
3744  int k = 0;
3745  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3746  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end());
3747 
3748  v.resize(5);
3749  for (int i = 0; i < 5; ++i)
3750  QCOMPARE(*reference[i], copy[i]);
3751  }
3752 
3753  // special case due to prepend:
3754  {
3755  QList<T> v;
3756  v.reserve(20);
3757  const qsizetype capacity = v.capacity();
3758  const T *ptr = v.constData();
3759  v.prepend(SimpleValue<T>::at(0)); // now there's free space at begin
3760  v.resize(10);
3761  QVERIFY(v.size() < v.capacity());
3762  // here we abuse the internal details of QList. since there's enough
3763  // free space, QList should've only rearranged the data in memory,
3764  // without reallocating.
3765  QCOMPARE(capacity, v.capacity()); // otherwise cannot rely on ptr
3766  const qsizetype freeSpaceAtBegin = v.constData() - ptr;
3767  const qsizetype freeSpaceAtEnd = v.capacity() - v.size() - freeSpaceAtBegin;
3768  QVERIFY(freeSpaceAtEnd > 0); // otherwise this test is useless
3769  QVERIFY(v.size() + freeSpaceAtBegin + freeSpaceAtEnd == v.capacity());
3770  int k = 0;
3771  std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); });
3772  auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end());
3773 
3774  v.resize(v.size() + freeSpaceAtEnd);
3775  for (int i = 0; i < copy.size(); ++i)
3776  QCOMPARE(*reference[i], copy[i]);
3777  }
3778 }
3779 
3781 #include "tst_qlist.moc"
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
Foo(const Foo &other)
Definition: tst_qlist.cpp:2872
int * p
Definition: tst_qlist.cpp:2869
void operator=(const Foo &)
Definition: tst_qlist.cpp:2874
~Foo()
Definition: tst_qlist.cpp:2876
The QAtomicInt class provides platform-independent atomic operations on int.
Definition: qatomic.h:158
The QAtomicPointer class is a template class that provides platform-independent atomic operations on ...
Definition: qatomic.h:172
T loadAcquire() const noexcept
Definition: qbasicatomic.h:93
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:84
template< typename Enum > size_t qHash(QFlags< Enum > flags, size_t seed=0) noexcept
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
Definition: qlist.h:108
qsizetype size() const noexcept
Definition: qlist.h:414
QList< T > & fill(parameter_type t, qsizetype size=-1)
Definition: qlist.h:907
const_pointer constData() const noexcept
Definition: qlist.h:444
bool isEmpty() const noexcept
Definition: qlist.h:418
bool isDetached() const noexcept
Definition: qlist.h:438
void removeAt(qsizetype i)
Definition: qlist.h:588
bool isSharedWith(const QList< T > &other) const
Definition: qlist.h:440
iterator insert(qsizetype i, parameter_type t)
Definition: qlist.h:499
bool empty() const noexcept
Definition: qlist.h:697
bool removeOne(const AT &t)
Definition: qlist.h:596
qsizetype capacity() const
Definition: qlist.h:433
void swapItemsAt(qsizetype i, qsizetype j)
Definition: qlist.h:679
void push_back(parameter_type t)
Definition: qlist.h:687
void detach()
Definition: qlist.h:437
const T & constFirst() const noexcept
Definition: qlist.h:645
bool endsWith(parameter_type t) const
Definition: qlist.h:650
bool startsWith(parameter_type t) const
Definition: qlist.h:649
iterator end()
Definition: qlist.h:624
qsizetype length() const noexcept
Definition: qlist.h:416
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
T value(qsizetype i) const
Definition: qlist.h:676
static QList< T > fromList(const QList< T > &list) noexcept
Definition: qlist.h:726
const_reverse_iterator crbegin() const noexcept
Definition: qlist.h:636
T & last()
Definition: qlist.h:646
const_iterator constBegin() const noexcept
Definition: qlist.h:630
void remove(qsizetype i, qsizetype n=1)
Definition: qlist.h:798
qsizetype removeIf(Predicate pred)
Definition: qlist.h:602
reference front()
Definition: qlist.h:699
qsizetype removeAll(const AT &t)
Definition: qlist.h:590
qsizetype count() const noexcept
Definition: qlist.h:415
void squeeze()
Definition: qlist.h:778
reference emplaceBack(Args &&... args)
Definition: qlist.h:886
reverse_iterator rend()
Definition: qlist.h:633
void prepend(rvalue_ref t)
Definition: qlist.h:484
iterator begin()
Definition: qlist.h:623
iterator emplace(const_iterator before, Args &&... args)
Definition: qlist.h:528
void reserve(qsizetype size)
Definition: qlist.h:757
reverse_iterator rbegin()
Definition: qlist.h:632
pointer data()
Definition: qlist.h:442
const T & constLast() const noexcept
Definition: qlist.h:648
void removeLast() noexcept
Definition: qlist.h:819
void resize(qsizetype size)
Definition: qlist.h:420
T & first()
Definition: qlist.h:643
static QList< T > fromReadOnlyData(const T(&t)[N]) noexcept
Definition: qlist.h:733
const_iterator cend() const noexcept
Definition: qlist.h:629
void append(parameter_type t)
Definition: qlist.h:469
const_iterator constEnd() const noexcept
Definition: qlist.h:631
const_iterator cbegin() const noexcept
Definition: qlist.h:628
void clear()
Definition: qlist.h:445
QList< T > toList() const noexcept
Definition: qlist.h:727
const_reverse_iterator crend() const noexcept
Definition: qlist.h:637
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
The QScopedValueRollback class resets a variable to its previous value on destruction.
The QSemaphore class provides a general counting semaphore.
Definition: qsemaphore.h:55
void acquire(int n=1)
Definition: qsemaphore.cpp:323
void release(int n=1)
Definition: qsemaphore.cpp:351
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
static QString number(int, int base=10)
Definition: qstring.cpp:7538
static void yieldCurrentThread()
Definition: qthread.cpp:889
#define T(x)
Definition: main.cpp:42
#define this
Definition: dialogs.cpp:56
QString str
[2]
double e
QCOMPARE(spy.count(), 1)
else opt state
[0]
FT_Vector * vec
Definition: ftbbox.c:469
auto generate(StringRef generatorName, SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
Definition: catch_p_p.h:4085
typename C::value_type value_type
[15]
Definition: tst_encoder.cpp:33
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT QTestData & addRow(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition: qtestcase.cpp:2690
char * toString(const MyPoint &point)
typing.Tuple[int, int] test(str binary_directory, *debug=False)
set set set set set set set macro pixldst1 op
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
EGLOutputLayerEXT EGLint EGLAttrib value
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
QList(InputIterator, InputIterator) -> QList< ValueType >
#define qWarning
Definition: qlogging.h:179
GLint GLfloat GLfloat GLfloat v2
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLsizei const GLchar ** strings
[1]
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum src
GLint reference
GLint GLfloat GLfloat v1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLint GLfloat GLfloat GLfloat GLfloat v3
GLint ref
GLint first
GLint y
GLuint counter
const GLubyte * c
Definition: qopenglext.h:12701
GLuint GLfloat * val
Definition: qopenglext.h:1513
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLenum GLenum GLenum input
Definition: qopenglext.h:10816
#define QStringLiteral(str)
#define v1
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
@ Q_RELOCATABLE_TYPE
Definition: qtypeinfo.h:156
Q_UNUSED(salary)
[21]
QLatin1String world("world")
QList< int > vector
[14]
HelloWorldTask * hello
QSharedPointer< T > other(t)
[5]
QSize t2(10, 12)
QList< QTreeWidgetItem * > items
QAction * at
QStringList::Iterator it
QStringList list
[0]
~ConstructionCounted()=default
ConstructionCounted & operator=(ConstructionCounted &&other) noexcept
Definition: tst_qlist.cpp:806
ConstructionCounted & operator=(const ConstructionCounted &other) noexcept
Definition: tst_qlist.cpp:821
ConstructionCounted(int i)
Definition: tst_qlist.cpp:797
ConstructionCounted(ConstructionCounted &&other) noexcept
Definition: tst_qlist.cpp:798
friend bool operator==(const ConstructionCounted &lhs, const ConstructionCounted &rhs)
Definition: tst_qlist.cpp:830
ConstructionCounted(const ConstructionCounted &other) noexcept
Definition: tst_qlist.cpp:817
friend bool operator==(const CustomAligned &x, const CustomAligned &y)
Definition: tst_qlist.cpp:3468
CustomAligned(qint64 i)
Definition: tst_qlist.cpp:3467
CustomAligned()=default
static QAtomicInt counter
Definition: tst_qlist.cpp:186
Custom & operator=(const Custom &other)
Definition: tst_qlist.cpp:179
bool operator==(const Custom &other) const
Definition: tst_qlist.cpp:165
bool operator<(const Custom &other) const
Definition: tst_qlist.cpp:172
char i
Definition: tst_qlist.cpp:188
Custom(const Custom &other)
Definition: tst_qlist.cpp:148
Custom(char input='j')
Definition: tst_qlist.cpp:141
int instancesCount
Definition: tst_qlist.cpp:223
bool operator==(const Movable &other) const
Definition: tst_qlist.cpp:90
Movable & operator=(const Movable &other)
Definition: tst_qlist.cpp:97
Movable(Movable &&other)
Definition: tst_qlist.cpp:72
Movable & operator=(Movable &&other)
Definition: tst_qlist.cpp:105
char i
Definition: tst_qlist.cpp:118
static QAtomicInt counter
Definition: tst_qlist.cpp:119
bool wasConstructedAt(const Movable *other) const
Definition: tst_qlist.cpp:114
Movable(const Movable &other)
Definition: tst_qlist.cpp:64
Movable(char input='j')
Definition: tst_qlist.cpp:57
~Movable()
Definition: tst_qlist.cpp:82
qsizetype lastIndexOf(const QString &str, qsizetype from=-1) const noexcept
Definition: qstringlist.h:160
qsizetype indexOf(const QString &str, qsizetype from=0) const noexcept
Definition: qstringlist.h:158
bool contains(QLatin1String str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition: qstringlist.h:150
RemoveLastTestClass * other
Definition: tst_qlist.cpp:2074
SharedVectorChecker(const QList< T > &original, bool doCopyVector)
Definition: tst_qlist.cpp:1255
QList< T > * copy
Definition: tst_qlist.cpp:1276
static const T Values[MaxIndex]
Definition: tst_qlist.cpp:517
static T at(int index)
Definition: tst_qlist.cpp:503
static const uint MaxIndex
Definition: tst_qlist.cpp:516
static QList< T > vector(int size)
Definition: tst_qlist.cpp:508
Definition: main.cpp:38
bool run(const QString &name, QString *errorMessage)
int fooDtor
Definition: tst_qlist.cpp:2865
#define T_FOO
Definition: tst_qlist.cpp:528
decltype(auto) qlistCopyAndReferenceFromRange(It first, It last)
Definition: tst_qlist.cpp:537
int fooCtor
Definition: tst_qlist.cpp:2864
QAtomicPointer< QList< T > > * detachThreadSafetyData()
Definition: tst_qlist.cpp:3055
#define T_BAR
Definition: tst_qlist.cpp:529
#define T_BAZ
Definition: tst_qlist.cpp:530
QT_END_NAMESPACE Q_DECLARE_METATYPE(Movable)
QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(Movable, Q_RELOCATABLE_TYPE)
size_t qHash(const Movable &key, size_t seed=0)
Definition: tst_qlist.cpp:132
#define TST_QLIST_CHECK_LEAKS(Type)
Definition: tst_qlist.cpp:229
#define CHECK(Type, One, Two, Three)
U convert(const T &t)
#define rhs
QSet< QThread * > threads