QtBase  v6.3.1
tst_collections.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 
30 // test the container forwards
31 #include <QtContainerFwd>
32 
33 static QCache<int, int> *cacheX;
34 static QHash<int, int> *hashX;
35 static QList<int> *listX;
36 static QMap<int, int> *mapX;
37 static QMultiHash<int, int> *multiHashX;
38 static QMultiMap<int, int> *multiMapX;
39 static QPair<int, int> *pairX;
40 static QQueue<int> *queueX;
41 static QSet<int> *setX;
42 static QStack<int> *stackX;
43 static QVarLengthArray<int> *varLengthArrayX;
44 static QVarLengthArray<int, 512> *varLengthArrayY;
45 static QList<int> *vectorX;
46 
47 void foo()
48 {
49  cacheX = 0;
50  hashX = 0;
51  listX = 0;
52  mapX = 0;
53  multiHashX = 0;
54  multiMapX = 0;
55  pairX = 0;
56  queueX = 0;
57  setX = 0;
58  stackX = 0;
59  varLengthArrayX = 0;
60  varLengthArrayY = 0;
61  vectorX = 0;
62 }
63 
64 #include <QTest>
65 #include <QVector>
66 #include <QScopedPointer>
67 #include <QThread>
68 #include <QSemaphore>
69 
70 #include <algorithm>
71 
72 #include "qbitarray.h"
73 #include "qbytearray.h"
74 #include "qcache.h"
75 #include "qhash.h"
76 #include "qlist.h"
77 #include "qmap.h"
78 #include "qpair.h"
79 #include "qregularexpression.h"
80 #include "qset.h"
81 #include "qstack.h"
82 #include "qstring.h"
83 #include "qstringlist.h"
84 #include "qvarlengtharray.h"
85 #include "qqueue.h"
86 
87 class tst_Collections : public QObject
88 {
89  Q_OBJECT
90 
91 private slots:
92  void typeinfo();
93  void qstring();
94  void list();
95  void vector();
96  void byteArray();
97  void stack();
98  void hash();
99  void map();
100  void bitArray();
101  void cache();
102 #if QT_CONFIG(regularexpression)
103  void regexp();
104 #endif
105  void pair();
106  void sharableQList();
107  void sharableQVector();
108  void sharableQMap();
109  void sharableQHash();
110  void q_foreach();
111  void conversions();
112  void javaStyleIterators();
113  void constAndNonConstStlIterators();
114  void vector_stl_data();
115  void vector_stl();
116  void list_stl_data();
117  void list_stl();
118  void q_init();
119  void pointersize();
120  void containerInstantiation();
121  void qtimerList();
122  void containerTypedefs();
123  void forwardDeclared();
124  void alignment();
125  void QTBUG13079_collectionInsideCollection();
126 
127  void foreach_2();
128  void insert_remove_loop();
129 
130  void detachAssociativeContainerQMap() { detachAssociativeContainerImpl<QMap>(); }
131  void detachAssociativeContainerQMultiMap() { detachAssociativeContainerImpl<QMultiMap>(); }
132  void detachAssociativeContainerQHash() { detachAssociativeContainerImpl<QHash>(); }
133  void detachAssociativeContainerQMultiHash() { detachAssociativeContainerImpl<QMultiHash>(); }
134 
135 private:
136  template <template<typename, typename> typename Container>
137  void detachAssociativeContainerImpl();
138 };
139 
140 struct LargeStatic {
141  static int count;
143  LargeStatic(const LargeStatic& o):c(o.c) { ++count; }
145  {
146  c = o.c;
147  ++count;
148  return *this;
149  };
151  int c;
152  int data[8];
153 };
154 
155 int LargeStatic::count = 0;
156 
157 struct Movable {
158  static int count;
159  Movable():c(count) { ++count; }
160  Movable(const Movable& o):c(o.c) { ++count; }
161  ~Movable() { --count; }
162  int c;
163 };
164 
165 int Movable::count = 0;
169 
170 
171 struct Pod {
172  int i1, i2;
173 };
174 
175 // Compile-time checks for recursive containers
176 struct Dummy
177 {
178  bool operator==(const Dummy &) const { return false; }
179  bool operator<(const Dummy &) const { return false; }
180 };
181 
182 struct RecursiveList : public QList<RecursiveList> {};
183 struct RecursiveSet : public QSet<RecursiveSet> {};
184 struct RecursiveMapV : public QMap<Dummy, RecursiveMapV> {};
185 struct RecursiveMapK : public QMap<RecursiveMapK, Dummy> {};
186 struct RecursiveMultiMapV : public QMultiMap<Dummy, RecursiveMultiMapV> {};
187 struct RecursiveMultiMapK : public QMultiMap<RecursiveMultiMapK, Dummy> {};
188 struct RecursiveHashV : public QHash<Dummy, RecursiveHashV> {};
189 struct RecursiveHashK : public QHash<RecursiveHashK, Dummy> {};
190 struct RecursiveMultiHashV : public QMultiHash<Dummy, RecursiveMultiHashV> {};
191 struct RecursiveMultiHashK : public QMultiHash<RecursiveMultiHashK, Dummy> {};
192 
193 struct Empty {};
194 struct NoCmpParamRecursiveMapV : public QMap<Empty, NoCmpParamRecursiveMapV> {};
195 struct NoCmpParamRecursiveMapK : public QMap<NoCmpParamRecursiveMapK, Empty> {};
196 struct NoCmpParamRecursiveMultiMapV : public QMultiMap<Empty, NoCmpParamRecursiveMultiMapV> {};
197 struct NoCmpParamRecursiveMultiMapK : public QMultiMap<NoCmpParamRecursiveMultiMapK, Empty> {};
198 struct NoCmpParamRecursiveHashV : public QHash<Empty, NoCmpParamRecursiveHashV> {};
199 struct NoCmpParamRecursiveHashK : public QHash<NoCmpParamRecursiveHashK, Empty> {};
200 struct NoCmpParamRecursiveMultiHashV : public QMultiHash<Empty, NoCmpParamRecursiveMultiHashV> {};
201 struct NoCmpParamRecursiveMultiHashK : public QMultiHash<NoCmpParamRecursiveMultiHashK, Empty> {};
202 
203 struct NoCmpRecursiveList : public QList<NoCmpRecursiveList>
204 {
205  bool operator==(const RecursiveList &) const = delete;
206  bool operator<(const RecursiveList &) const = delete;
207 };
208 struct NoCmpRecursiveSet : public QSet<NoCmpRecursiveSet>
209 {
210  bool operator==(const NoCmpRecursiveSet &) const = delete;
211 };
212 struct NoCmpRecursiveMapV : public QMap<Dummy, NoCmpRecursiveMapV>
213 {
214  bool operator==(const NoCmpRecursiveMapV &) const = delete;
215 };
216 struct NoCmpRecursiveMapK : public QMap<NoCmpRecursiveMapK, Dummy>
217 {
218  bool operator==(const NoCmpRecursiveMapK &) const = delete;
219 };
220 struct NoCmpRecursiveMultiMapV : public QMultiMap<Dummy, NoCmpRecursiveMultiMapV>
221 {
222  bool operator==(const NoCmpRecursiveMultiMapV &) const = delete;
223 };
224 struct NoCmpRecursiveMultiMapK : public QMultiMap<NoCmpRecursiveMultiMapK, Dummy>
225 {
226  bool operator==(const NoCmpRecursiveMultiMapK &) const = delete;
227 };
228 struct NoCmpRecursiveHashV : public QHash<Dummy, NoCmpRecursiveHashV>
229 {
230  bool operator==(const NoCmpRecursiveHashV &) const = delete;
231 };
232 struct NoCmpRecursiveHashK : public QHash<NoCmpRecursiveHashK, Dummy>
233 {
234  bool operator==(const NoCmpRecursiveHashK &) const = delete;
235 };
236 struct NoCmpRecursiveMultiHashV : public QMultiHash<Dummy, NoCmpRecursiveMultiHashV>
237 {
238  bool operator==(const NoCmpRecursiveMultiHashV &) const = delete;
239 };
240 struct NoCmpRecursiveMultiHashK : public QMultiHash<NoCmpRecursiveMultiHashK, Dummy>
241 {
242  bool operator==(const NoCmpRecursiveMultiHashK &) const = delete;
243 };
244 
245 uint qHash(const Dummy &) { return 0; }
246 uint qHash(const RecursiveSet &) { return 0; }
247 uint qHash(const RecursiveHashK &) { return 0; }
248 uint qHash(const RecursiveHashV &) { return 0; }
249 uint qHash(const RecursiveMultiHashK &) { return 0; }
250 uint qHash(const RecursiveMultiHashV &) { return 0; }
251 
262 
271 
281 
282 static_assert(QTypeTraits::has_operator_equal_v<RecursiveList>);
283 static_assert(QTypeTraits::has_operator_less_than_v<RecursiveList>);
284 static_assert(QTypeTraits::has_operator_equal_v<RecursiveSet>);
285 static_assert(QTypeTraits::has_operator_equal_v<RecursiveMapV>);
286 static_assert(QTypeTraits::has_operator_equal_v<RecursiveMapK>);
287 static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiMapV>);
288 static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiMapK>);
289 static_assert(QTypeTraits::has_operator_equal_v<RecursiveHashV>);
290 static_assert(QTypeTraits::has_operator_equal_v<RecursiveHashK>);
291 static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiHashV>);
292 static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiHashK>);
293 
294 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMapV>);
295 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMapK>);
296 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiMapV>);
297 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiMapK>);
298 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveHashV>);
299 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveHashK>);
300 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiHashV>);
301 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiHashK>);
302 
303 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveList>);
304 static_assert(!QTypeTraits::has_operator_less_than_v<NoCmpRecursiveList>);
305 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveSet>);
306 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMapV>);
307 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMapK>);
308 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiMapV>);
309 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiMapK>);
310 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveHashV>);
311 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveHashK>);
312 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiHashV>);
313 static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiHashK>);
314 
315 template <typename T>
316 constexpr inline bool has_prepend_v = true;
317 template <typename T, qsizetype N>
318 constexpr inline bool has_prepend_v<QVarLengthArray<T,N>> = false; // deprecated in Qt 6.3
319 
320 void tst_Collections::typeinfo()
321 {
326 }
327 
328 void tst_Collections::list()
329 {
330  {
331  QList<int> list;
332  QVERIFY(list.isEmpty());
333  list.append(1);
334  QVERIFY(list.size() == 1);
335 
336  QVERIFY(*list.begin() == 1);
337 
338  list.push_back(2);
339  list += (3);
340  list << 4 << 5 << 6;
341  QVERIFY(!list.isEmpty());
342  QVERIFY(list.size() == 6);
343  QVERIFY(list.end() - list.begin() == list.size());
344 
345  {
346  int sum = 0;
347  QListIterator<int> i(list);
348  while (i.hasNext())
349  sum += i.next();
350  QVERIFY(sum == 21);
351  }
352 
353  {
354  QList<int> list1;
355  list1 << 1 << 2 << 3 << 5 << 7 << 8 << 9;
356  QList<int> list2 = list1;
357 
358  QMutableListIterator<int> i1(list1);
359  while (i1.hasNext()) {
360  if (i1.next() % 2 != 0)
361  i1.remove();
362  }
363 
364  QMutableListIterator<int> i2(list2);
365  i2.toBack();
366  while (i2.hasPrevious()) {
367  if (i2.previous() % 2 != 0)
368  i2.remove();
369  }
370  QVERIFY(list1.size() == 2);
371  QVERIFY(list2.size() == 2);
372  QVERIFY(list1 == list2);
373  }
374 
375  {
376  int sum = 0;
377  for (int i = 0; i < list.size(); ++i)
378  sum += list[i];
379  QVERIFY(sum == 21);
380  }
381  {
382  int sum = 0;
384  while (i != list.end())
385  sum += *i++;
386  QVERIFY(sum == 21);
387  }
388  {
389  int sum = 0;
390  QList<int>::ConstIterator i = list.begin();
391  while (i != list.end())
392  sum += *i++;
393  QVERIFY(sum == 21);
394  }
395  {
396  QList<int>::Iterator i = list.begin();
397  i += 2;
398  QCOMPARE(*i, 3);
399  i -= 1;
400  QCOMPARE(*i, 2);
401  }
402  {
403  QList<int>::ConstIterator i = list.begin();
404  i += 2;
405  QCOMPARE(*i, 3);
406  i -= 1;
407  QCOMPARE(*i, 2);
408  }
409  {
410  int sum = 0;
411  int i;
412  for (i = 0; i < list.size(); ++i)
413  list[i] = list[i] +1;
414  for (i = 0; i < list.size(); ++i)
415  sum += list[i];
416  QVERIFY(sum == 21 + list.size());
417  }
418  {
419  int sum = 0;
420  int i;
421  for (i = 0; i < list.size(); ++i)
422  --list[i];
423  for (i = 0; i < list.size(); ++i)
424  sum += list[i];
425  QVERIFY(sum == 21);
426  }
427  {
428  QMutableListIterator<int> i(list);
429  while (i.hasNext())
430  i.setValue(2*i.next());
431  }
432  {
433  int sum = 0;
434  QListIterator<int> i(list);
435  i.toBack();
436  while (i.hasPrevious())
437  sum += i.previous();
438  QVERIFY(sum == 2*21);
439  }
440  {
441  QMutableListIterator<int> i(list);
442  i.toBack();
443  while (i.hasPrevious())
444  i.setValue(2*i.previous());
445  }
446  {
447  int sum = 0;
448  QListIterator<int> i(list);
449  i.toBack();
450  while (i.hasPrevious())
451  sum += i.previous();
452  QVERIFY(sum == 2*2*21);
453  }
454  {
455  QMutableListIterator<int> i(list);
456  while (i.hasNext()) {
457  int a = i.next();
458  i.insert(a);
459  }
460  }
461  {
462  int sum = 0;
463  QList<int>::iterator i = list.begin();
464  while (i != list.end())
465  sum += *i++;
466  QVERIFY(sum == 2*2*2*21);
467  }
468  {
469  int duplicates = 0;
470  QListIterator<int> i(list);
471  while (i.hasNext()) {
472  int a = i.next();
473  if (i.hasNext() && a == i.peekNext())
474  duplicates++;
475  }
476  QVERIFY(duplicates == 6);
477  }
478  {
479  int duplicates = 0;
480  QListIterator<int> i(list);
481  i.toBack();
482  while (i.hasPrevious()) {
483  int a = i.previous();
484  if (i.hasPrevious() && a == i.peekPrevious())
485  duplicates++;
486  }
487  QVERIFY(duplicates == 6);
488  }
489  {
490  QMutableListIterator<int> i(list);
491  while (i.hasNext()) {
492  int a = i.next();
493  if (i.hasNext() &&
494  i.peekNext() == a)
495  i.remove();
496  }
497  }
498  {
499  int duplicates = 0;
500  QMutableListIterator<int> i = list;
501  i.toBack();
502  while (i.hasPrevious()) {
503  int a = i.previous();
504  if (i.hasPrevious() && a == i.peekPrevious())
505  duplicates++;
506  }
507  QVERIFY(duplicates == 0);
508  }
509  {
510  QVERIFY(list.size() == 6);
511  QMutableListIterator<int> i = list;
512  while (i.hasNext()) {
513  int a = i.peekNext();
514  i.insert(42);
515  QVERIFY(i.peekPrevious() == 42 && i.peekNext() == a);
516  i.next();
517  }
518  QVERIFY(list.size() == 12);
519  i.toFront();
520  while (i.findNext(42))
521  i.remove();
522  }
523  {
524  QList<int> l;
525  l << 4 << 8 << 12 << 16 << 20 << 24;
526  QVERIFY(l == list);
527  QList<int> copy = list;
528  list += list;
529  QVERIFY(l != list && l.size() == list.size()/2 && l == copy);
530  l += copy;
531  QVERIFY(l == list);
532  list = copy;
533  }
534  {
535  QList<int> copy = list;
536  list << 8;
537  QVERIFY(list.indexOf(8) == 1);
538  QVERIFY(list.indexOf(8, list.indexOf(8)+1) == 6);
539  int a = list.indexOf(8);
540  QVERIFY(list.count(8) == 2);
541  int r = list.removeAll(8);
542  QVERIFY(r == 2);
543  list.insert(a, 8);
544  QVERIFY(list == copy);
545  }
546  {
548  list << "one" << "two" << "three" << "four" << "five" << "six";
549  while (!list.isEmpty())
550  list.removeAll(list.first());
551  }
552  {
554  list << "one" << "two" << "one" << "two";
555  QVERIFY(!list.removeOne("three"));
556  QVERIFY(list.removeOne("two"));
557  QCOMPARE(list, QList<QString>() << "one" << "one" << "two");;
558  QVERIFY(list.removeOne("two"));
559  QCOMPARE(list, QList<QString>() << "one" << "one");
560  QVERIFY(!list.removeOne("two"));
561  QCOMPARE(list, QList<QString>() << "one" << "one");
562  QVERIFY(list.removeOne("one"));
563  QCOMPARE(list, QList<QString>() << "one");
564  QVERIFY(list.removeOne("one"));
565  QVERIFY(list.isEmpty());
566  QVERIFY(!list.removeOne("one"));
567  QVERIFY(list.isEmpty());
568  }
569  {
570  QList<int> copy = list;
571  list << 8;
572  QVERIFY(list.lastIndexOf(8) == 6);
573  QVERIFY(list.lastIndexOf(8, list.lastIndexOf(8)-1) == 1);
574  list = copy;
575  }
576  {
577  QList<int> copy = list;
578  list.insert(3, 999);
579  QVERIFY(list[3] == 999);
580  list.replace(3, 222);
581  QVERIFY(list[3] == 222);
582  QVERIFY(list.contains(222) && ! list.contains(999));
583  list.removeAt(3);
584  list = copy;
585  QVERIFY(list == copy);
586  }
587  {
588  list.clear();
589  QVERIFY(list.isEmpty());
590  QVERIFY(list.begin() == list.end());
591  QListIterator<int> i(list);
592  QVERIFY(!i.hasNext() && !i.hasPrevious());
593  }
594  {
595  QList<int> l1;
596  QList<int> l2;
597  l1 << 1 << 2 << 3;
598  l2 << 4 << 5 << 6;
599  QList<int> l3 = l1 + l2;
600  l1 += l2;
601  QVERIFY(l3 == l1);
602  }
603  {
605  QVERIFY(list.isEmpty());
606  list.append(1);
608  list2 = list;
609  list2.clear();
610  QVERIFY(list2.size() == 0);
611  QVERIFY(list.size() == 1);
612  }
613  {
615  list.append(1);
617 QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
618  list = list;
620  QVERIFY(list.size() == 1);
621  }
622  }
623  {
625  list.append(0);
626  list.append((void*)42);
627  QCOMPARE(list.size(), 2);
628  QCOMPARE(list.at(0), (void*)0);
629  QCOMPARE(list.at(1), (void*)42);
630  }
631 
632  {
633  QList<QString> vector(5);
634  vector[0] = "99";
635  vector[4] ="100";
636  QList<QString> list = vector.toList();
637 
638  QVERIFY(list.size() == 5);
639  QCOMPARE(list.at(0), QLatin1String("99"));
640  QCOMPARE(list.at(4), QLatin1String("100"));
641  list[0] = "10";
642  QCOMPARE(list.at(0), QLatin1String("10"));
643  QCOMPARE(vector.at(0), QLatin1String("99"));
644 
645  }
646 
647  {
649  list.append("Hello");
650 
651  QList<QString>::iterator it = list.begin();
652  QVERIFY((*it)[0] == QChar('H'));
653  QVERIFY(it->constData()[0] == QChar('H'));
654  it->replace(QChar('H'), QChar('X'));
655  QCOMPARE(list.first(), QLatin1String("Xello"));
656 
657  QList<QString>::const_iterator cit = list.constBegin();
658  QCOMPARE((*cit).toLower(), QLatin1String("xello"));
659  QCOMPARE(cit->toUpper(), QLatin1String("XELLO"));
660 
661  cit = list.cbegin();
662  QCOMPARE((*cit).toLower(),QLatin1String("xello"));
663  QCOMPARE(cit->toUpper(), QLatin1String("XELLO"));
664  }
665 
666  {
668  QVERIFY(list.value(0) == 0);
669  int i;
670  list.append(&i);
671  QVERIFY(list.value(0) == &i);
672  }
673  {
675  QVERIFY(list.value(0) == 0);
676  int i;
677  list.append(&i);
678  QVERIFY(list.value(0) == &i);
679  }
680  {
682  QVERIFY(list.value(0) == 0);
683  list.append(10);
684  QVERIFY(list.value(0) == 10);
685  }
686  {
688  QCOMPARE(list.value(0).i1, 0);
689  QCOMPARE(list.value(0).i2, 0);
690  }
691 
692  {
694  list << "alpha" << "beta";
695  list += list;
696  QVERIFY(list.size() == 4);
697  QCOMPARE(list.at(0), QLatin1String("alpha"));
698  QCOMPARE(list.at(1), QLatin1String("beta"));
699  QCOMPARE(list.at(2), QLatin1String("alpha"));
700  QCOMPARE(list.at(3), QLatin1String("beta"));
701  }
702 
703  // test endcases for inserting into a qlist
704  {
706  list << "foo" << "bar";
707  QVERIFY(!list.isEmpty());
708 
709  list.insert(0, "atzero");
710  QCOMPARE(list.at(0), QString("atzero"));
711 
712  int listCount = list.count();
713  list.insert(listCount, "atcount");
714  QCOMPARE(list.at(listCount), QString("atcount"));
715  }
716 
717  {
718  QList<int> list1;
719  list1 << 0 << 1 << 2 << 3;
720  list1.removeFirst();
721 
722  list1.swapItemsAt(0, 0);
723  QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
724 
725  list1.swapItemsAt(1, 1);
726  QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
727 
728  list1.swapItemsAt(2, 2);
729  QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
730 
731  list1.swapItemsAt(0, 1);
732  QVERIFY(list1 == QList<int>() << 2 << 1 << 3);
733 
734  list1.swapItemsAt(0, 2);
735  QVERIFY(list1 == QList<int>() << 3 << 1 << 2);
736 
737  list1.swapItemsAt(1, 2);
738  QVERIFY(list1 == QList<int>() << 3 << 2 << 1);
739 
740  list1.swapItemsAt(1, 2);
741  QVERIFY(list1 == QList<int>() << 3 << 1 << 2);
742 
744  list2 << "1" << "2" << "3";
745 
746  list2.swapItemsAt(0, 0);
747  QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
748 
749  list2.swapItemsAt(1, 1);
750  QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
751 
752  list2.swapItemsAt(2, 2);
753  QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
754 
755  list2.swapItemsAt(0, 1);
756  QVERIFY(list2 == QList<QString>() << "2" << "1" << "3");
757 
758  list2.swapItemsAt(0, 2);
759  QVERIFY(list2 == QList<QString>() << "3" << "1" << "2");
760 
761  list2.swapItemsAt(1, 2);
762  QVERIFY(list2 == QList<QString>() << "3" << "2" << "1");
763 
764  list2.swapItemsAt(1, 2);
765  QVERIFY(list2 == QList<QString>() << "3" << "1" << "2");
766 
768  list3 << 1.0 << 2.0 << 3.0;
769 
770  list3.swapItemsAt(0, 0);
771  QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
772 
773  list3.swapItemsAt(1, 1);
774  QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
775 
776  list3.swapItemsAt(2, 2);
777  QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
778 
779  list3.swapItemsAt(0, 1);
780  QVERIFY(list3 == QList<double>() << 2.0 << 1.0 << 3.0);
781 
782  list3.swapItemsAt(0, 2);
783  QVERIFY(list3 == QList<double>() << 3.0 << 1.0 << 2.0);
784 
785  list3.swapItemsAt(1, 2);
786  QVERIFY(list3 == QList<double>() << 3.0 << 2.0 << 1.0);
787 
788  list3.swapItemsAt(1, 2);
789  QVERIFY(list3 == QList<double>() << 3.0 << 1.0 << 2.0);
790  }
791 
792  // Check what happens when using references to own items.
793  // Ideally we should run valgrind on this.
794  {
795  int i;
796 
797  QList<void *> list1;
798  list1.append(reinterpret_cast<void *>(50));
799 
800  for (i = 1; i < 100; ++i) {
801  list1.append(list1.at(i - 1));
802  list1.prepend(list1.at(i));
803  list1.insert(i, list1.at(i - 1));
804  list1.insert(i, list1.at(i));
805  list1.insert(i, list1.at(i + 1));
806  list1.replace(i, list1.at(i - 1));
807  list1.replace(i, list1.at(i));
808  list1.replace(i, list1.at(i + 1));
809  }
810  QCOMPARE(list1.size(), 496);
811  for (i = 0; i < list1.size(); ++i) {
812  QCOMPARE(list1.at(i), reinterpret_cast<void *>(50));
813  }
814 
816  list2.append("50");
817 
818  for (i = 1; i < 100; ++i) {
819  list2.append(list2.at(i - 1));
820  list2.prepend(list2.at(i));
821  list2.insert(i, list2.at(i - 1));
822  list2.insert(i, list2.at(i));
823  list2.insert(i, list2.at(i + 1));
824  list2.replace(i, list2.at(i - 1));
825  list2.replace(i, list2.at(i));
826  list2.replace(i, list2.at(i + 1));
827  }
828  QCOMPARE(list2.size(), 496);
829  for (i = 0; i < list2.size(); ++i) {
831  }
832 
834  list3.append(50.0);
835 
836  for (i = 1; i < 100; ++i) {
837  list3.append(list3.at(i - 1));
838  list3.prepend(list3.at(i));
839  list3.insert(i, list3.at(i - 1));
840  list3.insert(i, list3.at(i));
841  list3.insert(i, list3.at(i + 1));
842  list3.replace(i, list3.at(i - 1));
843  list3.replace(i, list3.at(i));
844  list3.replace(i, list3.at(i + 1));
845  }
846  QCOMPARE(list3.size(), 496);
847  for (i = 0; i < list3.size(); ++i) {
848  QCOMPARE(list3.at(i), 50.0);
849  }
850 
851  QList<QTime> list4;
852  list4.append(QTime(12, 34, 56));
853 
854  for (i = 1; i < 100; ++i) {
855  list4.append(list4.at(i - 1));
856  list4.prepend(list4.at(i));
857  list4.insert(i, list4.at(i - 1));
858  list4.insert(i, list4.at(i));
859  list4.insert(i, list4.at(i + 1));
860  list4.replace(i, list4.at(i - 1));
861  list4.replace(i, list4.at(i));
862  list4.replace(i, list4.at(i + 1));
863  }
864  QCOMPARE(list4.size(), 496);
865  for (i = 0; i < list4.size(); ++i) {
866  QVERIFY(list4.at(i) == QTime(12, 34, 56));
867  }
868 
869  }
870  {
871  QList<int> a;
872  QCOMPARE(a.startsWith(1), false);
873  QCOMPARE(a.endsWith(1), false);
874  a.append(1);
875  QCOMPARE(a.startsWith(1), true);
876  QCOMPARE(a.startsWith(2), false);
877  QCOMPARE(a.endsWith(1), true);
878  QCOMPARE(a.endsWith(2), false);
879  a.append(2);
880  QCOMPARE(a.startsWith(1), true);
881  QCOMPARE(a.startsWith(2), false);
882  QCOMPARE(a.endsWith(1), false);
883  QCOMPARE(a.endsWith(2), true);
884  }
885 }
886 
887 void tst_Collections::vector()
888 {
889  QList<int> v1;
890  v1 << 1 << 2 << 3;
892  v2 << 4 << 5;
894  v3 << 1 << 2 << 3 << 4 << 5;
895  QVERIFY(v1 + v2 == v3);
896 
897  QVector<int> emptyVector;
898  // emptyVector.remove(3, -3); // Q_ASSERT_X() triggered with "index out of range" message.
899  QCOMPARE(emptyVector.size(), 0);
900 
901  emptyVector.remove(0, 0);
902  QCOMPARE(emptyVector.size(), 0);
903 
904  QVector<int> v4;
905  v4 << 1 << 2 << 3;
906  QCOMPARE(v4.size(), 3);
907  v4.remove(1, 0);
908  QCOMPARE(v4.size(), 3);
909 
910  QVector<int> v;
911  v.append(2);
912  QVERIFY(*v.begin() == 2);
913  v.prepend(1);
914  QVERIFY(*v.begin() == 1);
915  QVERIFY(*(v.begin() + 1) == 2);
916 
917  v.clear();
918  v << 1 << 2 << 3;
919  v.insert(v.begin(), 0);
920  v.insert(v.end(), 4);
921  v.insert(v.begin()+2, 9);
922 
924  result << 0 << 1 << 9 << 2 << 3 << 4;
925 
926  QVERIFY( v == result );
927 
928  v.clear();
929  v << 1 << 2 << 3;
930  v.insert(0, 0);
931  v.insert(4, 4);
932  v.insert(2, 9);
933 
934  QVERIFY( v == result );
935 
937  vec << "foo" << "bar";
938  vec.reserve( 512 );
939  QCOMPARE(vec[0], QLatin1String("foo"));
940  QCOMPARE(vec[1], QLatin1String("bar"));
941 
942  int initialLargeStaticCount = LargeStatic::count;
943  {
944  QVector<LargeStatic> vector;
946  vector.resize(0);
947  }
948  QCOMPARE(LargeStatic::count, initialLargeStaticCount);
949 
950  {
952  vector << "alpha" << "beta";
953  vector += vector;
954  QVERIFY(vector.size() == 4);
955  QCOMPARE(vector.at(0), QLatin1String("alpha"));
956  QCOMPARE(vector.at(1), QLatin1String("beta"));
957  QCOMPARE(vector.at(2), QLatin1String("alpha"));
958  QCOMPARE(vector.at(3), QLatin1String("beta"));
959  }
960 
961  int originalLargeStaticCount = LargeStatic::count;
962  {
964  }
965  QVERIFY(LargeStatic::count == originalLargeStaticCount);
966  {
969  }
970  QVERIFY(LargeStatic::count == originalLargeStaticCount);
971  {
973  LargeStatic *dummy = nullptr;
974  for (int i = 0; i < 10000; ++i) {
975  delete dummy;
976  dummy = new LargeStatic;
978  }
979  delete dummy;
980  }
981  QVERIFY(LargeStatic::count == originalLargeStaticCount);
982 
983  int originalMovableCount = Movable::count;
984  {
986  }
987  QVERIFY(Movable::count == originalMovableCount);
988  {
991  }
992  QVERIFY(Movable::count == originalMovableCount);
993  {
995  Movable *dummy = nullptr;
996  for (int i = 0; i < 10000; ++i) {
997  delete dummy;
998  dummy = new Movable;
999  vector.append(Movable());
1000  }
1001  delete dummy;
1002  }
1003  QVERIFY(Movable::count == originalMovableCount);
1004 
1005  // Check what happens when using references to own items.
1006  // Ideally we should run valgrind on this.
1007  {
1008  int i;
1009 
1010  QVector<void *> vect1;
1011  vect1.append(reinterpret_cast<void *>(50));
1012 
1013  for (i = 1; i < 100; ++i) {
1014  vect1.append(vect1.at(i - 1));
1015  vect1.prepend(vect1.at(i));
1016  vect1.insert(i, vect1.at(i - 1));
1017  vect1.insert(i, vect1.at(i));
1018  vect1.insert(i, vect1.at(i + 1));
1019  vect1.replace(i, vect1.at(i - 1));
1020  vect1.replace(i, vect1.at(i));
1021  vect1.replace(i, vect1.at(i + 1));
1022  }
1023  QCOMPARE(vect1.size(), 496);
1024  for (i = 0; i < vect1.size(); ++i) {
1025  QCOMPARE(vect1.at(i), reinterpret_cast<void *>(50));
1026  }
1027 
1028  QVector<QString> vect2;
1029  vect2.append("50");
1030 
1031  for (i = 1; i < 100; ++i) {
1032  vect2.append(vect2.at(i - 1));
1033  vect2.prepend(vect2.at(i));
1034  vect2.insert(i, vect2.at(i - 1));
1035  vect2.insert(i, vect2.at(i));
1036  vect2.insert(i, vect2.at(i + 1));
1037  vect2.replace(i, vect2.at(i - 1));
1038  vect2.replace(i, vect2.at(i));
1039  vect2.replace(i, vect2.at(i + 1));
1040  }
1041  QCOMPARE(vect2.size(), 496);
1042  for (i = 0; i < vect2.size(); ++i) {
1043  QCOMPARE(vect2.at(i), QString::fromLatin1("50"));
1044  }
1045 
1046  QVector<double> vect3;
1047  vect3.append(50.0);
1048 
1049  for (i = 1; i < 100; ++i) {
1050  vect3.append(vect3.at(i - 1));
1051  vect3.prepend(vect3.at(i));
1052  vect3.insert(i, vect3.at(i - 1));
1053  vect3.insert(i, vect3.at(i));
1054  vect3.insert(i, vect3.at(i + 1));
1055  vect3.replace(i, vect3.at(i - 1));
1056  vect3.replace(i, vect3.at(i));
1057  vect3.replace(i, vect3.at(i + 1));
1058  }
1059  QCOMPARE(vect3.size(), 496);
1060  for (i = 0; i < vect3.size(); ++i) {
1061  QCOMPARE(vect3.at(i), 50.0);
1062  }
1063 
1064  QVector<QTime> vect4;
1065  vect4.append(QTime(12, 34, 56));
1066 
1067  for (i = 1; i < 100; ++i) {
1068  vect4.append(vect4.at(i - 1));
1069  vect4.prepend(vect4.at(i));
1070  vect4.insert(i, vect4.at(i - 1));
1071  vect4.insert(i, vect4.at(i));
1072  vect4.insert(i, vect4.at(i + 1));
1073  vect4.replace(i, vect4.at(i - 1));
1074  vect4.replace(i, vect4.at(i));
1075  vect4.replace(i, vect4.at(i + 1));
1076  }
1077  QCOMPARE(vect4.size(), 496);
1078  for (i = 0; i < vect4.size(); ++i) {
1079  QVERIFY(vect4.at(i) == QTime(12, 34, 56));
1080  }
1081  }
1082 
1083  // this used to trigger an uninitialized read in valgrind
1085  foo.resize(144);
1086 
1087  {
1088  QVector<int> a;
1089  QCOMPARE(a.startsWith(1), false);
1090  QCOMPARE(a.endsWith(1), false);
1091  a.append(1);
1092  QCOMPARE(a.startsWith(1), true);
1093  QCOMPARE(a.startsWith(2), false);
1094  QCOMPARE(a.endsWith(1), true);
1095  QCOMPARE(a.endsWith(2), false);
1096  a.append(2);
1097  QCOMPARE(a.startsWith(1), true);
1098  QCOMPARE(a.startsWith(2), false);
1099  QCOMPARE(a.endsWith(1), false);
1100  QCOMPARE(a.endsWith(2), true);
1101  }
1102 }
1103 
1104 void tst_Collections::byteArray()
1105 {
1106  QByteArray hello = "hello";
1107  QByteArray ello = "ello";
1108  QByteArray World = "World";
1109  QByteArray Wor = "Wor";
1110  QByteArray helloWorld = "helloWorld";
1111  QVERIFY(hello + World == helloWorld);
1112  QVERIFY(hello + "World" == helloWorld);
1113  QVERIFY("hello" + World == helloWorld);
1114 
1115  QVERIFY('h' + ello == hello);
1116  QVERIFY(Wor + 'l' + 'd' == "World");
1117  QVERIFY(hello + World == "helloWorld");
1118  QVERIFY(hello + "World" == "helloWorld");
1119  QVERIFY("hello" + World == "helloWorld");
1120  QVERIFY('h' + ello == "hello");
1121  QVERIFY(Wor + 'l' + 'd' == "World");
1122  QVERIFY("helloWorld" == hello + World);
1123  QVERIFY("helloWorld" == hello + "World");
1124  QVERIFY("helloWorld" == "hello" + World);
1125  QVERIFY("hello" == 'h' + ello);
1126  QVERIFY("World" == Wor + 'l' + 'd');
1127 
1128  QVERIFY(hello.contains('e'));
1129  QVERIFY (true == hello.contains('e'));
1130  QVERIFY (hello.contains('e') != false);
1131 
1132  QVERIFY(hello.indexOf('e') == 1);
1133  QVERIFY(hello.indexOf('e', -10) == 1);
1134  QVERIFY(hello.indexOf('l') == 2);
1135  QVERIFY(hello.indexOf('l',2) == 2);
1136  QVERIFY(hello.indexOf('l',3) == 3);
1137 
1138  QByteArray empty;
1139  QCOMPARE(empty.indexOf("x"), -1);
1140  QCOMPARE(empty.lastIndexOf("x"), -1);
1141  QCOMPARE(empty.lastIndexOf("x", 0), -1);
1142  QCOMPARE(empty.count("x"), 0);
1143  QCOMPARE(empty.indexOf(""), 0);
1144  QCOMPARE(empty.lastIndexOf(""), 0);
1145  QCOMPARE(empty.lastIndexOf("", -1), -1);
1146  QCOMPARE(empty.count(""), 1);
1147 
1148  QByteArray large = "000 100 200 300 400 500 600 700 800 900";
1149 
1150  QVERIFY(large.indexOf("700") == 28);
1151  QVERIFY(large.indexOf("700", 28) == 28);
1152  QVERIFY(large.indexOf("700", 29) == -1);
1153  QVERIFY(large.lastIndexOf("700") == 28);
1154  QVERIFY(large.lastIndexOf("700", 28) == 28);
1155  QVERIFY(large.lastIndexOf("700", 27) == -1);
1156 
1157  QVERIFY(large.contains("200"));
1158  QVERIFY(!large.contains("201"));
1159  QVERIFY(large.contains('3'));
1160  QVERIFY(!large.contains('a'));
1161 
1162  QVERIFY(large.count("00") == 11);
1163  QVERIFY(large.count('3') == 1);
1164  QVERIFY(large.count('0') == 21);
1165  QVERIFY(large.count("0") == 21);
1166  QVERIFY(large.count("200") == 1);
1167  QVERIFY(large.count("201") == 0);
1168 
1169  QVERIFY(hello.left(0) == "");
1170  QVERIFY(!hello.left(0).isNull());
1171  QVERIFY(hello.left(1) == "h");
1172  QVERIFY(hello.left(2) == "he");
1173  QVERIFY(hello.left(200) == "hello");
1174  QVERIFY(hello.left(hello.size()) == hello);
1175  QVERIFY(hello.left(hello.size()+1) == hello);
1176 
1177  QVERIFY(hello.right(0) == "");
1178  QVERIFY(!hello.right(0).isNull());
1179  QVERIFY(hello.right(1) == "o");
1180  QVERIFY(hello.right(2) == "lo");
1181  QVERIFY(hello.right(200) == "hello");
1182  QVERIFY(hello.right(hello.size()) == hello);
1183  QVERIFY(hello.right(hello.size()+1) == hello);
1184 
1185  QVERIFY(!hello.mid(0, 0).isNull());
1186  QVERIFY(hello.mid(0, 1) == "h");
1187  QVERIFY(hello.mid(0, 2) == "he");
1188  QVERIFY(hello.mid(0, 200) == "hello");
1189  QVERIFY(hello.mid(0) == "hello");
1190  QVERIFY(hello.mid(0, hello.size()) == hello);
1191  QVERIFY(hello.mid(0, hello.size()+1) == hello);
1192 
1193  QVERIFY(hello.mid(hello.size()-0) == "");
1194  QVERIFY(hello.mid(hello.size()-0).isEmpty());
1195  QVERIFY(!hello.mid(hello.size()-0).isNull());
1196  QVERIFY(hello.mid(hello.size()-1) == "o");
1197  QVERIFY(hello.mid(hello.size()-2) == "lo");
1198  QVERIFY(hello.mid(hello.size()-200) == "hello");
1199 
1200  QByteArray nullByteArray;
1201  QByteArray nonNullByteArray = "";
1202  QVERIFY(nullByteArray.left(10).isNull());
1203  QVERIFY(nullByteArray.mid(0).isNull());
1204 
1205  QVERIFY(nullByteArray.isEmpty() == nonNullByteArray.isEmpty());
1206  QVERIFY(nullByteArray.size() == nonNullByteArray.size());
1207 
1208  QVERIFY(nullByteArray == QByteArray()); // QByteArray() is both null and empty.
1209  QVERIFY(QByteArray() == nullByteArray);
1210 
1211  QVERIFY(nonNullByteArray == QByteArray("")); // QByteArray("") is empty, but not null.
1212  QVERIFY(QByteArray("") == nonNullByteArray);
1213 
1214  QVERIFY(nullByteArray == nonNullByteArray);
1215  QVERIFY(QByteArray() == QByteArray(""));
1216 
1217  QByteArray str = "Hello";
1218  QByteArray cstr(str.data(), str.size());
1219  QVERIFY(str == "Hello");
1220  QVERIFY(cstr == "Hello");
1221  cstr.clear();
1222  QVERIFY(str == "Hello");
1223  QVERIFY(cstr.isEmpty());
1224 
1225  {
1226  QByteArray ba1("Foo");
1227  ba1.prepend(ba1);
1228  QCOMPARE(ba1, QByteArray("FooFoo"));
1229  ba1.append(ba1);
1230  QCOMPARE(ba1, QByteArray("FooFooFooFoo"));
1231  ba1.insert(2, ba1);
1232  QCOMPARE(ba1, QByteArray("FoFooFooFooFoooFooFooFoo"));
1233  ba1.replace(3, 3, ba1);
1234  QCOMPARE(ba1, QByteArray("FoFFoFooFooFooFoooFooFooFooooFooFoooFooFooFoo"));
1235  ba1 = "FooFoo";
1236  ba1.replace(char('F'), ba1);
1237  QCOMPARE(ba1, QByteArray("FooFooooFooFoooo"));
1238  ba1 = "FooFoo";
1239  ba1.replace(char('o'), ba1);
1240  QCOMPARE(ba1, QByteArray("FFooFooFooFooFFooFooFooFoo"));
1241 
1242  ba1.replace(ba1, "xxx");
1243  QCOMPARE(ba1, QByteArray("xxx"));
1244  ba1.replace(ba1, QByteArray("yyy"));
1245  QCOMPARE(ba1, QByteArray("yyy"));
1246  ba1 += ba1;
1247  QCOMPARE(ba1, QByteArray("yyyyyy"));
1248 
1249  ba1.remove(1, -1); // do nothing
1250  QCOMPARE(ba1, QByteArray("yyyyyy"));
1251 
1252  ba1.replace(0, -1, "ZZZ");
1253  QCOMPARE(ba1, QByteArray("ZZZyyyyyy"));
1254  }
1255 };
1256 
1257 void tst_Collections::stack()
1258 {
1259  QStack<int> stack;
1260  stack.push(1);
1261  stack.push(2);
1262  stack.push(3);
1263  QListIterator<int> i = stack;
1264  i.toBack();
1265  int sum = 0;
1266  while (i.hasPrevious())
1267  sum += i.previous();
1268  QVERIFY(sum == 6);
1269 
1270  sum = 0;
1271  for (QStack<int>::iterator i = stack.begin(); i != stack.end(); ++i)
1272  sum += *i;
1273  QVERIFY(sum == 6);
1274 
1275  while (!stack.isEmpty())
1276  sum -= stack.pop();
1277  QVERIFY(sum == 0);
1278 }
1279 
1280 void tst_Collections::hash()
1281 {
1282  const char *hello = "hello";
1283  const char *world = "world";
1284  const char *allo = "allo";
1285  const char *monde = "monde";
1286 
1287  {
1288  typedef QHash<QString, QString> Hash;
1289  Hash hash;
1290  QString key = QLatin1String(" ");
1291  for (int i = 0; i < 10; ++i) {
1292  key[0] = QChar(i + '0');
1293  for (int j = 0; j < 10; ++j) {
1294  key[1] = QChar(j + '0');
1295  hash.insert(key, "V" + key);
1296  }
1297  }
1298 
1299  for (int i = 0; i < 10; ++i) {
1300  key[0] = QChar(i + '0');
1301  for (int j = 0; j < 10; ++j) {
1302  key[1] = QChar(j + '0');
1303  hash.remove(key);
1304  }
1305  }
1306  }
1307 
1308  {
1310  Hash hash;
1311  hash.insert(1, hello);
1312  hash.insert(2, world);
1313 
1314  QVERIFY(hash.size() == 2);
1315  QVERIFY(!hash.isEmpty());
1316 
1318 QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
1319  {
1320  Hash hash2 = hash;
1321  hash2 = hash;
1322  hash = hash2;
1323  hash2 = hash2;
1324  hash = hash;
1325  hash2.clear();
1326  hash2 = hash2;
1327  QVERIFY(hash2.size() == 0);
1328  QVERIFY(hash2.isEmpty());
1329  }
1330  QVERIFY(hash.size() == 2);
1332 
1333  {
1334  Hash hash2 = hash;
1335  hash2[1] = allo;
1336  hash2[2] = monde;
1337 
1338  QVERIFY(hash2[1] == allo);
1339  QVERIFY(hash2[2] == monde);
1340  QVERIFY(hash[1] == hello);
1341  QVERIFY(hash[2] == world);
1342 
1343  hash2[1] = hash[1];
1344  hash2[2] = hash[2];
1345 
1346  QVERIFY(hash2[1] == hello);
1347  QVERIFY(hash2[2] == world);
1348 
1349  hash[1] = hash[1];
1350  QVERIFY(hash[1] == hello);
1351  }
1352 
1353  {
1354  Hash hash2 = hash;
1355  hash2.detach();
1356  hash2.remove(1);
1357  QVERIFY(hash2.size() == 1);
1358  hash2.remove(1);
1359  QVERIFY(hash2.size() == 1);
1360  hash2.remove(0);
1361  QVERIFY(hash2.size() == 1);
1362  hash2.remove(2);
1363  QVERIFY(hash2.size() == 0);
1364  QVERIFY(hash.size() == 2);
1365  }
1366 
1367  hash.detach();
1368 
1369  {
1370  Hash::iterator it1 = hash.find(1);
1371  QVERIFY(it1 != hash.end());
1372 
1373  Hash::iterator it2 = hash.find(0);
1374  QVERIFY(it2 != hash.begin());
1375  QVERIFY(it2 == hash.end());
1376 
1377  *it1 = monde;
1378  QVERIFY(*it1 == monde);
1379  QVERIFY(hash[1] == monde);
1380 
1381  *it1 = hello;
1382  QVERIFY(*it1 == hello);
1383  QVERIFY(hash[1] == hello);
1384 
1385  hash[1] = monde;
1386  QVERIFY(it1.key() == 1);
1387  QVERIFY(it1.value() == monde);
1388  QVERIFY(*it1 == monde);
1389  QVERIFY(hash[1] == monde);
1390 
1391  hash[1] = hello;
1392  QVERIFY(*it1 == hello);
1393  QVERIFY(hash[1] == hello);
1394  }
1395 
1396  {
1397  const Hash hash2 = hash;
1398 
1399  Hash::const_iterator it1 = hash2.find(1);
1400  QVERIFY(it1 != hash2.end());
1401  QVERIFY(it1.key() == 1);
1402  QVERIFY(it1.value() == hello);
1403  QVERIFY(*it1 == hello);
1404 
1405  Hash::const_iterator it2 = hash2.find(2);
1406  QVERIFY(it1 != it2);
1407  QVERIFY(it1 != hash2.end());
1408  QVERIFY(it2 != hash2.end());
1409 
1410  int count = 0;
1411  it1 = hash2.begin();
1412  while (it1 != hash2.end()) {
1413  count++;
1414  ++it1;
1415  }
1416  QVERIFY(count == 2);
1417 
1418  count = 0;
1419  it1 = hash.begin();
1420  while (it1 != hash.end()) {
1421  count++;
1422  ++it1;
1423  }
1424  QVERIFY(count == 2);
1425  }
1426 
1427  {
1428  QVERIFY(hash.contains(1));
1429  QVERIFY(hash.contains(2));
1430  QVERIFY(!hash.contains(0));
1431  QVERIFY(!hash.contains(3));
1432  }
1433 
1434  {
1435  QVERIFY(hash.value(1) == hello);
1436  QVERIFY(hash.value(2) == world);
1437  QVERIFY(hash.value(3) == 0);
1438  QVERIFY(hash.value(1, allo) == hello);
1439  QVERIFY(hash.value(2, allo) == world);
1440  QVERIFY(hash.value(3, allo) == allo);
1441  QVERIFY(hash.value(0, monde) == monde);
1442  }
1443 
1444  {
1446  for (int i = 0; i < 10; i++)
1447  hash.insert(i, LargeStatic());
1448  QVERIFY(LargeStatic::count == 10);
1449  hash.remove(7);
1451 
1452  }
1454  {
1456  QVERIFY(((const QHash<int,int*>*) &hash)->operator[](7) == 0);
1457  }
1458 
1459  {
1460  /*
1461  This test relies on a certain implementation of
1462  QHash. If you change the way QHash works internally,
1463  change this test as well.
1464  */
1466  for (int i = 0; i < 1000; ++i)
1467  hash.insert(i, i);
1468  QVERIFY(hash.capacity() > 1000);
1469 
1470  for (int j = 0; j < 900; ++j)
1471  hash.remove(j);
1472  QVERIFY(hash.capacity() > 1000);
1473  hash.squeeze();
1474  QVERIFY(hash.capacity() < 200);
1475  }
1476  }
1477 
1478  {
1480  hash.insert(0, "Hello");
1481 
1483  QVERIFY((*it)[0] == QChar('H'));
1484  QVERIFY(it->constData()[0] == QChar('H'));
1485  it->replace(QChar('H'), QChar('X'));
1486  QCOMPARE(*hash.begin(), QLatin1String("Xello"));
1487 
1488  QHash<int, QString>::const_iterator cit = hash.constBegin();
1489  QCOMPARE((*cit).toLower(), QLatin1String("xello"));
1490  QCOMPARE(cit->toUpper(), QLatin1String("XELLO"));
1491 
1492  cit = hash.cbegin();
1493  QCOMPARE((*cit).toLower(), QLatin1String("xello"));
1494  QCOMPARE(cit->toUpper(), QLatin1String("XELLO"));
1495  }
1496 
1497  {
1498  QMultiHash<int, QString> hash1, hash2;
1499  hash1.insert(1, "Alpha");
1500  hash1.insert(1, "Gamma");
1501  hash2.insert(1, "Beta");
1502  hash2.insert(1, "Gamma");
1503  hash2.insert(1, "Gamma");
1504 
1505  hash1.unite(hash2);
1506  QCOMPARE(hash1.size(), 5);
1507  auto values = hash1.values();
1508  std::sort(values.begin(), values.end());
1509  QList<QString> expected;
1510  expected << "Gamma" << "Gamma" << "Beta" << "Gamma" << "Alpha";
1511  std::sort(expected.begin(), expected.end());
1512  QCOMPARE(values, expected);
1513 
1514  hash2 = hash1;
1515  hash2.unite(hash2);
1516  QCOMPARE(hash2.size(), 10);
1517  values = hash2.values();
1518  std::sort(values.begin(), values.end());
1519  expected += expected;
1520  std::sort(expected.begin(), expected.end());
1521  QCOMPARE(values, expected);
1522  }
1523 }
1524 
1525 void tst_Collections::map()
1526 {
1527  const char *hello = "hello";
1528  const char *world = "world";
1529  const char *allo = "allo";
1530  const char *monde = "monde";
1531 
1532  {
1533  typedef QMap<int, const char *> Map;
1534  Map map;
1535  map.insert(1, hello);
1536  map.insert(2, world);
1537 
1538  QVERIFY(*map.begin() == hello);
1539 
1540  QVERIFY(map.size() == 2);
1541  QVERIFY(!map.isEmpty());
1542 
1544 QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
1545  {
1546  Map map2 = map;
1547  map2 = map;
1548  map = map2;
1549  map2 = map2;
1550  map = map;
1551  map2.clear();
1552  map2 = map2;
1553  QVERIFY(map2.size() == 0);
1554  QVERIFY(map2.isEmpty());
1555  }
1556  QVERIFY(map.size() == 2);
1558 
1559  {
1560  Map map2 = map;
1561  map2[1] = allo;
1562  map2[2] = monde;
1563 
1564  QVERIFY(map2[1] == allo);
1565  QVERIFY(map2[2] == monde);
1566  QVERIFY(map[1] == hello);
1567  QVERIFY(map[2] == world);
1568 
1569  map2[1] = map[1];
1570  map2[2] = map[2];
1571 
1572  QVERIFY(map2[1] == hello);
1573  QVERIFY(map2[2] == world);
1574 
1575  map[1] = map[1];
1576  QVERIFY(map[1] == hello);
1577  }
1578 
1579  {
1580  Map map2 = map;
1581  map2.detach();
1582  map2.remove(1);
1583  QVERIFY(map2.size() == 1);
1584  map2.remove(1);
1585  QVERIFY(map2.size() == 1);
1586  map2.remove(0);
1587  QVERIFY(map2.size() == 1);
1588  map2.remove(2);
1589  QVERIFY(map2.size() == 0);
1590  QVERIFY(map.size() == 2);
1591  }
1592 
1593  map.detach();
1594 
1595  {
1596  Map::iterator it1 = map.find(1);
1597  QVERIFY(it1 == map.begin());
1598  QVERIFY(it1 != map.end());
1599 
1600  Map::iterator it2 = map.find(0);
1601  QVERIFY(it2 != map.begin());
1602  QVERIFY(it2 == map.end());
1603 
1604  *it1 = monde;
1605  QVERIFY(*it1 == monde);
1606  QVERIFY(map[1] == monde);
1607 
1608  *it1 = hello;
1609  QVERIFY(*it1 == hello);
1610  QVERIFY(map[1] == hello);
1611 
1612  map[1] = monde;
1613  QVERIFY(it1.key() == 1);
1614  QVERIFY(it1.value() == monde);
1615  QVERIFY(*it1 == monde);
1616  QVERIFY(map[1] == monde);
1617 
1618  map[1] = hello;
1619  QVERIFY(*it1 == hello);
1620  QVERIFY(map[1] == hello);
1621 
1622  *++it1 = allo;
1623  QVERIFY(*it1 == allo);
1624  QVERIFY(map[2] == allo);
1625  *it1 = world;
1626 
1627  ++it1;
1628  QVERIFY(it1 == map.end());
1629 
1630  int count = 0;
1631  it1 = map.begin();
1632  while (it1 != map.end()) {
1633  count++;
1634  ++it1;
1635  }
1636  QVERIFY(count == 2);
1637  }
1638 
1639  {
1640  const Map map2 = map;
1641 
1642  Map::const_iterator it1 = map2.find(1);
1643  QVERIFY(it1 != map2.end());
1644  QVERIFY(it1.key() == 1);
1645  QVERIFY(it1.value() == hello);
1646  QVERIFY(*it1 == hello);
1647  ++it1;
1648 
1649  Map::const_iterator it2 = map2.find(2);
1650  QVERIFY(it1 == it2);
1651  ++it1;
1652  QVERIFY(it1 == map2.end());
1653  QVERIFY(it2 != map2.end());
1654  QVERIFY(it1 != it2);
1655 
1656  int count = 0;
1657  it1 = map2.begin();
1658  while (it1 != map2.end()) {
1659  count++;
1660  ++it1;
1661  }
1662  QVERIFY(count == 2);
1663 
1664  count = 0;
1665  it1 = map.begin();
1666  while (it1 != map.end()) {
1667  count++;
1668  ++it1;
1669  }
1670  QVERIFY(count == 2);
1671  }
1672 
1673  {
1674  QVERIFY(map.contains(1));
1675  QVERIFY(map.contains(2));
1676  QVERIFY(!map.contains(0));
1677  QVERIFY(!map.contains(3));
1678  }
1679 
1680  {
1681  QVERIFY(map.value(1) == hello);
1682  QVERIFY(map.value(2) == world);
1683  QVERIFY(map.value(3) == 0);
1684  QVERIFY(map.value(1, allo) == hello);
1685  QVERIFY(map.value(2, allo) == world);
1686  QVERIFY(map.value(3, allo) == allo);
1687  QVERIFY(map.value(0, monde) == monde);
1688  }
1689  int originalLargeStaticCount = LargeStatic::count;
1690  {
1692  for (int i = 0; i < 10; i++)
1693  map.insert(i, LargeStatic());
1694  QVERIFY(LargeStatic::count == (originalLargeStaticCount + 10));
1695  map.remove(7);
1696  QVERIFY(LargeStatic::count == (originalLargeStaticCount + 9));
1697 
1698  }
1699  QVERIFY(LargeStatic::count == originalLargeStaticCount);
1700  {
1702  QVERIFY(((const QMap<int,int*>*) &map)->operator[](7) == 0);
1703  }
1704 
1705  {
1707  map[0] = 1;
1708  map[1] = 2;
1709  map[2] = 4;
1710  map[3] = 8;
1711  int sum = 0;
1712  int sumkey = 0;
1713  QMapIterator<int,int> i = map;
1714  while (i.hasNext()) {
1715  sum += i.next().value();
1716  sumkey += i.key();
1717  }
1718  QVERIFY(sum == 15);
1719  QVERIFY(sumkey == 6);
1720  }
1721  {
1723  map[0] = 1;
1724  map[1] = 2;
1725  map[2] = 4;
1726  map[3] = 8;
1727  int sum = 0;
1728  QMutableMapIterator<int,int> i = map;
1729  while (i.hasNext())
1730  if (i.next().key() == 2)
1731  i.remove();
1732  i.toFront();
1733  while (i.hasNext()) {
1734  sum += i.next().value();
1735  i.setValue(10);
1736  i.value() += 22;
1737  QVERIFY(i.value() == 32);
1738  }
1739  QVERIFY(sum == 11);
1740  }
1741  {
1743  map[0] = 1;
1744  QMutableMapIterator<int,int> i(map);
1745  i.toBack();
1746  while (i.hasPrevious()) {
1747  i.previous();
1748  QCOMPARE(i.key(), 0);
1749  QCOMPARE(i.value(), 1);
1750  }
1751  }
1752  }
1753 
1754  {
1756  map1.insert("1", 2);
1757  map1.insert("1", 1);
1758  map1.insert("a", 3);
1759  map1.insert("a", 2);
1760  map1.insert("a", 1);
1761  map1.insert("b", 2);
1762  map1.insert("b", 1);
1763 
1765 
1766  j1 = map1.lowerBound("0"); k1 = map1.upperBound("0");
1767  QVERIFY(j1 == map1.begin() && k1 == j1);
1768  j1 = map1.lowerBound("00"); k1 = map1.upperBound("00");
1769  QVERIFY(j1 == map1.find("1") && k1 == j1);
1770  j1 = map1.lowerBound("1"); k1 = map1.upperBound("1");
1771  QVERIFY(j1 == map1.find("1") && --(--k1) == j1);
1772  j1 = map1.lowerBound("11"); k1 = map1.upperBound("11");
1773  QVERIFY(j1 == map1.find("a") && k1 == j1);
1774  j1 = map1.lowerBound("a"); k1 = map1.upperBound("a");
1775  QVERIFY(j1 == map1.find("a") && k1 == map1.find("b"));
1776  QVERIFY(j1.value() == 1 && j1.value() == 1);
1777  j1 = map1.lowerBound("aa"); k1 = map1.upperBound("aa");
1778  QVERIFY(j1 == map1.find("b") && k1 == j1);
1779  QVERIFY(j1.value() == 1);
1780  j1 = map1.lowerBound("b"); k1 = map1.upperBound("b");
1781  QVERIFY(j1 == map1.find("b") && k1 == map1.end());
1782  QVERIFY(j1.value() == 1);
1783  j1 = map1.lowerBound("bb"); k1 = map1.upperBound("bb");
1784  QVERIFY(j1 == map1.end() && k1 == j1);
1785 
1786  const QMultiMap<QString, int> map2 = map1;
1788 
1789  j2 = map2.lowerBound("0"); k2 = map2.upperBound("0");
1790  QVERIFY(j2 == map2.begin() && k2 == j2);
1791  j2 = map2.lowerBound("00"); k2 = map2.upperBound("00");
1792  QVERIFY(j2 == map2.find("1") && k2 == j2);
1793  j2 = map2.lowerBound("1"); k2 = map2.upperBound("1");
1794  QVERIFY(j2 == map2.find("1") && --(--k2) == j2);
1795  j2 = map2.lowerBound("11"); k2 = map2.upperBound("11");
1796  QVERIFY(j2 == map2.find("a") && k2 == j2);
1797  j2 = map2.lowerBound("a"); k2 = map2.upperBound("a");
1798  QVERIFY(j2 == map2.find("a") && k2 == map2.find("b"));
1799  QVERIFY(j2.value() == 1 && j2.value() == 1);
1800  j2 = map2.lowerBound("aa"); k2 = map2.upperBound("aa");
1801  QVERIFY(j2 == map2.find("b") && k2 == j2);
1802  QVERIFY(j2.value() == 1);
1803  j2 = map2.lowerBound("b"); k2 = map2.upperBound("b");
1804  QVERIFY(j2 == map2.find("b") && k2 == map2.end());
1805  QVERIFY(j2.value() == 1);
1806  j2 = map2.lowerBound("bb"); k2 = map2.upperBound("bb");
1807  QVERIFY(j2 == map2.end() && k2 == j2);
1808  }
1809 
1810  {
1812  map.insert(0, "Hello");
1813 
1815  QVERIFY((*it)[0] == QChar('H'));
1816  QVERIFY(it->constData()[0] == QChar('H'));
1817  it->replace(QChar('H'), QChar('X'));
1818  QCOMPARE(*map.begin(), QLatin1String("Xello"));
1819 
1821  QCOMPARE((*cit).toLower(), QLatin1String("xello"));
1822  QCOMPARE(cit->toUpper(), QLatin1String("XELLO"));
1823 
1824  cit = map.cbegin();
1825  QCOMPARE((*cit).toLower(), QLatin1String("xello"));
1826  QCOMPARE(cit->toUpper(), QLatin1String("XELLO"));
1827  }
1828 
1829  {
1830  QMultiMap<int, QString> map1, map2;
1831  map1.insert(1, "Alpha");
1832  map1.insert(1, "Gamma");
1833  map2.insert(1, "Beta");
1834  map2.insert(1, "Gamma");
1835  map2.insert(1, "Gamma");
1836 
1837  map1.unite(map2);
1838  QCOMPARE(map1.size(), 5);
1839  QCOMPARE(static_cast<QStringList>(map1.values()),
1840  (QStringList() << "Gamma" << "Gamma" << "Beta" << "Gamma" << "Alpha"));
1841 
1842  map2 = map1;
1843  map2.unite(map2);
1844  QCOMPARE(map2.size(), 10);
1845  QCOMPARE(map2.values(), map1.values() + map1.values());
1846  }
1847 }
1848 
1849 void tst_Collections::qstring()
1850 {
1851  QString hello = "hello";
1852  QString ello = "ello";
1853  QString World = "World";
1854  QString Wor = "Wor";
1855  QString helloWorld = "helloWorld";
1856 
1857  QString s = hello + "World";
1858  QVERIFY(hello + World == helloWorld);
1859  QVERIFY(hello + "World" == helloWorld);
1860  QVERIFY("hello" + World == helloWorld);
1861 
1862  QVERIFY('h' + ello == hello);
1863  QVERIFY(Wor + 'l' + 'd' == "World");
1864  QVERIFY(hello + World == "helloWorld");
1865  QVERIFY(hello + "World" == "helloWorld");
1866  QVERIFY("hello" + World == "helloWorld");
1867  QVERIFY('h' + ello == "hello");
1868  QVERIFY(Wor + 'l' + 'd' == "World");
1869  QVERIFY("helloWorld" == hello + World);
1870  QVERIFY("helloWorld" == hello + "World");
1871  QVERIFY("helloWorld" == "hello" + World);
1872  QVERIFY("hello" == 'h' + ello);
1873  QVERIFY("World" == Wor + 'l' + 'd');
1874 
1875  QVERIFY(hello.contains('e'));
1876  QVERIFY (true == hello.contains('e'));
1877  QVERIFY (hello.contains('e') != false);
1878 
1879  QVERIFY(hello.indexOf('e') == 1);
1880  QVERIFY(hello.indexOf('e', -10) == -1);
1881  QVERIFY(hello.indexOf('l') == 2);
1882  QVERIFY(hello.indexOf('l',2) == 2);
1883  QVERIFY(hello.indexOf('l',3) == 3);
1884 
1885  QString empty;
1886  QCOMPARE(empty.indexOf("x"), -1);
1887  QCOMPARE(empty.lastIndexOf("x"), -1);
1888  QCOMPARE(empty.lastIndexOf("x", 0), -1);
1889  QCOMPARE(empty.count("x"), 0);
1890  QCOMPARE(empty.indexOf(""), 0);
1891  QCOMPARE(empty.lastIndexOf(""), 0);
1892  QCOMPARE(empty.lastIndexOf("", -1), -1);
1893  QCOMPARE(empty.count(""), 1);
1894 
1895  QString large = "000 100 200 300 400 500 600 700 800 900";
1896 
1897  QVERIFY(large.indexOf("700") == 28);
1898  QVERIFY(large.indexOf("700", 28) == 28);
1899  QVERIFY(large.indexOf("700", 29) == -1);
1900  QVERIFY(large.lastIndexOf("700") == 28);
1901  QVERIFY(large.lastIndexOf("700", 28) == 28);
1902  QVERIFY(large.lastIndexOf("700", 27) == -1);
1903 
1904  QCOMPARE(large.indexOf(""), 0);
1905  QCOMPARE(large.indexOf(QString()), 0);
1906  QCOMPARE(large.indexOf(QLatin1String()), 0);
1907  QCOMPARE(large.indexOf(QStringView()), 0);
1908  QCOMPARE(large.lastIndexOf(""), large.size());
1909  QCOMPARE(large.lastIndexOf("", -1), large.size() - 1);
1910  QCOMPARE(large.lastIndexOf(QString()), large.size());
1911  QCOMPARE(large.lastIndexOf(QLatin1String()), large.size());
1912  QCOMPARE(large.lastIndexOf(QStringView()), large.size());
1913  QCOMPARE(large.count(""), large.size() + 1);
1914  QCOMPARE(large.count(QString()), large.size() + 1);
1915  QCOMPARE(large.count(QLatin1String()), large.size() + 1);
1916  QCOMPARE(large.count(QStringView()), large.size() + 1);
1917 
1918  QVERIFY(large.contains("200"));
1919  QVERIFY(!large.contains("201"));
1920  QVERIFY(large.contains('3'));
1921  QVERIFY(!large.contains('a'));
1922 
1923  QVERIFY(large.count("00") == 11);
1924  QVERIFY(large.count('3') == 1);
1925  QVERIFY(large.count('0') == 21);
1926  QVERIFY(large.count("0") == 21);
1927  QVERIFY(large.count("200") == 1);
1928  QVERIFY(large.count("201") == 0);
1929 
1930  QVERIFY(hello.left(0) == "");
1931  QVERIFY(!hello.left(0).isNull());
1932  QCOMPARE(hello.left(1), QLatin1String("h"));
1933  QCOMPARE(hello.left(2), QLatin1String("he"));
1934  QCOMPARE(hello.left(200), QLatin1String("hello"));
1935  QVERIFY(hello.left(hello.size()) == hello);
1936  QVERIFY(hello.left(hello.size()+1) == hello);
1937 
1938  QVERIFY(hello.right(0) == "");
1939  QVERIFY(!hello.right(0).isNull());
1940  QCOMPARE(hello.right(1), QLatin1String("o"));
1941  QCOMPARE(hello.right(2), QLatin1String("lo"));
1942  QCOMPARE(hello.right(200), QLatin1String("hello"));
1943  QVERIFY(hello.right(hello.size()) == hello);
1944  QVERIFY(hello.right(hello.size()+1) == hello);
1945 
1946  QVERIFY(!hello.mid(0, 0).isNull());
1947  QVERIFY(hello.mid(0, 1) == "h");
1948  QVERIFY(hello.mid(0, 2) == "he");
1949  QVERIFY(hello.mid(0, 200) == "hello");
1950  QCOMPARE(hello.mid(0), QLatin1String("hello"));
1951  QVERIFY(hello.mid(0, hello.size()) == hello);
1952  QVERIFY(hello.mid(0, hello.size()+1) == hello);
1953 
1954  QVERIFY(hello.mid(hello.size()-0) == "");
1955  QVERIFY(hello.mid(hello.size()-0).isEmpty());
1956  QVERIFY(!hello.mid(hello.size()-0).isNull());
1957  QCOMPARE(hello.mid(hello.size()-1), QLatin1String("o"));
1958  QCOMPARE(hello.mid(hello.size()-2), QLatin1String("lo"));
1959  QCOMPARE(hello.mid(hello.size()-200), QLatin1String("hello"));
1960 
1961  QString null;
1962  QString nonNull = "";
1963  QVERIFY(null.left(10).isNull());
1964  QVERIFY(null.mid(0).isNull());
1965  QVERIFY(null.isNull());
1966  QVERIFY(!nonNull.isNull());
1967 
1968  QString fill = "123";
1969  fill.fill('a');
1970  QCOMPARE(fill, QLatin1String("aaa"));
1971 
1972  s.clear();
1973  s = hello;
1974  s.append(World);
1975  QVERIFY(s == helloWorld);
1976  s.clear();
1977  s = World;
1978  s.insert(0,hello);
1979  QVERIFY(s == helloWorld);
1980  s = "012345";
1981  s.insert(3, 'E');
1982  QCOMPARE(s, QLatin1String("012E345"));
1983  s.insert(3, "INSID");
1984  QCOMPARE(s, QLatin1String("012INSIDE345"));
1985  s = "short";
1986  s.insert(7, 'E');
1987  QCOMPARE(s, QLatin1String("short E"));
1988  s = "short";
1989  s.insert(7, "END");
1990  QCOMPARE(s, QLatin1String("short END"));
1991 
1992  QVERIFY(QString::fromLatin1("hello") == "hello");
1993 
1994  s = "first";
1995  QVERIFY(s.toLatin1() == "first");
1996  s = "second";
1997  QVERIFY(s.toLatin1() == "second");
1998  s.clear();
1999  QVERIFY(s.isNull());
2000  QVERIFY(s.toLatin1().size() == 0);
2001  QVERIFY(s.toLatin1().isEmpty());
2002  QVERIFY(s.toLatin1().isNull());
2003 
2004  s = "first-utf8";
2005  QVERIFY(s.toUtf8() == "first-utf8");
2006  s = "second-utf8";
2007  QVERIFY(s.toUtf8() == "second-utf8");
2008  s.clear();
2009  QVERIFY(s.isNull());
2010  QVERIFY(s.toUtf8().size() == 0);
2011  QVERIFY(s.toUtf8().isEmpty());
2012  QVERIFY(s.toUtf8().isNull());
2013 
2014  s = "first-utf8";
2015  QVERIFY(s.toUtf8() == "first-utf8");
2016  s = "second-utf8";
2017  QVERIFY(s.toUtf8() == "second-utf8");
2018  s.clear();
2019  QVERIFY(s.isNull());
2020  QVERIFY(s.toUtf8().size() == 0);
2021  QVERIFY(s.toUtf8().isEmpty());
2022  QVERIFY(s.toUtf8().isNull());
2023 
2024  s = "first-local8Bit";
2025  QVERIFY(s.toLocal8Bit() == "first-local8Bit");
2026  s = "second-local8Bit";
2027  QVERIFY(s.toLocal8Bit() == "second-local8Bit");
2028  s.clear();
2029  QVERIFY(s.isNull());
2030  QVERIFY(s.toLocal8Bit().size() == 0);
2031  QVERIFY(s.toLocal8Bit().isEmpty());
2032 
2033  s = "first-ascii";
2034  QVERIFY(s.toLatin1() == "first-ascii");
2035  s = "second-ascii";
2036  QVERIFY(s.toLatin1() == "second-ascii");
2037  s.clear();
2038  QVERIFY(s.isNull());
2039  QVERIFY(s.toLatin1().size() == 0);
2040  QVERIFY(s.toLatin1().isEmpty());
2041  QVERIFY(s.toLatin1().isNull());
2042 
2043  s = "ascii";
2044  s += QChar((uchar) 0xb0);
2045  QVERIFY(s.toUtf8() != s.toLatin1());
2046  QCOMPARE(s[s.length()-1].unicode(), (ushort)0xb0);
2047  QCOMPARE(s.left(s.length()-1), QLatin1String("ascii"));
2048 
2049  QVERIFY(s == QString::fromUtf8(s.toUtf8().constData()));
2050 
2051  s = "12";
2052  s.append('3');
2053  s += '4';
2054  QCOMPARE(s, QLatin1String("1234"));
2055 
2056  s = "repend";
2057  s.prepend('p');
2058  QCOMPARE(s, QLatin1String("prepend"));
2059  s.prepend("abc ");
2060  QCOMPARE(s, QLatin1String("abc prepend"));
2061 
2062  s = " whitespace ";
2063  QCOMPARE(s.trimmed(), QLatin1String("whitespace"));
2064  s = " lots of stuff ";
2065  QCOMPARE(s.simplified(), QLatin1String("lots of stuff"));
2066 
2067  s = "a hat, a stick, a ski";
2068  QVERIFY(s[2] == 'h');
2069  QVERIFY(s[1] < 'b');
2070 
2071 
2072  s = "12223";
2073  s.remove(1, 2);
2074  QCOMPARE(s, QLatin1String("123"));
2075 
2076  s = "(%1)(%2)";
2077  s = s.arg("foo").arg(7);
2078  QCOMPARE(s, QLatin1String("(foo)(7)"));
2079 
2080  s = "stl rocks";
2081  std::string stl_string = s.toStdString(); // TODO: std::string stl_string = s does not work.
2082  QCOMPARE(s, QLatin1String("stl rocks"));
2083  s = QString::fromStdString(stl_string); // TODO: s = stl_string does not work.
2084  QCOMPARE(s, QLatin1String("stl rocks"));
2085 
2086  {
2087  QString str("Bananas");
2088  QVERIFY(str.startsWith("Ban"));
2089  QVERIFY(false == str.startsWith("Car"));
2090  }
2091  {
2092  QString str("Bananas");
2093  QVERIFY(str.endsWith("anas"));
2094  QVERIFY(false == str.endsWith("pple"));
2095  }
2096 
2097 
2098  QString str = "Hello";
2100  QCOMPARE(str, QLatin1String("Hello"));
2101  QCOMPARE(cstr, QLatin1String("Hello"));
2102  cstr.clear();
2103  QCOMPARE(str, QLatin1String("Hello"));
2104  QVERIFY(cstr.isEmpty());
2105 
2106  {
2107  QString str1("Foo");
2108  str1.prepend(str1);
2109  QCOMPARE(str1, QString("FooFoo"));
2110  str1.append(str1);
2111  QCOMPARE(str1, QString("FooFooFooFoo"));
2112  str1.insert(2, str1);
2113  QCOMPARE(str1, QString("FoFooFooFooFoooFooFooFoo"));
2114  str1.replace(3, 3, str1);
2115  QCOMPARE(str1, QString("FoFFoFooFooFooFoooFooFooFooooFooFoooFooFooFoo"));
2116  str1 = "FooFoo";
2117  str1.replace(char('F'), str1);
2118  QCOMPARE(str1, QString("FooFooooFooFoooo"));
2119  str1 = "FooFoo";
2120  str1.replace(char('o'), str1);
2121  QCOMPARE(str1, QString("FFooFooFooFooFFooFooFooFoo"));
2122 
2123  str1 = "Foo";
2124  str1.replace("Foo", str1);
2125  QCOMPARE(str1, QString("Foo"));
2126  str1.replace(str1, str1);
2127  QCOMPARE(str1, QString("Foo"));
2128 
2129  str1 = "Foo";
2130  str1.replace("Foo", str1, Qt::CaseInsensitive);
2131  QCOMPARE(str1, QString("Foo"));
2132  str1.replace(str1, str1);
2133  QCOMPARE(str1, QString("Foo"));
2134 
2135  str1 = "FooFoo";
2136  str1.reserve(100);
2137  str1.replace("oo", str1);
2138  QCOMPARE(str1, QString("FFooFooFFooFoo"));
2139 
2140  str1 = "Bar";
2141  str1.replace("FooFoo", str1);
2142  QCOMPARE(str1, QString("Bar"));
2143 
2144  str1.replace(str1, "xxx");
2145  QCOMPARE(str1, QString("xxx"));
2146  str1.replace(str1, QString("yyy"));
2147  QCOMPARE(str1, QString("yyy"));
2148  str1 += str1;
2149  QCOMPARE(str1, QString("yyyyyy"));
2150  }
2151 }
2152 
2153 
2154 void tst_Collections::bitArray()
2155 {
2156  QBitArray ba(20);
2157  QVERIFY(!ba.testBit(17));
2158  ba.setBit(17);
2159  QVERIFY(ba.size() == 20);
2160  QVERIFY(ba.testBit(17)==true);
2161  QVERIFY(!ba.testBit(16));
2162  ba[4] = true;
2163  QVERIFY(ba.testBit(4));
2164  QVERIFY(ba[4]);
2165  int sum = 0;
2166  for(int i = 0; i < 20; i++)
2167  sum += ba.testBit(i) ? 1 : 0;
2168  QVERIFY(sum == 2);
2169 
2170  ba = QBitArray(7, true);
2171  QVERIFY(ba.size() == 7);
2172  QVERIFY(ba[5]);
2173 
2174  ba = QBitArray(3);
2175  ba[0] = ba[2] = true;
2176 
2177  QBitArray nba(3);
2178  nba[1] = true;
2179 
2180  QVERIFY(~ba == nba);
2181 
2182 };
2183 
2184 struct CacheFoo
2185 {
2186  CacheFoo(int v):val(v) { counter++; }
2188  int val;
2189  static int counter;
2190  bool isDetached() const { return val != 2; }
2191 };
2192 
2193 int CacheFoo::counter = 0;
2194 
2195 void tst_Collections::cache()
2196 {
2197  {
2198  QCache<int, CacheFoo> cache(120);
2199  int i;
2200  for (i = 0; i < 30; i++) {
2201  cache.object(10);
2202  cache.insert(i, new CacheFoo(i), i);
2203  }
2204 
2205  QVERIFY(cache.contains(10));
2206  QVERIFY(!cache.contains(1));
2207  QVERIFY(!cache.contains(2));
2208  delete cache.take(10);
2209  }
2210  {
2211  QCache<int, QString> cache(120);
2212  int i;
2213  QString two;
2214  for (i = 0; i < 30; i++) {
2216  cache.insert(i, new QString(s), i);
2217  if (i == 2)
2218  two = s;
2219  }
2220  QVERIFY(!cache.contains(3));
2221  QVERIFY(!cache.contains(2));
2222  }
2223  {
2224  QCache<int, int> cache(100);
2225  cache.insert(2, new int(2));
2226  *cache[2] = 3;
2227  QVERIFY(*cache.object(2) == 3);
2228  }
2229 
2230  QVERIFY(CacheFoo::counter == 0);
2231 
2232 }
2233 
2234 #if QT_CONFIG(regularexpression)
2235 void tst_Collections::regexp()
2236 {
2237  QRegularExpression rx("^\\d\\d?$");
2238  QVERIFY(!rx.match("123").hasMatch());
2239  QVERIFY(!rx.match("-6").hasMatch());
2240  QVERIFY(rx.match("6").hasMatch()) ;
2241 }
2242 #endif
2243 
2244 void tst_Collections::pair()
2245 {
2247  QVERIFY(p.first == 0.0);
2248  QVERIFY(p.second == 0);
2249 
2250  QPair<int, QString> a(1, "Zebra"), b(2, "Ying"), c(3, "Yang"), d(3, "Ying"), e(5, "Alabama");
2251  QVERIFY(a.first == 1);
2252  QCOMPARE(a.second, QLatin1String("Zebra"));
2253  QVERIFY(a == qMakePair(1, QString("Zebra")));
2254 
2255  QVERIFY(a == a && b == b && c == c && d == d && e == e);
2256  QVERIFY(a != b && a != c && a != d && a != e && b != c && b != d && b != e && c != d && c != e
2257  && d != e);
2258 
2259  QVERIFY(a < b && b < c && c < d && d < e);
2260  QVERIFY(a <= b && b <= c && c <= d && d <= e);
2261 
2262  QVERIFY(e > d && d > c && c > b && b > a);
2263  QVERIFY(e >= d && d >= c && c >= b && b >= a);
2264 
2265  QVERIFY(!(a > b || b > c || c > d || d > e));
2266  QVERIFY(!(a >= b || b >= c || c >= d || d >= e));
2267 
2268  QVERIFY(!(e < d || d < c || c < b || b < a));
2269  QVERIFY(!(e <= d || d <= c || c <= b || b <= a));
2270 
2271  QVERIFY(a <= a && b <= b && c <= c && d <= d && e <= e);
2272  QVERIFY(!(a < a || b < b || c < c || d < d || e < e));
2273 
2274  QVERIFY(a >= a && b >= b && c >= c && d >= d && e >= e);
2275  QVERIFY(!(a > a || b > b || c > c || d > d || e > e));
2276 }
2277 
2278 /*
2279  These test that Java-style mutable iterators don't trash shared
2280  copy (the setSharable() mechanism).
2281 */
2282 
2283 template <class Container>
2285 
2286 template <>
2287 void populate(QList<int> &container)
2288 {
2289  container << 1 << 2 << 4 << 8;
2290 }
2291 
2292 template <>
2293 void populate(QMap<int, int> &container)
2294 {
2295  container.insert(1, 1);
2296  container.insert(2, 2);
2297  container.insert(4, 4);
2298  container.insert(8, 8);
2299 }
2300 
2301 template <>
2302 void populate(QHash<int, int> &container)
2303 {
2304  container.insert(1, 1);
2305  container.insert(2, 2);
2306  container.insert(4, 4);
2307  container.insert(8, 8);
2308 }
2309 
2310 template <class Container>
2311 bool isSharable(const Container &container)
2312 {
2313  Container copy = container;
2314  return !container.isDetached();
2315 }
2316 
2317 template <class Container> Container newInstance() {
2318  Container container;
2319  populate(container);
2320  if (!container.isEmpty())
2321  return container;
2322  return Container();
2323 }
2324 
2325 template <class Container, class ContainerMutableIterator>
2327 {
2328  /*
2329  Verify that shared_null's 'sharable' flag is set to true.
2330  */
2331  {
2332  Container c1;
2333  QVERIFY(!c1.isDetached());
2334 
2335  Container c2 = c1;
2336  QVERIFY(!c1.isDetached());
2337  QVERIFY(!c2.isDetached());
2338  }
2339 
2340  /*
2341  Verify that the 'sharable' flag is true in populated containers.
2342  */
2343  {
2344  Container c1;
2345  populate(c1);
2346  QVERIFY(c1.size() == 4);
2347  QVERIFY(c1.isDetached());
2348 
2349  Container c2 = c1;
2350  QVERIFY(c1.size() == 4);
2351  QVERIFY(c2.size() == 4);
2352  QVERIFY(!c1.isDetached());
2353  QVERIFY(!c2.isDetached());
2354  }
2355 
2356  /* test that the move operators work properly */
2357  {
2358  Container c1 = Container(newInstance<Container>());
2359  QVERIFY(c1.size() == 4);
2360  QVERIFY(c1 == newInstance<Container>());
2361  c1 = newInstance<Container>();
2362  QVERIFY(c1.size() == 4);
2363  QVERIFY(c1 == newInstance<Container>());
2364  Container c2 = std::move(c1);
2365  QVERIFY(c2.size() == 4);
2366  QVERIFY(c2 == newInstance<Container>());
2367  }
2368 }
2369 
2370 #define TEST_SEQUENTIAL_CONTAINER(Container) \
2371  testContainer<Q##Container<int>, QMutable##Container##Iterator<int> >() \
2372 
2373 #define TEST_ASSOCIATIVE_CONTAINER(Container) \
2374  testContainer<Q##Container<int, int>, QMutable##Container##Iterator<int, int> >()
2375 
2376 void tst_Collections::sharableQList()
2377 {
2379 }
2380 
2381 void tst_Collections::sharableQVector()
2382 {
2383  TEST_SEQUENTIAL_CONTAINER(Vector);
2384 }
2385 
2386 void tst_Collections::sharableQMap()
2387 {
2389 }
2390 
2391 void tst_Collections::sharableQHash()
2392 {
2394 }
2395 
2396 static int getList_calls = 0;
2398 {
2399  ++getList_calls;
2400  QList<int> list;
2401  list << 1 << 2 << 3 << 4 << 5 << 6;
2402  return list;
2403 }
2404 
2405 
2406 void tst_Collections::q_foreach()
2407 {
2408  QList<int> list;
2409  list << -2 << -1 << 0 << 1 << 2;
2410 
2411  int sum = 0;
2412  int j = 0;
2413  foreach(int i, list) {
2414  QCOMPARE(i, list.at(j));
2415  sum += i;
2416  ++j;
2417  }
2418  QCOMPARE(sum, 0);
2419 
2420  // again, but without scope
2421  foreach(int i, list)
2422  sum += i;
2423  QCOMPARE(sum, 0);
2424 
2425  foreach(int i, list) {
2426  sum += i;
2427  if (i == 0)
2428  break;
2429  }
2430  QCOMPARE(sum, -3);
2431 
2432  sum = 0;
2433  foreach(int i, list) {
2434  if (i < 0)
2435  continue;
2436  sum += i;
2437  }
2438  QCOMPARE(sum, 3);
2439 
2440  sum = 0;
2441  getList_calls = 0;
2442  foreach(int i, getList())
2443  sum += i;
2444  QCOMPARE(sum, 21);
2445  QCOMPARE(getList_calls, 1);
2446 }
2447 
2448 
2449 void tst_Collections::conversions()
2450 {
2451 #define STUFF "A" << "C" << "B" << "A"
2452 
2453  {
2454  QList<QString> list1;
2455  list1 << STUFF;
2456 
2457  QVector<QString> vect1 = list1.toVector();
2458  QCOMPARE(list1.size(), 4);
2459  QVERIFY(vect1 == (QVector<QString>() << STUFF));
2460 
2461  QList<QString> list2 = vect1.toList();
2462  QCOMPARE(list2.size(), 4);
2463  QVERIFY(list2 == (QList<QString>() << STUFF));
2464 
2465 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2466  QSet<QString> set1 = list1.toSet();
2467 #else
2468  QSet<QString> set1(list1.begin(), list1.end());
2469 #endif
2470  QCOMPARE(set1.size(), 3);
2471  QVERIFY(set1.contains("A"));
2472  QVERIFY(set1.contains("B"));
2473  QVERIFY(set1.contains("C"));
2474  QVERIFY(!set1.contains("D"));
2475 
2476  QList<QString> list3 = set1.values();
2477  QCOMPARE(list3.size(), 3);
2478  QVERIFY(list3.contains("A"));
2479  QVERIFY(list3.contains("B"));
2480  QVERIFY(list3.contains("C"));
2481  QVERIFY(!list3.contains("D"));
2482 
2483  QVERIFY(QList<int>().toVector().isEmpty());
2484  QVERIFY(QVector<int>().toList().isEmpty());
2485 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2486  QVERIFY(QList<int>().toSet().isEmpty());
2487  QVERIFY(QSet<int>().toList().isEmpty());
2488 #endif
2489  }
2490 
2491  {
2492  QList<QString> list1;
2493  list1 << STUFF;
2494 
2496  QCOMPARE(list1.size(), 4);
2497  QVERIFY(vect1 == (QVector<QString>() << STUFF));
2498 
2500  QCOMPARE(list2.size(), 4);
2501  QVERIFY(list2 == (QList<QString>() << STUFF));
2502 
2503 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2504  QSet<QString> set1 = QSet<QString>::fromList(list1);
2505 #else
2506  QSet<QString> set1(list1.begin(), list1.end());
2507 #endif
2508  QCOMPARE(set1.size(), 3);
2509  QVERIFY(set1.contains("A"));
2510  QVERIFY(set1.contains("B"));
2511  QVERIFY(set1.contains("C"));
2512  QVERIFY(!set1.contains("D"));
2513 
2514 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2516 #else
2517  QList<QString> list3 = set1.values();
2518 #endif
2519  QCOMPARE(list3.size(), 3);
2520  QVERIFY(list3.contains("A"));
2521  QVERIFY(list3.contains("B"));
2522  QVERIFY(list3.contains("C"));
2523  QVERIFY(!list3.contains("D"));
2524 
2527 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2528  QVERIFY(QSet<int>::fromList(QList<int>()).isEmpty());
2529  QVERIFY(QList<int>::fromSet(QSet<int>()).isEmpty());
2530 #endif
2531  }
2532 #undef STUFF
2533 }
2534 
2535 void tst_Collections::javaStyleIterators()
2536 {
2537  QStringList list;
2538  list << "a" << "b" << "c";
2540  while (i.hasNext()) {
2541  i.next();
2542  i.setValue("");
2543  }
2544  while (i.hasPrevious()) {
2545  i.previous();
2546  QVERIFY(i.value().isEmpty());
2547  i.value() = "x";
2548  QCOMPARE(i.value(), QString("x"));
2549  }
2550 }
2551 
2552 template <class Container>
2554 {
2555  Container fake;
2556  typename Container::value_type t = {};
2557  fake << t;
2558 
2559  typename Container::iterator i1 = fake.begin(), i2 = i1 + 1;
2560  typename Container::const_iterator c1 = i1, c2 = c1 + 1;
2561 
2562  QVERIFY(i1 == i1);
2563  QVERIFY(i1 == c1);
2564  QVERIFY(c1 == i1);
2565  QVERIFY(c1 == c1);
2566  QVERIFY(i2 == i2);
2567  QVERIFY(i2 == c2);
2568  QVERIFY(c2 == i2);
2569  QVERIFY(c2 == c2);
2570  QVERIFY(1 + i1 == i1 + 1);
2571  QVERIFY(1 + c1 == c1 + 1);
2572 
2573  QVERIFY(i1 != i2);
2574  QVERIFY(i1 != c2);
2575  QVERIFY(c1 != i2);
2576  QVERIFY(c1 != c2);
2577  QVERIFY(i2 != i1);
2578  QVERIFY(i2 != c1);
2579  QVERIFY(c2 != i1);
2580  QVERIFY(c2 != c1);
2581 }
2582 
2583 template <class Container>
2585 {
2586  testLinkedListLikeStlIterators<Container>();
2587 
2588  Container fake;
2589  typename Container::value_type t = {};
2590  fake << t;
2591 
2592  typename Container::iterator i1 = fake.begin(), i2 = i1 + 1;
2593  typename Container::const_iterator c1 = i1, c2 = c1 + 1;
2594 
2595  QVERIFY(i1 < i2);
2596  QVERIFY(i1 < c2);
2597  QVERIFY(c1 < i2);
2598  QVERIFY(c1 < c2);
2599  QVERIFY(!(i2 < i1));
2600  QVERIFY(!(i2 < c1));
2601  QVERIFY(!(c2 < i1));
2602  QVERIFY(!(c2 < c1));
2603  QVERIFY(!(i1 < i1));
2604  QVERIFY(!(i1 < c1));
2605  QVERIFY(!(c1 < i1));
2606  QVERIFY(!(c1 < c1));
2607  QVERIFY(!(i2 < i2));
2608  QVERIFY(!(i2 < c2));
2609  QVERIFY(!(c2 < i2));
2610  QVERIFY(!(c2 < c2));
2611 
2612  QVERIFY(i2 > i1);
2613  QVERIFY(i2 > c1);
2614  QVERIFY(c2 > i1);
2615  QVERIFY(c2 > c1);
2616  QVERIFY(!(i1 > i2));
2617  QVERIFY(!(i1 > c2));
2618  QVERIFY(!(c1 > i2));
2619  QVERIFY(!(c1 > c2));
2620  QVERIFY(!(i1 > i1));
2621  QVERIFY(!(i1 > c1));
2622  QVERIFY(!(c1 > i1));
2623  QVERIFY(!(c1 > c1));
2624  QVERIFY(!(i2 > i2));
2625  QVERIFY(!(i2 > c2));
2626  QVERIFY(!(c2 > i2));
2627  QVERIFY(!(c2 > c2));
2628 
2629  QVERIFY(!(i1 >= i2));
2630  QVERIFY(!(i1 >= c2));
2631  QVERIFY(!(c1 >= i2));
2632  QVERIFY(!(c1 >= c2));
2633  QVERIFY(i2 >= i1);
2634  QVERIFY(i2 >= c1);
2635  QVERIFY(c2 >= i1);
2636  QVERIFY(c2 >= c1);
2637  QVERIFY(i1 >= i1);
2638  QVERIFY(i1 >= c1);
2639  QVERIFY(c1 >= i1);
2640  QVERIFY(c1 >= c1);
2641  QVERIFY(i2 >= i2);
2642  QVERIFY(i2 >= c2);
2643  QVERIFY(c2 >= i2);
2644  QVERIFY(c2 >= c2);
2645 
2646  QVERIFY(!(i2 <= i1));
2647  QVERIFY(!(i2 <= c1));
2648  QVERIFY(!(c2 <= i1));
2649  QVERIFY(!(c2 <= c1));
2650  QVERIFY(i1 <= i2);
2651  QVERIFY(i1 <= c2);
2652  QVERIFY(c1 <= i2);
2653  QVERIFY(c1 <= c2);
2654  QVERIFY(i1 <= i1);
2655  QVERIFY(i1 <= c1);
2656  QVERIFY(c1 <= i1);
2657  QVERIFY(c1 <= c1);
2658  QVERIFY(i2 <= i2);
2659  QVERIFY(i2 <= c2);
2660  QVERIFY(c2 <= i2);
2661  QVERIFY(c2 <= c2);
2662 }
2663 
2664 template <class Container>
2666 {
2667  Container fake;
2668  QString k;
2669  QString t;
2670  fake.insert(k, t);
2671 
2672  typename Container::iterator i1 = fake.begin(), i2 = i1;
2673  ++i2;
2674  typename Container::const_iterator c1 = i1, c2 = c1;
2675  ++c2;
2676 
2677  QVERIFY(i1 == i1);
2678  QVERIFY(i1 == c1);
2679  QVERIFY(c1 == i1);
2680  QVERIFY(c1 == c1);
2681  QVERIFY(i2 == i2);
2682  QVERIFY(i2 == c2);
2683  QVERIFY(c2 == i2);
2684  QVERIFY(c2 == c2);
2685 
2686  QVERIFY(i1 != i2);
2687  QVERIFY(i1 != c2);
2688  QVERIFY(c1 != i2);
2689  QVERIFY(c1 != c2);
2690  QVERIFY(i2 != i1);
2691  QVERIFY(i2 != c1);
2692  QVERIFY(c2 != i1);
2693  QVERIFY(c2 != c1);
2694 }
2695 
2696 void tst_Collections::constAndNonConstStlIterators()
2697 {
2698  testListLikeStlIterators<QList<int>>();
2699  testListLikeStlIterators<QStringList>();
2700  testMapLikeStlIterators<QMap<QString, QString>>();
2701  testMapLikeStlIterators<QMultiMap<QString, QString>>();
2702  testMapLikeStlIterators<QHash<QString, QString>>();
2703  testMapLikeStlIterators<QMultiHash<QString, QString>>();
2704 }
2705 
2706 void tst_Collections::vector_stl_data()
2707 {
2708  QTest::addColumn<QStringList>("elements");
2709 
2710  QTest::newRow("empty") << QStringList();
2711  QTest::newRow("one") << (QStringList() << "Hei");
2712  QTest::newRow("two") << (QStringList() << "Hei" << "Hopp");
2713  QTest::newRow("three") << (QStringList() << "Hei" << "Hopp" << "Sann");
2714 }
2715 
2716 void tst_Collections::vector_stl()
2717 {
2718  QFETCH(QStringList, elements);
2719 
2721  for (int i = 0; i < elements.count(); ++i)
2722  vector << elements.at(i);
2723 
2724 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2725  std::vector<QString> stdVector = vector.toStdVector();
2726 #else
2727  std::vector<QString> stdVector(vector.begin(), vector.end());
2728 #endif
2729  QCOMPARE(int(stdVector.size()), elements.size());
2730 
2731  std::vector<QString>::const_iterator it = stdVector.begin();
2732  for (uint j = 0; j < stdVector.size() && it != stdVector.end(); ++j, ++it)
2733  QCOMPARE(*it, vector[j]);
2734 
2735 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2736  QCOMPARE(QList<QString>::fromStdVector(stdVector), vector);
2737 #endif
2738  QCOMPARE(QList<QString>(stdVector.begin(), stdVector.end()), vector);
2739 }
2740 
2741 void tst_Collections::list_stl_data()
2742 {
2743  QTest::addColumn<QStringList>("elements");
2744 
2745  QTest::newRow("empty") << QStringList();
2746  QTest::newRow("one") << (QStringList() << "Hei");
2747  QTest::newRow("two") << (QStringList() << "Hei" << "Hopp");
2748  QTest::newRow("three") << (QStringList() << "Hei" << "Hopp" << "Sann");
2749 }
2750 
2751 void tst_Collections::list_stl()
2752 {
2753  QFETCH(QStringList, elements);
2754 
2756  for (int i = 0; i < elements.count(); ++i)
2757  list << elements.at(i);
2758 
2759 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2760  std::list<QString> stdList = list.toStdList();
2761 #else
2762  std::list<QString> stdList(list.begin(), list.end());
2763 #endif
2764 
2765  QCOMPARE(int(stdList.size()), elements.size());
2766 
2767  std::list<QString>::const_iterator it = stdList.begin();
2768  for (uint j = 0; j < stdList.size() && it != stdList.end(); ++j, ++it)
2769  QCOMPARE(*it, list[j]);
2770 
2771 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2772  QCOMPARE(QList<QString>::fromStdList(stdList), list);
2773 #endif
2774  QCOMPARE(QList<QString>(stdList.begin(), stdList.end()), list);
2775 }
2776 
2777 template <typename T>
2778 T qtInit(T * = nullptr)
2779 {
2780  return T();
2781 }
2782 
2783 void tst_Collections::q_init()
2784 {
2785  QCOMPARE(qtInit<int>(), 0);
2786  QCOMPARE(qtInit<double>(), 0.0);
2787  QCOMPARE(qtInit<QString>(), QString());
2788  QCOMPARE(qtInit<int *>(), static_cast<int *>(nullptr));
2789  QCOMPARE(qtInit<double *>(), static_cast<double *>(nullptr));
2790  QCOMPARE(qtInit<QString *>(), static_cast<QString *>(nullptr));
2791  QCOMPARE(qtInit<Pod>().i1, 0);
2792  QCOMPARE(qtInit<Pod>().i2, 0);
2793 }
2794 
2795 void tst_Collections::pointersize()
2796 {
2797  QCOMPARE(int(sizeof(void *)), QT_POINTER_SIZE);
2798 }
2799 
2801 {
2802 public:
2803  bool operator<(const LessThanComparable &) const { return true; }
2804  bool operator==(const LessThanComparable &) const { return true; }
2805 };
2806 
2808 {
2809 public:
2810  bool operator==(const EqualsComparable &) const { return true; }
2811 };
2812 
2813 size_t qHash(const EqualsComparable &)
2814 {
2815  return 0;
2816 }
2817 
2818 /*
2819  The following functions instatiates every member functions in the
2820  Qt containers that requires either operator== or operator<.
2821  They are ordered in a concept inheritance tree:
2822 
2823  Container
2824  MutableIterationContainer
2825  Sequence (QLinkedList)
2826  Random Access (QVector, QList, QQueue, QStack)
2827  Pair Associative (QHash, QMap)
2828  Associative (QSet)
2829 */
2830 template <typename ContainerType, typename ValueType>
2832 {
2833  const ValueType value = ValueType();
2834  ContainerType container;
2835  const ContainerType constContainer(container);
2836 
2837  typename ContainerType::const_iterator constIt;
2838  constIt = constContainer.begin();
2839  constIt = container.cbegin();
2840  container.constBegin();
2841 
2842  constIt = constContainer.end();
2843  constIt = constContainer.cend();
2844  container.constEnd();
2845  Q_UNUSED(constIt);
2846 
2847  container.clear();
2848  container.contains(value);
2849  container.count();
2850  container.empty();
2851  container.isEmpty();
2852  container.size();
2853 
2854  Q_UNUSED((container != constContainer));
2855  Q_UNUSED((container == constContainer));
2856  container = constContainer;
2857 }
2858 
2859 template <typename ContainerType, typename ValueType>
2861 {
2862  instantiateContainer<ContainerType, ValueType>();
2863  ContainerType container;
2864 
2865  typename ContainerType::iterator it;
2866  it = container.begin();
2867  it = container.end();
2868  Q_UNUSED(it);
2869 }
2870 
2871 template <typename ContainerType, typename ValueType>
2873 {
2874  instantiateMutableIterationContainer<ContainerType, ValueType>();
2875 
2877  ContainerType container;
2878  container.removeAll(value);
2879 }
2880 
2881 template <typename ContainerType, typename ValueType>
2883 {
2884  instantiateSequence<ContainerType, ValueType>();
2885 
2887  ContainerType container;
2888  container.indexOf(value);
2889  container.lastIndexOf(value);
2890 }
2891 
2892 template <typename ContainerType, typename ValueType>
2894 {
2895  instantiateContainer<ContainerType, ValueType>();
2896 
2897  const ValueType value = ValueType();
2898  ContainerType container;
2899  const ContainerType constContainer(container);
2900 
2901  container.reserve(1);
2902  container.capacity();
2903  container.squeeze();
2904 
2905  container.remove(value);
2906  container.values();
2907 
2908  container.unite(constContainer);
2909  container.intersect(constContainer);
2910  container.subtract(constContainer);
2911 
2912  Q_UNUSED((container != constContainer));
2913  Q_UNUSED((container == constContainer));
2914  container & constContainer;
2915  container &= constContainer;
2916  container &= value;
2917  container + constContainer;
2918  container += constContainer;
2919  container += value;
2920  container - constContainer;
2921  container -= constContainer;
2922  container -= value;
2923  container | constContainer;
2924  container |= constContainer;
2925  container |= value;
2926 }
2927 
2928 template <typename ContainerType, typename KeyType, typename ValueType>
2930 {
2931  instantiateMutableIterationContainer<ContainerType, KeyType>();
2932 
2933  const KeyType key = KeyType();
2934  const ValueType value = ValueType();
2935  ContainerType container;
2936  const ContainerType constContainer(container);
2937 
2938  auto it = container.insert(key, value);
2939  container.erase(it);
2940  container.find(key);
2941  container.constFind(key);
2942  constContainer.find(key);
2943 
2944  container.key(value);
2945  container.keys();
2946  constContainer.keys();
2947  container.remove(key);
2948  container.take(key);
2949  container.insert(constContainer);
2950  container.value(key);
2951  container.value(key, value);
2952  container.values();
2953  container[key];
2954  const int foo = constContainer[key];
2955  Q_UNUSED(foo);
2956 }
2957 
2958 /*
2959  Instantiate all Qt containers using a datatype that
2960  defines the minimum amount of operators.
2961 */
2962 void tst_Collections::containerInstantiation()
2963 {
2964  // Instantiate QHash member functions.
2966  instantiatePairAssociative<Hash, EqualsComparable, int>();
2967 
2968  Hash hash;
2969  hash.reserve(1);
2970  hash.capacity();
2971  hash.squeeze();
2972 
2973  // Instantiate QMap member functions.
2975  instantiatePairAssociative<Map, LessThanComparable, int>();
2976 
2977  // Instantiate QSet member functions.
2978  typedef QSet<EqualsComparable> Set;
2979  instantiateAssociative<Set, EqualsComparable>();
2980 
2981  //Instantiate QList member functions.
2982  typedef QList<EqualsComparable> List;
2983  instantiateRandomAccess<List, EqualsComparable>();
2984  {
2986  List list;
2987  list.removeAll(value);
2988  }
2989 
2990  //Instantiate QQueue member functions.
2991  typedef QQueue<EqualsComparable> Queue;
2992  instantiateRandomAccess<Queue, EqualsComparable>();
2993 
2994  //Instantiate QStack member functions.
2995  typedef QStack<EqualsComparable> Stack;
2996  instantiateRandomAccess<Stack, EqualsComparable>();
2997 }
2998 
2999 void tst_Collections::qtimerList()
3000 {
3002  const int N = 10000;
3003 
3004  foo.append(99.9);
3005  foo.append(99.9);
3006  foo.append(99.9);
3007 
3008  for(int i = 0; i < N; i++) {
3009  foo.removeFirst();
3010  foo.insert(1, 99.9);
3011  }
3012 
3014  for (int i = 0; i < (N / 2) - 10; ++i) {
3015  foo.prepend(99.9);
3016  if (foo.end() != end)
3017  return;
3018  }
3019  QFAIL("QList preallocates too much memory");
3020 }
3021 
3022 #define QVERIFY_TYPE(Type) QVERIFY(sizeof(Type) > 0)
3023 
3024 template <typename Container>
3026 {
3027  Q_UNUSED(container);
3028  { QVERIFY_TYPE(typename Container::value_type); }
3029  { QVERIFY_TYPE(typename Container::iterator); }
3031  { QVERIFY_TYPE(typename Container::reference); }
3033  { QVERIFY_TYPE(typename Container::pointer); }
3034  { QVERIFY_TYPE(typename Container::difference_type); }
3035  { QVERIFY_TYPE(typename Container::size_type); }
3036 }
3037 
3038 template <typename Container>
3040 {
3041  Q_UNUSED(container);
3042 
3043 // TODO: Not sure how to define value_type for our associative containers
3044 // { QVERIFY_TYPE(typename Container::value_type); }
3045 // { QVERIFY_TYPE(typename Container::const_iterator); }
3046 // { QVERIFY_TYPE(typename Container::reference); }
3047 // { QVERIFY_TYPE(typename Container::const_reference); }
3048 // { QVERIFY_TYPE(typename Container::pointer); }
3049 
3050  { QVERIFY_TYPE(typename Container::difference_type); }
3051  { QVERIFY_TYPE(typename Container::size_type); }
3052  { QVERIFY_TYPE(typename Container::iterator); }
3053  { QVERIFY_TYPE(typename Container::key_type); }
3054  { QVERIFY_TYPE(typename Container::mapped_type); }
3055 // TODO
3056 // { QVERIFY_TYPE(typename Container::key_compare); }
3057 // { QVERIFY_TYPE(typename Container::value_comare); }
3058 }
3059 
3060 template <typename Container>
3062 {
3063  Q_UNUSED(container);
3064  { QVERIFY_TYPE(typename Container::iterator); }
3066  { QVERIFY_TYPE(typename Container::reference); }
3068  { QVERIFY_TYPE(typename Container::pointer); }
3069  { QVERIFY_TYPE(typename Container::difference_type); }
3070  { QVERIFY_TYPE(typename Container::size_type); }
3071  { QVERIFY_TYPE(typename Container::key_type); }
3072 }
3073 
3074 /*
3075  Compile-time test that verifies that the Qt containers
3076  have STL-compatable typedefs.
3077 */
3078 void tst_Collections::containerTypedefs()
3079 {
3083 
3087 
3089 }
3090 
3091 class Key1;
3092 class T1;
3093 class T2;
3094 
3095 void tst_Collections::forwardDeclared()
3096 {
3097 #define COMMA ,
3098 #define TEST(type) do { \
3099  using C = type; \
3100  C *x = nullptr; \
3101  C::iterator i; \
3102  C::const_iterator j; \
3103  Q_UNUSED(x); \
3104  Q_UNUSED(i); \
3105  Q_UNUSED(j); \
3106  } while (false)
3107 
3111  TEST(QList<T1>);
3112  TEST(QVector<T1>);
3113  TEST(QStack<T1>);
3114  TEST(QQueue<T1>);
3115  TEST(QSet<T1>);
3116 #undef TEST
3117 #undef COMMA
3118 
3119  {
3120  using C = QPair<T1, T2>;
3121  C *x = nullptr;
3122  Q_UNUSED(x);
3123  }
3124 
3125  {
3126  using C = QSet<T1>;
3127  C *x = nullptr;
3129  Q_UNUSED(x);
3130  Q_UNUSED(j);
3131  }
3132 }
3133 
3134 #if defined(Q_PROCESSOR_ARM)
3135 # if defined(Q_COMPILER_ALIGNAS) && defined(__BIGGEST_ALIGNMENT__)
3136  // On ARM __BIGGEST_ALIGNMENT__ must be multiplied by 8 to
3137  // get the same limit as enforced by alignas()
3138 # define BIGGEST_ALIGNMENT_TO_TEST (__BIGGEST_ALIGNMENT__ << 3)
3139 # endif
3140 #endif
3141 
3142 #if !defined(BIGGEST_ALIGNMENT_TO_TEST)
3143 # define BIGGEST_ALIGNMENT_TO_TEST 128
3144 #endif
3145 
3146 template <size_t Alignment>
3147 class alignas(Alignment) AlignedClass
3148 {
3149  char i;
3150 
3151 public:
3152  AlignedClass(int i = 0) : i(i) {}
3153 
3154  enum { PreferredAlignment = Alignment };
3155 
3156  inline bool operator==(const AlignedClass &other) const { return i == other.i; }
3157  inline bool operator<(const AlignedClass &other) const { return i < other.i; }
3158  friend inline size_t qHash(const AlignedClass &a) { return qHash(a.i); }
3159 };
3160 
3162 static_assert(alignof(Aligned4) % 4 == 0);
3163 
3164 using AlignedStdMax = AlignedClass<alignof(std::max_align_t)>;
3165 static_assert(alignof(AlignedStdMax) % alignof(std::max_align_t) == 0);
3166 
3168 static_assert(BIGGEST_ALIGNMENT_TO_TEST > alignof(std::max_align_t), "Not overly aligned");
3169 static_assert(alignof(AlignedBiggest) % BIGGEST_ALIGNMENT_TO_TEST == 0);
3170 
3171 template<typename C>
3173 {
3174  typedef typename C::value_type Aligned;
3175  C container;
3176  container.append(Aligned());
3177  QCOMPARE(quintptr(&container[0]) % Aligned::PreferredAlignment, quintptr(0));
3178 
3179  for (int i = 0; i < 200; ++i)
3180  container.append(Aligned());
3181 
3182  for (int i = 0; i < container.size(); ++i)
3183  QCOMPARE(quintptr(&container.at(i)) % Aligned::PreferredAlignment, quintptr(0));
3184 }
3185 
3186 template<typename C>
3188 {
3189  typedef typename C::value_type Aligned;
3190  C container(150);
3191  container.append(Aligned());
3192  QCOMPARE(quintptr(&container[container.firstIndex()]) % Aligned::PreferredAlignment, quintptr(0));
3193 
3194  for (int i = 0; i < 200; ++i)
3195  container.append(Aligned());
3196 
3197  for (int i = container.firstIndex(); i < container.lastIndex(); ++i)
3198  QCOMPARE(quintptr(&container.at(i)) % Aligned::PreferredAlignment, quintptr(0));
3199 }
3200 
3201 template<typename C>
3203 {
3204  typedef typename C::key_type Key;
3205  typedef typename C::mapped_type Value;
3206  C container;
3207  container.insert(Key(), Value());
3208 
3209  typename C::const_iterator it = container.constBegin();
3210  QCOMPARE(quintptr(&it.key()) % Key::PreferredAlignment, quintptr(0));
3211  QCOMPARE(quintptr(&it.value()) % Value::PreferredAlignment, quintptr(0));
3212 
3213  // add some more elements
3214  for (int i = 0; i < 200; ++i)
3215  container.insert(Key(i), Value(i));
3216 
3217  it = container.constBegin();
3218  for ( ; it != container.constEnd(); ++it) {
3219  QCOMPARE(quintptr(&it.key()) % Key::PreferredAlignment, quintptr(0));
3220  QCOMPARE(quintptr(&it.value()) % Value::PreferredAlignment, quintptr(0));
3221  }
3222 }
3223 
3224 void tst_Collections::alignment()
3225 {
3226  testVectorAlignment<QList<Aligned4> >();
3227  testVectorAlignment<QList<AlignedStdMax> >();
3228  testVectorAlignment<QList<AlignedBiggest> >();
3229 
3230  testContiguousCacheAlignment<QContiguousCache<Aligned4> >();
3231  testContiguousCacheAlignment<QContiguousCache<AlignedStdMax> >();
3232  testContiguousCacheAlignment<QContiguousCache<AlignedBiggest> >();
3233 
3234  // there's no guarentee that std::map supports over-aligned types
3235  testAssociativeContainerAlignment<QMap<Aligned4, Aligned4> >();
3236  testAssociativeContainerAlignment<QMap<Aligned4, AlignedStdMax> >();
3237  testAssociativeContainerAlignment<QMap<AlignedStdMax, Aligned4> >();
3238  testAssociativeContainerAlignment<QMap<AlignedStdMax, AlignedStdMax> >();
3239 
3240  testAssociativeContainerAlignment<QHash<Aligned4, Aligned4> >();
3241  testAssociativeContainerAlignment<QHash<Aligned4, AlignedStdMax> >();
3242  testAssociativeContainerAlignment<QHash<Aligned4, AlignedBiggest> >();
3243  testAssociativeContainerAlignment<QHash<AlignedStdMax, Aligned4> >();
3244  testAssociativeContainerAlignment<QHash<AlignedStdMax, AlignedStdMax> >();
3245  testAssociativeContainerAlignment<QHash<AlignedStdMax, AlignedBiggest> >();
3246  testAssociativeContainerAlignment<QHash<AlignedBiggest, Aligned4> >();
3247  testAssociativeContainerAlignment<QHash<AlignedBiggest, AlignedStdMax> >();
3248  testAssociativeContainerAlignment<QHash<AlignedBiggest, AlignedBiggest> >();
3249 }
3250 
3251 #ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
3252 
3253 template<template<class> class C>
3257 
3259  children.begin(); //play with memory
3260  }
3261 };
3262 template<template<class> class C> void QTBUG13079_collectionInsideCollectionImpl()
3263 {
3264  C<QTBUG13079_Node<C> > nodeList;
3265  nodeList << QTBUG13079_Node<C>();
3266  nodeList.first().s = "parent";
3267  nodeList.first().children << QTBUG13079_Node<C>();
3268  nodeList.first().children.first().s = "child";
3269 
3270  nodeList = nodeList.first().children;
3271  QCOMPARE(nodeList.first().s, QString::fromLatin1("child"));
3272 
3273  nodeList = nodeList.first().children;
3274  QCOMPARE(nodeList.count(), 0);
3275  nodeList << QTBUG13079_Node<C>();
3276 }
3277 
3278 template<template<class, class> class C>
3282 
3284  children.begin(); //play with memory
3285  }
3286 };
3287 template<template<class, class> class C> void QTBUG13079_collectionInsideCollectionAssocImpl()
3288 {
3290  nodeMap[18] = QTBUG13079_NodeAssoc<C>();
3291  nodeMap[18].s = "parent";
3292  nodeMap[18].children[12] = QTBUG13079_NodeAssoc<C>();
3293  nodeMap[18].children[12].s = "child";
3294 
3295  nodeMap = nodeMap[18].children;
3296  QCOMPARE(nodeMap[12].s, QString::fromLatin1("child"));
3297 
3298  nodeMap = nodeMap[12].children;
3299  QCOMPARE(nodeMap.count(), 0);
3300  nodeMap[42] = QTBUG13079_NodeAssoc<C>();
3301 }
3302 
3303 
3305 {
3306  return 0;
3307 }
3308 
3310 {
3311  return a.s == b.s && a.children == b.children;
3312 }
3313 
3314 template<template<class> class C>
3319 
3322  next = child.data(); //play with memory
3323  }
3324 };
3325 template<template<class> class C> void QTBUG13079_collectionInsidePtrImpl()
3326 {
3327  typedef C<QTBUG13079_NodePtr<C> > Ptr;
3328  {
3329  Ptr nodePtr;
3330  nodePtr = Ptr(new QTBUG13079_NodePtr<C>());
3331  nodePtr->s = "parent";
3332  nodePtr->child = Ptr(new QTBUG13079_NodePtr<C>());
3333  nodePtr->child->s = "child";
3334  nodePtr = nodePtr->child;
3335  QCOMPARE(nodePtr->s, QString::fromLatin1("child"));
3336  nodePtr = nodePtr->child;
3337  QVERIFY(!nodePtr);
3338  }
3339  {
3340  Ptr nodePtr;
3341  nodePtr = Ptr(new QTBUG13079_NodePtr<C>());
3342  nodePtr->s = "parent";
3343  nodePtr->next = new QTBUG13079_NodePtr<C>();
3344  nodePtr->next->s = "next";
3345  nodePtr = Ptr(nodePtr->next);
3346  QCOMPARE(nodePtr->s, QString::fromLatin1("next"));
3347  nodePtr = Ptr(nodePtr->next);
3348  QVERIFY(!nodePtr);
3349  }
3350 }
3351 
3352 #endif
3353 
3354 void tst_Collections::QTBUG13079_collectionInsideCollection()
3355 {
3356 #ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
3357  QTBUG13079_collectionInsideCollectionImpl<QVector>();
3358  QTBUG13079_collectionInsideCollectionImpl<QStack>();
3359  QTBUG13079_collectionInsideCollectionImpl<QList>();
3360  QTBUG13079_collectionInsideCollectionImpl<QQueue>();
3361 
3362  {
3363  QSet<QTBUG13079_Node<QSet> > nodeSet;
3364  nodeSet << QTBUG13079_Node<QSet>();
3365  nodeSet = nodeSet.begin()->children;
3366  QCOMPARE(nodeSet.count(), 0);
3367  }
3368 
3369  QTBUG13079_collectionInsideCollectionAssocImpl<QMap>();
3370  QTBUG13079_collectionInsideCollectionAssocImpl<QHash>();
3371 
3372  QTBUG13079_collectionInsidePtrImpl<QSharedPointer>();
3373  QTBUG13079_collectionInsidePtrImpl<QExplicitlySharedDataPointer>();
3374  QTBUG13079_collectionInsidePtrImpl<QSharedDataPointer>();
3375 #endif
3376 }
3377 
3378 template<class Container> void foreach_test_arrays(const Container &container)
3379 {
3380  typedef typename Container::value_type T;
3381  int i = 0;
3382  QSet <T> set;
3383  foreach(const T & val, container) {
3384  QVERIFY( val == container[i] );
3385  set << val;
3386  i++;
3387  }
3388  QCOMPARE(set.count(), container.count());
3389 
3390  //modify the container while iterating.
3391  Container c2 = container;
3392  Container c3;
3393  i = 0;
3394  foreach (T val, c2) {
3395  c3 << val;
3396  c2.insert((i * 89) % c2.size(), T() );
3397  QVERIFY( val == container.at(i) );
3398  val = T();
3399  i++;
3400  }
3401  QVERIFY(c3 == container);
3402 }
3403 
3404 
3405 void tst_Collections::foreach_2()
3406 {
3407  QStringList strlist = QString::fromLatin1("a,b,c,d,e,f,g,h,ih,kl,mn,op,qr,st,uvw,xyz").split(QLatin1Char(','));
3408  foreach_test_arrays(strlist);
3410  foreach_test_arrays(strlist.toVector());
3411 
3412  QList<int> intlist;
3413  intlist << 1 << 2 << 3 << 4 <<5 << 6 << 7 << 8 << 9;
3414  foreach_test_arrays(intlist);
3415  foreach_test_arrays(intlist.toVector());
3416 
3417  QVarLengthArray<int> varl1;
3420  foreach(int i, intlist) {
3421  varl1 << i;
3422  varl2 << i;
3423  varl3 << i;
3424  }
3425  QCOMPARE(varl1.count(), intlist.count());
3426  QCOMPARE(varl2.count(), intlist.count());
3427  QCOMPARE(varl3.count(), intlist.count());
3428 
3432  foreach(const QString &str, strlist) {
3433  varl4 << str;
3434  varl5 << str;
3435  varl6 << str;
3436  }
3437  QCOMPARE(varl4.count(), strlist.count());
3438  QCOMPARE(varl5.count(), strlist.count());
3439  QCOMPARE(varl6.count(), strlist.count());
3440 }
3441 
3443 {
3444  int val;
3445  IntOrString(int v) : val(v) { }
3446  IntOrString(const QString &v) : val(v.toInt()) { }
3447  operator int() { return val; }
3448  operator QString() { return QString::number(val); }
3449  operator std::string() { return QString::number(val).toStdString(); }
3450  IntOrString(const std::string &v) : val(QString::fromStdString(v).toInt()) { }
3451 };
3452 
3453 template<class Container> void insert_remove_loop_impl()
3454 {
3455  typedef typename Container::value_type T;
3456  Container t;
3457  t.append(T(IntOrString(1)));
3458  t << (T(IntOrString(2)));
3459  t += (T(IntOrString(3)));
3460  if constexpr (has_prepend_v<Container>)
3461  t.prepend(T(IntOrString(4)));
3462  else
3463  t.insert(t.cbegin(), T(IntOrString(4)));
3464  t.insert(2, 3 , T(IntOrString(5)));
3465  t.insert(4, T(IntOrString(6)));
3466  t.insert(t.begin() + 2, T(IntOrString(7)));
3467  t.insert(t.begin() + 5, 3, T(IntOrString(8)));
3468  int expect1[] = { 4 , 1 , 7, 5 , 5 , 8, 8, 8, 6, 5, 2 , 3 };
3469  QCOMPARE(size_t(t.count()), sizeof(expect1)/sizeof(int));
3470  for (int i = 0; i < t.count(); i++) {
3471  QCOMPARE(t[i], T(IntOrString(expect1[i])));
3472  }
3473 
3474  Container compare_test1 = t;
3475  t.replace(5, T(IntOrString(9)));
3476  Container compare_test2 = t;
3477  QVERIFY(!(compare_test1 == t));
3478  QVERIFY( (compare_test1 != t));
3479  QVERIFY( (compare_test2 == t));
3480  QVERIFY(!(compare_test2 != t));
3481  t.remove(7);
3482  t.remove(2, 3);
3483  int expect2[] = { 4 , 1 , 9, 8, 6, 5, 2 , 3 };
3484  QCOMPARE(size_t(t.count()), sizeof(expect2)/sizeof(int));
3485  for (int i = 0; i < t.count(); i++) {
3486  QCOMPARE(t[i], T(IntOrString(expect2[i])));
3487  }
3488 
3489  for (typename Container::iterator it = t.begin(); it != t.end(); ) {
3490  if ( int(IntOrString(*it)) % 2 )
3491  ++it;
3492  else
3493  it = t.erase(it);
3494  }
3495 
3496  int expect3[] = { 1 , 9, 5, 3 };
3497  QCOMPARE(size_t(t.count()), sizeof(expect3)/sizeof(int));
3498  for (int i = 0; i < t.count(); i++) {
3499  QCOMPARE(t[i], T(IntOrString(expect3[i])));
3500  }
3501 
3502  t.erase(t.begin() + 1, t.end() - 1);
3503 
3504  int expect4[] = { 1 , 3 };
3505  QCOMPARE(size_t(t.count()), sizeof(expect4)/sizeof(int));
3506  for (int i = 0; i < t.count(); i++) {
3507  QCOMPARE(t[i], T(IntOrString(expect4[i])));
3508  }
3509 
3510  t << T(IntOrString(10)) << T(IntOrString(11)) << T(IntOrString(12)) << T(IntOrString(13));
3511  t << T(IntOrString(14)) << T(IntOrString(15)) << T(IntOrString(16)) << T(IntOrString(17));
3512  t << T(IntOrString(18)) << T(IntOrString(19)) << T(IntOrString(20)) << T(IntOrString(21));
3513  for (typename Container::iterator it = t.begin(); it != t.end(); ++it) {
3514  int iv = int(IntOrString(*it));
3515  if ( iv % 2 ) {
3516  it = t.insert(it, T(IntOrString(iv * iv)));
3517  it = t.insert(it + 2, T(IntOrString(iv * iv + 1)));
3518  }
3519  }
3520 
3521  int expect5[] = { 1, 1, 2, 3*3, 3, 3*3+1, 10, 11*11, 11, 11*11+1, 12 , 13*13, 13, 13*13+1, 14,
3522  15*15, 15, 15*15+1, 16 , 17*17, 17, 17*17+1 ,18 , 19*19, 19, 19*19+1, 20, 21*21, 21, 21*21+1 };
3523  QCOMPARE(size_t(t.count()), sizeof(expect5)/sizeof(int));
3524  for (int i = 0; i < t.count(); i++) {
3525  QCOMPARE(t[i], T(IntOrString(expect5[i])));
3526  }
3527 
3528  t.clear();
3529  t << T(IntOrString(1)) << T(IntOrString(2)) << T(IntOrString(3)) << T(IntOrString(4));
3530  t.insert(2, 4, T(IntOrString(9)));
3531  t.insert(2, 4, T(IntOrString(7)));
3532 
3533  int expect6[] = { 1, 2, 7, 7, 7, 7, 9, 9, 9, 9, 3, 4 };
3534  QCOMPARE(size_t(t.count()), sizeof(expect6)/sizeof(int));
3535  for (int i = 0; i < t.count(); i++) {
3536  QCOMPARE(t[i], T(IntOrString(expect6[i])));
3537  }
3538 
3539 }
3540 
3541 
3542 template<typename T>
3544 
3545 void tst_Collections::insert_remove_loop()
3546 {
3547  insert_remove_loop_impl<ExtList<int>>();
3548  insert_remove_loop_impl<ExtList<QString>>();
3549  insert_remove_loop_impl<QList<int>>();
3550  insert_remove_loop_impl<QList<QString>>();
3551  insert_remove_loop_impl<QVarLengthArray<int>>();
3552  insert_remove_loop_impl<QVarLengthArray<QString>>();
3553  insert_remove_loop_impl<QVarLengthArray<int, 10>>();
3554  insert_remove_loop_impl<QVarLengthArray<QString, 10>>();
3555  insert_remove_loop_impl<QVarLengthArray<int, 3>>();
3556  insert_remove_loop_impl<QVarLengthArray<QString, 3>>();
3557  insert_remove_loop_impl<QVarLengthArray<int, 15>>();
3558  insert_remove_loop_impl<QVarLengthArray<QString, 15>>();
3559 
3560  insert_remove_loop_impl<ExtList<std::string>>();
3561  insert_remove_loop_impl<QList<std::string>>();
3562  insert_remove_loop_impl<QVarLengthArray<std::string>>();
3563  insert_remove_loop_impl<QVarLengthArray<std::string, 10>>();
3564  insert_remove_loop_impl<QVarLengthArray<std::string, 3>>();
3565  insert_remove_loop_impl<QVarLengthArray<std::string, 15>>();
3566 }
3567 
3568 template <template<typename, typename> typename Container>
3569 void tst_Collections::detachAssociativeContainerImpl()
3570 {
3571  constexpr int RUNS = 50;
3572 
3573  for (int run = 0; run < RUNS; ++run) {
3574  Container<int, int> container;
3575 
3576  for (int i = 0; i < 1'000; ++i) {
3577  container.insert(i, i);
3578  container.insert(i, i); // for multi-keyed containers
3579  }
3580 
3581  const auto it = container.constBegin();
3582  const auto &key = it.key();
3583  const auto &value = it.value();
3584  const auto keyCopy = key;
3585  const auto valueCopy = value;
3586 
3587  QSemaphore sem1, sem2;
3588  auto detachInAnotherThread = [&sem1, &sem2, copy = container]() mutable {
3589  sem1.release();
3590  sem2.acquire();
3591  copy.clear(); // <==
3592  };
3593 
3594  QScopedPointer thread(QThread::create(std::move(detachInAnotherThread)));
3595  thread->start();
3596 
3597  sem2.release();
3598  sem1.acquire();
3599 
3600  // The following call may detach (because the container is
3601  // shared), and then use key/value to search+insert.
3602  //
3603  // This means that key/value, as references, have to be valid
3604  // throughout the insertion procedure. Note that they are
3605  // references into the container *itself*; and that the
3606  // insertion procedure is working on a new (detached) copy of
3607  // the container's payload.
3608  //
3609  // There is now a possible scenario in which the clear() above
3610  // finds the copy's refcount at 1, hence not perform a detach,
3611  // and destroy its payload. But key/value were references into
3612  // *that* payload (it's the payload that `container` itself
3613  // used to share). If inside insert() we don't take extra
3614  // measures to keep the payload alive, now they're dangling and
3615  // the insertion will malfunction.
3616 
3617  container.insert(key, value);
3618 
3619  QVERIFY(container.contains(keyCopy));
3620  QCOMPARE(container.value(keyCopy), valueCopy);
3621 
3622  thread->wait();
3623  }
3624 }
3625 
3627 #include "tst_collections.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define value
[5]
friend size_t qHash(const AlignedClass &a)
bool operator==(const AlignedClass &other) const
bool operator<(const AlignedClass &other) const
bool operator==(const EqualsComparable &) const
bool operator<(const LessThanComparable &) const
bool operator==(const LessThanComparable &) const
The QBitArray class provides an array of bits.
Definition: qbitarray.h:49
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
qsizetype size() const noexcept
Definition: qbytearray.h:470
qsizetype indexOf(char c, qsizetype from=0) const
bool contains(char c) const
Definition: qbytearray.h:565
bool isEmpty() const noexcept
Definition: qbytearray.h:129
QByteArray left(qsizetype len) const
qsizetype lastIndexOf(char c, qsizetype from=-1) const
qsizetype count(char c) const
bool isNull() const noexcept
QByteArray mid(qsizetype index, qsizetype len=-1) const
Definition: qcache.h:50
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
iterator insert(const Key &key, const T &value)
Definition: qhash.h:1228
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
qsizetype size() const noexcept
Definition: qlist.h:414
void removeFirst() noexcept
Definition: qlist.h:811
bool isEmpty() const noexcept
Definition: qlist.h:418
iterator insert(qsizetype i, parameter_type t)
Definition: qlist.h:499
void swapItemsAt(qsizetype i, qsizetype j)
Definition: qlist.h:679
void detach()
Definition: qlist.h:437
iterator end()
Definition: qlist.h:624
static QList< T > fromVector(const QList< T > &vector) noexcept
Definition: qlist.h:729
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
static QList< T > fromList(const QList< T > &list) noexcept
Definition: qlist.h:726
void remove(qsizetype i, qsizetype n=1)
Definition: qlist.h:798
qsizetype count() const noexcept
Definition: qlist.h:415
void prepend(rvalue_ref t)
Definition: qlist.h:484
iterator begin()
Definition: qlist.h:623
void replace(qsizetype i, parameter_type t)
Definition: qlist.h:541
void resize(qsizetype size)
Definition: qlist.h:420
void append(parameter_type t)
Definition: qlist.h:469
QList< T > toVector() const noexcept
Definition: qlist.h:730
void clear()
Definition: qlist.h:445
QList< T > toList() const noexcept
Definition: qlist.h:727
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:392
bool contains(const Key &key) const
Definition: qmap.h:376
size_type remove(const Key &key)
Definition: qmap.h:335
const_iterator cbegin() const
Definition: qmap.h:636
iterator find(const Key &key)
Definition: qmap.h:672
void detach()
Definition: qmap.h:306
bool isEmpty() const
Definition: qmap.h:304
iterator begin()
Definition: qmap.h:633
iterator end()
Definition: qmap.h:637
const_iterator constBegin() const
Definition: qmap.h:635
size_type size() const
Definition: qmap.h:302
The QMultiHash class is a convenience QHash subclass that provides multi-valued hashes.
Definition: qhash.h:1293
QMultiHash & unite(const QMultiHash &other)
Definition: qhash.h:2023
QList< T > values() const
Definition: qhash.h:1617
iterator insert(const Key &key, const T &value)
Definition: qhash.h:1861
qsizetype size() const noexcept
Definition: qhash.h:1435
const T & value() const
Definition: qmap.h:1244
T & value() const
Definition: qmap.h:1173
iterator lowerBound(const Key &key)
Definition: qmap.h:1425
QMultiMap & unite(const QMultiMap &other)
Definition: qmap.h:1539
iterator end()
Definition: qmap.h:1332
iterator find(const Key &key)
Definition: qmap.h:1372
iterator insert(const Key &key, const T &value)
Definition: qmap.h:1453
size_type size() const
Definition: qmap.h:943
QList< T > values() const
Definition: qmap.h:1110
iterator upperBound(const Key &key)
Definition: qmap.h:1439
iterator begin()
Definition: qmap.h:1328
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
const QObjectList & children() const
Definition: qobject.h:206
QThread * thread() const
Definition: qobject.cpp:1527
The QQueue class is a generic container that provides a queue.
Definition: qqueue.h:50
The QRegularExpression class provides pattern matching using regular expressions.
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
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
qsizetype size() const
Definition: qset.h:86
QList< T > values() const
Definition: qset.h:333
iterator begin()
Definition: qset.h:172
qsizetype count() const
Definition: qset.h:190
bool contains(const T &value) const
Definition: qset.h:107
The QSharedData class is a base class for shared data objects. \reentrant.
Definition: qshareddata.h:55
T pop()
Definition: qstack.h:54
void push(const T &t)
Definition: qstack.h:53
The QString class provides a Unicode character string.
Definition: qstring.h:388
qsizetype count() const
Definition: qstring.h:414
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition: qstring.h:514
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:5092
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:7672
static QString fromStdString(const std::string &s)
Definition: qstring.h:1452
void clear()
Definition: qstring.h:1240
bool isNull() const
Definition: qstring.h:1078
qsizetype size() const
Definition: qstring.h:413
std::string toStdString() const
Definition: qstring.h:1449
static QString fromUtf8(QByteArrayView utf8)
Definition: qstring.cpp:5632
static QString fromRawData(const QChar *, qsizetype size)
Definition: qstring.cpp:8938
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:5143
bool isEmpty() const
Definition: qstring.h:1216
QString & insert(qsizetype i, QChar c)
Definition: qstring.cpp:3043
QChar * data()
Definition: qstring.h:1228
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:1353
static QString number(int, int base=10)
Definition: qstring.cpp:7538
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:4197
qsizetype length() const
Definition: qstring.h:415
const QChar * unicode() const
Definition: qstring.h:1218
The QStringList class provides a list of strings.
The QStringView class provides a unified view on UTF-16 strings with a read-only subset of the QStrin...
Definition: qstringview.h:122
void start(Priority=InheritPriority)
Definition: qthread.cpp:836
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition: qthread.cpp:863
The QTime class provides clock time functions.
Definition: qdatetime.h:166
qsizetype count() const
#define T(x)
Definition: main.cpp:42
VariantOrderedMap Map
Definition: converter.h:70
float rx
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
QString str
[2]
double e
QCOMPARE(spy.count(), 1)
FT_Vector * vec
Definition: ftbbox.c:469
short next
Definition: keywords.cpp:454
HBUINT16 Value
typename C::value_type value_type
typename C::const_iterator const_iterator
typename C::key_type key_type
typename C::mapped_type mapped_type
typename C::iterator iterator
KeyType
Definition: qssl.h:51
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
const T & const_reference()
@ CaseInsensitive
Definition: qnamespace.h:1283
#define QString()
Definition: parse-defines.h:51
#define QT_WARNING_POP
#define QT_WARNING_PUSH
#define QT_WARNING_DISABLE_CLANG(text)
std::pair< T1, T2 > QPair
Definition: qcontainerfwd.h:56
QList< QString > QStringList
Definition: qcontainerfwd.h:64
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
Definition: qglobal.h:332
size_t quintptr
Definition: qglobal.h:310
unsigned int uint
Definition: qglobal.h:334
unsigned short ushort
Definition: qglobal.h:333
GLint GLfloat GLfloat GLfloat v2
GLenum GLsizei GLsizei GLint * values
[16]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLboolean r
[2]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum GLenum GLsizei count
GLint reference
GLint left
GLint GLfloat GLfloat v1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLfloat GLfloat GLfloat GLfloat v3
GLuint counter
const GLubyte * c
Definition: qopenglext.h:12701
GLuint GLfloat * val
Definition: qopenglext.h:1513
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLsizei const void * pointer
Definition: qopenglext.h:384
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLsizei const GLchar *const * string
[0]
Definition: qopenglext.h:694
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition: qpair.h:55
#define QT_POINTER_SIZE
QMutableListIterator< QString > QMutableStringListIterator
Definition: qstringlist.h:57
#define v1
#define k1
#define QTEST_APPLESS_MAIN(TestObject)
Definition: qtest.h:632
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QFAIL(message)
Definition: qtestcase.h:70
#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]
struct Hash Hash
Definition: sqlite3.c:13430
QLatin1String world("world")
QFuture< int > sum
QFuture< QSet< QChar > > set
[10]
QList< int > vector
[14]
HelloWorldTask * hello
QByteArray ba
[0]
MyCustomStruct c2
ba fill(true)
QBitArray().isNull()
[3]
Definition: qbitarray.h:149
QSharedPointer< T > other(t)
[5]
QLayoutItem * child
[0]
view create()
QStringList::Iterator it
QStringList list
[0]
bool isDetached() const
static int counter
bool operator==(const Dummy &) const
bool operator<(const Dummy &) const
IntOrString(const std::string &v)
IntOrString(const QString &v)
static int count
LargeStatic & operator=(const LargeStatic &o)
LargeStatic(const LargeStatic &o)
Movable(const Movable &o)
static int count
bool operator==(const NoCmpRecursiveHashK &) const =delete
bool operator==(const NoCmpRecursiveHashV &) const =delete
bool operator==(const RecursiveList &) const =delete
bool operator<(const RecursiveList &) const =delete
bool operator==(const NoCmpRecursiveMapK &) const =delete
bool operator==(const NoCmpRecursiveMapV &) const =delete
bool operator==(const NoCmpRecursiveMultiHashK &) const =delete
bool operator==(const NoCmpRecursiveMultiHashV &) const =delete
bool operator==(const NoCmpRecursiveMultiMapK &) const =delete
bool operator==(const NoCmpRecursiveMultiMapV &) const =delete
bool operator==(const NoCmpRecursiveSet &) const =delete
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
C< int, QTBUG13079_NodeAssoc > children
C< QTBUG13079_Node > children
C< QTBUG13079_NodePtr > child
QTBUG13079_NodePtr * next
Definition: main.cpp:38
QThreadStorage< int * > dummy[8]
Q_DECLARE_METATYPE(RecursiveList)
void testListLikeStlIterators()
void populate(Container &)
#define TEST_SEQUENTIAL_CONTAINER(Container)
void testContainer()
void testSetContainerTypedefs(Container container)
void instantiateRandomAccess()
uint qHash(const Dummy &)
constexpr bool has_prepend_v
void QTBUG13079_collectionInsidePtrImpl()
void instantiateMutableIterationContainer()
void instantiateContainer()
bool operator==(const QTBUG13079_Node< QSet > &a, const QTBUG13079_Node< QSet > &b)
#define TEST_ASSOCIATIVE_CONTAINER(Container)
void instantiatePairAssociative()
QList< int > getList()
T qtInit(T *=nullptr)
void testContiguousCacheAlignment()
#define QVERIFY_TYPE(Type)
void testLinkedListLikeStlIterators()
void testMapLikeStlIterators()
bool isSharable(const Container &container)
void testVectorAlignment()
#define BIGGEST_ALIGNMENT_TO_TEST
void testPairAssociativeContainerTypedefs(Container container)
#define TEST(type)
void instantiateAssociative()
void foo()
#define STUFF
void insert_remove_loop_impl()
Container newInstance()
QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(Movable, Q_RELOCATABLE_TYPE)
void QTBUG13079_collectionInsideCollectionAssocImpl()
void testContainerTypedefs(Container container)
void foreach_test_arrays(const Container &container)
void instantiateSequence()
void QTBUG13079_collectionInsideCollectionImpl()
void testAssociativeContainerAlignment()
bool run(const QString &name, QString *errorMessage)