| 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 |  | 
| 37 | class tst_QHash : public QObject | 
| 38 | { | 
| 39 |     Q_OBJECT | 
| 40 | private 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 |  | 
| 75 | struct IdentityTracker { | 
| 76 |     int value, id; | 
| 77 | }; | 
| 78 |  | 
| 79 | inline uint qHash(IdentityTracker key) { return qHash(key: key.value); } | 
| 80 | inline bool operator==(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value == rhs.value; } | 
| 81 |  | 
| 82 |  | 
| 83 | struct 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 |  | 
| 92 | int Foo::count = 0; | 
| 93 |  | 
| 94 | //copied from tst_QMap.cpp | 
| 95 | class MyClass | 
| 96 | { | 
| 97 | public: | 
| 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 |  | 
| 117 | int MyClass::count = 0; | 
| 118 |  | 
| 119 | typedef QHash<QString, MyClass> MyMap; | 
| 120 |  | 
| 121 | //void tst_QMap::count() | 
| 122 | void 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 | } | 
| 267 | void 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 |  | 
| 470 | void 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 |  | 
| 503 | void 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 |  | 
| 574 | void 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 | 
| 585 | void 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 | 
| 603 | void 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 | 
| 618 | void 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 | 
| 651 | void 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 | 
| 684 | void 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 |  | 
| 701 | namespace { | 
| 702 | class QGlobalQHashSeedResetter | 
| 703 | { | 
| 704 |     int oldSeed; | 
| 705 | public: | 
| 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 |  | 
| 720 | template <typename Key, typename T> | 
| 721 | QHash<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 |  | 
| 729 | template <typename AssociativeContainer> | 
| 730 | void make_test_data(AssociativeContainer &c) | 
| 731 | { | 
| 732 |     c["one" ] = "1" ; | 
| 733 |     c["two" ] = "2" ; | 
| 734 | } | 
| 735 |  | 
| 736 | } | 
| 737 |  | 
| 738 | void 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 | 
| 765 | void 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 | 
| 777 | void 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 |  | 
| 920 | void 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 |  | 
| 948 | void 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 | 
| 988 | void 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 |  | 
| 1097 | void 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 |  | 
| 1129 | void 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 |  | 
| 1189 | void 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 |  | 
| 1199 | class Bar | 
| 1200 | { | 
| 1201 | public: | 
| 1202 |     Bar(int i) : j(i) {} | 
| 1203 |  | 
| 1204 |     int j; | 
| 1205 | }; | 
| 1206 |  | 
| 1207 | void 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 |  | 
| 1224 | void 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 |  | 
| 1329 | template <typename T> | 
| 1330 | QList<T> sorted(const QList<T> &list) | 
| 1331 | { | 
| 1332 |     QList<T> res = list; | 
| 1333 |     std::sort(res.begin(), res.end()); | 
| 1334 |     return res; | 
| 1335 | } | 
| 1336 |  | 
| 1337 | void 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 |  | 
| 1365 | void 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 |  | 
| 1379 | void 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 | 
| 1393 | static int wrongqHashOverload = 0; | 
| 1394 |  | 
| 1395 | struct OneArgumentQHashStruct1 {}; | 
| 1396 | bool operator==(const OneArgumentQHashStruct1 &, const OneArgumentQHashStruct1 &) { return false; } | 
| 1397 | uint qHash(OneArgumentQHashStruct1) { return 0; } | 
| 1398 |  | 
| 1399 | struct OneArgumentQHashStruct2 {}; | 
| 1400 | bool operator==(const OneArgumentQHashStruct2 &, const OneArgumentQHashStruct2 &) { return false; } | 
| 1401 | uint qHash(const OneArgumentQHashStruct2 &) { return 0; } | 
| 1402 |  | 
| 1403 | struct OneArgumentQHashStruct3 {}; | 
| 1404 | bool operator==(const OneArgumentQHashStruct3 &, const OneArgumentQHashStruct3 &) { return false; } | 
| 1405 | uint qHash(OneArgumentQHashStruct3) { return 0; } | 
| 1406 | uint qHash(OneArgumentQHashStruct3 &, uint) { wrongqHashOverload = 1; return 0; } | 
| 1407 |  | 
| 1408 | struct OneArgumentQHashStruct4 {}; | 
| 1409 | bool operator==(const OneArgumentQHashStruct4 &, const OneArgumentQHashStruct4 &) { return false; } | 
| 1410 | uint qHash(const OneArgumentQHashStruct4 &) { return 0; } | 
| 1411 | uint qHash(OneArgumentQHashStruct4 &, uint) { wrongqHashOverload = 1; return 0; } | 
| 1412 |  | 
| 1413 |  | 
| 1414 | struct TwoArgumentsQHashStruct1 {}; | 
| 1415 | bool operator==(const TwoArgumentsQHashStruct1 &, const TwoArgumentsQHashStruct1 &) { return false; } | 
| 1416 | uint qHash(const TwoArgumentsQHashStruct1 &) { wrongqHashOverload = 1; return 0; } | 
| 1417 | uint qHash(const TwoArgumentsQHashStruct1 &, uint) { return 0; } | 
| 1418 |  | 
| 1419 | struct TwoArgumentsQHashStruct2 {}; | 
| 1420 | bool operator==(const TwoArgumentsQHashStruct2 &, const TwoArgumentsQHashStruct2 &) { return false; } | 
| 1421 | uint qHash(TwoArgumentsQHashStruct2) { wrongqHashOverload = 1; return 0; } | 
| 1422 | uint qHash(const TwoArgumentsQHashStruct2 &, uint) { return 0; } | 
| 1423 |  | 
| 1424 | struct TwoArgumentsQHashStruct3 {}; | 
| 1425 | bool operator==(const TwoArgumentsQHashStruct3 &, const TwoArgumentsQHashStruct3 &) { return false; } | 
| 1426 | uint qHash(const TwoArgumentsQHashStruct3 &) { wrongqHashOverload = 1; return 0; } | 
| 1427 | uint qHash(TwoArgumentsQHashStruct3, uint) { return 0; } | 
| 1428 |  | 
| 1429 | struct TwoArgumentsQHashStruct4 {}; | 
| 1430 | bool operator==(const TwoArgumentsQHashStruct4 &, const TwoArgumentsQHashStruct4 &) { return false; } | 
| 1431 | uint qHash(TwoArgumentsQHashStruct4) { wrongqHashOverload = 1; return 0; } | 
| 1432 | uint 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 | */ | 
| 1445 | void 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 |  | 
| 1488 | void 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 |  | 
| 1518 | void 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 |  | 
| 1547 | void 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 |  | 
| 1653 | void 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 |  | 
| 1725 | QTEST_APPLESS_MAIN(tst_QHash) | 
| 1726 | #include "tst_qhash.moc" | 
| 1727 |  |