1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30
31#include <qhash.h>
32#include <qmap.h>
33
34#include <algorithm>
35#include <vector>
36
37class tst_QHash : public QObject
38{
39 Q_OBJECT
40private slots:
41 void insert1();
42 void erase();
43 void key();
44
45 void swap();
46 void count(); // copied from tst_QMap
47 void clear(); // copied from tst_QMap
48 void empty(); // copied from tst_QMap
49 void find(); // copied from tst_QMap
50 void constFind(); // copied from tst_QMap
51 void contains(); // copied from tst_QMap
52 void qhash();
53 void take(); // copied from tst_QMap
54 void operator_eq(); // slightly modified from tst_QMap
55 void rehash_isnt_quadratic();
56 void dont_need_default_constructor();
57 void qmultihash_specific();
58
59 void compare();
60 void compare2();
61 void iterators(); // sligthly modified from tst_QMap
62 void keyIterator();
63 void keyValueIterator();
64 void keys_values_uniqueKeys(); // slightly modified from tst_QMap
65 void noNeedlessRehashes();
66
67 void const_shared_null();
68 void twoArguments_qHash();
69 void initializerList();
70 void eraseValidIteratorOnSharedHash();
71 void equal_range();
72 void insert_hash();
73};
74
75struct IdentityTracker {
76 int value, id;
77};
78
79inline uint qHash(IdentityTracker key) { return qHash(key: key.value); }
80inline bool operator==(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value == rhs.value; }
81
82
83struct Foo {
84 static int count;
85 Foo():c(count) { ++count; }
86 Foo(const Foo& o):c(o.c) { ++count; }
87 ~Foo() { --count; }
88 int c;
89 int data[8];
90};
91
92int Foo::count = 0;
93
94//copied from tst_QMap.cpp
95class MyClass
96{
97public:
98 MyClass() { ++count;
99 }
100 MyClass( const QString& c) {
101 count++; str = c;
102 }
103 ~MyClass() {
104 count--;
105 }
106 MyClass( const MyClass& c ) {
107 count++; str = c.str;
108 }
109 MyClass &operator =(const MyClass &o) {
110 str = o.str; return *this;
111 }
112
113 QString str;
114 static int count;
115};
116
117int MyClass::count = 0;
118
119typedef QHash<QString, MyClass> MyMap;
120
121//void tst_QMap::count()
122void tst_QHash::count()
123{
124 {
125 MyMap map;
126 MyMap map2( map );
127 QCOMPARE( map.count(), 0 );
128 QCOMPARE( map2.count(), 0 );
129 QCOMPARE( MyClass::count, 0 );
130 // detach
131 map2["Hallo"] = MyClass( "Fritz" );
132 QCOMPARE( map.count(), 0 );
133 QCOMPARE( map2.count(), 1 );
134#ifndef Q_CC_SUN
135 QCOMPARE( MyClass::count, 1 );
136#endif
137 }
138 QCOMPARE( MyClass::count, 0 );
139
140 {
141 typedef QHash<QString, MyClass> Map;
142 Map map;
143 QCOMPARE( map.count(), 0);
144 map.insert( akey: "Torben", avalue: MyClass("Weis") );
145 QCOMPARE( map.count(), 1 );
146 map.insert( akey: "Claudia", avalue: MyClass("Sorg") );
147 QCOMPARE( map.count(), 2 );
148 map.insert( akey: "Lars", avalue: MyClass("Linzbach") );
149 map.insert( akey: "Matthias", avalue: MyClass("Ettrich") );
150 map.insert( akey: "Sue", avalue: MyClass("Paludo") );
151 map.insert( akey: "Eirik", avalue: MyClass("Eng") );
152 map.insert( akey: "Haavard", avalue: MyClass("Nord") );
153 map.insert( akey: "Arnt", avalue: MyClass("Gulbrandsen") );
154 map.insert( akey: "Paul", avalue: MyClass("Tvete") );
155 QCOMPARE( map.count(), 9 );
156 map.insert( akey: "Paul", avalue: MyClass("Tvete 1") );
157 map.insert( akey: "Paul", avalue: MyClass("Tvete 2") );
158 map.insert( akey: "Paul", avalue: MyClass("Tvete 3") );
159 map.insert( akey: "Paul", avalue: MyClass("Tvete 4") );
160 map.insert( akey: "Paul", avalue: MyClass("Tvete 5") );
161 map.insert( akey: "Paul", avalue: MyClass("Tvete 6") );
162
163 QCOMPARE( map.count(), 9 );
164#ifndef Q_CC_SUN
165 QCOMPARE( MyClass::count, 9 );
166#endif
167
168 Map map2( map );
169 QVERIFY( map2.count() == 9 );
170#ifndef Q_CC_SUN
171 QCOMPARE( MyClass::count, 9 );
172#endif
173
174 map2.insert( akey: "Kay", avalue: MyClass("Roemer") );
175 QVERIFY( map2.count() == 10 );
176 QVERIFY( map.count() == 9 );
177#ifndef Q_CC_SUN
178 QCOMPARE( MyClass::count, 19 );
179#endif
180
181 map2 = map;
182 QVERIFY( map.count() == 9 );
183 QVERIFY( map2.count() == 9 );
184#ifndef Q_CC_SUN
185 QCOMPARE( MyClass::count, 9 );
186#endif
187
188 map2.insert( akey: "Kay", avalue: MyClass("Roemer") );
189 QVERIFY( map2.count() == 10 );
190#ifndef Q_CC_SUN
191 QCOMPARE( MyClass::count, 19 );
192#endif
193
194 map2.clear();
195 QVERIFY( map.count() == 9 );
196 QVERIFY( map2.count() == 0 );
197#ifndef Q_CC_SUN
198 QCOMPARE( MyClass::count, 9 );
199#endif
200
201 map2 = map;
202 QVERIFY( map.count() == 9 );
203 QVERIFY( map2.count() == 9 );
204#ifndef Q_CC_SUN
205 QCOMPARE( MyClass::count, 9 );
206#endif
207
208 map2.clear();
209 QVERIFY( map.count() == 9 );
210 QVERIFY( map2.count() == 0 );
211#ifndef Q_CC_SUN
212 QCOMPARE( MyClass::count, 9 );
213#endif
214
215 map.remove( akey: "Lars" );
216 QVERIFY( map.count() == 8 );
217 QVERIFY( map2.count() == 0 );
218#ifndef Q_CC_SUN
219 QCOMPARE( MyClass::count, 8 );
220#endif
221
222 map.remove( akey: "Mist" );
223 QVERIFY( map.count() == 8 );
224 QVERIFY( map2.count() == 0 );
225#ifndef Q_CC_SUN
226 QCOMPARE( MyClass::count, 8 );
227#endif
228 }
229 QVERIFY( MyClass::count == 0 );
230
231 {
232 typedef QHash<QString,MyClass> Map;
233 Map map;
234 map["Torben"] = MyClass("Weis");
235#ifndef Q_CC_SUN
236 QVERIFY( MyClass::count == 1 );
237#endif
238 QVERIFY( map.count() == 1 );
239
240 (void)map["Torben"].str;
241 (void)map["Lars"].str;
242#ifndef Q_CC_SUN
243 QVERIFY( MyClass::count == 2 );
244#endif
245 QVERIFY( map.count() == 2 );
246
247 const Map& cmap = map;
248 (void)cmap["Depp"].str;
249#ifndef Q_CC_SUN
250 QVERIFY( MyClass::count == 2 );
251#endif
252 QVERIFY( map.count() == 2 );
253 QVERIFY( cmap.count() == 2 );
254 }
255 QCOMPARE( MyClass::count, 0 );
256 {
257 for ( int i = 0; i < 100; ++i )
258 {
259 QHash<int, MyClass> map;
260 for (int j = 0; j < i; ++j)
261 map.insert(akey: j, avalue: MyClass(QString::number(j)));
262 }
263 QCOMPARE( MyClass::count, 0 );
264 }
265 QCOMPARE( MyClass::count, 0 );
266}
267void tst_QHash::insert1()
268{
269 const char *hello = "hello";
270 const char *world = "world";
271 const char *allo = "allo";
272 const char *monde = "monde";
273
274 {
275 typedef QHash<QString, QString> Hash;
276 Hash hash;
277 QString key = QLatin1String(" ");
278 for (int i = 0; i < 10; ++i) {
279 key[0] = i + '0';
280 for (int j = 0; j < 10; ++j) {
281 key[1] = j + '0';
282 hash.insert(akey: key, avalue: "V" + key);
283 }
284 }
285
286 for (int i = 0; i < 10; ++i) {
287 key[0] = i + '0';
288 for (int j = 0; j < 10; ++j) {
289 key[1] = j + '0';
290 hash.remove(akey: key);
291 }
292 }
293 }
294
295 {
296 typedef QHash<int, const char *> Hash;
297 Hash hash;
298 hash.insert(akey: 1, avalue: hello);
299 hash.insert(akey: 2, avalue: world);
300
301 QVERIFY(hash.size() == 2);
302 QVERIFY(!hash.isEmpty());
303
304 {
305 Hash hash2 = hash;
306 hash2 = hash;
307 hash = hash2;
308 hash2 = hash2;
309 hash = hash;
310 hash2.clear();
311 hash2 = hash2;
312 QVERIFY(hash2.size() == 0);
313 QVERIFY(hash2.isEmpty());
314 }
315 QVERIFY(hash.size() == 2);
316
317 {
318 Hash hash2 = hash;
319 hash2[1] = allo;
320 hash2[2] = monde;
321
322 QVERIFY(hash2[1] == allo);
323 QVERIFY(hash2[2] == monde);
324 QVERIFY(hash[1] == hello);
325 QVERIFY(hash[2] == world);
326
327 hash2[1] = hash[1];
328 hash2[2] = hash[2];
329
330 QVERIFY(hash2[1] == hello);
331 QVERIFY(hash2[2] == world);
332
333 hash[1] = hash[1];
334 QVERIFY(hash[1] == hello);
335 }
336 {
337 Hash hash2 = hash;
338 hash2.detach();
339 hash2.remove(akey: 1);
340 QVERIFY(hash2.size() == 1);
341 hash2.remove(akey: 1);
342 QVERIFY(hash2.size() == 1);
343 hash2.remove(akey: 0);
344 QVERIFY(hash2.size() == 1);
345 hash2.remove(akey: 2);
346 QVERIFY(hash2.size() == 0);
347 QVERIFY(hash.size() == 2);
348 }
349
350 hash.detach();
351
352 {
353 Hash::iterator it1 = hash.find(akey: 1);
354 QVERIFY(it1 != hash.end());
355
356 Hash::iterator it2 = hash.find(akey: 0);
357 QVERIFY(it2 != hash.begin());
358 QVERIFY(it2 == hash.end());
359
360 *it1 = monde;
361 QVERIFY(*it1 == monde);
362 QVERIFY(hash[1] == monde);
363
364 *it1 = hello;
365 QVERIFY(*it1 == hello);
366 QVERIFY(hash[1] == hello);
367
368 hash[1] = monde;
369 QVERIFY(it1.key() == 1);
370 QVERIFY(it1.value() == monde);
371 QVERIFY(*it1 == monde);
372 QVERIFY(hash[1] == monde);
373
374 hash[1] = hello;
375 QVERIFY(*it1 == hello);
376 QVERIFY(hash[1] == hello);
377 }
378
379 {
380 const Hash hash2 = hash;
381
382 Hash::const_iterator it1 = hash2.find(akey: 1);
383 QVERIFY(it1 != hash2.end());
384 QVERIFY(it1.key() == 1);
385 QVERIFY(it1.value() == hello);
386 QVERIFY(*it1 == hello);
387
388 Hash::const_iterator it2 = hash2.find(akey: 2);
389 QVERIFY(it1 != it2);
390 QVERIFY(it1 != hash2.end());
391 QVERIFY(it2 != hash2.end());
392
393 int count = 0;
394 it1 = hash2.begin();
395 while (it1 != hash2.end()) {
396 count++;
397 ++it1;
398 }
399 QVERIFY(count == 2);
400
401 count = 0;
402 it1 = hash.constBegin();
403 while (it1 != hash.constEnd()) {
404 count++;
405 ++it1;
406 }
407 QVERIFY(count == 2);
408 }
409
410 {
411 QVERIFY(hash.contains(1));
412 QVERIFY(hash.contains(2));
413 QVERIFY(!hash.contains(0));
414 QVERIFY(!hash.contains(3));
415 }
416
417 {
418 QVERIFY(hash.value(1) == hello);
419 QVERIFY(hash.value(2) == world);
420 QVERIFY(hash.value(3) == 0);
421 QVERIFY(hash.value(1, allo) == hello);
422 QVERIFY(hash.value(2, allo) == world);
423 QVERIFY(hash.value(3, allo) == allo);
424 QVERIFY(hash.value(0, monde) == monde);
425 }
426
427 {
428 QHash<int,Foo> hash;
429 for (int i = 0; i < 10; i++)
430 hash.insert(akey: i, avalue: Foo());
431 QVERIFY(Foo::count == 10);
432 hash.remove(akey: 7);
433 QVERIFY(Foo::count == 9);
434
435 }
436 QVERIFY(Foo::count == 0);
437 {
438 QHash<int, int*> hash;
439 QVERIFY(((const QHash<int,int*>*) &hash)->operator[](7) == 0);
440 }
441 }
442 {
443 QHash<IdentityTracker, int> hash;
444 QCOMPARE(hash.size(), 0);
445 const int dummy = -1;
446 IdentityTracker id00 = {.value: 0, .id: 0}, id01 = {.value: 0, .id: 1}, searchKey = {.value: 0, .id: dummy};
447 QCOMPARE(hash.insert(id00, id00.id).key().id, id00.id);
448 QCOMPARE(hash.size(), 1);
449 QCOMPARE(hash.insert(id01, id01.id).key().id, id00.id); // first key inserted is kept
450 QCOMPARE(hash.size(), 1);
451 QCOMPARE(hash.find(searchKey).value(), id01.id); // last-inserted value
452 QCOMPARE(hash.find(searchKey).key().id, id00.id); // but first-inserted key
453 }
454 {
455 QMultiHash<IdentityTracker, int> hash;
456 QCOMPARE(hash.size(), 0);
457 const int dummy = -1;
458 IdentityTracker id00 = {.value: 0, .id: 0}, id01 = {.value: 0, .id: 1}, searchKey = {.value: 0, .id: dummy};
459 QCOMPARE(hash.insert(id00, id00.id).key().id, id00.id);
460 QCOMPARE(hash.size(), 1);
461 QCOMPARE(hash.insert(id01, id01.id).key().id, id01.id);
462 QCOMPARE(hash.size(), 2);
463 QMultiHash<IdentityTracker, int>::const_iterator pos = hash.constFind(akey: searchKey);
464 QCOMPARE(pos.value(), pos.key().id); // key fits to value it was inserted with
465 ++pos;
466 QCOMPARE(pos.value(), pos.key().id); // key fits to value it was inserted with
467 }
468}
469
470void tst_QHash::erase()
471{
472 QHash<int, int> h1;
473 h1.insert(akey: 1, avalue: 2);
474 h1.erase(it: h1.begin());
475 QVERIFY(h1.size() == 0);
476 QVERIFY(h1.begin() == h1.end());
477 h1.insert(akey: 3, avalue: 4);
478 QVERIFY(*h1.begin() == 4);
479 h1.insert(akey: 5, avalue: 6);
480 QVERIFY(h1.size() == 2);
481 QHash<int, int>::iterator it1 = h1.begin();
482 ++it1;
483 it1 = h1.erase(it: it1);
484 QVERIFY(it1 == h1.end());
485 h1.insert(akey: 7, avalue: 8);
486 h1.insert(akey: 9, avalue: 10);
487 it1 = h1.begin();
488 int n = 0;
489 while (it1 != h1.end()) {
490 it1 = h1.erase(it: it1);
491 ++n;
492 }
493 QVERIFY(n == 3);
494 QHash<int, int> h2;
495 h2.insertMulti(key: 20, value: 41);
496 h2.insertMulti(key: 20, value: 42);
497 QVERIFY(h2.size() == 2);
498 it1 = h2.erase(it: h2.begin());
499 it1 = h2.erase(it: h2.begin());
500 QVERIFY(it1 == h2.end());
501}
502
503void tst_QHash::key()
504{
505 {
506 QString def("default value");
507
508 QHash<QString, int> hash1;
509 QCOMPARE(hash1.key(1), QString());
510 QCOMPARE(hash1.key(1, def), def);
511
512 hash1.insert(akey: "one", avalue: 1);
513 QCOMPARE(hash1.key(1), QLatin1String("one"));
514 QCOMPARE(hash1.key(1, def), QLatin1String("one"));
515 QCOMPARE(hash1.key(2), QString());
516 QCOMPARE(hash1.key(2, def), def);
517
518 hash1.insert(akey: "two", avalue: 2);
519 QCOMPARE(hash1.key(1), QLatin1String("one"));
520 QCOMPARE(hash1.key(1, def), QLatin1String("one"));
521 QCOMPARE(hash1.key(2), QLatin1String("two"));
522 QCOMPARE(hash1.key(2, def), QLatin1String("two"));
523 QCOMPARE(hash1.key(3), QString());
524 QCOMPARE(hash1.key(3, def), def);
525
526 hash1.insert(akey: "deux", avalue: 2);
527 QCOMPARE(hash1.key(1), QLatin1String("one"));
528 QCOMPARE(hash1.key(1, def), QLatin1String("one"));
529 QVERIFY(hash1.key(2) == QLatin1String("deux") || hash1.key(2) == QLatin1String("two"));
530 QVERIFY(hash1.key(2, def) == QLatin1String("deux") || hash1.key(2, def) == QLatin1String("two"));
531 QCOMPARE(hash1.key(3), QString());
532 QCOMPARE(hash1.key(3, def), def);
533 }
534
535 {
536 int def = 666;
537
538 QHash<int, QString> hash2;
539 QCOMPARE(hash2.key("one"), 0);
540 QCOMPARE(hash2.key("one", def), def);
541
542 hash2.insert(akey: 1, avalue: "one");
543 QCOMPARE(hash2.key("one"), 1);
544 QCOMPARE(hash2.key("one", def), 1);
545 QCOMPARE(hash2.key("two"), 0);
546 QCOMPARE(hash2.key("two", def), def);
547
548 hash2.insert(akey: 2, avalue: "two");
549 QCOMPARE(hash2.key("one"), 1);
550 QCOMPARE(hash2.key("one", def), 1);
551 QCOMPARE(hash2.key("two"), 2);
552 QCOMPARE(hash2.key("two", def), 2);
553 QCOMPARE(hash2.key("three"), 0);
554 QCOMPARE(hash2.key("three", def), def);
555
556 hash2.insert(akey: 3, avalue: "two");
557 QCOMPARE(hash2.key("one"), 1);
558 QCOMPARE(hash2.key("one", def), 1);
559 QVERIFY(hash2.key("two") == 2 || hash2.key("two") == 3);
560 QVERIFY(hash2.key("two", def) == 2 || hash2.key("two", def) == 3);
561 QCOMPARE(hash2.key("three"), 0);
562 QCOMPARE(hash2.key("three", def), def);
563
564 hash2.insert(akey: -1, avalue: "two");
565 QVERIFY(hash2.key("two") == 2 || hash2.key("two") == 3 || hash2.key("two") == -1);
566 QVERIFY(hash2.key("two", def) == 2 || hash2.key("two", def) == 3 || hash2.key("two", def) == -1);
567
568 hash2.insert(akey: 0, avalue: "zero");
569 QCOMPARE(hash2.key("zero"), 0);
570 QCOMPARE(hash2.key("zero", def), 0);
571 }
572}
573
574void tst_QHash::swap()
575{
576 QHash<int,QString> h1, h2;
577 h1[0] = "h1[0]";
578 h2[1] = "h2[1]";
579 h1.swap(other&: h2);
580 QCOMPARE(h1.value(1),QLatin1String("h2[1]"));
581 QCOMPARE(h2.value(0),QLatin1String("h1[0]"));
582}
583
584// copied from tst_QMap
585void tst_QHash::clear()
586{
587 {
588 MyMap map;
589 map.clear();
590 QVERIFY( map.isEmpty() );
591 map.insert( akey: "key", avalue: MyClass( "value" ) );
592 map.clear();
593 QVERIFY( map.isEmpty() );
594 map.insert( akey: "key0", avalue: MyClass( "value0" ) );
595 map.insert( akey: "key0", avalue: MyClass( "value1" ) );
596 map.insert( akey: "key1", avalue: MyClass( "value2" ) );
597 map.clear();
598 QVERIFY( map.isEmpty() );
599 }
600 QCOMPARE( MyClass::count, int(0) );
601}
602//copied from tst_QMap
603void tst_QHash::empty()
604{
605 QHash<int, QString> map1;
606
607 QVERIFY(map1.isEmpty());
608
609 map1.insert(akey: 1, avalue: "one");
610 QVERIFY(!map1.isEmpty());
611
612 map1.clear();
613 QVERIFY(map1.isEmpty());
614
615}
616
617//copied from tst_QMap
618void tst_QHash::find()
619{
620 QHash<int, QString> map1;
621 QString testString="Teststring %0";
622 QString compareString;
623 int i,count=0;
624
625 QVERIFY(map1.find(1) == map1.end());
626
627 map1.insert(akey: 1,avalue: "Mensch");
628 map1.insert(akey: 1,avalue: "Mayer");
629 map1.insert(akey: 2,avalue: "Hej");
630
631 QCOMPARE(map1.find(1).value(), QLatin1String("Mayer"));
632 QCOMPARE(map1.find(2).value(), QLatin1String("Hej"));
633
634 for(i = 3; i < 10; ++i) {
635 compareString = testString.arg(a: i);
636 map1.insertMulti(key: 4, value: compareString);
637 }
638
639 QHash<int, QString>::const_iterator it=map1.constFind(akey: 4);
640
641 for(i = 9; i > 2 && it != map1.constEnd() && it.key() == 4; --i) {
642 compareString = testString.arg(a: i);
643 QVERIFY(it.value() == compareString);
644 ++it;
645 ++count;
646 }
647 QCOMPARE(count, 7);
648}
649
650// copied from tst_QMap
651void tst_QHash::constFind()
652{
653 QHash<int, QString> map1;
654 QString testString="Teststring %0";
655 QString compareString;
656 int i,count=0;
657
658 QVERIFY(map1.constFind(1) == map1.constEnd());
659
660 map1.insert(akey: 1,avalue: "Mensch");
661 map1.insert(akey: 1,avalue: "Mayer");
662 map1.insert(akey: 2,avalue: "Hej");
663
664 QCOMPARE(map1.constFind(1).value(), QLatin1String("Mayer"));
665 QCOMPARE(map1.constFind(2).value(), QLatin1String("Hej"));
666
667 for(i = 3; i < 10; ++i) {
668 compareString = testString.arg(a: i);
669 map1.insertMulti(key: 4, value: compareString);
670 }
671
672 QHash<int, QString>::const_iterator it=map1.constFind(akey: 4);
673
674 for(i = 9; i > 2 && it != map1.constEnd() && it.key() == 4; --i) {
675 compareString = testString.arg(a: i);
676 QVERIFY(it.value() == compareString);
677 ++it;
678 ++count;
679 }
680 QCOMPARE(count, 7);
681}
682
683// copied from tst_QMap
684void tst_QHash::contains()
685{
686 QHash<int, QString> map1;
687 int i;
688
689 map1.insert(akey: 1, avalue: "one");
690 QVERIFY(map1.contains(1));
691
692 for(i=2; i < 100; ++i)
693 map1.insert(akey: i, avalue: "teststring");
694 for(i=99; i > 1; --i)
695 QVERIFY(map1.contains(i));
696
697 map1.remove(akey: 43);
698 QVERIFY(!map1.contains(43));
699}
700
701namespace {
702class QGlobalQHashSeedResetter
703{
704 int oldSeed;
705public:
706 // not entirely correct (may lost changes made by another thread between the query
707 // of the old and the setting of the new seed), but qSetGlobalQHashSeed doesn't
708 // return the old value, so this is the best we can do:
709 explicit QGlobalQHashSeedResetter(int newSeed)
710 : oldSeed(qGlobalQHashSeed())
711 {
712 qSetGlobalQHashSeed(newSeed);
713 }
714 ~QGlobalQHashSeedResetter()
715 {
716 qSetGlobalQHashSeed(newSeed: oldSeed);
717 }
718};
719
720template <typename Key, typename T>
721QHash<T, Key> inverted(const QHash<Key, T> &in)
722{
723 QHash<T, Key> result;
724 for (auto it = in.begin(), end = in.end(); it != end; ++it)
725 result[it.value()] = it.key();
726 return result;
727}
728
729template <typename AssociativeContainer>
730void make_test_data(AssociativeContainer &c)
731{
732 c["one"] = "1";
733 c["two"] = "2";
734}
735
736}
737
738void tst_QHash::qhash()
739{
740 const QGlobalQHashSeedResetter seed1(0);
741
742 QHash<QString, QString> hash1;
743 make_test_data(c&: hash1);
744 const QHash<QString, QString> hsah1 = inverted(in: hash1);
745
746 const QGlobalQHashSeedResetter seed2(1);
747
748 QHash<QString, QString> hash2;
749 make_test_data(c&: hash2);
750 const QHash<QString, QString> hsah2 = inverted(in: hash2);
751
752 QCOMPARE(hash1, hash2);
753 QCOMPARE(hsah1, hsah2);
754 QCOMPARE(qHash(hash1), qHash(hash2));
755 QCOMPARE(qHash(hsah1), qHash(hsah2));
756
757 // by construction this is almost impossible to cause false collisions:
758 QVERIFY(hash1 != hsah1);
759 QVERIFY(hash2 != hsah2);
760 QVERIFY(qHash(hash1) != qHash(hsah1));
761 QVERIFY(qHash(hash2) != qHash(hsah2));
762}
763
764//copied from tst_QMap
765void tst_QHash::take()
766{
767 QHash<int, QString> map;
768
769 map.insert(akey: 2, avalue: "zwei");
770 map.insert(akey: 3, avalue: "drei");
771
772 QCOMPARE(map.take(3), QLatin1String("drei"));
773 QVERIFY(!map.contains(3));
774}
775
776// slightly modified from tst_QMap
777void tst_QHash::operator_eq()
778{
779 {
780 // compare for equality:
781 QHash<int, int> a;
782 QHash<int, int> b;
783
784 QVERIFY(a == b);
785 QVERIFY(!(a != b));
786
787 a.insert(akey: 1,avalue: 1);
788 b.insert(akey: 1,avalue: 1);
789 QVERIFY(a == b);
790 QVERIFY(!(a != b));
791
792 a.insert(akey: 0,avalue: 1);
793 b.insert(akey: 0,avalue: 1);
794 QVERIFY(a == b);
795 QVERIFY(!(a != b));
796
797 // compare for inequality:
798 a.insert(akey: 42,avalue: 0);
799 QVERIFY(a != b);
800 QVERIFY(!(a == b));
801
802 a.insert(akey: 65, avalue: -1);
803 QVERIFY(a != b);
804 QVERIFY(!(a == b));
805
806 b.insert(akey: -1, avalue: -1);
807 QVERIFY(a != b);
808 QVERIFY(!(a == b));
809 }
810
811 {
812 // a more complex map
813 QHash<QString, QString> a;
814 QHash<QString, QString> b;
815
816 QVERIFY(a == b);
817 QVERIFY(!(a != b));
818
819 a.insert(akey: "Hello", avalue: "World");
820 QVERIFY(a != b);
821 QVERIFY(!(a == b));
822
823 b.insert(akey: "Hello", avalue: "World");
824 QVERIFY(a == b);
825 QVERIFY(!(a != b));
826
827 a.insert(akey: "Goodbye", avalue: "cruel world");
828 QVERIFY(a != b);
829 QVERIFY(!(a == b));
830
831 b.insert(akey: "Goodbye", avalue: "cruel world");
832
833 // what happens if we insert nulls?
834 a.insert(akey: QString(), avalue: QString());
835 QVERIFY(a != b);
836 QVERIFY(!(a == b));
837
838 // empty keys and null keys match:
839 b.insert(akey: QString(""), avalue: QString());
840 QVERIFY(a == b);
841 QVERIFY(!(a != b));
842 }
843
844 {
845 QHash<QString, int> a;
846 QHash<QString, int> b;
847
848 a.insert(akey: "otto", avalue: 1);
849 b.insert(akey: "willy", avalue: 1);
850 QVERIFY(a != b);
851 QVERIFY(!(a == b));
852 }
853
854 // unlike multi-maps, multi-hashes should be equal iff their contents are equal,
855 // regardless of insertion or iteration order
856
857 {
858 QHash<int, int> a;
859 QHash<int, int> b;
860
861 a.insertMulti(key: 0, value: 0);
862 a.insertMulti(key: 0, value: 1);
863
864 b.insertMulti(key: 0, value: 1);
865 b.insertMulti(key: 0, value: 0);
866
867 QVERIFY(a == b);
868 QVERIFY(!(a != b));
869 }
870
871 {
872 QHash<int, int> a;
873 QHash<int, int> b;
874
875 enum { Count = 100 };
876
877 for (int key = 0; key < Count; ++key) {
878 for (int value = 0; value < Count; ++value)
879 a.insertMulti(key, value);
880 }
881
882 for (int key = Count - 1; key >= 0; --key) {
883 for (int value = 0; value < Count; ++value)
884 b.insertMulti(key, value);
885 }
886
887 QVERIFY(a == b);
888 QVERIFY(!(a != b));
889 }
890
891 {
892 QHash<int, int> a;
893 QHash<int, int> b;
894
895 enum {
896 Count = 100,
897 KeyStep = 17, // coprime with Count
898 ValueStep = 23, // coprime with Count
899 };
900
901 for (int key = 0; key < Count; ++key) {
902 for (int value = 0; value < Count; ++value)
903 a.insertMulti(key, value);
904 }
905
906 // Generates two permutations of [0, Count) for the keys and values,
907 // so that b will be identical to a, just built in a very different order.
908
909 for (int k = 0; k < Count; ++k) {
910 const int key = (k * KeyStep) % Count;
911 for (int v = 0; v < Count; ++v)
912 b.insertMulti(key, value: (v * ValueStep) % Count);
913 }
914
915 QVERIFY(a == b);
916 QVERIFY(!(a != b));
917 }
918}
919
920void tst_QHash::compare()
921{
922 QHash<int, QString> hash1,hash2;
923 QString testString = "Teststring %1";
924 int i;
925
926 for(i = 0; i < 1000; ++i)
927 hash1.insert(akey: i,avalue: testString.arg(a: i));
928
929 for(--i; i >= 0; --i)
930 hash2.insert(akey: i,avalue: testString.arg(a: i));
931
932 hash1.squeeze();
933 hash2.squeeze();
934
935 QVERIFY(hash1 == hash2);
936 QVERIFY(!(hash1 != hash2));
937
938 hash1.take(akey: 234);
939 hash2.take(akey: 234);
940 QVERIFY(hash1 == hash2);
941 QVERIFY(!(hash1 != hash2));
942
943 hash2.take(akey: 261);
944 QVERIFY(!(hash1 == hash2));
945 QVERIFY(hash1 != hash2);
946}
947
948void tst_QHash::compare2()
949{
950 QHash<int, int> a;
951 QHash<int, int> b;
952
953 a.insertMulti(key: 17, value: 1);
954 a.insertMulti(key: 17 * 2, value: 1);
955 b.insertMulti(key: 17 * 2, value: 1);
956 b.insertMulti(key: 17, value: 1);
957 QVERIFY(a == b);
958 QVERIFY(b == a);
959
960 a.insertMulti(key: 17, value: 2);
961 a.insertMulti(key: 17 * 2, value: 3);
962 b.insertMulti(key: 17 * 2, value: 3);
963 b.insertMulti(key: 17, value: 2);
964 QVERIFY(a == b);
965 QVERIFY(b == a);
966
967 a.insertMulti(key: 17, value: 4);
968 a.insertMulti(key: 17 * 2, value: 5);
969 b.insertMulti(key: 17 * 2, value: 4);
970 b.insertMulti(key: 17, value: 5);
971 QVERIFY(!(a == b));
972 QVERIFY(!(b == a));
973
974 a.clear();
975 b.clear();
976 a.insertMulti(key: 1, value: 1);
977 a.insertMulti(key: 1, value: 2);
978 a.insertMulti(key: 1, value: 3);
979 b.insertMulti(key: 1, value: 1);
980 b.insertMulti(key: 1, value: 2);
981 b.insertMulti(key: 1, value: 3);
982 b.insertMulti(key: 1, value: 4);
983 QVERIFY(!(a == b));
984 QVERIFY(!(b == a));
985}
986
987//sligthly modified from tst_QMap
988void tst_QHash::iterators()
989{
990 QHash<int, QString> hash;
991 QMap<int, QString> testMap;
992 QString testString="Teststring %1";
993 QString testString1;
994 int i;
995
996 for(i = 1; i < 100; ++i)
997 hash.insert(akey: i, avalue: testString.arg(a: i));
998
999 //to get some chaos in the hash
1000 hash.squeeze();
1001
1002 //STL-Style iterators
1003
1004 QHash<int, QString>::iterator stlIt = hash.begin();
1005 for (stlIt = hash.begin(), i = 1; stlIt != hash.end() && i < 100; ++stlIt, ++i) {
1006 testMap.insert(akey: i,avalue: stlIt.value());
1007 //QVERIFY(stlIt.value() == hash.value(
1008 }
1009 stlIt = hash.begin();
1010
1011 QVERIFY(stlIt.value() == testMap.value(1));
1012
1013 stlIt+=5;
1014 QVERIFY(stlIt.value() == testMap.value(6));
1015
1016 stlIt++;
1017 QVERIFY(stlIt.value() == testMap.value(7));
1018
1019 stlIt-=3;
1020 QVERIFY(stlIt.value() == testMap.value(4));
1021
1022 stlIt--;
1023 QVERIFY(stlIt.value() == testMap.value(3));
1024
1025 testMap.clear();
1026
1027 //STL-Style const-iterators
1028
1029 QHash<int, QString>::const_iterator cstlIt = hash.constBegin();
1030 for (cstlIt = hash.constBegin(), i = 1; cstlIt != hash.constEnd() && i < 100; ++cstlIt, ++i) {
1031 testMap.insert(akey: i,avalue: cstlIt.value());
1032 //QVERIFY(stlIt.value() == hash.value(
1033 }
1034 cstlIt = hash.constBegin();
1035
1036 QVERIFY(cstlIt.value() == testMap.value(1));
1037
1038 cstlIt+=5;
1039 QVERIFY(cstlIt.value() == testMap.value(6));
1040
1041 cstlIt++;
1042 QVERIFY(cstlIt.value() == testMap.value(7));
1043
1044 cstlIt-=3;
1045 QVERIFY(cstlIt.value() == testMap.value(4));
1046
1047 cstlIt--;
1048 QVERIFY(cstlIt.value() == testMap.value(3));
1049
1050 testMap.clear();
1051
1052 //Java-Style iterators
1053
1054 QHashIterator<int, QString> javaIt(hash);
1055
1056 //walk through
1057 i = 0;
1058 while(javaIt.hasNext()) {
1059 ++i;
1060 javaIt.next();
1061 testMap.insert(akey: i,avalue: javaIt.value());
1062 }
1063 javaIt.toFront();
1064 i = 0;
1065 while(javaIt.hasNext()) {
1066 ++i;
1067 javaIt.next();
1068 QVERIFY(javaIt.value() == testMap.value(i));
1069 }
1070
1071 ++i;
1072 while(javaIt.hasPrevious()) {
1073 --i;
1074 javaIt.previous();
1075 QVERIFY(javaIt.value() == testMap.value(i));
1076 }
1077
1078 //peekNext() peekPrevious()
1079 javaIt.toFront();
1080 javaIt.next();
1081 while(javaIt.hasNext()) {
1082 testString = javaIt.value();
1083 testString1 = javaIt.peekNext().value();
1084 javaIt.next();
1085 QVERIFY(javaIt.value() == testString1);
1086 QCOMPARE(javaIt.peekPrevious().value(), testString1);
1087 }
1088 while(javaIt.hasPrevious()) {
1089 testString = javaIt.value();
1090 testString1 = javaIt.peekPrevious().value();
1091 javaIt.previous();
1092 QVERIFY(javaIt.value() == testString1);
1093 QCOMPARE(javaIt.peekNext().value(), testString1);
1094 }
1095}
1096
1097void tst_QHash::keyIterator()
1098{
1099 QHash<int, int> hash;
1100
1101 for (int i = 0; i < 100; ++i)
1102 hash.insert(akey: i, avalue: i*100);
1103
1104 QHash<int, int>::key_iterator key_it = hash.keyBegin();
1105 QHash<int, int>::const_iterator it = hash.cbegin();
1106 for (int i = 0; i < 100; ++i) {
1107 QCOMPARE(*key_it, it.key());
1108 key_it++;
1109 it++;
1110 }
1111
1112 key_it = std::find(first: hash.keyBegin(), last: hash.keyEnd(), val: 50);
1113 it = std::find(first: hash.cbegin(), last: hash.cend(), val: 50 * 100);
1114
1115 QVERIFY(key_it != hash.keyEnd());
1116 QCOMPARE(*key_it, it.key());
1117 QCOMPARE(*(key_it++), (it++).key());
1118 QCOMPARE(*(key_it--), (it--).key());
1119 QCOMPARE(*(++key_it), (++it).key());
1120 QCOMPARE(*(--key_it), (--it).key());
1121
1122 QCOMPARE(std::count(hash.keyBegin(), hash.keyEnd(), 99), 1);
1123
1124 // DefaultConstructible test
1125 typedef QHash<int, int>::key_iterator keyIterator;
1126 Q_STATIC_ASSERT(std::is_default_constructible<keyIterator>::value);
1127}
1128
1129void tst_QHash::keyValueIterator()
1130{
1131 QHash<int, int> hash;
1132 typedef QHash<int, int>::const_key_value_iterator::value_type entry_type;
1133
1134 for (int i = 0; i < 100; ++i)
1135 hash.insert(akey: i, avalue: i * 100);
1136
1137 auto key_value_it = hash.constKeyValueBegin();
1138 auto it = hash.cbegin();
1139
1140
1141 for (int i = 0; i < hash.size(); ++i) {
1142 QVERIFY(key_value_it != hash.constKeyValueEnd());
1143 QVERIFY(it != hash.cend());
1144
1145 entry_type pair(it.key(), it.value());
1146 QCOMPARE(*key_value_it, pair);
1147 QCOMPARE(key_value_it->first, pair.first);
1148 QCOMPARE(key_value_it->second, pair.second);
1149 QCOMPARE(&(*key_value_it).first, &it.key());
1150 QCOMPARE(&key_value_it->first, &it.key());
1151 QCOMPARE(&(*key_value_it).second, &it.value());
1152 QCOMPARE(&key_value_it->second, &it.value());
1153 ++key_value_it;
1154 ++it;
1155 }
1156
1157 QVERIFY(key_value_it == hash.constKeyValueEnd());
1158 QVERIFY(it == hash.cend());
1159
1160 int key = 50;
1161 int value = 50 * 100;
1162 entry_type pair(key, value);
1163 key_value_it = std::find(first: hash.constKeyValueBegin(), last: hash.constKeyValueEnd(), val: pair);
1164 it = std::find(first: hash.cbegin(), last: hash.cend(), val: value);
1165
1166 QVERIFY(key_value_it != hash.constKeyValueEnd());
1167 QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
1168
1169 ++it;
1170 ++key_value_it;
1171 QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
1172
1173 --it;
1174 --key_value_it;
1175 QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
1176
1177 ++it;
1178 ++key_value_it;
1179 QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
1180
1181 --it;
1182 --key_value_it;
1183 QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
1184 key = 99;
1185 value = 99 * 100;
1186 QCOMPARE(std::count(hash.constKeyValueBegin(), hash.constKeyValueEnd(), entry_type(key, value)), 1);
1187}
1188
1189void tst_QHash::rehash_isnt_quadratic()
1190{
1191 // this test should be incredibly slow if rehash() is quadratic
1192 for (int j = 0; j < 5; ++j) {
1193 QHash<int, int> testHash;
1194 for (int i = 0; i < 500000; ++i)
1195 testHash.insertMulti(key: 1, value: 1);
1196 }
1197}
1198
1199class Bar
1200{
1201public:
1202 Bar(int i) : j(i) {}
1203
1204 int j;
1205};
1206
1207void tst_QHash::dont_need_default_constructor()
1208{
1209 QHash<int, Bar> hash1;
1210 for (int i = 0; i < 100; ++i) {
1211 hash1.insert(akey: i, avalue: Bar(2 * i));
1212 QVERIFY(hash1.value(i, Bar(-1)).j == 2 * i);
1213 QVERIFY(hash1.size() == i + 1);
1214 }
1215
1216 QHash<QString, Bar> hash2;
1217 for (int i = 0; i < 100; ++i) {
1218 hash2.insert(akey: QString::number(i), avalue: Bar(2 * i));
1219 QVERIFY(hash2.value(QString::number(i), Bar(-1)).j == 2 * i);
1220 QVERIFY(hash2.size() == i + 1);
1221 }
1222}
1223
1224void tst_QHash::qmultihash_specific()
1225{
1226 QMultiHash<int, int> hash1;
1227 for (int i = 1; i <= 9; ++i) {
1228 for (int j = 1; j <= i; ++j) {
1229 int k = i * 10 + j;
1230 QVERIFY(!hash1.contains(i, k));
1231 hash1.insert(akey: i, avalue: k);
1232 QVERIFY(hash1.contains(i, k));
1233 }
1234 }
1235
1236 for (int i = 1; i <= 9; ++i) {
1237 for (int j = 1; j <= i; ++j) {
1238 int k = i * 10 + j;
1239 QVERIFY(hash1.contains(i, k));
1240 }
1241 }
1242
1243 QVERIFY(hash1.contains(9, 99));
1244 QCOMPARE(hash1.count(), 45);
1245 hash1.remove(key: 9, value: 99);
1246 QVERIFY(!hash1.contains(9, 99));
1247 QCOMPARE(hash1.count(), 44);
1248
1249 hash1.remove(key: 9, value: 99);
1250 QVERIFY(!hash1.contains(9, 99));
1251 QCOMPARE(hash1.count(), 44);
1252
1253 hash1.remove(key: 1, value: 99);
1254 QCOMPARE(hash1.count(), 44);
1255
1256 hash1.insert(akey: 1, avalue: 99);
1257 hash1.insert(akey: 1, avalue: 99);
1258
1259 QCOMPARE(hash1.count(), 46);
1260 hash1.remove(key: 1, value: 99);
1261 QCOMPARE(hash1.count(), 44);
1262 hash1.remove(key: 1, value: 99);
1263 QCOMPARE(hash1.count(), 44);
1264
1265 {
1266 QMultiHash<int, int>::const_iterator i = hash1.constFind(key: 1, value: 11);
1267 QVERIFY(i.key() == 1);
1268 QVERIFY(i.value() == 11);
1269
1270 i = hash1.constFind(key: 2, value: 22);
1271 QVERIFY(i.key() == 2);
1272 QVERIFY(i.value() == 22);
1273
1274 i = hash1.constFind(key: 9, value: 98);
1275 QVERIFY(i.key() == 9);
1276 QVERIFY(i.value() == 98);
1277 }
1278
1279 {
1280 const QMultiHash<int, int> hash2(hash1);
1281 QMultiHash<int, int>::const_iterator i = hash2.find(key: 1, value: 11);
1282 QVERIFY(i.key() == 1);
1283 QVERIFY(i.value() == 11);
1284
1285 i = hash2.find(key: 2, value: 22);
1286 QVERIFY(i.key() == 2);
1287 QVERIFY(i.value() == 22);
1288
1289 i = hash2.find(key: 9, value: 98);
1290 QVERIFY(i.key() == 9);
1291 QVERIFY(i.value() == 98);
1292 }
1293
1294 {
1295 QMultiHash<int, int>::iterator i = hash1.find(key: 1, value: 11);
1296 QVERIFY(i.key() == 1);
1297 QVERIFY(i.value() == 11);
1298
1299 i = hash1.find(key: 2, value: 22);
1300 QVERIFY(i.key() == 2);
1301 QVERIFY(i.value() == 22);
1302
1303 i = hash1.find(key: 9, value: 98);
1304 QVERIFY(i.key() == 9);
1305 QVERIFY(i.value() == 98);
1306 }
1307
1308 {
1309 QMultiHash<int, int> map1;
1310 map1.insert(akey: 42, avalue: 1);
1311 map1.insert(akey: 10, avalue: 2);
1312 map1.insert(akey: 48, avalue: 3);
1313 QMultiHash<int, int> map2;
1314 map2.insert(akey: 8, avalue: 4);
1315 map2.insert(akey: 42, avalue: 5);
1316 map2.insert(akey: 95, avalue: 12);
1317
1318 map1+=map2;
1319 map2.insert(akey: 42, avalue: 1);
1320 map2.insert(akey: 10, avalue: 2);
1321 map2.insert(akey: 48, avalue: 3);
1322 QCOMPARE(map1.count(), map2.count());
1323 QVERIFY(map1.remove(42,5));
1324 QVERIFY(map2.remove(42,5));
1325 QVERIFY(map1 == map2);
1326 }
1327}
1328
1329template <typename T>
1330QList<T> sorted(const QList<T> &list)
1331{
1332 QList<T> res = list;
1333 std::sort(res.begin(), res.end());
1334 return res;
1335}
1336
1337void tst_QHash::keys_values_uniqueKeys()
1338{
1339 QHash<QString, int> hash;
1340 QVERIFY(hash.uniqueKeys().isEmpty());
1341 QVERIFY(hash.keys().isEmpty());
1342 QVERIFY(hash.values().isEmpty());
1343
1344 hash.insertMulti(key: "alpha", value: 1);
1345 QVERIFY(sorted(hash.keys()) == (QList<QString>() << "alpha"));
1346 QVERIFY(hash.keys() == hash.uniqueKeys());
1347 QVERIFY(hash.values() == (QList<int>() << 1));
1348
1349 hash.insertMulti(key: "beta", value: -2);
1350 QVERIFY(sorted(hash.keys()) == (QList<QString>() << "alpha" << "beta"));
1351 QVERIFY(hash.keys() == hash.uniqueKeys());
1352 QVERIFY(sorted(hash.values()) == sorted(QList<int>() << 1 << -2));
1353
1354 hash.insertMulti(key: "alpha", value: 2);
1355 QVERIFY(sorted(hash.uniqueKeys()) == (QList<QString>() << "alpha" << "beta"));
1356 QVERIFY(sorted(hash.keys()) == (QList<QString>() << "alpha" << "alpha" << "beta"));
1357 QVERIFY(sorted(hash.values()) == sorted(QList<int>() << 2 << 1 << -2));
1358
1359 hash.insertMulti(key: "beta", value: 4);
1360 QVERIFY(sorted(hash.uniqueKeys()) == (QList<QString>() << "alpha" << "beta"));
1361 QVERIFY(sorted(hash.keys()) == (QList<QString>() << "alpha" << "alpha" << "beta" << "beta"));
1362 QVERIFY(sorted(hash.values()) == sorted(QList<int>() << 2 << 1 << 4 << -2));
1363}
1364
1365void tst_QHash::noNeedlessRehashes()
1366{
1367 QHash<int, int> hash;
1368 for (int i = 0; i < 512; ++i) {
1369 int j = (i * 345) % 512;
1370 hash.insert(akey: j, avalue: j);
1371 int oldCapacity = hash.capacity();
1372 hash[j] = j + 1;
1373 QCOMPARE(oldCapacity, hash.capacity());
1374 hash.insert(akey: j, avalue: j + 1);
1375 QCOMPARE(oldCapacity, hash.capacity());
1376 }
1377}
1378
1379void tst_QHash::const_shared_null()
1380{
1381 QHash<int, QString> hash2;
1382#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
1383 QHash<int, QString> hash1;
1384 hash1.setSharable(false);
1385 QVERIFY(hash1.isDetached());
1386
1387 hash2.setSharable(true);
1388#endif
1389 QVERIFY(!hash2.isDetached());
1390}
1391
1392// This gets set to != 0 in wrong qHash overloads
1393static int wrongqHashOverload = 0;
1394
1395struct OneArgumentQHashStruct1 {};
1396bool operator==(const OneArgumentQHashStruct1 &, const OneArgumentQHashStruct1 &) { return false; }
1397uint qHash(OneArgumentQHashStruct1) { return 0; }
1398
1399struct OneArgumentQHashStruct2 {};
1400bool operator==(const OneArgumentQHashStruct2 &, const OneArgumentQHashStruct2 &) { return false; }
1401uint qHash(const OneArgumentQHashStruct2 &) { return 0; }
1402
1403struct OneArgumentQHashStruct3 {};
1404bool operator==(const OneArgumentQHashStruct3 &, const OneArgumentQHashStruct3 &) { return false; }
1405uint qHash(OneArgumentQHashStruct3) { return 0; }
1406uint qHash(OneArgumentQHashStruct3 &, uint) { wrongqHashOverload = 1; return 0; }
1407
1408struct OneArgumentQHashStruct4 {};
1409bool operator==(const OneArgumentQHashStruct4 &, const OneArgumentQHashStruct4 &) { return false; }
1410uint qHash(const OneArgumentQHashStruct4 &) { return 0; }
1411uint qHash(OneArgumentQHashStruct4 &, uint) { wrongqHashOverload = 1; return 0; }
1412
1413
1414struct TwoArgumentsQHashStruct1 {};
1415bool operator==(const TwoArgumentsQHashStruct1 &, const TwoArgumentsQHashStruct1 &) { return false; }
1416uint qHash(const TwoArgumentsQHashStruct1 &) { wrongqHashOverload = 1; return 0; }
1417uint qHash(const TwoArgumentsQHashStruct1 &, uint) { return 0; }
1418
1419struct TwoArgumentsQHashStruct2 {};
1420bool operator==(const TwoArgumentsQHashStruct2 &, const TwoArgumentsQHashStruct2 &) { return false; }
1421uint qHash(TwoArgumentsQHashStruct2) { wrongqHashOverload = 1; return 0; }
1422uint qHash(const TwoArgumentsQHashStruct2 &, uint) { return 0; }
1423
1424struct TwoArgumentsQHashStruct3 {};
1425bool operator==(const TwoArgumentsQHashStruct3 &, const TwoArgumentsQHashStruct3 &) { return false; }
1426uint qHash(const TwoArgumentsQHashStruct3 &) { wrongqHashOverload = 1; return 0; }
1427uint qHash(TwoArgumentsQHashStruct3, uint) { return 0; }
1428
1429struct TwoArgumentsQHashStruct4 {};
1430bool operator==(const TwoArgumentsQHashStruct4 &, const TwoArgumentsQHashStruct4 &) { return false; }
1431uint qHash(TwoArgumentsQHashStruct4) { wrongqHashOverload = 1; return 0; }
1432uint qHash(TwoArgumentsQHashStruct4, uint) { return 0; }
1433
1434/*!
1435 \internal
1436
1437 Check that QHash picks up the right overload.
1438 The best one, for a type T, is the two-args version of qHash:
1439 either uint qHash(T, uint) or uint qHash(const T &, uint).
1440
1441 If neither of these exists, then one between
1442 uint qHash(T) or uint qHash(const T &) must exist
1443 (and it gets selected instead).
1444*/
1445void tst_QHash::twoArguments_qHash()
1446{
1447 QHash<OneArgumentQHashStruct1, int> oneArgHash1;
1448 OneArgumentQHashStruct1 oneArgObject1;
1449 oneArgHash1[oneArgObject1] = 1;
1450 QCOMPARE(wrongqHashOverload, 0);
1451
1452 QHash<OneArgumentQHashStruct2, int> oneArgHash2;
1453 OneArgumentQHashStruct2 oneArgObject2;
1454 oneArgHash2[oneArgObject2] = 1;
1455 QCOMPARE(wrongqHashOverload, 0);
1456
1457 QHash<OneArgumentQHashStruct3, int> oneArgHash3;
1458 OneArgumentQHashStruct3 oneArgObject3;
1459 oneArgHash3[oneArgObject3] = 1;
1460 QCOMPARE(wrongqHashOverload, 0);
1461
1462 QHash<OneArgumentQHashStruct4, int> oneArgHash4;
1463 OneArgumentQHashStruct4 oneArgObject4;
1464 oneArgHash4[oneArgObject4] = 1;
1465 QCOMPARE(wrongqHashOverload, 0);
1466
1467 QHash<TwoArgumentsQHashStruct1, int> twoArgsHash1;
1468 TwoArgumentsQHashStruct1 twoArgsObject1;
1469 twoArgsHash1[twoArgsObject1] = 1;
1470 QCOMPARE(wrongqHashOverload, 0);
1471
1472 QHash<TwoArgumentsQHashStruct2, int> twoArgsHash2;
1473 TwoArgumentsQHashStruct2 twoArgsObject2;
1474 twoArgsHash2[twoArgsObject2] = 1;
1475 QCOMPARE(wrongqHashOverload, 0);
1476
1477 QHash<TwoArgumentsQHashStruct3, int> twoArgsHash3;
1478 TwoArgumentsQHashStruct3 twoArgsObject3;
1479 twoArgsHash3[twoArgsObject3] = 1;
1480 QCOMPARE(wrongqHashOverload, 0);
1481
1482 QHash<TwoArgumentsQHashStruct4, int> twoArgsHash4;
1483 TwoArgumentsQHashStruct4 twoArgsObject4;
1484 twoArgsHash4[twoArgsObject4] = 1;
1485 QCOMPARE(wrongqHashOverload, 0);
1486}
1487
1488void tst_QHash::initializerList()
1489{
1490 QHash<int, QString> hash = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}};
1491 QCOMPARE(hash.count(), 2);
1492 QCOMPARE(hash[1], QString("hello"));
1493 QCOMPARE(hash[2], QString("initializer_list"));
1494
1495 // note the difference to std::unordered_map:
1496 // std::unordered_map<int, QString> stdh = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}};
1497 // QCOMPARE(stdh.size(), 2UL);
1498 // QCOMPARE(stdh[1], QString("bar"));
1499
1500 QMultiHash<QString, int> multiHash{{"il", 1}, {"il", 2}, {"il", 3}};
1501 QCOMPARE(multiHash.count(), 3);
1502 QList<int> values = multiHash.values(akey: "il");
1503 QCOMPARE(values.count(), 3);
1504
1505 QHash<int, int> emptyHash{};
1506 QVERIFY(emptyHash.isEmpty());
1507
1508 QHash<int, char> emptyPairs{{}, {}};
1509 QVERIFY(!emptyPairs.isEmpty());
1510
1511 QMultiHash<QString, double> emptyMultiHash{};
1512 QVERIFY(emptyMultiHash.isEmpty());
1513
1514 QMultiHash<int, float> emptyPairs2{{}, {}};
1515 QVERIFY(!emptyPairs2.isEmpty());
1516}
1517
1518void tst_QHash::eraseValidIteratorOnSharedHash()
1519{
1520 QHash<int, int> a, b;
1521 a.insert(akey: 10, avalue: 10);
1522 a.insertMulti(key: 10, value: 25);
1523 a.insertMulti(key: 10, value: 30);
1524 a.insert(akey: 20, avalue: 20);
1525 a.insert(akey: 40, avalue: 40);
1526
1527 QHash<int, int>::iterator i = a.begin();
1528 while (i.value() != 25)
1529 ++i;
1530
1531 b = a;
1532 a.erase(it: i);
1533
1534 QCOMPARE(b.size(), 5);
1535 QCOMPARE(a.size(), 4);
1536
1537 for (i = a.begin(); i != a.end(); ++i)
1538 QVERIFY(i.value() != 25);
1539
1540 int itemsWith10 = 0;
1541 for (i = b.begin(); i != b.end(); ++i)
1542 itemsWith10 += (i.key() == 10);
1543
1544 QCOMPARE(itemsWith10, 3);
1545}
1546
1547void tst_QHash::equal_range()
1548{
1549 QHash<int, QString> hash;
1550
1551 auto result = hash.equal_range(akey: 0);
1552 QCOMPARE(result.first, hash.end());
1553 QCOMPARE(result.second, hash.end());
1554
1555 hash.insert(akey: 1, avalue: "one");
1556
1557 result = hash.equal_range(akey: 1);
1558
1559 QCOMPARE(result.first, hash.find(1));
1560 QVERIFY(std::distance(result.first, result.second) == 1);
1561
1562 QHash<int, int> h1;
1563 {
1564 auto p = h1.equal_range(akey: 0);
1565 QVERIFY(p.first == p.second);
1566 QVERIFY(p.first == h1.end());
1567 }
1568
1569 h1.insert(akey: 1, avalue: 2);
1570 {
1571 auto p1 = h1.equal_range(akey: 9);
1572 QVERIFY(p1.first == p1.second);
1573 QVERIFY(p1.first == h1.end());
1574 }
1575 {
1576 auto p2 = h1.equal_range(akey: 1);
1577 QVERIFY(p2.first != p2.second);
1578 QVERIFY(p2.first == h1.begin());
1579 QVERIFY(p2.second == h1.end());
1580 }
1581
1582 QMultiHash<int, int> m1 = h1;
1583 m1.insert(akey: 1, avalue: 0);
1584 QCOMPARE(m1.size(), 2);
1585 {
1586 auto p1 = m1.equal_range(akey: 9);
1587 QVERIFY(p1.first == p1.second);
1588 QVERIFY(p1.first == m1.end());
1589 }
1590 {
1591 auto p2 = m1.equal_range(akey: 1);
1592 QVERIFY(p2.first != p2.second);
1593 QVERIFY(p2.first == m1.begin());
1594 QVERIFY(p2.second == m1.end());
1595 QCOMPARE(std::distance(p2.first, p2.second), 2);
1596 }
1597
1598 m1.insert(akey: 0, avalue: 0);
1599 QCOMPARE(m1.size(), 3);
1600 {
1601 auto p1 = m1.equal_range(akey: 9);
1602 QVERIFY(p1.first == p1.second);
1603 QVERIFY(p1.first == m1.end());
1604 }
1605 {
1606 const auto p2 = m1.equal_range(akey: 1);
1607 QVERIFY(p2.first != p2.second);
1608 QCOMPARE(p2.first.key(), 1);
1609 QCOMPARE(std::distance(p2.first, p2.second), 2);
1610 QVERIFY(p2.first == m1.begin() || p2.second == m1.end());
1611 }
1612
1613 const QHash<int, int> ch1 = h1;
1614 {
1615 auto p1 = ch1.equal_range(akey: 9);
1616 QVERIFY(p1.first == p1.second);
1617 QVERIFY(p1.first == ch1.end());
1618 }
1619 {
1620 auto p2 = ch1.equal_range(akey: 1);
1621 QVERIFY(p2.first != p2.second);
1622 QVERIFY(p2.first == ch1.begin());
1623 QVERIFY(p2.second == ch1.end());
1624 }
1625
1626 const QMultiHash<int, int> cm1 = m1;
1627 {
1628 auto p1 = cm1.equal_range(akey: 9);
1629 QVERIFY(p1.first == p1.second);
1630 QVERIFY(p1.first == cm1.end());
1631 }
1632 {
1633 auto p2 = cm1.equal_range(akey: 1);
1634 QVERIFY(p2.first != p2.second);
1635 QCOMPARE(std::distance(p2.first, p2.second), 2);
1636 QVERIFY(p2.first == cm1.cbegin() || p2.second == cm1.cend());
1637 }
1638
1639 QHash<int, int> h2;
1640 for (int i = 0; i < 8; ++i)
1641 for (int j = 0; j < 8; ++j)
1642 h2.insertMulti(key: i, value: i*j);
1643
1644 for (int i = 0; i < 8; ++i) {
1645 auto pair = h2.equal_range(akey: i);
1646 std::vector<int> vec(pair.first, pair.second);
1647 std::sort(first: vec.begin(), last: vec.end());
1648 for (int j = 0; j < 8; ++j)
1649 QCOMPARE(i*j, vec[j]);
1650 }
1651}
1652
1653void tst_QHash::insert_hash()
1654{
1655 {
1656 QHash<int, int> hash;
1657 hash.insert(akey: 1, avalue: 1);
1658 hash.insert(akey: 2, avalue: 2);
1659 hash.insert(akey: 0, avalue: -1);
1660
1661 QHash<int, int> hash2;
1662 hash2.insert(akey: 0, avalue: 0);
1663 hash2.insert(akey: 3, avalue: 3);
1664 hash2.insert(akey: 4, avalue: 4);
1665
1666 hash.insert(hash: hash2);
1667
1668 QCOMPARE(hash.count(), 5);
1669 for (int i = 0; i < 5; ++i)
1670 QCOMPARE(hash[i], i);
1671 }
1672 {
1673 QHash<int, int> hash;
1674 hash.insert(akey: 0, avalue: 5);
1675
1676 QHash<int, int> hash2;
1677
1678 hash.insert(hash: hash2);
1679
1680 QCOMPARE(hash.count(), 1);
1681 QCOMPARE(hash[0], 5);
1682 }
1683 {
1684 QHash<int, int> hash;
1685 QHash<int, int> hash2;
1686 hash2.insert(akey: 0, avalue: 5);
1687
1688 hash.insert(hash: hash2);
1689
1690 QCOMPARE(hash.count(), 1);
1691 QCOMPARE(hash[0], 5);
1692 QCOMPARE(hash, hash2);
1693 }
1694 {
1695 QHash<int, int> hash;
1696 hash.insert(akey: 0, avalue: 7);
1697 hash.insert(akey: 2, avalue: 5);
1698 hash.insert(akey: 7, avalue: 55);
1699
1700 // insert into ourself, nothing should happen
1701 hash.insert(hash);
1702
1703 QCOMPARE(hash.count(), 3);
1704 QCOMPARE(hash[0], 7);
1705 QCOMPARE(hash[2], 5);
1706 QCOMPARE(hash[7], 55);
1707 }
1708 {
1709 // This will use a QMultiHash and then insert that into QHash,
1710 // the ordering is undefined so we won't test that but make
1711 // sure this isn't adding multiple entries with the same key
1712 // to the QHash.
1713 QHash<int, int> hash;
1714 QMultiHash<int, int> hash2;
1715 hash2.insert(akey: 0, avalue: 5);
1716 hash2.insert(akey: 0, avalue: 6);
1717 hash2.insert(akey: 0, avalue: 7);
1718
1719 hash.insert(hash: hash2);
1720
1721 QCOMPARE(hash.count(), 1);
1722 }
1723}
1724
1725QTEST_APPLESS_MAIN(tst_QHash)
1726#include "tst_qhash.moc"
1727

source code of qtbase/tests/auto/corelib/tools/qhash/tst_qhash.cpp