| 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 | |
| 32 | #include <QJSEngine> |
| 33 | #include <QJSValue> |
| 34 | #include <QJSValueIterator> |
| 35 | |
| 36 | class tst_QJSValueIterator : public QObject |
| 37 | { |
| 38 | Q_OBJECT |
| 39 | |
| 40 | public: |
| 41 | tst_QJSValueIterator(); |
| 42 | virtual ~tst_QJSValueIterator(); |
| 43 | |
| 44 | private slots: |
| 45 | void iterateForward_data(); |
| 46 | void iterateForward(); |
| 47 | void iterateArray_data(); |
| 48 | void iterateArray(); |
| 49 | void iterateString(); |
| 50 | #if 0 |
| 51 | void iterateGetterSetter(); |
| 52 | #endif |
| 53 | void assignObjectToIterator(); |
| 54 | void iterateNonObject(); |
| 55 | void iterateOverObjectFromDeletedEngine(); |
| 56 | void iterateWithNext(); |
| 57 | }; |
| 58 | |
| 59 | tst_QJSValueIterator::tst_QJSValueIterator() |
| 60 | { |
| 61 | } |
| 62 | |
| 63 | tst_QJSValueIterator::~tst_QJSValueIterator() |
| 64 | { |
| 65 | } |
| 66 | |
| 67 | void tst_QJSValueIterator::iterateForward_data() |
| 68 | { |
| 69 | QTest::addColumn<QStringList>(name: "propertyNames" ); |
| 70 | QTest::addColumn<QStringList>(name: "propertyValues" ); |
| 71 | |
| 72 | QTest::newRow(dataTag: "no properties" ) |
| 73 | << QStringList() << QStringList(); |
| 74 | QTest::newRow(dataTag: "foo=bar" ) |
| 75 | << (QStringList() << "foo" ) |
| 76 | << (QStringList() << "bar" ); |
| 77 | QTest::newRow(dataTag: "foo=bar, baz=123" ) |
| 78 | << (QStringList() << "foo" << "baz" ) |
| 79 | << (QStringList() << "bar" << "123" ); |
| 80 | QTest::newRow(dataTag: "foo=bar, baz=123, rab=oof" ) |
| 81 | << (QStringList() << "foo" << "baz" << "rab" ) |
| 82 | << (QStringList() << "bar" << "123" << "oof" ); |
| 83 | } |
| 84 | |
| 85 | void tst_QJSValueIterator::iterateForward() |
| 86 | { |
| 87 | QFETCH(QStringList, propertyNames); |
| 88 | QFETCH(QStringList, propertyValues); |
| 89 | QMap<QString, QString> pmap; |
| 90 | QCOMPARE(propertyNames.size(), propertyValues.size()); |
| 91 | |
| 92 | QJSEngine engine; |
| 93 | QJSValue object = engine.newObject(); |
| 94 | for (int i = 0; i < propertyNames.size(); ++i) { |
| 95 | QString name = propertyNames.at(i); |
| 96 | QString value = propertyValues.at(i); |
| 97 | pmap.insert(akey: name, avalue: value); |
| 98 | object.setProperty(name, value: engine.toScriptValue(value)); |
| 99 | } |
| 100 | QJSValue otherObject = engine.newObject(); |
| 101 | otherObject.setProperty(name: "foo" , value: engine.toScriptValue(value: 123456)); |
| 102 | otherObject.setProperty(name: "protoProperty" , value: engine.toScriptValue(value: 654321)); |
| 103 | object.setPrototype(otherObject); // should not affect iterator |
| 104 | |
| 105 | QStringList lst; |
| 106 | QJSValueIterator it(object); |
| 107 | while (!pmap.isEmpty()) { |
| 108 | QCOMPARE(it.hasNext(), true); |
| 109 | QCOMPARE(it.hasNext(), true); |
| 110 | it.next(); |
| 111 | QString name = it.name(); |
| 112 | QCOMPARE(pmap.contains(name), true); |
| 113 | QCOMPARE(it.name(), name); |
| 114 | QCOMPARE(it.value().strictlyEquals(engine.toScriptValue(pmap.value(name))), true); |
| 115 | pmap.remove(akey: name); |
| 116 | lst.append(t: name); |
| 117 | } |
| 118 | |
| 119 | QCOMPARE(it.hasNext(), false); |
| 120 | QCOMPARE(it.hasNext(), false); |
| 121 | |
| 122 | it = object; |
| 123 | for (int i = 0; i < lst.count(); ++i) { |
| 124 | QCOMPARE(it.hasNext(), true); |
| 125 | it.next(); |
| 126 | QCOMPARE(it.name(), lst.at(i)); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | void tst_QJSValueIterator::iterateArray_data() |
| 131 | { |
| 132 | QTest::addColumn<QStringList>(name: "propertyNames" ); |
| 133 | QTest::addColumn<QStringList>(name: "propertyValues" ); |
| 134 | |
| 135 | QTest::newRow(dataTag: "no elements" ) << QStringList() << QStringList(); |
| 136 | |
| 137 | QTest::newRow(dataTag: "0=foo, 1=barr" ) |
| 138 | << (QStringList() << "0" << "1" ) |
| 139 | << (QStringList() << "foo" << "bar" ); |
| 140 | |
| 141 | |
| 142 | QTest::newRow(dataTag: "0=foo, 3=barr" ) |
| 143 | << (QStringList() << "0" << "1" << "2" << "3" ) |
| 144 | << (QStringList() << "foo" << "" << "" << "bar" ); |
| 145 | } |
| 146 | |
| 147 | void tst_QJSValueIterator::iterateArray() |
| 148 | { |
| 149 | QFETCH(QStringList, propertyNames); |
| 150 | QFETCH(QStringList, propertyValues); |
| 151 | |
| 152 | QJSEngine engine; |
| 153 | QJSValue array = engine.newArray(); |
| 154 | |
| 155 | // Fill the array |
| 156 | for (int i = 0; i < propertyNames.size(); ++i) { |
| 157 | array.setProperty(name: propertyNames.at(i), value: propertyValues.at(i)); |
| 158 | } |
| 159 | |
| 160 | // Iterate thru array properties. Note that the QJSValueIterator doesn't guarantee |
| 161 | // any order on the iteration! |
| 162 | int length = array.property(name: "length" ).toInt(); |
| 163 | QCOMPARE(length, propertyNames.size()); |
| 164 | |
| 165 | bool iteratedThruLength = false; |
| 166 | QHash<QString, QJSValue> arrayProperties; |
| 167 | QJSValueIterator it(array); |
| 168 | |
| 169 | // Iterate forward |
| 170 | while (it.hasNext()) { |
| 171 | it.next(); |
| 172 | |
| 173 | const QString name = it.name(); |
| 174 | if (name == QString::fromLatin1(str: "length" )) { |
| 175 | QVERIFY(it.value().isNumber()); |
| 176 | QCOMPARE(it.value().toInt(), length); |
| 177 | QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration." ); |
| 178 | iteratedThruLength = true; |
| 179 | continue; |
| 180 | } |
| 181 | |
| 182 | // Storing the properties we iterate in a hash to compare with test data. |
| 183 | QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration." ); |
| 184 | arrayProperties.insert(akey: name, avalue: it.value()); |
| 185 | QVERIFY(it.value().strictlyEquals(array.property(name))); |
| 186 | } |
| 187 | |
| 188 | // Verify properties |
| 189 | QVERIFY(iteratedThruLength); |
| 190 | QCOMPARE(arrayProperties.size(), propertyNames.size()); |
| 191 | for (int i = 0; i < propertyNames.size(); ++i) { |
| 192 | QVERIFY(arrayProperties.contains(propertyNames.at(i))); |
| 193 | QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); |
| 194 | } |
| 195 | |
| 196 | #if 0 |
| 197 | |
| 198 | // Iterate backwards |
| 199 | arrayProperties.clear(); |
| 200 | iteratedThruLength = false; |
| 201 | it.toBack(); |
| 202 | |
| 203 | while (it.hasPrevious()) { |
| 204 | it.previous(); |
| 205 | |
| 206 | const QString name = it.name(); |
| 207 | if (name == QString::fromLatin1("length" )) { |
| 208 | QVERIFY(it.value().isNumber()); |
| 209 | QCOMPARE(it.value().toInt(), length); |
| 210 | QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); |
| 211 | QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration." ); |
| 212 | iteratedThruLength = true; |
| 213 | continue; |
| 214 | } |
| 215 | |
| 216 | // Storing the properties we iterate in a hash to compare with test data. |
| 217 | QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration." ); |
| 218 | arrayProperties.insert(name, it.value()); |
| 219 | QCOMPARE(it.flags(), array.propertyFlags(name)); |
| 220 | QVERIFY(it.value().strictlyEquals(array.property(name))); |
| 221 | } |
| 222 | |
| 223 | // Verify properties |
| 224 | QVERIFY(iteratedThruLength); |
| 225 | QCOMPARE(arrayProperties.size(), propertyNames.size()); |
| 226 | for (int i = 0; i < propertyNames.size(); ++i) { |
| 227 | QVERIFY(arrayProperties.contains(propertyNames.at(i))); |
| 228 | QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); |
| 229 | } |
| 230 | |
| 231 | // ### Do we still need this test? |
| 232 | // Forward test again but as object |
| 233 | arrayProperties.clear(); |
| 234 | iteratedThruLength = false; |
| 235 | QJSValue arrayObject = engine.toObject(array); |
| 236 | QJSValueIterator it2(arrayObject); |
| 237 | |
| 238 | while (it2.hasNext()) { |
| 239 | it2.next(); |
| 240 | |
| 241 | const QString name = it2.name(); |
| 242 | if (name == QString::fromLatin1("length" )) { |
| 243 | QVERIFY(it2.value().isNumber()); |
| 244 | QCOMPARE(it2.value().toInt(), length); |
| 245 | QCOMPARE(it2.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); |
| 246 | QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration." ); |
| 247 | iteratedThruLength = true; |
| 248 | continue; |
| 249 | } |
| 250 | |
| 251 | // Storing the properties we iterate in a hash to compare with test data. |
| 252 | QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration." ); |
| 253 | arrayProperties.insert(name, it2.value()); |
| 254 | QCOMPARE(it2.flags(), arrayObject.propertyFlags(name)); |
| 255 | QVERIFY(it2.value().strictlyEquals(arrayObject.property(name))); |
| 256 | } |
| 257 | |
| 258 | // Verify properties |
| 259 | QVERIFY(iteratedThruLength); |
| 260 | QCOMPARE(arrayProperties.size(), propertyNames.size()); |
| 261 | for (int i = 0; i < propertyNames.size(); ++i) { |
| 262 | QVERIFY(arrayProperties.contains(propertyNames.at(i))); |
| 263 | QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); |
| 264 | } |
| 265 | #endif |
| 266 | } |
| 267 | |
| 268 | void tst_QJSValueIterator::iterateString() |
| 269 | { |
| 270 | QJSEngine engine; |
| 271 | QJSValue obj = engine.evaluate(program: "new String('ciao')" ); |
| 272 | QVERIFY(obj.property("length" ).isNumber()); |
| 273 | int length = obj.property(name: "length" ).toInt(); |
| 274 | QCOMPARE(length, 4); |
| 275 | |
| 276 | QJSValueIterator it(obj); |
| 277 | QHash<QString, QJSValue> stringProperties; |
| 278 | bool iteratedThruLength = false; |
| 279 | |
| 280 | while (it.hasNext()) { |
| 281 | it.next(); |
| 282 | const QString name = it.name(); |
| 283 | |
| 284 | if (name == QString::fromLatin1(str: "length" )) { |
| 285 | QVERIFY(it.value().isNumber()); |
| 286 | QCOMPARE(it.value().toInt(), length); |
| 287 | QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration." ); |
| 288 | iteratedThruLength = true; |
| 289 | continue; |
| 290 | } |
| 291 | |
| 292 | QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration." ); |
| 293 | stringProperties.insert(akey: name, avalue: it.value()); |
| 294 | QVERIFY(it.value().strictlyEquals(obj.property(name))); |
| 295 | } |
| 296 | |
| 297 | QVERIFY(iteratedThruLength); |
| 298 | QCOMPARE(stringProperties.size(), length); |
| 299 | #if 0 |
| 300 | // And going backwards |
| 301 | iteratedThruLength = false; |
| 302 | stringProperties.clear(); |
| 303 | it.toBack(); |
| 304 | |
| 305 | while (it.hasPrevious()) { |
| 306 | it.previous(); |
| 307 | const QString name = it.name(); |
| 308 | |
| 309 | if (name == QString::fromLatin1("length" )) { |
| 310 | QVERIFY(it.value().isNumber()); |
| 311 | QCOMPARE(it.value().toInt(), length); |
| 312 | QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration." ); |
| 313 | iteratedThruLength = true; |
| 314 | continue; |
| 315 | } |
| 316 | |
| 317 | QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration." ); |
| 318 | stringProperties.insert(name, it.value()); |
| 319 | QVERIFY(it.value().strictlyEquals(obj.property(name))); |
| 320 | } |
| 321 | #endif |
| 322 | } |
| 323 | |
| 324 | #if 0 // FIXME what we should to keep from here? |
| 325 | static QJSValue myGetterSetter(QScriptContext *ctx, QJSEngine *) |
| 326 | { |
| 327 | if (ctx->argumentCount() == 1) |
| 328 | ctx->thisObject().setProperty("bar" , ctx->argument(0)); |
| 329 | return ctx->thisObject().property("bar" ); |
| 330 | } |
| 331 | |
| 332 | static QJSValue myGetter(QScriptContext *ctx, QJSEngine *) |
| 333 | { |
| 334 | return ctx->thisObject().property("bar" ); |
| 335 | } |
| 336 | |
| 337 | static QJSValue mySetter(QScriptContext *ctx, QJSEngine *) |
| 338 | { |
| 339 | ctx->thisObject().setProperty("bar" , ctx->argument(0)); |
| 340 | return ctx->argument(0); |
| 341 | } |
| 342 | |
| 343 | void tst_QJSValueIterator::iterateGetterSetter() |
| 344 | { |
| 345 | // unified getter/setter function |
| 346 | { |
| 347 | QJSEngine eng; |
| 348 | QJSValue obj = eng.newObject(); |
| 349 | obj.setProperty("foo" , eng.newFunction(myGetterSetter), |
| 350 | QScriptValue::PropertyGetter | QScriptValue::PropertySetter); |
| 351 | QJSValue val(&eng, 123); |
| 352 | obj.setProperty("foo" , val); |
| 353 | QVERIFY(obj.property("bar" ).strictlyEquals(val)); |
| 354 | QVERIFY(obj.property("foo" ).strictlyEquals(val)); |
| 355 | |
| 356 | QJSValueIterator it(obj); |
| 357 | QVERIFY(it.hasNext()); |
| 358 | it.next(); |
| 359 | QCOMPARE(it.name(), QString::fromLatin1("foo" )); |
| 360 | QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter)); |
| 361 | QVERIFY(it.value().strictlyEquals(val)); |
| 362 | QJSValue val2(&eng, 456); |
| 363 | it.setValue(val2); |
| 364 | QVERIFY(obj.property("bar" ).strictlyEquals(val2)); |
| 365 | QVERIFY(obj.property("foo" ).strictlyEquals(val2)); |
| 366 | |
| 367 | QVERIFY(it.hasNext()); |
| 368 | it.next(); |
| 369 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 370 | QVERIFY(!it.hasNext()); |
| 371 | |
| 372 | QVERIFY(it.hasPrevious()); |
| 373 | it.previous(); |
| 374 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 375 | QVERIFY(it.hasPrevious()); |
| 376 | it.previous(); |
| 377 | QCOMPARE(it.name(), QString::fromLatin1("foo" )); |
| 378 | QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter)); |
| 379 | QVERIFY(it.value().strictlyEquals(val2)); |
| 380 | it.setValue(val); |
| 381 | QVERIFY(obj.property("bar" ).strictlyEquals(val)); |
| 382 | QVERIFY(obj.property("foo" ).strictlyEquals(val)); |
| 383 | } |
| 384 | // separate getter/setter function |
| 385 | for (int x = 0; x < 2; ++x) { |
| 386 | QJSEngine eng; |
| 387 | QJSValue obj = eng.newObject(); |
| 388 | if (x == 0) { |
| 389 | obj.setProperty("foo" , eng.newFunction(myGetter), QScriptValue::PropertyGetter); |
| 390 | obj.setProperty("foo" , eng.newFunction(mySetter), QScriptValue::PropertySetter); |
| 391 | } else { |
| 392 | obj.setProperty("foo" , eng.newFunction(mySetter), QScriptValue::PropertySetter); |
| 393 | obj.setProperty("foo" , eng.newFunction(myGetter), QScriptValue::PropertyGetter); |
| 394 | } |
| 395 | QJSValue val(&eng, 123); |
| 396 | obj.setProperty("foo" , val); |
| 397 | QVERIFY(obj.property("bar" ).strictlyEquals(val)); |
| 398 | QVERIFY(obj.property("foo" ).strictlyEquals(val)); |
| 399 | |
| 400 | QJSValueIterator it(obj); |
| 401 | QVERIFY(it.hasNext()); |
| 402 | it.next(); |
| 403 | QCOMPARE(it.name(), QString::fromLatin1("foo" )); |
| 404 | QVERIFY(it.value().strictlyEquals(val)); |
| 405 | QJSValue val2(&eng, 456); |
| 406 | it.setValue(val2); |
| 407 | QVERIFY(obj.property("bar" ).strictlyEquals(val2)); |
| 408 | QVERIFY(obj.property("foo" ).strictlyEquals(val2)); |
| 409 | |
| 410 | QVERIFY(it.hasNext()); |
| 411 | it.next(); |
| 412 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 413 | QVERIFY(!it.hasNext()); |
| 414 | |
| 415 | QVERIFY(it.hasPrevious()); |
| 416 | it.previous(); |
| 417 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 418 | QVERIFY(it.hasPrevious()); |
| 419 | it.previous(); |
| 420 | QCOMPARE(it.name(), QString::fromLatin1("foo" )); |
| 421 | QVERIFY(it.value().strictlyEquals(val2)); |
| 422 | it.setValue(val); |
| 423 | QVERIFY(obj.property("bar" ).strictlyEquals(val)); |
| 424 | QVERIFY(obj.property("foo" ).strictlyEquals(val)); |
| 425 | } |
| 426 | } |
| 427 | #endif |
| 428 | |
| 429 | void tst_QJSValueIterator::assignObjectToIterator() |
| 430 | { |
| 431 | QJSEngine eng; |
| 432 | QJSValue obj1 = eng.newObject(); |
| 433 | obj1.setProperty(name: "foo" , value: 123); |
| 434 | QJSValue obj2 = eng.newObject(); |
| 435 | obj2.setProperty(name: "bar" , value: 456); |
| 436 | |
| 437 | QJSValueIterator it(obj1); |
| 438 | QVERIFY(it.hasNext()); |
| 439 | it.next(); |
| 440 | it = obj2; |
| 441 | QVERIFY(it.hasNext()); |
| 442 | it.next(); |
| 443 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 444 | |
| 445 | it = obj1; |
| 446 | QVERIFY(it.hasNext()); |
| 447 | it.next(); |
| 448 | QCOMPARE(it.name(), QString::fromLatin1("foo" )); |
| 449 | |
| 450 | it = obj2; |
| 451 | QVERIFY(it.hasNext()); |
| 452 | it.next(); |
| 453 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 454 | |
| 455 | it = obj2; |
| 456 | QVERIFY(it.hasNext()); |
| 457 | it.next(); |
| 458 | QCOMPARE(it.name(), QString::fromLatin1("bar" )); |
| 459 | } |
| 460 | |
| 461 | void tst_QJSValueIterator::iterateNonObject() |
| 462 | { |
| 463 | QJSValueIterator it(123); |
| 464 | QVERIFY(!it.hasNext()); |
| 465 | it.next(); |
| 466 | it.name(); |
| 467 | it.value(); |
| 468 | QJSValue num(5); |
| 469 | it = num; |
| 470 | QVERIFY(!it.hasNext()); |
| 471 | } |
| 472 | |
| 473 | void tst_QJSValueIterator::iterateOverObjectFromDeletedEngine() |
| 474 | { |
| 475 | QJSEngine *engine = new QJSEngine; |
| 476 | QJSValue objet = engine->newObject(); |
| 477 | |
| 478 | // populate object with properties |
| 479 | QHash<QString, int> properties; |
| 480 | properties.insert(akey: "foo" ,avalue: 1235); |
| 481 | properties.insert(akey: "oof" ,avalue: 5321); |
| 482 | properties.insert(akey: "ofo" ,avalue: 3521); |
| 483 | QHash<QString, int>::const_iterator i = properties.constBegin(); |
| 484 | for (; i != properties.constEnd(); ++i) { |
| 485 | objet.setProperty(name: i.key(), value: i.value()); |
| 486 | } |
| 487 | |
| 488 | // start iterating |
| 489 | QJSValueIterator it(objet); |
| 490 | it.next(); |
| 491 | QVERIFY(properties.contains(it.name())); |
| 492 | |
| 493 | delete engine; |
| 494 | |
| 495 | QVERIFY(objet.isUndefined()); |
| 496 | QVERIFY(it.name().isEmpty()); |
| 497 | QVERIFY(it.value().isUndefined()); |
| 498 | |
| 499 | QVERIFY(!it.hasNext()); |
| 500 | it.next(); |
| 501 | |
| 502 | QVERIFY(it.name().isEmpty()); |
| 503 | QVERIFY(it.value().isUndefined()); |
| 504 | |
| 505 | } |
| 506 | |
| 507 | void tst_QJSValueIterator::iterateWithNext() |
| 508 | { |
| 509 | QJSEngine engine; |
| 510 | QJSValue value = engine.newObject(); |
| 511 | value.setProperty(name: "one" , value: 1); |
| 512 | value.setProperty(name: "two" , value: 2); |
| 513 | value.setProperty(name: "three" , value: 3); |
| 514 | |
| 515 | QStringList list; |
| 516 | list << QStringLiteral("one" ) << QStringLiteral("three" ) << QStringLiteral("two" ); |
| 517 | |
| 518 | int counter = 0; |
| 519 | QJSValueIterator it(value); |
| 520 | QStringList actualList; |
| 521 | while (it.next()) { |
| 522 | ++counter; |
| 523 | actualList << it.name(); |
| 524 | } |
| 525 | |
| 526 | std::sort(first: actualList.begin(), last: actualList.end()); |
| 527 | |
| 528 | QCOMPARE(counter, 3); |
| 529 | QCOMPARE(list, actualList); |
| 530 | |
| 531 | } |
| 532 | |
| 533 | QTEST_MAIN(tst_QJSValueIterator) |
| 534 | #include "tst_qjsvalueiterator.moc" |
| 535 | |