| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the test suite of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 21 | ** included in the packaging of this file. Please review the following | 
| 22 | ** information to ensure the GNU General Public License requirements will | 
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 24 | ** | 
| 25 | ** $QT_END_LICENSE$ | 
| 26 | ** | 
| 27 | ****************************************************************************/ | 
| 28 |  | 
| 29 |  | 
| 30 | #include <QtTest/QtTest> | 
| 31 | #include <QtCore/QString> | 
| 32 | #include <QtCore/qarraydata.h> | 
| 33 |  | 
| 34 | #include "simplevector.h" | 
| 35 |  | 
| 36 | struct SharedNullVerifier | 
| 37 | { | 
| 38 |     SharedNullVerifier() | 
| 39 |     { | 
| 40 |         Q_ASSERT(QArrayData::shared_null[0].ref.isStatic()); | 
| 41 |         Q_ASSERT(QArrayData::shared_null[0].ref.isShared()); | 
| 42 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 43 |         Q_ASSERT(QArrayData::shared_null[0].ref.isSharable()); | 
| 44 | #endif | 
| 45 |     } | 
| 46 | }; | 
| 47 |  | 
| 48 | // This is meant to verify/ensure that shared_null is not being dynamically | 
| 49 | // initialized and stays away from the order-of-static-initialization fiasco. | 
| 50 | // | 
| 51 | // Of course, if this was to fail, qmake and the build should have crashed and | 
| 52 | // burned before we ever got to this point :-) | 
| 53 | SharedNullVerifier globalInit; | 
| 54 |  | 
| 55 | class tst_QArrayData : public QObject | 
| 56 | { | 
| 57 |     Q_OBJECT | 
| 58 |  | 
| 59 | private slots: | 
| 60 |     void referenceCounting(); | 
| 61 |     void sharedNullEmpty(); | 
| 62 |     void staticData(); | 
| 63 |     void simpleVector(); | 
| 64 |     void simpleVectorReserve_data(); | 
| 65 |     void simpleVectorReserve(); | 
| 66 |     void allocate_data(); | 
| 67 |     void allocate(); | 
| 68 |     void reallocate_data() { allocate_data(); } | 
| 69 |     void reallocate(); | 
| 70 |     void alignment_data(); | 
| 71 |     void alignment(); | 
| 72 |     void typedData(); | 
| 73 |     void gccBug43247(); | 
| 74 |     void arrayOps(); | 
| 75 |     void arrayOps2(); | 
| 76 |     void setSharable_data(); | 
| 77 |     void setSharable(); | 
| 78 |     void fromRawData_data(); | 
| 79 |     void fromRawData(); | 
| 80 |     void literals(); | 
| 81 |     void variadicLiterals(); | 
| 82 |     void rValueReferences(); | 
| 83 |     void grow(); | 
| 84 | }; | 
| 85 |  | 
| 86 | template <class T> const T &const_(const T &t) { return t; } | 
| 87 |  | 
| 88 | void tst_QArrayData::referenceCounting() | 
| 89 | { | 
| 90 |     { | 
| 91 |         // Reference counting initialized to 1 (owned) | 
| 92 |         QArrayData array = { .ref: { Q_BASIC_ATOMIC_INITIALIZER(1) }, .size: 0, .alloc: 0, .capacityReserved: 0, .offset: 0 }; | 
| 93 |  | 
| 94 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 1); | 
| 95 |  | 
| 96 |         QVERIFY(!array.ref.isStatic()); | 
| 97 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 98 |         QVERIFY(array.ref.isSharable()); | 
| 99 | #endif | 
| 100 |  | 
| 101 |         QVERIFY(array.ref.ref()); | 
| 102 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 2); | 
| 103 |  | 
| 104 |         QVERIFY(array.ref.deref()); | 
| 105 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 1); | 
| 106 |  | 
| 107 |         QVERIFY(array.ref.ref()); | 
| 108 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 2); | 
| 109 |  | 
| 110 |         QVERIFY(array.ref.deref()); | 
| 111 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 1); | 
| 112 |  | 
| 113 |         QVERIFY(!array.ref.deref()); | 
| 114 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 0); | 
| 115 |  | 
| 116 |         // Now would be a good time to free/release allocated data | 
| 117 |     } | 
| 118 |  | 
| 119 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 120 |     { | 
| 121 |         // Reference counting initialized to 0 (non-sharable) | 
| 122 |         QArrayData array = { .ref: { Q_BASIC_ATOMIC_INITIALIZER(0) }, .size: 0, .alloc: 0, .capacityReserved: 0, .offset: 0 }; | 
| 123 |  | 
| 124 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 0); | 
| 125 |  | 
| 126 |         QVERIFY(!array.ref.isStatic()); | 
| 127 |         QVERIFY(!array.ref.isSharable()); | 
| 128 |  | 
| 129 |         QVERIFY(!array.ref.ref()); | 
| 130 |         // Reference counting fails, data should be copied | 
| 131 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 0); | 
| 132 |  | 
| 133 |         QVERIFY(!array.ref.deref()); | 
| 134 |         QCOMPARE(array.ref.atomic.loadRelaxed(), 0); | 
| 135 |  | 
| 136 |         // Free/release data | 
| 137 |     } | 
| 138 | #endif | 
| 139 |  | 
| 140 |     { | 
| 141 |         // Reference counting initialized to -1 (static read-only data) | 
| 142 |         QArrayData array = { Q_REFCOUNT_INITIALIZE_STATIC, .size: 0, .alloc: 0, .capacityReserved: 0, .offset: 0 }; | 
| 143 |  | 
| 144 |         QCOMPARE(array.ref.atomic.loadRelaxed(), -1); | 
| 145 |  | 
| 146 |         QVERIFY(array.ref.isStatic()); | 
| 147 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 148 |         QVERIFY(array.ref.isSharable()); | 
| 149 | #endif | 
| 150 |  | 
| 151 |         QVERIFY(array.ref.ref()); | 
| 152 |         QCOMPARE(array.ref.atomic.loadRelaxed(), -1); | 
| 153 |  | 
| 154 |         QVERIFY(array.ref.deref()); | 
| 155 |         QCOMPARE(array.ref.atomic.loadRelaxed(), -1); | 
| 156 |  | 
| 157 |     } | 
| 158 | } | 
| 159 |  | 
| 160 | void tst_QArrayData::sharedNullEmpty() | 
| 161 | { | 
| 162 |     QArrayData *null = const_cast<QArrayData *>(QArrayData::shared_null); | 
| 163 |     QArrayData *empty = QArrayData::allocate(objectSize: 1, Q_ALIGNOF(QArrayData), capacity: 0); | 
| 164 |  | 
| 165 |     QVERIFY(null->ref.isStatic()); | 
| 166 |     QVERIFY(null->ref.isShared()); | 
| 167 |  | 
| 168 |     QVERIFY(empty->ref.isStatic()); | 
| 169 |     QVERIFY(empty->ref.isShared()); | 
| 170 |  | 
| 171 |     QCOMPARE(null->ref.atomic.loadRelaxed(), -1); | 
| 172 |     QCOMPARE(empty->ref.atomic.loadRelaxed(), -1); | 
| 173 |  | 
| 174 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 175 |     QVERIFY(null->ref.isSharable()); | 
| 176 |     QVERIFY(empty->ref.isSharable()); | 
| 177 | #endif | 
| 178 |  | 
| 179 |     QVERIFY(null->ref.ref()); | 
| 180 |     QVERIFY(empty->ref.ref()); | 
| 181 |  | 
| 182 |     QCOMPARE(null->ref.atomic.loadRelaxed(), -1); | 
| 183 |     QCOMPARE(empty->ref.atomic.loadRelaxed(), -1); | 
| 184 |  | 
| 185 |     QVERIFY(null->ref.deref()); | 
| 186 |     QVERIFY(empty->ref.deref()); | 
| 187 |  | 
| 188 |     QCOMPARE(null->ref.atomic.loadRelaxed(), -1); | 
| 189 |     QCOMPARE(empty->ref.atomic.loadRelaxed(), -1); | 
| 190 |  | 
| 191 |     QVERIFY(null != empty); | 
| 192 |  | 
| 193 |     QCOMPARE(null->size, 0); | 
| 194 |     QCOMPARE(null->alloc, 0u); | 
| 195 |     QCOMPARE(null->capacityReserved, 0u); | 
| 196 |  | 
| 197 |     QCOMPARE(empty->size, 0); | 
| 198 |     QCOMPARE(empty->alloc, 0u); | 
| 199 |     QCOMPARE(empty->capacityReserved, 0u); | 
| 200 | } | 
| 201 |  | 
| 202 | void tst_QArrayData::staticData() | 
| 203 | { | 
| 204 |     QStaticArrayData<char, 10> charArray = { | 
| 205 |         Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(char, 10), | 
| 206 |         .data: { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } | 
| 207 |     }; | 
| 208 |     QStaticArrayData<int, 10> intArray = { | 
| 209 |         Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 10), | 
| 210 |         .data: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } | 
| 211 |     }; | 
| 212 |     QStaticArrayData<double, 10> doubleArray = { | 
| 213 |         Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(double, 10), | 
| 214 |         .data: { 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f } | 
| 215 |     }; | 
| 216 |  | 
| 217 |     QCOMPARE(charArray.header.size, 10); | 
| 218 |     QCOMPARE(intArray.header.size, 10); | 
| 219 |     QCOMPARE(doubleArray.header.size, 10); | 
| 220 |  | 
| 221 |     QCOMPARE(charArray.header.data(), reinterpret_cast<void *>(&charArray.data)); | 
| 222 |     QCOMPARE(intArray.header.data(), reinterpret_cast<void *>(&intArray.data)); | 
| 223 |     QCOMPARE(doubleArray.header.data(), reinterpret_cast<void *>(&doubleArray.data)); | 
| 224 | } | 
| 225 |  | 
| 226 | void tst_QArrayData::simpleVector() | 
| 227 | { | 
| 228 |     QArrayData data0 = { Q_REFCOUNT_INITIALIZE_STATIC, .size: 0, .alloc: 0, .capacityReserved: 0, .offset: 0 }; | 
| 229 |     QStaticArrayData<int, 7> data1 = { | 
| 230 |             Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 7), | 
| 231 |             .data: { 0, 1, 2, 3, 4, 5, 6 } | 
| 232 |         }; | 
| 233 |  | 
| 234 |     int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | 
| 235 |  | 
| 236 |     SimpleVector<int> v1; | 
| 237 |     SimpleVector<int> v2(v1); | 
| 238 |     SimpleVector<int> v3(static_cast<QTypedArrayData<int> *>(&data0)); | 
| 239 |     SimpleVector<int> v4(static_cast<QTypedArrayData<int> *>(&data1.header)); | 
| 240 |     SimpleVector<int> v5(static_cast<QTypedArrayData<int> *>(&data0)); | 
| 241 |     SimpleVector<int> v6(static_cast<QTypedArrayData<int> *>(&data1.header)); | 
| 242 |     SimpleVector<int> v7(10, 5); | 
| 243 |     SimpleVector<int> v8(array, array + sizeof(array)/sizeof(*array)); | 
| 244 |  | 
| 245 |     v3 = v1; | 
| 246 |     v1.swap(other&: v3); | 
| 247 |     v4.clear(); | 
| 248 |  | 
| 249 |     QVERIFY(v1.isNull()); | 
| 250 |     QVERIFY(v2.isNull()); | 
| 251 |     QVERIFY(v3.isNull()); | 
| 252 |     QVERIFY(v4.isNull()); | 
| 253 |     QVERIFY(!v5.isNull()); | 
| 254 |     QVERIFY(!v6.isNull()); | 
| 255 |     QVERIFY(!v7.isNull()); | 
| 256 |     QVERIFY(!v8.isNull()); | 
| 257 |  | 
| 258 |     QVERIFY(v1.isEmpty()); | 
| 259 |     QVERIFY(v2.isEmpty()); | 
| 260 |     QVERIFY(v3.isEmpty()); | 
| 261 |     QVERIFY(v4.isEmpty()); | 
| 262 |     QVERIFY(v5.isEmpty()); | 
| 263 |     QVERIFY(!v6.isEmpty()); | 
| 264 |     QVERIFY(!v7.isEmpty()); | 
| 265 |     QVERIFY(!v8.isEmpty()); | 
| 266 |  | 
| 267 |     QCOMPARE(v1.size(), size_t(0)); | 
| 268 |     QCOMPARE(v2.size(), size_t(0)); | 
| 269 |     QCOMPARE(v3.size(), size_t(0)); | 
| 270 |     QCOMPARE(v4.size(), size_t(0)); | 
| 271 |     QCOMPARE(v5.size(), size_t(0)); | 
| 272 |     QCOMPARE(v6.size(), size_t(7)); | 
| 273 |     QCOMPARE(v7.size(), size_t(10)); | 
| 274 |     QCOMPARE(v8.size(), size_t(10)); | 
| 275 |  | 
| 276 |     QCOMPARE(v1.capacity(), size_t(0)); | 
| 277 |     QCOMPARE(v2.capacity(), size_t(0)); | 
| 278 |     QCOMPARE(v3.capacity(), size_t(0)); | 
| 279 |     QCOMPARE(v4.capacity(), size_t(0)); | 
| 280 |     QCOMPARE(v5.capacity(), size_t(0)); | 
| 281 |     // v6.capacity() is unspecified, for now | 
| 282 |     QVERIFY(v7.capacity() >= size_t(10)); | 
| 283 |     QVERIFY(v8.capacity() >= size_t(10)); | 
| 284 |  | 
| 285 |     QVERIFY(v1.isStatic()); | 
| 286 |     QVERIFY(v2.isStatic()); | 
| 287 |     QVERIFY(v3.isStatic()); | 
| 288 |     QVERIFY(v4.isStatic()); | 
| 289 |     QVERIFY(v5.isStatic()); | 
| 290 |     QVERIFY(v6.isStatic()); | 
| 291 |     QVERIFY(!v7.isStatic()); | 
| 292 |     QVERIFY(!v8.isStatic()); | 
| 293 |  | 
| 294 |     QVERIFY(v1.isShared()); | 
| 295 |     QVERIFY(v2.isShared()); | 
| 296 |     QVERIFY(v3.isShared()); | 
| 297 |     QVERIFY(v4.isShared()); | 
| 298 |     QVERIFY(v5.isShared()); | 
| 299 |     QVERIFY(v6.isShared()); | 
| 300 |     QVERIFY(!v7.isShared()); | 
| 301 |     QVERIFY((SimpleVector<int>(v7), v7.isShared())); | 
| 302 |     QVERIFY(!v7.isShared()); | 
| 303 |     QVERIFY(!v8.isShared()); | 
| 304 |  | 
| 305 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 306 |     QVERIFY(v1.isSharable()); | 
| 307 |     QVERIFY(v2.isSharable()); | 
| 308 |     QVERIFY(v3.isSharable()); | 
| 309 |     QVERIFY(v4.isSharable()); | 
| 310 |     QVERIFY(v5.isSharable()); | 
| 311 |     QVERIFY(v6.isSharable()); | 
| 312 |     QVERIFY(v7.isSharable()); | 
| 313 |     QVERIFY(v8.isSharable()); | 
| 314 | #endif | 
| 315 |  | 
| 316 |     QVERIFY(v1.isSharedWith(v2)); | 
| 317 |     QVERIFY(v1.isSharedWith(v3)); | 
| 318 |     QVERIFY(v1.isSharedWith(v4)); | 
| 319 |     QVERIFY(!v1.isSharedWith(v5)); | 
| 320 |     QVERIFY(!v1.isSharedWith(v6)); | 
| 321 |  | 
| 322 |     QCOMPARE(v1.constBegin(), v1.constEnd()); | 
| 323 |     QCOMPARE(v4.constBegin(), v4.constEnd()); | 
| 324 |     QCOMPARE((v6.constBegin() + v6.size()), v6.constEnd()); | 
| 325 |     QCOMPARE((v7.constBegin() + v7.size()), v7.constEnd()); | 
| 326 |     QCOMPARE((v8.constBegin() + v8.size()), v8.constEnd()); | 
| 327 |  | 
| 328 |     QVERIFY(v1 == v2); | 
| 329 |     QVERIFY(v1 == v3); | 
| 330 |     QVERIFY(v1 == v4); | 
| 331 |     QVERIFY(v1 == v5); | 
| 332 |     QVERIFY(!(v1 == v6)); | 
| 333 |  | 
| 334 |     QVERIFY(v1 != v6); | 
| 335 |     QVERIFY(v4 != v6); | 
| 336 |     QVERIFY(v5 != v6); | 
| 337 |     QVERIFY(!(v1 != v5)); | 
| 338 |  | 
| 339 |     QVERIFY(v1 < v6); | 
| 340 |     QVERIFY(!(v6 < v1)); | 
| 341 |     QVERIFY(v6 > v1); | 
| 342 |     QVERIFY(!(v1 > v6)); | 
| 343 |     QVERIFY(v1 <= v6); | 
| 344 |     QVERIFY(!(v6 <= v1)); | 
| 345 |     QVERIFY(v6 >= v1); | 
| 346 |     QVERIFY(!(v1 >= v6)); | 
| 347 |  | 
| 348 |     { | 
| 349 |         SimpleVector<int> temp(v6); | 
| 350 |  | 
| 351 |         QCOMPARE(const_(v6).front(), 0); | 
| 352 |         QCOMPARE(const_(v6).back(), 6); | 
| 353 |  | 
| 354 |         QVERIFY(temp.isShared()); | 
| 355 |         QVERIFY(temp.isSharedWith(v6)); | 
| 356 |  | 
| 357 |         QCOMPARE(temp.front(), 0); | 
| 358 |         QCOMPARE(temp.back(), 6); | 
| 359 |  | 
| 360 |         // Detached | 
| 361 |         QVERIFY(!temp.isShared()); | 
| 362 |         const int *const tempBegin = temp.begin(); | 
| 363 |  | 
| 364 |         for (size_t i = 0; i < v6.size(); ++i) { | 
| 365 |             QCOMPARE(const_(v6)[i], int(i)); | 
| 366 |             QCOMPARE(const_(v6).at(i), int(i)); | 
| 367 |             QCOMPARE(&const_(v6)[i], &const_(v6).at(i)); | 
| 368 |  | 
| 369 |             QCOMPARE(const_(v8)[i], const_(v6)[i]); | 
| 370 |  | 
| 371 |             QCOMPARE(temp[i], int(i)); | 
| 372 |             QCOMPARE(temp.at(i), int(i)); | 
| 373 |             QCOMPARE(&temp[i], &temp.at(i)); | 
| 374 |         } | 
| 375 |  | 
| 376 |         // A single detach should do | 
| 377 |         QCOMPARE((const int *)temp.begin(), tempBegin); | 
| 378 |     } | 
| 379 |  | 
| 380 |     { | 
| 381 |         int count = 0; | 
| 382 |         Q_FOREACH (int value, v7) { | 
| 383 |             QCOMPARE(value, 5); | 
| 384 |             ++count; | 
| 385 |         } | 
| 386 |  | 
| 387 |         QCOMPARE(count, 10); | 
| 388 |     } | 
| 389 |  | 
| 390 |     { | 
| 391 |         int count = 0; | 
| 392 |         Q_FOREACH (int value, v8) { | 
| 393 |             QCOMPARE(value, count); | 
| 394 |             ++count; | 
| 395 |         } | 
| 396 |  | 
| 397 |         QCOMPARE(count, 10); | 
| 398 |     } | 
| 399 |  | 
| 400 |     v5 = v6; | 
| 401 |     QVERIFY(v5.isSharedWith(v6)); | 
| 402 |     QVERIFY(!v1.isSharedWith(v5)); | 
| 403 |  | 
| 404 |     v1.swap(other&: v6); | 
| 405 |     QVERIFY(v6.isNull()); | 
| 406 |     QVERIFY(v1.isSharedWith(v5)); | 
| 407 |  | 
| 408 |     { | 
| 409 |         using std::swap; | 
| 410 |         swap(v1, v2&: v6); | 
| 411 |         QVERIFY(v5.isSharedWith(v6)); | 
| 412 |         QVERIFY(!v1.isSharedWith(v5)); | 
| 413 |     } | 
| 414 |  | 
| 415 |     v1.prepend(first: array, last: array + sizeof(array)/sizeof(array[0])); | 
| 416 |     QCOMPARE(v1.size(), size_t(10)); | 
| 417 |     QVERIFY(v1 == v8); | 
| 418 |  | 
| 419 |     v6 = v1; | 
| 420 |     QVERIFY(v1.isSharedWith(v6)); | 
| 421 |  | 
| 422 |     v1.prepend(first: array, last: array + sizeof(array)/sizeof(array[0])); | 
| 423 |     QVERIFY(!v1.isSharedWith(v6)); | 
| 424 |     QCOMPARE(v1.size(), size_t(20)); | 
| 425 |     QCOMPARE(v6.size(), size_t(10)); | 
| 426 |  | 
| 427 |     for (int i = 0; i < 20; ++i) | 
| 428 |         QCOMPARE(v1[i], v6[i % 10]); | 
| 429 |  | 
| 430 |     v1.clear(); | 
| 431 |  | 
| 432 |     v1.append(first: array, last: array + sizeof(array)/sizeof(array[0])); | 
| 433 |     // v1 is now [0 .. 9] | 
| 434 |     QCOMPARE(v1.size(), size_t(10)); | 
| 435 |     QVERIFY(v1 == v8); | 
| 436 |  | 
| 437 |     v6 = v1; | 
| 438 |     QVERIFY(v1.isSharedWith(v6)); | 
| 439 |  | 
| 440 |     v1.append(first: array, last: array + sizeof(array)/sizeof(array[0])); | 
| 441 |     // v1 is now [0 .. 9, 0 .. 9] | 
| 442 |     QVERIFY(!v1.isSharedWith(v6)); | 
| 443 |     QCOMPARE(v1.size(), size_t(20)); | 
| 444 |     QCOMPARE(v6.size(), size_t(10)); | 
| 445 |  | 
| 446 |     for (int i = 0; i < 20; ++i) | 
| 447 |         QCOMPARE(v1[i], v6[i % 10]); | 
| 448 |  | 
| 449 |     v1.insert(position: 0, first: v6.constBegin(), last: v6.constEnd()); | 
| 450 |     // v1 is now [ 0 .. 9, 0 .. 9, 0 .. 9] | 
| 451 |     QCOMPARE(v1.size(), size_t(30)); | 
| 452 |  | 
| 453 |     for (int i = 0; i < 30; ++i) | 
| 454 |         QCOMPARE(v1[i], v8[i % 10]); | 
| 455 |  | 
| 456 |     v6 = v1; | 
| 457 |     QVERIFY(v1.isSharedWith(v6)); | 
| 458 |  | 
| 459 |     v1.insert(position: 10, first: v6.constBegin(), last: v6.constEnd()); | 
| 460 |     // v1 is now [ 0..9, <new data>0..9, 0..9, 0..9</new data>, 0..9, 0..9 ] | 
| 461 |     QVERIFY(!v1.isSharedWith(v6)); | 
| 462 |     QCOMPARE(v1.size(), size_t(60)); | 
| 463 |     QCOMPARE(v6.size(), size_t(30)); | 
| 464 |  | 
| 465 |     for (int i = 0; i < 30; ++i) | 
| 466 |         QCOMPARE(v6[i], v8[i % 10]); | 
| 467 |     for (int i = 0; i < 60; ++i) | 
| 468 |         QCOMPARE(v1[i], v8[i % 10]); | 
| 469 |  | 
| 470 |     v1.insert(position: int(v1.size()), first: v6.constBegin(), last: v6.constEnd()); | 
| 471 |     // v1 is now [ 0..9 x 6, <new data>0..9 x 3</new data> ] | 
| 472 |     QCOMPARE(v1.size(), size_t(90)); | 
| 473 |  | 
| 474 |     for (int i = 0; i < 90; ++i) | 
| 475 |         QCOMPARE(v1[i], v8[i % 10]); | 
| 476 |  | 
| 477 |     v1.insert(position: -1, first: v8.constBegin(), last: v8.constEnd()); | 
| 478 |     // v1 is now [ 0..9 x 9, <new data>0..9</new data> ] | 
| 479 |     QCOMPARE(v1.size(), size_t(100)); | 
| 480 |  | 
| 481 |     for (int i = 0; i < 100; ++i) | 
| 482 |         QCOMPARE(v1[i], v8[i % 10]); | 
| 483 |  | 
| 484 |     v1.insert(position: -11, first: v8.constBegin(), last: v8.constEnd()); | 
| 485 |     // v1 is now [ 0..9 x 9, <new data>0..9</new data>, 0..9 ] | 
| 486 |     QCOMPARE(v1.size(), size_t(110)); | 
| 487 |  | 
| 488 |     for (int i = 0; i < 110; ++i) | 
| 489 |         QCOMPARE(v1[i], v8[i % 10]); | 
| 490 |  | 
| 491 |     v1.insert(position: -200, first: v8.constBegin(), last: v8.constEnd()); | 
| 492 |     // v1 is now [ <new data>0..9</new data>, 0..9 x 11 ] | 
| 493 |     QCOMPARE(v1.size(), size_t(120)); | 
| 494 |  | 
| 495 |     for (int i = 0; i < 120; ++i) | 
| 496 |         QCOMPARE(v1[i], v8[i % 10]); | 
| 497 |  | 
| 498 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 499 |     { | 
| 500 |         v7.setSharable(true); | 
| 501 |         QVERIFY(v7.isSharable()); | 
| 502 |  | 
| 503 |         SimpleVector<int> copy1(v7); | 
| 504 |         QVERIFY(copy1.isSharedWith(v7)); | 
| 505 |  | 
| 506 |         v7.setSharable(false); | 
| 507 |         QVERIFY(!v7.isSharable()); | 
| 508 |  | 
| 509 |         QVERIFY(!copy1.isSharedWith(v7)); | 
| 510 |         QCOMPARE(v7.size(), copy1.size()); | 
| 511 |         for (size_t i = 0; i < copy1.size(); ++i) | 
| 512 |             QCOMPARE(v7[i], copy1[i]); | 
| 513 |  | 
| 514 |         SimpleVector<int> clone(v7); | 
| 515 |         QVERIFY(!clone.isSharedWith(v7)); | 
| 516 |         QCOMPARE(clone.size(), copy1.size()); | 
| 517 |         for (size_t i = 0; i < copy1.size(); ++i) | 
| 518 |             QCOMPARE(clone[i], copy1[i]); | 
| 519 |  | 
| 520 |         v7.setSharable(true); | 
| 521 |         QVERIFY(v7.isSharable()); | 
| 522 |  | 
| 523 |         SimpleVector<int> copy2(v7); | 
| 524 |         QVERIFY(copy2.isSharedWith(v7)); | 
| 525 |     } | 
| 526 |  | 
| 527 |     { | 
| 528 |         SimpleVector<int> null; | 
| 529 |         SimpleVector<int> empty(0, 5); | 
| 530 |  | 
| 531 |         QVERIFY(null.isSharable()); | 
| 532 |         QVERIFY(empty.isSharable()); | 
| 533 |  | 
| 534 |         null.setSharable(true); | 
| 535 |         empty.setSharable(true); | 
| 536 |  | 
| 537 |         QVERIFY(null.isSharable()); | 
| 538 |         QVERIFY(empty.isSharable()); | 
| 539 |  | 
| 540 |         QVERIFY(null.isEmpty()); | 
| 541 |         QVERIFY(empty.isEmpty()); | 
| 542 |  | 
| 543 |         null.setSharable(false); | 
| 544 |         empty.setSharable(false); | 
| 545 |  | 
| 546 |         QVERIFY(!null.isSharable()); | 
| 547 |         QVERIFY(!empty.isSharable()); | 
| 548 |  | 
| 549 |         QVERIFY(null.isEmpty()); | 
| 550 |         QVERIFY(empty.isEmpty()); | 
| 551 |  | 
| 552 |         null.setSharable(true); | 
| 553 |         empty.setSharable(true); | 
| 554 |  | 
| 555 |         QVERIFY(null.isSharable()); | 
| 556 |         QVERIFY(empty.isSharable()); | 
| 557 |  | 
| 558 |         QVERIFY(null.isEmpty()); | 
| 559 |         QVERIFY(empty.isEmpty()); | 
| 560 |     } | 
| 561 | #endif | 
| 562 | } | 
| 563 |  | 
| 564 | Q_DECLARE_METATYPE(SimpleVector<int>) | 
| 565 |  | 
| 566 | void tst_QArrayData::simpleVectorReserve_data() | 
| 567 | { | 
| 568 |     QTest::addColumn<SimpleVector<int> >(name: "vector" ); | 
| 569 |     QTest::addColumn<size_t>(name: "capacity" ); | 
| 570 |     QTest::addColumn<size_t>(name: "size" ); | 
| 571 |  | 
| 572 |     QTest::newRow(dataTag: "null" ) << SimpleVector<int>() << size_t(0) << size_t(0); | 
| 573 |     QTest::newRow(dataTag: "empty" ) << SimpleVector<int>(0, 42) << size_t(0) << size_t(0); | 
| 574 |     QTest::newRow(dataTag: "non-empty" ) << SimpleVector<int>(5, 42) << size_t(5) << size_t(5); | 
| 575 |  | 
| 576 |     static const QStaticArrayData<int, 15> array = { | 
| 577 |         Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 15), | 
| 578 |         .data: { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }; | 
| 579 |     QArrayDataPointerRef<int> p = { | 
| 580 |          .ptr: static_cast<QTypedArrayData<int> *>( | 
| 581 |             const_cast<QArrayData *>(&array.header)) }; | 
| 582 |  | 
| 583 |     QTest::newRow(dataTag: "static" ) << SimpleVector<int>(p) << size_t(0) << size_t(15); | 
| 584 |     QTest::newRow(dataTag: "raw-data" ) << SimpleVector<int>::fromRawData(data: array.data, size: 15) << size_t(0) << size_t(15); | 
| 585 | } | 
| 586 |  | 
| 587 | void tst_QArrayData::simpleVectorReserve() | 
| 588 | { | 
| 589 |     QFETCH(SimpleVector<int>, vector); | 
| 590 |     QFETCH(size_t, capacity); | 
| 591 |     QFETCH(size_t, size); | 
| 592 |  | 
| 593 |     QVERIFY(!capacity || capacity >= size); | 
| 594 |  | 
| 595 |     QCOMPARE(vector.capacity(), capacity); | 
| 596 |     QCOMPARE(vector.size(), size); | 
| 597 |  | 
| 598 |     const SimpleVector<int> copy(vector); | 
| 599 |  | 
| 600 |     vector.reserve(n: 0); | 
| 601 |     QCOMPARE(vector.capacity(), capacity); | 
| 602 |     QCOMPARE(vector.size(), size); | 
| 603 |  | 
| 604 |     vector.reserve(n: 10); | 
| 605 |  | 
| 606 |     // zero-capacity (immutable) resets with detach | 
| 607 |     if (!capacity) | 
| 608 |         capacity = size; | 
| 609 |  | 
| 610 |     QCOMPARE(vector.capacity(), qMax(size_t(10), capacity)); | 
| 611 |     QCOMPARE(vector.size(), size); | 
| 612 |  | 
| 613 |     vector.reserve(n: 20); | 
| 614 |     QCOMPARE(vector.capacity(), size_t(20)); | 
| 615 |     QCOMPARE(vector.size(), size); | 
| 616 |  | 
| 617 |     vector.reserve(n: 30); | 
| 618 |     QCOMPARE(vector.capacity(), size_t(30)); | 
| 619 |     QCOMPARE(vector.size(), size); | 
| 620 |  | 
| 621 |     QVERIFY(vector == copy); | 
| 622 | } | 
| 623 |  | 
| 624 | struct Deallocator | 
| 625 | { | 
| 626 |     Deallocator(size_t objectSize, size_t alignment) | 
| 627 |         : objectSize(objectSize) | 
| 628 |         , alignment(alignment) | 
| 629 |     { | 
| 630 |     } | 
| 631 |  | 
| 632 |     ~Deallocator() | 
| 633 |     { | 
| 634 |         Q_FOREACH (QArrayData *data, headers) | 
| 635 |             QArrayData::deallocate(data, objectSize, alignment); | 
| 636 |     } | 
| 637 |  | 
| 638 |     size_t objectSize; | 
| 639 |     size_t alignment; | 
| 640 |     QVector<QArrayData *> ; | 
| 641 | }; | 
| 642 |  | 
| 643 | Q_DECLARE_METATYPE(const QArrayData *) | 
| 644 | Q_DECLARE_METATYPE(QArrayData::AllocationOptions) | 
| 645 |  | 
| 646 | void tst_QArrayData::allocate_data() | 
| 647 | { | 
| 648 |     QTest::addColumn<size_t>(name: "objectSize" ); | 
| 649 |     QTest::addColumn<size_t>(name: "alignment" ); | 
| 650 |     QTest::addColumn<QArrayData::AllocationOptions>(name: "allocateOptions" ); | 
| 651 |     QTest::addColumn<bool>(name: "isCapacityReserved" ); | 
| 652 |     QTest::addColumn<bool>(name: "isSharable" );       // ### Qt6: remove | 
| 653 |     QTest::addColumn<const QArrayData *>(name: "commonEmpty" ); | 
| 654 |  | 
| 655 |     struct { | 
| 656 |         char const *typeName; | 
| 657 |         size_t objectSize; | 
| 658 |         size_t alignment; | 
| 659 |     } types[] = { | 
| 660 |         { .typeName: "char" , .objectSize: sizeof(char), Q_ALIGNOF(char) }, | 
| 661 |         { .typeName: "short" , .objectSize: sizeof(short), Q_ALIGNOF(short) }, | 
| 662 |         { .typeName: "void *" , .objectSize: sizeof(void *), Q_ALIGNOF(void *) } | 
| 663 |     }; | 
| 664 |  | 
| 665 |     QArrayData *shared_empty = QArrayData::allocate(objectSize: 0, Q_ALIGNOF(QArrayData), capacity: 0); | 
| 666 |     QVERIFY(shared_empty); | 
| 667 |  | 
| 668 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 669 |     QArrayData *unsharable_empty = QArrayData::allocate(objectSize: 0, Q_ALIGNOF(QArrayData), capacity: 0, options: QArrayData::Unsharable); | 
| 670 |     QVERIFY(unsharable_empty); | 
| 671 | #endif | 
| 672 |  | 
| 673 |     struct { | 
| 674 |         char const *description; | 
| 675 |         QArrayData::AllocationOptions allocateOptions; | 
| 676 |         bool isCapacityReserved; | 
| 677 |         bool isSharable; | 
| 678 |         const QArrayData *commonEmpty; | 
| 679 |     } options[] = { | 
| 680 |         { .description: "Default" , .allocateOptions: QArrayData::Default, .isCapacityReserved: false, .isSharable: true, .commonEmpty: shared_empty }, | 
| 681 |         { .description: "Reserved" , .allocateOptions: QArrayData::CapacityReserved, .isCapacityReserved: true, .isSharable: true, .commonEmpty: shared_empty }, | 
| 682 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 683 |         { .description: "Reserved | Unsharable" , | 
| 684 |             .allocateOptions: QArrayData::CapacityReserved | QArrayData::Unsharable, .isCapacityReserved: true, .isSharable: false, | 
| 685 |             .commonEmpty: unsharable_empty }, | 
| 686 |         { .description: "Unsharable" , .allocateOptions: QArrayData::Unsharable, .isCapacityReserved: false, .isSharable: false, .commonEmpty: unsharable_empty }, | 
| 687 | #endif | 
| 688 |         { .description: "Grow" , .allocateOptions: QArrayData::Grow, .isCapacityReserved: false, .isSharable: true, .commonEmpty: shared_empty } | 
| 689 |     }; | 
| 690 |  | 
| 691 |     for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i) | 
| 692 |         for (size_t j = 0; j < sizeof(options)/sizeof(options[0]); ++j) | 
| 693 |             QTest::newRow(qPrintable( | 
| 694 |                         QLatin1String(types[i].typeName) | 
| 695 |                         + QLatin1String(": " ) | 
| 696 |                         + QLatin1String(options[j].description))) | 
| 697 |                 << types[i].objectSize << types[i].alignment | 
| 698 |                 << options[j].allocateOptions << options[j].isCapacityReserved | 
| 699 |                 << options[j].isSharable << options[j].commonEmpty; | 
| 700 | } | 
| 701 |  | 
| 702 | void tst_QArrayData::allocate() | 
| 703 | { | 
| 704 |     QFETCH(size_t, objectSize); | 
| 705 |     QFETCH(size_t, alignment); | 
| 706 |     QFETCH(QArrayData::AllocationOptions, allocateOptions); | 
| 707 |     QFETCH(bool, isCapacityReserved); | 
| 708 |     QFETCH(const QArrayData *, commonEmpty); | 
| 709 |  | 
| 710 |     // Minimum alignment that can be requested is that of QArrayData. | 
| 711 |     // Typically, this alignment is sizeof(void *) and ensured by malloc. | 
| 712 |     size_t minAlignment = qMax(a: alignment, Q_ALIGNOF(QArrayData)); | 
| 713 |  | 
| 714 |     // Shared Empty | 
| 715 |     QCOMPARE(QArrayData::allocate(objectSize, minAlignment, 0, | 
| 716 |                 QArrayData::AllocationOptions(allocateOptions)), commonEmpty); | 
| 717 |  | 
| 718 |     Deallocator keeper(objectSize, minAlignment); | 
| 719 |     keeper.headers.reserve(asize: 1024); | 
| 720 |  | 
| 721 |     for (int capacity = 1; capacity <= 1024; capacity <<= 1) { | 
| 722 |         QArrayData *data = QArrayData::allocate(objectSize, alignment: minAlignment, | 
| 723 |                 capacity, options: QArrayData::AllocationOptions(allocateOptions)); | 
| 724 |         keeper.headers.append(t: data); | 
| 725 |  | 
| 726 |         QCOMPARE(data->size, 0); | 
| 727 |         if (allocateOptions & QArrayData::Grow) | 
| 728 |             QVERIFY(data->alloc > uint(capacity)); | 
| 729 |         else | 
| 730 |             QCOMPARE(data->alloc, uint(capacity)); | 
| 731 |         QCOMPARE(data->capacityReserved, uint(isCapacityReserved)); | 
| 732 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 733 |         QFETCH(bool, isSharable); | 
| 734 |         QCOMPARE(data->ref.isSharable(), isSharable); | 
| 735 | #endif | 
| 736 |  | 
| 737 |         // Check that the allocated array can be used. Best tested with a | 
| 738 |         // memory checker, such as valgrind, running. | 
| 739 |         ::memset(s: data->data(), c: 'A', n: objectSize * capacity); | 
| 740 |     } | 
| 741 | } | 
| 742 |  | 
| 743 | void tst_QArrayData::reallocate() | 
| 744 | { | 
| 745 |     QFETCH(size_t, objectSize); | 
| 746 |     QFETCH(size_t, alignment); | 
| 747 |     QFETCH(QArrayData::AllocationOptions, allocateOptions); | 
| 748 |     QFETCH(bool, isCapacityReserved); | 
| 749 |  | 
| 750 |     // Maximum alignment that can be requested is that of QArrayData, | 
| 751 |     // otherwise, we can't use reallocate(). | 
| 752 |     Q_ASSERT(alignment <= Q_ALIGNOF(QArrayData)); | 
| 753 |  | 
| 754 |     // Minimum alignment that can be requested is that of QArrayData. | 
| 755 |     // Typically, this alignment is sizeof(void *) and ensured by malloc. | 
| 756 |     size_t minAlignment = qMax(a: alignment, Q_ALIGNOF(QArrayData)); | 
| 757 |  | 
| 758 |     int capacity = 10; | 
| 759 |     Deallocator keeper(objectSize, minAlignment); | 
| 760 |     QArrayData *data = QArrayData::allocate(objectSize, alignment: minAlignment, capacity, | 
| 761 |                                             options: QArrayData::AllocationOptions(allocateOptions) & ~QArrayData::Grow); | 
| 762 |     keeper.headers.append(t: data); | 
| 763 |  | 
| 764 |     memset(s: data->data(), c: 'A', n: objectSize * capacity); | 
| 765 |     data->size = capacity; | 
| 766 |  | 
| 767 |     // now try to reallocate | 
| 768 |     int newCapacity = 40; | 
| 769 |     data = QArrayData::reallocateUnaligned(data, objectSize, newCapacity, | 
| 770 |                                            newOptions: QArrayData::AllocationOptions(allocateOptions)); | 
| 771 |     QVERIFY(data); | 
| 772 |     keeper.headers.clear(); | 
| 773 |     keeper.headers.append(t: data); | 
| 774 |  | 
| 775 |     QCOMPARE(data->size, capacity); | 
| 776 |     if (allocateOptions & QArrayData::Grow) | 
| 777 |         QVERIFY(data->alloc > uint(newCapacity)); | 
| 778 |     else | 
| 779 |         QCOMPARE(data->alloc, uint(newCapacity)); | 
| 780 |     QCOMPARE(data->capacityReserved, uint(isCapacityReserved)); | 
| 781 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 782 |     QFETCH(bool, isSharable); | 
| 783 |     QCOMPARE(data->ref.isSharable(), isSharable); | 
| 784 | #endif | 
| 785 |  | 
| 786 |     for (int i = 0; i < capacity; ++i) | 
| 787 |         QCOMPARE(static_cast<char *>(data->data())[i], 'A'); | 
| 788 | } | 
| 789 |  | 
| 790 | class Unaligned | 
| 791 | { | 
| 792 |     char dummy[8]; | 
| 793 | }; | 
| 794 |  | 
| 795 | void tst_QArrayData::alignment_data() | 
| 796 | { | 
| 797 |     QTest::addColumn<size_t>(name: "alignment" ); | 
| 798 |  | 
| 799 |     for (size_t i = 1; i < 10; ++i) { | 
| 800 |         size_t alignment = size_t(1u) << i; | 
| 801 |         QTest::newRow(qPrintable(QString::number(alignment))) << alignment; | 
| 802 |     } | 
| 803 | } | 
| 804 |  | 
| 805 | void tst_QArrayData::alignment() | 
| 806 | { | 
| 807 |     QFETCH(size_t, alignment); | 
| 808 |  | 
| 809 |     // Minimum alignment that can be requested is that of QArrayData. | 
| 810 |     // Typically, this alignment is sizeof(void *) and ensured by malloc. | 
| 811 |     size_t minAlignment = qMax(a: alignment, Q_ALIGNOF(QArrayData)); | 
| 812 |  | 
| 813 |     Deallocator keeper(sizeof(Unaligned), minAlignment); | 
| 814 |     keeper.headers.reserve(asize: 100); | 
| 815 |  | 
| 816 |     for (int i = 0; i < 100; ++i) { | 
| 817 |         QArrayData *data = QArrayData::allocate(objectSize: sizeof(Unaligned), | 
| 818 |                 alignment: minAlignment, capacity: 8, options: QArrayData::Default); | 
| 819 |         keeper.headers.append(t: data); | 
| 820 |  | 
| 821 |         QVERIFY(data); | 
| 822 |         QCOMPARE(data->size, 0); | 
| 823 |         QVERIFY(data->alloc >= uint(8)); | 
| 824 |  | 
| 825 |         // These conditions should hold as long as header and array are | 
| 826 |         // allocated together | 
| 827 |         QVERIFY(data->offset >= qptrdiff(sizeof(QArrayData))); | 
| 828 |         QVERIFY(data->offset <= qptrdiff(sizeof(QArrayData) | 
| 829 |                     + minAlignment - Q_ALIGNOF(QArrayData))); | 
| 830 |  | 
| 831 |         // Data is aligned | 
| 832 |         QCOMPARE(quintptr(quintptr(data->data()) % alignment), quintptr(0u)); | 
| 833 |  | 
| 834 |         // Check that the allocated array can be used. Best tested with a | 
| 835 |         // memory checker, such as valgrind, running. | 
| 836 |         ::memset(s: data->data(), c: 'A', n: sizeof(Unaligned) * 8); | 
| 837 |     } | 
| 838 | } | 
| 839 |  | 
| 840 | void tst_QArrayData::typedData() | 
| 841 | { | 
| 842 |     QStaticArrayData<int, 10> data = { | 
| 843 |             Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 10), | 
| 844 |             .data: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } | 
| 845 |         }; | 
| 846 |     QCOMPARE(data.header.size, 10); | 
| 847 |  | 
| 848 |     { | 
| 849 |         QTypedArrayData<int> *array = | 
| 850 |             static_cast<QTypedArrayData<int> *>(&data.header); | 
| 851 |         QCOMPARE(array->data(), data.data); | 
| 852 |  | 
| 853 |         int j = 0; | 
| 854 |         for (QTypedArrayData<int>::iterator iter = array->begin(); | 
| 855 |                 iter != array->end(); ++iter, ++j) | 
| 856 |             QCOMPARE((const int *)iter, data.data + j); | 
| 857 |         QCOMPARE(j, 10); | 
| 858 |     } | 
| 859 |  | 
| 860 |     { | 
| 861 |         const QTypedArrayData<int> *array = | 
| 862 |             static_cast<const QTypedArrayData<int> *>(&data.header); | 
| 863 |  | 
| 864 |         QCOMPARE(array->data(), data.data); | 
| 865 |  | 
| 866 |         int j = 0; | 
| 867 |         for (QTypedArrayData<int>::const_iterator iter = array->begin(); | 
| 868 |                 iter != array->end(); ++iter, ++j) | 
| 869 |             QCOMPARE((const int *)iter, data.data + j); | 
| 870 |         QCOMPARE(j, 10); | 
| 871 |     } | 
| 872 |  | 
| 873 |     { | 
| 874 |         QTypedArrayData<int> *null = QTypedArrayData<int>::sharedNull(); | 
| 875 |         QTypedArrayData<int> *empty = QTypedArrayData<int>::allocate(capacity: 0); | 
| 876 |  | 
| 877 |         QVERIFY(null != empty); | 
| 878 |  | 
| 879 |         QCOMPARE(null->size, 0); | 
| 880 |         QCOMPARE(empty->size, 0); | 
| 881 |  | 
| 882 |         QCOMPARE(null->begin(), null->end()); | 
| 883 |         QCOMPARE(empty->begin(), empty->end()); | 
| 884 |     } | 
| 885 |  | 
| 886 |  | 
| 887 |     { | 
| 888 |         Deallocator keeper(sizeof(char), | 
| 889 |                 Q_ALIGNOF(QTypedArrayData<char>::AlignmentDummy)); | 
| 890 |         QArrayData *array = QTypedArrayData<char>::allocate(capacity: 10); | 
| 891 |         keeper.headers.append(t: array); | 
| 892 |  | 
| 893 |         QVERIFY(array); | 
| 894 |         QCOMPARE(array->size, 0); | 
| 895 |         QCOMPARE(array->alloc, 10u); | 
| 896 |  | 
| 897 |         // Check that the allocated array can be used. Best tested with a | 
| 898 |         // memory checker, such as valgrind, running. | 
| 899 |         ::memset(s: array->data(), c: 0, n: 10 * sizeof(char)); | 
| 900 |  | 
| 901 |         keeper.headers.clear(); | 
| 902 |         QTypedArrayData<short>::deallocate(data: array); | 
| 903 |  | 
| 904 |         QVERIFY(true); | 
| 905 |     } | 
| 906 |  | 
| 907 |     { | 
| 908 |         Deallocator keeper(sizeof(short), | 
| 909 |                 Q_ALIGNOF(QTypedArrayData<short>::AlignmentDummy)); | 
| 910 |         QArrayData *array = QTypedArrayData<short>::allocate(capacity: 10); | 
| 911 |         keeper.headers.append(t: array); | 
| 912 |  | 
| 913 |         QVERIFY(array); | 
| 914 |         QCOMPARE(array->size, 0); | 
| 915 |         QCOMPARE(array->alloc, 10u); | 
| 916 |  | 
| 917 |         // Check that the allocated array can be used. Best tested with a | 
| 918 |         // memory checker, such as valgrind, running. | 
| 919 |         ::memset(s: array->data(), c: 0, n: 10 * sizeof(short)); | 
| 920 |  | 
| 921 |         keeper.headers.clear(); | 
| 922 |         QTypedArrayData<short>::deallocate(data: array); | 
| 923 |  | 
| 924 |         QVERIFY(true); | 
| 925 |     } | 
| 926 |  | 
| 927 |     { | 
| 928 |         Deallocator keeper(sizeof(double), | 
| 929 |                 Q_ALIGNOF(QTypedArrayData<double>::AlignmentDummy)); | 
| 930 |         QArrayData *array = QTypedArrayData<double>::allocate(capacity: 10); | 
| 931 |         keeper.headers.append(t: array); | 
| 932 |  | 
| 933 |         QVERIFY(array); | 
| 934 |         QCOMPARE(array->size, 0); | 
| 935 |         QCOMPARE(array->alloc, 10u); | 
| 936 |  | 
| 937 |         // Check that the allocated array can be used. Best tested with a | 
| 938 |         // memory checker, such as valgrind, running. | 
| 939 |         ::memset(s: array->data(), c: 0, n: 10 * sizeof(double)); | 
| 940 |  | 
| 941 |         keeper.headers.clear(); | 
| 942 |         QTypedArrayData<double>::deallocate(data: array); | 
| 943 |  | 
| 944 |         QVERIFY(true); | 
| 945 |     } | 
| 946 | } | 
| 947 |  | 
| 948 | void tst_QArrayData::gccBug43247() | 
| 949 | { | 
| 950 |     // This test tries to verify QArrayData is not affected by GCC optimizer | 
| 951 |     // bug #43247. | 
| 952 |     // Reported on GCC 4.4.3, Linux, affects QVector | 
| 953 |  | 
| 954 |     QTest::ignoreMessage(type: QtDebugMsg, message: "GCC Optimization bug #43247 not triggered (3)" ); | 
| 955 |     QTest::ignoreMessage(type: QtDebugMsg, message: "GCC Optimization bug #43247 not triggered (4)" ); | 
| 956 |     QTest::ignoreMessage(type: QtDebugMsg, message: "GCC Optimization bug #43247 not triggered (5)" ); | 
| 957 |     QTest::ignoreMessage(type: QtDebugMsg, message: "GCC Optimization bug #43247 not triggered (6)" ); | 
| 958 |     QTest::ignoreMessage(type: QtDebugMsg, message: "GCC Optimization bug #43247 not triggered (7)" ); | 
| 959 |  | 
| 960 |     SimpleVector<int> array(10, 0); | 
| 961 |     // QVector<int> vector(10, 0); | 
| 962 |  | 
| 963 |     for (int i = 0; i < 10; ++i) { | 
| 964 |         if (i >= 3 && i < 8) | 
| 965 |             qDebug(msg: "GCC Optimization bug #43247 not triggered (%i)" , i); | 
| 966 |  | 
| 967 |         // When access to data is implemented through an array of size 1, this | 
| 968 |         // line lets the compiler assume i == 0, and the conditional above is | 
| 969 |         // skipped. | 
| 970 |         QVERIFY(array.at(i) == 0); | 
| 971 |         // QVERIFY(vector.at(i) == 0); | 
| 972 |     } | 
| 973 | } | 
| 974 |  | 
| 975 | struct CountedObject | 
| 976 | { | 
| 977 |     CountedObject() | 
| 978 |         : id(liveCount++) | 
| 979 |         , flags(DefaultConstructed) | 
| 980 |     { | 
| 981 |     } | 
| 982 |  | 
| 983 |     CountedObject(const CountedObject &other) | 
| 984 |         : id(other.id) | 
| 985 |         , flags(other.flags == DefaultConstructed | 
| 986 |                 ? ObjectFlags(CopyConstructed | DefaultConstructed) | 
| 987 |                 : CopyConstructed) | 
| 988 |     { | 
| 989 |         ++liveCount; | 
| 990 |     } | 
| 991 |  | 
| 992 |     ~CountedObject() | 
| 993 |     { | 
| 994 |         --liveCount; | 
| 995 |     } | 
| 996 |  | 
| 997 |     CountedObject &operator=(const CountedObject &other) | 
| 998 |     { | 
| 999 |         flags = ObjectFlags(other.flags | CopyAssigned); | 
| 1000 |         id = other.id; | 
| 1001 |         return *this; | 
| 1002 |     } | 
| 1003 |  | 
| 1004 |     struct LeakChecker | 
| 1005 |     { | 
| 1006 |         LeakChecker() | 
| 1007 |             : previousLiveCount(liveCount) | 
| 1008 |         { | 
| 1009 |         } | 
| 1010 |  | 
| 1011 |         ~LeakChecker() | 
| 1012 |         { | 
| 1013 |             QCOMPARE(liveCount, previousLiveCount); | 
| 1014 |         } | 
| 1015 |  | 
| 1016 |     private: | 
| 1017 |         const size_t previousLiveCount; | 
| 1018 |     }; | 
| 1019 |  | 
| 1020 |     enum ObjectFlags { | 
| 1021 |         DefaultConstructed  = 1, | 
| 1022 |         CopyConstructed     = 2, | 
| 1023 |         CopyAssigned        = 4 | 
| 1024 |     }; | 
| 1025 |  | 
| 1026 |     size_t id; // not unique | 
| 1027 |     ObjectFlags flags; | 
| 1028 |  | 
| 1029 |     static size_t liveCount; | 
| 1030 | }; | 
| 1031 |  | 
| 1032 | size_t CountedObject::liveCount = 0; | 
| 1033 |  | 
| 1034 | void tst_QArrayData::arrayOps() | 
| 1035 | { | 
| 1036 |     CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker) | 
| 1037 |  | 
| 1038 |     const int intArray[5] = { 80, 101, 100, 114, 111 }; | 
| 1039 |     const QString stringArray[5] = { | 
| 1040 |         QLatin1String("just" ), | 
| 1041 |         QLatin1String("for" ), | 
| 1042 |         QLatin1String("testing" ), | 
| 1043 |         QLatin1String("a" ), | 
| 1044 |         QLatin1String("vector" ) | 
| 1045 |     }; | 
| 1046 |     const CountedObject objArray[5]; | 
| 1047 |  | 
| 1048 |     QVERIFY(!QTypeInfo<int>::isComplex && !QTypeInfo<int>::isStatic); | 
| 1049 |     QVERIFY(QTypeInfo<QString>::isComplex && !QTypeInfo<QString>::isStatic); | 
| 1050 |     QVERIFY(QTypeInfo<CountedObject>::isComplex && QTypeInfo<CountedObject>::isStatic); | 
| 1051 |  | 
| 1052 |     QCOMPARE(CountedObject::liveCount, size_t(5)); | 
| 1053 |     for (size_t i = 0; i < 5; ++i) | 
| 1054 |         QCOMPARE(objArray[i].id, i); | 
| 1055 |  | 
| 1056 |     //////////////////////////////////////////////////////////////////////////// | 
| 1057 |     // copyAppend (I) | 
| 1058 |     SimpleVector<int> vi(intArray, intArray + 5); | 
| 1059 |     SimpleVector<QString> vs(stringArray, stringArray + 5); | 
| 1060 |     SimpleVector<CountedObject> vo(objArray, objArray + 5); | 
| 1061 |  | 
| 1062 |     QCOMPARE(CountedObject::liveCount, size_t(10)); | 
| 1063 |     for (int i = 0; i < 5; ++i) { | 
| 1064 |         QCOMPARE(vi[i], intArray[i]); | 
| 1065 |         QVERIFY(vs[i].isSharedWith(stringArray[i])); | 
| 1066 |  | 
| 1067 |         QCOMPARE(vo[i].id, objArray[i].id); | 
| 1068 |         QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed | 
| 1069 |                 | CountedObject::DefaultConstructed); | 
| 1070 |     } | 
| 1071 |  | 
| 1072 |     //////////////////////////////////////////////////////////////////////////// | 
| 1073 |     // destroyAll | 
| 1074 |     vi.clear(); | 
| 1075 |     vs.clear(); | 
| 1076 |     vo.clear(); | 
| 1077 |  | 
| 1078 |     QCOMPARE(CountedObject::liveCount, size_t(5)); | 
| 1079 |  | 
| 1080 |     //////////////////////////////////////////////////////////////////////////// | 
| 1081 |     // copyAppend (II) | 
| 1082 |     int referenceInt = 7; | 
| 1083 |     QString referenceString = QLatin1String("reference" ); | 
| 1084 |     CountedObject referenceObject; | 
| 1085 |  | 
| 1086 |     vi = SimpleVector<int>(5, referenceInt); | 
| 1087 |     vs = SimpleVector<QString>(5, referenceString); | 
| 1088 |     vo = SimpleVector<CountedObject>(5, referenceObject); | 
| 1089 |  | 
| 1090 |     QCOMPARE(vi.size(), size_t(5)); | 
| 1091 |     QCOMPARE(vs.size(), size_t(5)); | 
| 1092 |     QCOMPARE(vo.size(), size_t(5)); | 
| 1093 |  | 
| 1094 |     QCOMPARE(CountedObject::liveCount, size_t(11)); | 
| 1095 |     for (int i = 0; i < 5; ++i) { | 
| 1096 |         QCOMPARE(vi[i], referenceInt); | 
| 1097 |         QVERIFY(vs[i].isSharedWith(referenceString)); | 
| 1098 |  | 
| 1099 |         QCOMPARE(vo[i].id, referenceObject.id); | 
| 1100 |         QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed | 
| 1101 |                 | CountedObject::DefaultConstructed); | 
| 1102 |     } | 
| 1103 |  | 
| 1104 |     //////////////////////////////////////////////////////////////////////////// | 
| 1105 |     // insert | 
| 1106 |     vi.reserve(n: 30); | 
| 1107 |     vs.reserve(n: 30); | 
| 1108 |     vo.reserve(n: 30); | 
| 1109 |  | 
| 1110 |     QCOMPARE(vi.size(), size_t(5)); | 
| 1111 |     QCOMPARE(vs.size(), size_t(5)); | 
| 1112 |     QCOMPARE(vo.size(), size_t(5)); | 
| 1113 |  | 
| 1114 |     QVERIFY(vi.capacity() >= 30); | 
| 1115 |     QVERIFY(vs.capacity() >= 30); | 
| 1116 |     QVERIFY(vo.capacity() >= 30); | 
| 1117 |  | 
| 1118 |     // Displace as many elements as array is extended by | 
| 1119 |     vi.insert(position: 0, first: intArray, last: intArray + 5); | 
| 1120 |     vs.insert(position: 0, first: stringArray, last: stringArray + 5); | 
| 1121 |     vo.insert(position: 0, first: objArray, last: objArray + 5); | 
| 1122 |  | 
| 1123 |     QCOMPARE(vi.size(), size_t(10)); | 
| 1124 |     QCOMPARE(vs.size(), size_t(10)); | 
| 1125 |     QCOMPARE(vo.size(), size_t(10)); | 
| 1126 |  | 
| 1127 |     // Displace more elements than array is extended by | 
| 1128 |     vi.insert(position: 0, first: intArray, last: intArray + 5); | 
| 1129 |     vs.insert(position: 0, first: stringArray, last: stringArray + 5); | 
| 1130 |     vo.insert(position: 0, first: objArray, last: objArray + 5); | 
| 1131 |  | 
| 1132 |     QCOMPARE(vi.size(), size_t(15)); | 
| 1133 |     QCOMPARE(vs.size(), size_t(15)); | 
| 1134 |     QCOMPARE(vo.size(), size_t(15)); | 
| 1135 |  | 
| 1136 |     // Displace less elements than array is extended by | 
| 1137 |     vi.insert(position: 5, first: vi.constBegin(), last: vi.constEnd()); | 
| 1138 |     vs.insert(position: 5, first: vs.constBegin(), last: vs.constEnd()); | 
| 1139 |     vo.insert(position: 5, first: vo.constBegin(), last: vo.constEnd()); | 
| 1140 |  | 
| 1141 |     QCOMPARE(vi.size(), size_t(30)); | 
| 1142 |     QCOMPARE(vs.size(), size_t(30)); | 
| 1143 |     QCOMPARE(vo.size(), size_t(30)); | 
| 1144 |  | 
| 1145 |     QCOMPARE(CountedObject::liveCount, size_t(36)); | 
| 1146 |     for (int i = 0; i < 5; ++i) { | 
| 1147 |         QCOMPARE(vi[i], intArray[i % 5]); | 
| 1148 |         QVERIFY(vs[i].isSharedWith(stringArray[i % 5])); | 
| 1149 |  | 
| 1150 |         QCOMPARE(vo[i].id, objArray[i % 5].id); | 
| 1151 |         QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed | 
| 1152 |                 | CountedObject::CopyAssigned); | 
| 1153 |     } | 
| 1154 |  | 
| 1155 |     for (int i = 5; i < 15; ++i) { | 
| 1156 |         QCOMPARE(vi[i], intArray[i % 5]); | 
| 1157 |         QVERIFY(vs[i].isSharedWith(stringArray[i % 5])); | 
| 1158 |  | 
| 1159 |         QCOMPARE(vo[i].id, objArray[i % 5].id); | 
| 1160 |         QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed | 
| 1161 |                 | CountedObject::CopyAssigned); | 
| 1162 |     } | 
| 1163 |  | 
| 1164 |     for (int i = 15; i < 20; ++i) { | 
| 1165 |         QCOMPARE(vi[i], referenceInt); | 
| 1166 |         QVERIFY(vs[i].isSharedWith(referenceString)); | 
| 1167 |  | 
| 1168 |         QCOMPARE(vo[i].id, referenceObject.id); | 
| 1169 |         QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed | 
| 1170 |                 | CountedObject::CopyAssigned); | 
| 1171 |     } | 
| 1172 |  | 
| 1173 |     for (int i = 20; i < 25; ++i) { | 
| 1174 |         QCOMPARE(vi[i], intArray[i % 5]); | 
| 1175 |         QVERIFY(vs[i].isSharedWith(stringArray[i % 5])); | 
| 1176 |  | 
| 1177 |         QCOMPARE(vo[i].id, objArray[i % 5].id); | 
| 1178 |  | 
| 1179 |         //  Originally inserted as (DefaultConstructed | CopyAssigned), later | 
| 1180 |         //  get shuffled into place by std::rotate (SimpleVector::insert, | 
| 1181 |         //  overlapping mode). | 
| 1182 |         //  Depending on implementation of rotate, final assignment can be: | 
| 1183 |         //     - straight from source: DefaultConstructed | CopyAssigned | 
| 1184 |         //     - through a temporary: CopyConstructed | CopyAssigned | 
| 1185 |         QCOMPARE(vo[i].flags & CountedObject::CopyAssigned, | 
| 1186 |                 int(CountedObject::CopyAssigned)); | 
| 1187 |     } | 
| 1188 |  | 
| 1189 |     for (int i = 25; i < 30; ++i) { | 
| 1190 |         QCOMPARE(vi[i], referenceInt); | 
| 1191 |         QVERIFY(vs[i].isSharedWith(referenceString)); | 
| 1192 |  | 
| 1193 |         QCOMPARE(vo[i].id, referenceObject.id); | 
| 1194 |         QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed | 
| 1195 |                 | CountedObject::CopyAssigned); | 
| 1196 |     } | 
| 1197 | } | 
| 1198 |  | 
| 1199 | void tst_QArrayData::arrayOps2() | 
| 1200 | { | 
| 1201 |     CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker) | 
| 1202 |  | 
| 1203 |     //////////////////////////////////////////////////////////////////////////// | 
| 1204 |     // appendInitialize | 
| 1205 |     SimpleVector<int> vi(5); | 
| 1206 |     SimpleVector<QString> vs(5); | 
| 1207 |     SimpleVector<CountedObject> vo(5); | 
| 1208 |  | 
| 1209 |     QCOMPARE(vi.size(), size_t(5)); | 
| 1210 |     QCOMPARE(vs.size(), size_t(5)); | 
| 1211 |     QCOMPARE(vo.size(), size_t(5)); | 
| 1212 |  | 
| 1213 |     QCOMPARE(CountedObject::liveCount, size_t(5)); | 
| 1214 |     for (size_t i = 0; i < 5; ++i) { | 
| 1215 |         QCOMPARE(vi[i], 0); | 
| 1216 |         QVERIFY(vs[i].isNull()); | 
| 1217 |  | 
| 1218 |         QCOMPARE(vo[i].id, i); | 
| 1219 |         QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed)); | 
| 1220 |     } | 
| 1221 |  | 
| 1222 |     //////////////////////////////////////////////////////////////////////////// | 
| 1223 |     // appendInitialize, again | 
| 1224 |  | 
| 1225 |     // These will detach | 
| 1226 |     vi.resize(newSize: 10); | 
| 1227 |     vs.resize(newSize: 10); | 
| 1228 |     vo.resize(newSize: 10); | 
| 1229 |  | 
| 1230 |     QCOMPARE(vi.size(), size_t(10)); | 
| 1231 |     QCOMPARE(vs.size(), size_t(10)); | 
| 1232 |     QCOMPARE(vo.size(), size_t(10)); | 
| 1233 |  | 
| 1234 |     QCOMPARE(CountedObject::liveCount, size_t(10)); | 
| 1235 |     for (size_t i = 0; i < 5; ++i) { | 
| 1236 |         QCOMPARE(vi[i], 0); | 
| 1237 |         QVERIFY(vs[i].isNull()); | 
| 1238 |  | 
| 1239 |         QCOMPARE(vo[i].id, i); | 
| 1240 |         QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed | 
| 1241 |                 | CountedObject::CopyConstructed); | 
| 1242 |     } | 
| 1243 |  | 
| 1244 |     for (size_t i = 5; i < 10; ++i) { | 
| 1245 |         QCOMPARE(vi[i], 0); | 
| 1246 |         QVERIFY(vs[i].isNull()); | 
| 1247 |  | 
| 1248 |         QCOMPARE(vo[i].id, i + 5); | 
| 1249 |         QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed)); | 
| 1250 |     } | 
| 1251 |  | 
| 1252 |     //////////////////////////////////////////////////////////////////////////// | 
| 1253 |     // truncate | 
| 1254 |     QVERIFY(!vi.isShared()); | 
| 1255 |     QVERIFY(!vs.isShared()); | 
| 1256 |     QVERIFY(!vo.isShared()); | 
| 1257 |  | 
| 1258 |     // These shouldn't detach | 
| 1259 |     vi.resize(newSize: 7); | 
| 1260 |     vs.resize(newSize: 7); | 
| 1261 |     vo.resize(newSize: 7); | 
| 1262 |  | 
| 1263 |     QCOMPARE(vi.size(), size_t(7)); | 
| 1264 |     QCOMPARE(vs.size(), size_t(7)); | 
| 1265 |     QCOMPARE(vo.size(), size_t(7)); | 
| 1266 |  | 
| 1267 |     QCOMPARE(CountedObject::liveCount, size_t(7)); | 
| 1268 |     for (size_t i = 0; i < 5; ++i) { | 
| 1269 |         QCOMPARE(vi[i], 0); | 
| 1270 |         QVERIFY(vs[i].isNull()); | 
| 1271 |  | 
| 1272 |         QCOMPARE(vo[i].id, i); | 
| 1273 |         QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed | 
| 1274 |                 | CountedObject::CopyConstructed); | 
| 1275 |     } | 
| 1276 |  | 
| 1277 |     for (size_t i = 5; i < 7; ++i) { | 
| 1278 |         QCOMPARE(vi[i], 0); | 
| 1279 |         QVERIFY(vs[i].isNull()); | 
| 1280 |  | 
| 1281 |         QCOMPARE(vo[i].id, i + 5); | 
| 1282 |         QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed)); | 
| 1283 |     } | 
| 1284 |  | 
| 1285 |     //////////////////////////////////////////////////////////////////////////// | 
| 1286 |     vi.resize(newSize: 10); | 
| 1287 |     vs.resize(newSize: 10); | 
| 1288 |     vo.resize(newSize: 10); | 
| 1289 |  | 
| 1290 |     for (size_t i = 7; i < 10; ++i) { | 
| 1291 |         vi[i] = int(i); | 
| 1292 |         vs[i] = QString::number(i); | 
| 1293 |  | 
| 1294 |         QCOMPARE(vo[i].id, i); | 
| 1295 |         QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed)); | 
| 1296 |     } | 
| 1297 |  | 
| 1298 |     QCOMPARE(CountedObject::liveCount, size_t(10)); | 
| 1299 |  | 
| 1300 |     //////////////////////////////////////////////////////////////////////////// | 
| 1301 |     // erase | 
| 1302 |     vi.erase(first: vi.begin() + 2, last: vi.begin() + 5); | 
| 1303 |     vs.erase(first: vs.begin() + 2, last: vs.begin() + 5); | 
| 1304 |     vo.erase(first: vo.begin() + 2, last: vo.begin() + 5); | 
| 1305 |  | 
| 1306 |     QCOMPARE(vi.size(), size_t(7)); | 
| 1307 |     QCOMPARE(vs.size(), size_t(7)); | 
| 1308 |     QCOMPARE(vo.size(), size_t(7)); | 
| 1309 |  | 
| 1310 |     QCOMPARE(CountedObject::liveCount, size_t(7)); | 
| 1311 |     for (size_t i = 0; i < 2; ++i) { | 
| 1312 |         QCOMPARE(vi[i], 0); | 
| 1313 |         QVERIFY(vs[i].isNull()); | 
| 1314 |  | 
| 1315 |         QCOMPARE(vo[i].id, i); | 
| 1316 |         QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed | 
| 1317 |                 | CountedObject::CopyConstructed); | 
| 1318 |     } | 
| 1319 |  | 
| 1320 |     for (size_t i = 2; i < 4; ++i) { | 
| 1321 |         QCOMPARE(vi[i], 0); | 
| 1322 |         QVERIFY(vs[i].isNull()); | 
| 1323 |  | 
| 1324 |         QCOMPARE(vo[i].id, i + 8); | 
| 1325 |         QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed) | 
| 1326 |                 | CountedObject::CopyAssigned); | 
| 1327 |     } | 
| 1328 |  | 
| 1329 |     for (size_t i = 4; i < 7; ++i) { | 
| 1330 |         QCOMPARE(vi[i], int(i + 3)); | 
| 1331 |         QCOMPARE(vs[i], QString::number(i + 3)); | 
| 1332 |  | 
| 1333 |         QCOMPARE(vo[i].id, i + 3); | 
| 1334 |         QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed | 
| 1335 |                 | CountedObject::CopyAssigned); | 
| 1336 |     } | 
| 1337 | } | 
| 1338 |  | 
| 1339 | Q_DECLARE_METATYPE(QArrayDataPointer<int>) | 
| 1340 |  | 
| 1341 | static inline bool arrayIsFilledWith(const QArrayDataPointer<int> &array, | 
| 1342 |         int fillValue, size_t size) | 
| 1343 | { | 
| 1344 |     const int *iter = array->begin(); | 
| 1345 |     const int *const end = array->end(); | 
| 1346 |  | 
| 1347 |     for (size_t i = 0; i < size; ++i, ++iter) | 
| 1348 |         if (*iter != fillValue) | 
| 1349 |             return false; | 
| 1350 |  | 
| 1351 |     if (iter != end) | 
| 1352 |         return false; | 
| 1353 |  | 
| 1354 |     return true; | 
| 1355 | } | 
| 1356 |  | 
| 1357 | void tst_QArrayData::setSharable_data() | 
| 1358 | { | 
| 1359 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 1360 |     QTest::addColumn<QArrayDataPointer<int> >(name: "array" ); | 
| 1361 |     QTest::addColumn<size_t>(name: "size" ); | 
| 1362 |     QTest::addColumn<size_t>(name: "capacity" ); | 
| 1363 |     QTest::addColumn<bool>(name: "isCapacityReserved" ); | 
| 1364 |     QTest::addColumn<int>(name: "fillValue" ); | 
| 1365 |  | 
| 1366 |     QArrayDataPointer<int> null; | 
| 1367 |     QArrayDataPointer<int> empty; empty.clear(); | 
| 1368 |  | 
| 1369 |     static QStaticArrayData<int, 10> staticArrayData = { | 
| 1370 |             Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(int, 10), | 
| 1371 |             .data: { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 } | 
| 1372 |         }; | 
| 1373 |  | 
| 1374 |     QArrayDataPointer<int> emptyReserved(QTypedArrayData<int>::allocate(capacity: 5, | 
| 1375 |                 options: QArrayData::CapacityReserved)); | 
| 1376 |     QArrayDataPointer<int> nonEmpty(QTypedArrayData<int>::allocate(capacity: 5, | 
| 1377 |                 options: QArrayData::Default)); | 
| 1378 |     QArrayDataPointer<int> ( | 
| 1379 |             QTypedArrayData<int>::allocate(capacity: 10, options: QArrayData::Default)); | 
| 1380 |     QArrayDataPointer<int> nonEmptyReserved(QTypedArrayData<int>::allocate(capacity: 15, | 
| 1381 |                 options: QArrayData::CapacityReserved)); | 
| 1382 |     QArrayDataPointer<int> staticArray( | 
| 1383 |             static_cast<QTypedArrayData<int> *>(&staticArrayData.header)); | 
| 1384 |     QArrayDataPointer<int> rawData( | 
| 1385 |             QTypedArrayData<int>::fromRawData(data: staticArrayData.data, n: 10)); | 
| 1386 |  | 
| 1387 |     nonEmpty->copyAppend(n: 5, t: 1); | 
| 1388 |     nonEmptyExtraCapacity->copyAppend(n: 5, t: 1); | 
| 1389 |     nonEmptyReserved->copyAppend(n: 7, t: 2); | 
| 1390 |  | 
| 1391 |     QTest::newRow(dataTag: "shared-null" ) << null << size_t(0) << size_t(0) << false << 0; | 
| 1392 |     QTest::newRow(dataTag: "shared-empty" ) << empty << size_t(0) << size_t(0) << false << 0; | 
| 1393 |     // unsharable-empty implicitly tested in shared-empty | 
| 1394 |     QTest::newRow(dataTag: "empty-reserved" ) << emptyReserved << size_t(0) << size_t(5) << true << 0; | 
| 1395 |     QTest::newRow(dataTag: "non-empty" ) << nonEmpty << size_t(5) << size_t(5) << false << 1; | 
| 1396 |     QTest::newRow(dataTag: "non-empty-extra-capacity" ) << nonEmptyExtraCapacity << size_t(5) << size_t(10) << false << 1; | 
| 1397 |     QTest::newRow(dataTag: "non-empty-reserved" ) << nonEmptyReserved << size_t(7) << size_t(15) << true << 2; | 
| 1398 |     QTest::newRow(dataTag: "static-array" ) << staticArray << size_t(10) << size_t(0) << false << 3; | 
| 1399 |     QTest::newRow(dataTag: "raw-data" ) << rawData << size_t(10) << size_t(0) << false << 3; | 
| 1400 | #endif | 
| 1401 | } | 
| 1402 |  | 
| 1403 | void tst_QArrayData::setSharable() | 
| 1404 | { | 
| 1405 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 1406 |     QFETCH(QArrayDataPointer<int>, array); | 
| 1407 |     QFETCH(size_t, size); | 
| 1408 |     QFETCH(size_t, capacity); | 
| 1409 |     QFETCH(bool, isCapacityReserved); | 
| 1410 |     QFETCH(int, fillValue); | 
| 1411 |  | 
| 1412 |     QVERIFY(array->ref.isShared()); // QTest has a copy | 
| 1413 |     QVERIFY(array->ref.isSharable()); | 
| 1414 |  | 
| 1415 |     QCOMPARE(size_t(array->size), size); | 
| 1416 |     QCOMPARE(size_t(array->alloc), capacity); | 
| 1417 |     QCOMPARE(bool(array->capacityReserved), isCapacityReserved); | 
| 1418 |     QVERIFY(arrayIsFilledWith(array, fillValue, size)); | 
| 1419 |  | 
| 1420 |     // shared-null becomes shared-empty, may otherwise detach | 
| 1421 |     array.setSharable(true); | 
| 1422 |  | 
| 1423 |     QVERIFY(array->ref.isSharable()); | 
| 1424 |     QVERIFY(arrayIsFilledWith(array, fillValue, size)); | 
| 1425 |  | 
| 1426 |     { | 
| 1427 |         QArrayDataPointer<int> copy(array); | 
| 1428 |         QVERIFY(array->ref.isShared()); | 
| 1429 |         QVERIFY(array->ref.isSharable()); | 
| 1430 |         QCOMPARE(copy.data(), array.data()); | 
| 1431 |     } | 
| 1432 |  | 
| 1433 |     // Unshare, must detach | 
| 1434 |     array.setSharable(false); | 
| 1435 |  | 
| 1436 |     // Immutability (alloc == 0) is lost on detach, as is additional capacity | 
| 1437 |     // if capacityReserved flag is not set. | 
| 1438 |     if ((capacity == 0 && size != 0) | 
| 1439 |             || (!isCapacityReserved && capacity > size)) | 
| 1440 |         capacity = size; | 
| 1441 |  | 
| 1442 |     QVERIFY(!array->ref.isShared()); | 
| 1443 |     QVERIFY(!array->ref.isSharable()); | 
| 1444 |  | 
| 1445 |     QCOMPARE(size_t(array->size), size); | 
| 1446 |     QCOMPARE(size_t(array->alloc), capacity); | 
| 1447 |     QCOMPARE(bool(array->capacityReserved), isCapacityReserved); | 
| 1448 |     QVERIFY(arrayIsFilledWith(array, fillValue, size)); | 
| 1449 |  | 
| 1450 |     { | 
| 1451 |         QArrayDataPointer<int> copy(array); | 
| 1452 |         QVERIFY(!array->ref.isShared()); | 
| 1453 |         QVERIFY(!array->ref.isSharable()); | 
| 1454 |  | 
| 1455 |         // Null/empty is always shared | 
| 1456 |         QCOMPARE(copy->ref.isShared(), !(size || isCapacityReserved)); | 
| 1457 |         QVERIFY(copy->ref.isSharable()); | 
| 1458 |  | 
| 1459 |         QCOMPARE(size_t(copy->size), size); | 
| 1460 |         QCOMPARE(size_t(copy->alloc), capacity); | 
| 1461 |         QCOMPARE(bool(copy->capacityReserved), isCapacityReserved); | 
| 1462 |         QVERIFY(arrayIsFilledWith(copy, fillValue, size)); | 
| 1463 |     } | 
| 1464 |  | 
| 1465 |     // Make sharable, again | 
| 1466 |     array.setSharable(true); | 
| 1467 |  | 
| 1468 |     QCOMPARE(array->ref.isShared(), !(size || isCapacityReserved)); | 
| 1469 |     QVERIFY(array->ref.isSharable()); | 
| 1470 |  | 
| 1471 |     QCOMPARE(size_t(array->size), size); | 
| 1472 |     QCOMPARE(size_t(array->alloc), capacity); | 
| 1473 |     QCOMPARE(bool(array->capacityReserved), isCapacityReserved); | 
| 1474 |     QVERIFY(arrayIsFilledWith(array, fillValue, size)); | 
| 1475 |  | 
| 1476 |     { | 
| 1477 |         QArrayDataPointer<int> copy(array); | 
| 1478 |         QVERIFY(array->ref.isShared()); | 
| 1479 |         QCOMPARE(copy.data(), array.data()); | 
| 1480 |     } | 
| 1481 |  | 
| 1482 |     QCOMPARE(array->ref.isShared(), !(size || isCapacityReserved)); | 
| 1483 |     QVERIFY(array->ref.isSharable()); | 
| 1484 | #endif | 
| 1485 | } | 
| 1486 |  | 
| 1487 | struct ResetOnDtor | 
| 1488 | { | 
| 1489 |     ResetOnDtor() | 
| 1490 |         : value_() | 
| 1491 |     { | 
| 1492 |     } | 
| 1493 |  | 
| 1494 |     ResetOnDtor(int value) | 
| 1495 |         : value_(value) | 
| 1496 |     { | 
| 1497 |     } | 
| 1498 |  | 
| 1499 |     ~ResetOnDtor() | 
| 1500 |     { | 
| 1501 |         value_ = 0; | 
| 1502 |     } | 
| 1503 |  | 
| 1504 |     int value_; | 
| 1505 | }; | 
| 1506 |  | 
| 1507 | bool operator==(const ResetOnDtor &lhs, const ResetOnDtor &rhs) | 
| 1508 | { | 
| 1509 |     return lhs.value_ == rhs.value_; | 
| 1510 | } | 
| 1511 |  | 
| 1512 | template <class T> | 
| 1513 | void fromRawData_impl() | 
| 1514 | { | 
| 1515 |     static const T array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; | 
| 1516 |  | 
| 1517 |     { | 
| 1518 |         // Default: Immutable, sharable | 
| 1519 |         SimpleVector<T> raw = SimpleVector<T>::fromRawData(array, | 
| 1520 |                 sizeof(array)/sizeof(array[0]), QArrayData::Default); | 
| 1521 |  | 
| 1522 |         QCOMPARE(raw.size(), size_t(11)); | 
| 1523 |         QCOMPARE((const T *)raw.constBegin(), array); | 
| 1524 |         QCOMPARE((const T *)raw.constEnd(), (const T *)(array + sizeof(array)/sizeof(array[0]))); | 
| 1525 |  | 
| 1526 |         QVERIFY(!raw.isShared()); | 
| 1527 |         QVERIFY(SimpleVector<T>(raw).isSharedWith(raw)); | 
| 1528 |         QVERIFY(!raw.isShared()); | 
| 1529 |  | 
| 1530 |         // Detach | 
| 1531 |         QCOMPARE(raw.back(), T(11)); | 
| 1532 |         QVERIFY((const T *)raw.constBegin() != array); | 
| 1533 |     } | 
| 1534 |  | 
| 1535 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 1536 |     { | 
| 1537 |         // Immutable, unsharable | 
| 1538 |         SimpleVector<T> raw = SimpleVector<T>::fromRawData(array, | 
| 1539 |                 sizeof(array)/sizeof(array[0]), QArrayData::Unsharable); | 
| 1540 |  | 
| 1541 |         QCOMPARE(raw.size(), size_t(11)); | 
| 1542 |         QCOMPARE((const T *)raw.constBegin(), array); | 
| 1543 |         QCOMPARE((const T *)raw.constEnd(), (const T *)(array + sizeof(array)/sizeof(array[0]))); | 
| 1544 |  | 
| 1545 |         SimpleVector<T> copy(raw); | 
| 1546 |         QVERIFY(!copy.isSharedWith(raw)); | 
| 1547 |         QVERIFY(!raw.isShared()); | 
| 1548 |  | 
| 1549 |         QCOMPARE(copy.size(), size_t(11)); | 
| 1550 |  | 
| 1551 |         for (size_t i = 0; i < 11; ++i) { | 
| 1552 |             QCOMPARE(const_(copy)[i], const_(raw)[i]); | 
| 1553 |             QCOMPARE(const_(copy)[i], T(i + 1)); | 
| 1554 |         } | 
| 1555 |  | 
| 1556 |         QCOMPARE(raw.size(), size_t(11)); | 
| 1557 |         QCOMPARE((const T *)raw.constBegin(), array); | 
| 1558 |         QCOMPARE((const T *)raw.constEnd(), (const T *)(array + sizeof(array)/sizeof(array[0]))); | 
| 1559 |  | 
| 1560 |         // Detach | 
| 1561 |         QCOMPARE(raw.back(), T(11)); | 
| 1562 |         QVERIFY((const T *)raw.constBegin() != array); | 
| 1563 |     } | 
| 1564 | #endif | 
| 1565 | } | 
| 1566 |  | 
| 1567 | void tst_QArrayData::fromRawData_data() | 
| 1568 | { | 
| 1569 |     QTest::addColumn<int>(name: "type" ); | 
| 1570 |  | 
| 1571 |     QTest::newRow(dataTag: "int" ) << 0; | 
| 1572 |     QTest::newRow(dataTag: "ResetOnDtor" ) << 1; | 
| 1573 | } | 
| 1574 | void tst_QArrayData::fromRawData() | 
| 1575 | { | 
| 1576 |     QFETCH(int, type); | 
| 1577 |  | 
| 1578 |     switch (type) | 
| 1579 |     { | 
| 1580 |         case 0: | 
| 1581 |             fromRawData_impl<int>(); | 
| 1582 |             break; | 
| 1583 |         case 1: | 
| 1584 |             fromRawData_impl<ResetOnDtor>(); | 
| 1585 |             break; | 
| 1586 |  | 
| 1587 |         default: | 
| 1588 |             QFAIL("Unexpected type data" ); | 
| 1589 |     } | 
| 1590 | } | 
| 1591 |  | 
| 1592 | void tst_QArrayData::literals() | 
| 1593 | { | 
| 1594 |     { | 
| 1595 |         QArrayDataPointer<char> d = Q_ARRAY_LITERAL(char, "ABCDEFGHIJ" ); | 
| 1596 |         QCOMPARE(d->size, 10 + 1); | 
| 1597 |         for (int i = 0; i < 10; ++i) | 
| 1598 |             QCOMPARE(d->data()[i], char('A' + i)); | 
| 1599 |     } | 
| 1600 |  | 
| 1601 |     { | 
| 1602 |         // wchar_t is not necessarily 2-bytes | 
| 1603 |         QArrayDataPointer<wchar_t> d = Q_ARRAY_LITERAL(wchar_t, L"ABCDEFGHIJ" ); | 
| 1604 |         QCOMPARE(d->size, 10 + 1); | 
| 1605 |         for (int i = 0; i < 10; ++i) | 
| 1606 |             QCOMPARE(d->data()[i], wchar_t('A' + i)); | 
| 1607 |     } | 
| 1608 |  | 
| 1609 |     { | 
| 1610 |         SimpleVector<char> v = Q_ARRAY_LITERAL(char, "ABCDEFGHIJ" ); | 
| 1611 |  | 
| 1612 |         QVERIFY(!v.isNull()); | 
| 1613 |         QVERIFY(!v.isEmpty()); | 
| 1614 |         QCOMPARE(v.size(), size_t(11)); | 
| 1615 |         // v.capacity() is unspecified, for now | 
| 1616 |  | 
| 1617 |         QVERIFY(v.isStatic()); | 
| 1618 |  | 
| 1619 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 1620 |         QVERIFY(v.isSharable()); | 
| 1621 | #endif | 
| 1622 |         QCOMPARE((void*)(const char*)(v.constBegin() + v.size()), (void*)(const char*)v.constEnd()); | 
| 1623 |  | 
| 1624 |         for (int i = 0; i < 10; ++i) | 
| 1625 |             QCOMPARE(const_(v)[i], char('A' + i)); | 
| 1626 |         QCOMPARE(const_(v)[10], char('\0')); | 
| 1627 |     } | 
| 1628 |  | 
| 1629 |     { | 
| 1630 |         struct LiteralType { | 
| 1631 |             int value; | 
| 1632 |             Q_DECL_CONSTEXPR LiteralType(int v = 0) : value(v) {} | 
| 1633 |         }; | 
| 1634 |  | 
| 1635 |         QArrayDataPointer<LiteralType> d = Q_ARRAY_LITERAL(LiteralType, LiteralType(0), LiteralType(1), LiteralType(2)); | 
| 1636 |         QCOMPARE(d->size, 3); | 
| 1637 |         for (int i = 0; i < 3; ++i) | 
| 1638 |             QCOMPARE(d->data()[i].value, i); | 
| 1639 |     } | 
| 1640 | } | 
| 1641 |  | 
| 1642 | // Variadic Q_ARRAY_LITERAL need to be available in the current configuration. | 
| 1643 | void tst_QArrayData::variadicLiterals() | 
| 1644 | { | 
| 1645 |     { | 
| 1646 |         QArrayDataPointer<int> d = | 
| 1647 |             Q_ARRAY_LITERAL(int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); | 
| 1648 |         QCOMPARE(d->size, 10); | 
| 1649 |         for (int i = 0; i < 10; ++i) | 
| 1650 |             QCOMPARE(d->data()[i], i); | 
| 1651 |     } | 
| 1652 |  | 
| 1653 |     { | 
| 1654 |         QArrayDataPointer<char> d = Q_ARRAY_LITERAL(char, | 
| 1655 |                 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'); | 
| 1656 |         QCOMPARE(d->size, 10); | 
| 1657 |         for (int i = 0; i < 10; ++i) | 
| 1658 |             QCOMPARE(d->data()[i], char('A' + i)); | 
| 1659 |     } | 
| 1660 |  | 
| 1661 |     { | 
| 1662 |         QArrayDataPointer<const char *> d = Q_ARRAY_LITERAL(const char *, | 
| 1663 |                 "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" , "I" , "J" ); | 
| 1664 |         QCOMPARE(d->size, 10); | 
| 1665 |         for (int i = 0; i < 10; ++i) { | 
| 1666 |             QCOMPARE(d->data()[i][0], char('A' + i)); | 
| 1667 |             QCOMPARE(d->data()[i][1], '\0'); | 
| 1668 |         } | 
| 1669 |     } | 
| 1670 |  | 
| 1671 |     { | 
| 1672 |         SimpleVector<int> v = Q_ARRAY_LITERAL(int, 0, 1, 2, 3, 4, 5, 6); | 
| 1673 |  | 
| 1674 |         QVERIFY(!v.isNull()); | 
| 1675 |         QVERIFY(!v.isEmpty()); | 
| 1676 |         QCOMPARE(v.size(), size_t(7)); | 
| 1677 |         // v.capacity() is unspecified, for now | 
| 1678 |  | 
| 1679 |         QVERIFY(v.isStatic()); | 
| 1680 |  | 
| 1681 | #if !defined(QT_NO_UNSHARABLE_CONTAINERS) | 
| 1682 |         QVERIFY(v.isSharable()); | 
| 1683 | #endif | 
| 1684 |         QCOMPARE((const int *)(v.constBegin() + v.size()), (const int *)v.constEnd()); | 
| 1685 |  | 
| 1686 |         for (int i = 0; i < 7; ++i) | 
| 1687 |             QCOMPARE(const_(v)[i], i); | 
| 1688 |     } | 
| 1689 | } | 
| 1690 |  | 
| 1691 | // std::remove_reference is in C++11, but requires library support | 
| 1692 | template <class T> struct RemoveReference { typedef T Type; }; | 
| 1693 | template <class T> struct RemoveReference<T &> { typedef T Type; }; | 
| 1694 |  | 
| 1695 | // single-argument std::move is in C++11, but requires library support | 
| 1696 | template <class T> | 
| 1697 | typename RemoveReference<T>::Type &&cxx11Move(T &&t) | 
| 1698 | { | 
| 1699 |     return static_cast<typename RemoveReference<T>::Type &&>(t); | 
| 1700 | } | 
| 1701 |  | 
| 1702 | struct CompilerHasCxx11ImplicitMoves | 
| 1703 | { | 
| 1704 |     static bool value() | 
| 1705 |     { | 
| 1706 |         DetectImplicitMove d(cxx11Move(t: DetectImplicitMove())); | 
| 1707 |         return d.constructor == DetectConstructor::MoveConstructor; | 
| 1708 |     } | 
| 1709 |  | 
| 1710 |     struct DetectConstructor | 
| 1711 |     { | 
| 1712 |         Q_DECL_CONSTEXPR DetectConstructor() | 
| 1713 |             : constructor(DefaultConstructor) | 
| 1714 |         { | 
| 1715 |         } | 
| 1716 |  | 
| 1717 |         Q_DECL_CONSTEXPR DetectConstructor(const DetectConstructor &) | 
| 1718 |             : constructor(CopyConstructor) | 
| 1719 |         { | 
| 1720 |         } | 
| 1721 |  | 
| 1722 |         Q_DECL_CONSTEXPR DetectConstructor(DetectConstructor &&) | 
| 1723 |             : constructor(MoveConstructor) | 
| 1724 |         { | 
| 1725 |         } | 
| 1726 |  | 
| 1727 |         enum Constructor { | 
| 1728 |             DefaultConstructor, | 
| 1729 |             CopyConstructor, | 
| 1730 |             MoveConstructor | 
| 1731 |         }; | 
| 1732 |  | 
| 1733 |         Constructor constructor; | 
| 1734 |     }; | 
| 1735 |  | 
| 1736 |     struct DetectImplicitMove | 
| 1737 |         : DetectConstructor | 
| 1738 |     { | 
| 1739 |     }; | 
| 1740 | }; | 
| 1741 |  | 
| 1742 | // RValue references need to be supported in the current configuration | 
| 1743 | void tst_QArrayData::rValueReferences() | 
| 1744 | { | 
| 1745 |     if (!CompilerHasCxx11ImplicitMoves::value()) | 
| 1746 |         QSKIP("Implicit move ctor not supported in current configuration" ); | 
| 1747 |  | 
| 1748 |     SimpleVector<int> v1(1, 42); | 
| 1749 |     SimpleVector<int> v2; | 
| 1750 |  | 
| 1751 |     const SimpleVector<int>::const_iterator begin = v1.constBegin(); | 
| 1752 |  | 
| 1753 |     QVERIFY(!v1.isNull()); | 
| 1754 |     QVERIFY(v2.isNull()); | 
| 1755 |  | 
| 1756 |     // move-assign | 
| 1757 |     v2 = cxx11Move(t&: v1); | 
| 1758 |  | 
| 1759 |     QVERIFY(v1.isNull()); | 
| 1760 |     QVERIFY(!v2.isNull()); | 
| 1761 |     QCOMPARE(v2.constBegin(), begin); | 
| 1762 |  | 
| 1763 |     SimpleVector<int> v3(cxx11Move(t&: v2)); | 
| 1764 |  | 
| 1765 |     QVERIFY(v1.isNull()); | 
| 1766 |     QVERIFY(v2.isNull()); | 
| 1767 |     QVERIFY(!v3.isNull()); | 
| 1768 |     QCOMPARE(v3.constBegin(), begin); | 
| 1769 |  | 
| 1770 |     QCOMPARE(v3.size(), size_t(1)); | 
| 1771 |     QCOMPARE(v3.front(), 42); | 
| 1772 | } | 
| 1773 |  | 
| 1774 | void tst_QArrayData::grow() | 
| 1775 | { | 
| 1776 |     SimpleVector<int> vector; | 
| 1777 |  | 
| 1778 |     QCOMPARE(vector.size(), size_t(0)); | 
| 1779 |     QCOMPARE(vector.capacity(), size_t(0)); | 
| 1780 |  | 
| 1781 |     size_t previousCapacity = 0; | 
| 1782 |     size_t allocations = 0; | 
| 1783 |     for (size_t i = 1; i < (1 << 20); ++i) { | 
| 1784 |         int source[1] = { int(i) }; | 
| 1785 |         vector.append(first: source, last: source + 1); | 
| 1786 |         QCOMPARE(vector.size(), i); | 
| 1787 |         if (vector.capacity() != previousCapacity) { | 
| 1788 |             // Don't re-allocate until necessary | 
| 1789 |             QVERIFY(previousCapacity < i); | 
| 1790 |  | 
| 1791 |             previousCapacity = vector.capacity(); | 
| 1792 |             ++allocations; | 
| 1793 |  | 
| 1794 |             // Going element-wise is slow under valgrind | 
| 1795 |             if (previousCapacity - i > 10) { | 
| 1796 |                 i = previousCapacity - 5; | 
| 1797 |                 vector.back() = -int(i); | 
| 1798 |                 vector.resize(newSize: i); | 
| 1799 |  | 
| 1800 |                 // It's still not the time to re-allocate | 
| 1801 |                 QCOMPARE(vector.capacity(), previousCapacity); | 
| 1802 |             } | 
| 1803 |         } | 
| 1804 |     } | 
| 1805 |     QVERIFY(vector.size() >= size_t(1 << 20)); | 
| 1806 |  | 
| 1807 |     // QArrayData::Grow prevents excessive allocations on a growing container | 
| 1808 |     QVERIFY(allocations > 20 / 2); | 
| 1809 |     QVERIFY(allocations < 20 * 2); | 
| 1810 |  | 
| 1811 |     for (size_t i = 0; i < vector.size(); ++i) { | 
| 1812 |         int value = const_(t: vector).at(i); | 
| 1813 |         if (value < 0) { | 
| 1814 |             i = -value; | 
| 1815 |             continue; | 
| 1816 |         } | 
| 1817 |  | 
| 1818 |         QCOMPARE(value, int(i + 1)); | 
| 1819 |     } | 
| 1820 | } | 
| 1821 |  | 
| 1822 | QTEST_APPLESS_MAIN(tst_QArrayData) | 
| 1823 | #include "tst_qarraydata.moc" | 
| 1824 |  |