Add Missing Debug Operator Declaration for QTouchEvent::TouchPoint
[qt:qt.git] / tests / auto / qscriptvalueiterator / tst_qscriptvalueiterator.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #include <QtScript/qscriptengine.h>
46 #include <QtScript/qscriptvalueiterator.h>
47
48 //TESTED_CLASS=
49 //TESTED_FILES=
50
51 Q_DECLARE_METATYPE(QScriptValue);
52
53 class tst_QScriptValueIterator : public QObject
54 {
55     Q_OBJECT
56
57 public:
58     tst_QScriptValueIterator();
59     virtual ~tst_QScriptValueIterator();
60
61 private slots:
62     void iterateForward_data();
63     void iterateForward();
64     void iterateBackward_data();
65     void iterateBackward();
66     void iterateArray_data();
67     void iterateArray();
68     void iterateBackAndForth();
69     void setValue();
70     void remove();
71     void iterateString();
72     void iterateGetterSetter();
73     void assignObjectToIterator();
74     void iterateNonObject();
75     void iterateOverObjectFromDeletedEngine();
76 };
77
78 tst_QScriptValueIterator::tst_QScriptValueIterator()
79 {
80 }
81
82 tst_QScriptValueIterator::~tst_QScriptValueIterator()
83 {
84 }
85
86 void tst_QScriptValueIterator::iterateForward_data()
87 {
88     QTest::addColumn<QStringList>("propertyNames");
89     QTest::addColumn<QStringList>("propertyValues");
90
91     QTest::newRow("no properties")
92         << QStringList() << QStringList();
93     QTest::newRow("foo=bar")
94         << (QStringList() << "foo")
95         << (QStringList() << "bar");
96     QTest::newRow("foo=bar, baz=123")
97         << (QStringList() << "foo" << "baz")
98         << (QStringList() << "bar" << "123");
99     QTest::newRow("foo=bar, baz=123, rab=oof")
100         << (QStringList() << "foo" << "baz" << "rab")
101         << (QStringList() << "bar" << "123" << "oof");
102 }
103
104 void tst_QScriptValueIterator::iterateForward()
105 {
106     QFETCH(QStringList, propertyNames);
107     QFETCH(QStringList, propertyValues);
108     QMap<QString, QString> pmap;
109     QVERIFY(propertyNames.size() == propertyValues.size());
110
111     QScriptEngine engine;
112     QScriptValue object = engine.newObject();
113     for (int i = 0; i < propertyNames.size(); ++i) {
114         QString name = propertyNames.at(i);
115         QString value = propertyValues.at(i);
116         pmap.insert(name, value);
117         object.setProperty(name, QScriptValue(&engine, value));
118     }
119     QScriptValue otherObject = engine.newObject();
120     otherObject.setProperty("foo", QScriptValue(&engine, 123456));
121     otherObject.setProperty("protoProperty", QScriptValue(&engine, 654321));
122     object.setPrototype(otherObject); // should not affect iterator
123
124     QStringList lst;
125     QScriptValueIterator it(object);
126     while (!pmap.isEmpty()) {
127         QCOMPARE(it.hasNext(), true);
128         QCOMPARE(it.hasNext(), true);
129         it.next();
130         QString name = it.name();
131         QCOMPARE(pmap.contains(name), true);
132         QCOMPARE(it.name(), name);
133         QCOMPARE(it.flags(), object.propertyFlags(name));
134         QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true);
135         QCOMPARE(it.scriptName(), engine.toStringHandle(name));
136         pmap.remove(name);
137         lst.append(name);
138     }
139
140     QCOMPARE(it.hasNext(), false);
141     QCOMPARE(it.hasNext(), false);
142
143     it.toFront();
144     for (int i = 0; i < lst.count(); ++i) {
145         QCOMPARE(it.hasNext(), true);
146         it.next();
147         QCOMPARE(it.name(), lst.at(i));
148     }
149
150     for (int i = 0; i < lst.count(); ++i) {
151         QCOMPARE(it.hasPrevious(), true);
152         it.previous();
153         QCOMPARE(it.name(), lst.at(lst.count()-1-i));
154     }
155     QCOMPARE(it.hasPrevious(), false);
156 }
157
158 void tst_QScriptValueIterator::iterateBackward_data()
159 {
160     iterateForward_data();
161 }
162
163 void tst_QScriptValueIterator::iterateBackward()
164 {
165     QFETCH(QStringList, propertyNames);
166     QFETCH(QStringList, propertyValues);
167     QMap<QString, QString> pmap;
168     QVERIFY(propertyNames.size() == propertyValues.size());
169
170     QScriptEngine engine;
171     QScriptValue object = engine.newObject();
172     for (int i = 0; i < propertyNames.size(); ++i) {
173         QString name = propertyNames.at(i);
174         QString value = propertyValues.at(i);
175         pmap.insert(name, value);
176         object.setProperty(name, QScriptValue(&engine, value));
177     }
178
179     QStringList lst;
180     QScriptValueIterator it(object);
181     it.toBack();
182     while (!pmap.isEmpty()) {
183         QCOMPARE(it.hasPrevious(), true);
184         QCOMPARE(it.hasPrevious(), true);
185         it.previous();
186         QString name = it.name();
187         QCOMPARE(pmap.contains(name), true);
188         QCOMPARE(it.name(), name);
189         QCOMPARE(it.flags(), object.propertyFlags(name));
190         QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true);
191         pmap.remove(name);
192         lst.append(name);
193     }
194
195     QCOMPARE(it.hasPrevious(), false);
196     QCOMPARE(it.hasPrevious(), false);
197
198     it.toBack();
199     for (int i = 0; i < lst.count(); ++i) {
200         QCOMPARE(it.hasPrevious(), true);
201         it.previous();
202         QCOMPARE(it.name(), lst.at(i));
203     }
204
205     for (int i = 0; i < lst.count(); ++i) {
206         QCOMPARE(it.hasNext(), true);
207         it.next();
208         QCOMPARE(it.name(), lst.at(lst.count()-1-i));
209     }
210     QCOMPARE(it.hasNext(), false);
211 }
212
213 void tst_QScriptValueIterator::iterateArray_data()
214 {
215     QTest::addColumn<QStringList>("propertyNames");
216     QTest::addColumn<QStringList>("propertyValues");
217
218     QTest::newRow("no elements") << QStringList() << QStringList();
219
220     QTest::newRow("0=foo, 1=barr")
221         << (QStringList() << "0" << "1")
222         << (QStringList() << "foo" << "bar");
223
224
225     QTest::newRow("0=foo, 3=barr")
226         << (QStringList() << "0" << "1" << "2" << "3")
227         << (QStringList() << "foo" << "" << "" << "bar");
228 }
229
230 void tst_QScriptValueIterator::iterateArray()
231 {
232     QFETCH(QStringList, propertyNames);
233     QFETCH(QStringList, propertyValues);
234
235     QScriptEngine engine;
236     QScriptValue array = engine.newArray();
237
238     // Fill the array
239     for (int i = 0; i < propertyNames.size(); ++i) {
240         array.setProperty(propertyNames.at(i), propertyValues.at(i));
241     }
242
243     // Iterate thru array properties. Note that the QScriptValueIterator doesn't guarantee
244     // any order on the iteration!
245     int length = array.property("length").toInt32();
246     QCOMPARE(length, propertyNames.size());
247
248     bool iteratedThruLength = false;
249     QHash<QString, QScriptValue> arrayProperties;
250     QScriptValueIterator it(array);
251
252     // Iterate forward
253     while (it.hasNext()) {
254         it.next();
255
256         const QString name = it.name();
257         if (name == QString::fromLatin1("length")) {
258             QVERIFY(it.value().isNumber());
259             QCOMPARE(it.value().toInt32(), length);
260             QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
261             QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration.");
262             iteratedThruLength = true;
263             continue;
264         }
265
266         // Storing the properties we iterate in a hash to compare with test data.
267         QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration.");
268         arrayProperties.insert(name, it.value());
269         QCOMPARE(it.flags(), array.propertyFlags(name));
270         QVERIFY(it.value().strictlyEquals(array.property(name)));
271     }
272
273     // Verify properties
274     QVERIFY(iteratedThruLength);
275     QCOMPARE(arrayProperties.size(), propertyNames.size());
276     for (int i = 0; i < propertyNames.size(); ++i) {
277         QVERIFY(arrayProperties.contains(propertyNames.at(i)));
278         QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i));
279     }
280
281     // Iterate backwards
282     arrayProperties.clear();
283     iteratedThruLength = false;
284     it.toBack();
285
286     while (it.hasPrevious()) {
287         it.previous();
288
289         const QString name = it.name();
290         if (name == QString::fromLatin1("length")) {
291             QVERIFY(it.value().isNumber());
292             QCOMPARE(it.value().toInt32(), length);
293             QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
294             QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration.");
295             iteratedThruLength = true;
296             continue;
297         }
298
299         // Storing the properties we iterate in a hash to compare with test data.
300         QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration.");
301         arrayProperties.insert(name, it.value());
302         QCOMPARE(it.flags(), array.propertyFlags(name));
303         QVERIFY(it.value().strictlyEquals(array.property(name)));
304     }
305
306     // Verify properties
307     QVERIFY(iteratedThruLength);
308     QCOMPARE(arrayProperties.size(), propertyNames.size());
309     for (int i = 0; i < propertyNames.size(); ++i) {
310         QVERIFY(arrayProperties.contains(propertyNames.at(i)));
311         QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i));
312     }
313
314     // ### Do we still need this test?
315     // Forward test again but as object
316     arrayProperties.clear();
317     iteratedThruLength = false;
318     QScriptValue arrayObject = engine.toObject(array);
319     QScriptValueIterator it2(arrayObject);
320
321     while (it2.hasNext()) {
322         it2.next();
323
324         const QString name = it2.name();
325         if (name == QString::fromLatin1("length")) {
326             QVERIFY(it2.value().isNumber());
327             QCOMPARE(it2.value().toInt32(), length);
328             QCOMPARE(it2.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
329             QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration.");
330             iteratedThruLength = true;
331             continue;
332         }
333
334         // Storing the properties we iterate in a hash to compare with test data.
335         QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration.");
336         arrayProperties.insert(name, it2.value());
337         QCOMPARE(it2.flags(), arrayObject.propertyFlags(name));
338         QVERIFY(it2.value().strictlyEquals(arrayObject.property(name)));
339     }
340
341     // Verify properties
342     QVERIFY(iteratedThruLength);
343     QCOMPARE(arrayProperties.size(), propertyNames.size());
344     for (int i = 0; i < propertyNames.size(); ++i) {
345         QVERIFY(arrayProperties.contains(propertyNames.at(i)));
346         QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i));
347     }
348 }
349
350 void tst_QScriptValueIterator::iterateBackAndForth()
351 {
352     QScriptEngine engine;
353     {
354         QScriptValue object = engine.newObject();
355         object.setProperty("foo", QScriptValue(&engine, "bar"));
356         object.setProperty("rab", QScriptValue(&engine, "oof"),
357                            QScriptValue::SkipInEnumeration); // should not affect iterator
358         QScriptValueIterator it(object);
359         QVERIFY(it.hasNext());
360         it.next();
361         QCOMPARE(it.name(), QLatin1String("foo"));
362         QVERIFY(it.hasPrevious());
363         it.previous();
364         QCOMPARE(it.name(), QLatin1String("foo"));
365         QVERIFY(it.hasNext());
366         it.next();
367         QCOMPARE(it.name(), QLatin1String("foo"));
368         QVERIFY(it.hasPrevious());
369         it.previous();
370         QCOMPARE(it.name(), QLatin1String("foo"));
371         QVERIFY(it.hasNext());
372         it.next();
373         QCOMPARE(it.name(), QLatin1String("foo"));
374         QVERIFY(it.hasNext());
375         it.next();
376         QCOMPARE(it.name(), QLatin1String("rab"));
377         QVERIFY(it.hasPrevious());
378         it.previous();
379         QCOMPARE(it.name(), QLatin1String("rab"));
380         QVERIFY(it.hasNext());
381         it.next();
382         QCOMPARE(it.name(), QLatin1String("rab"));
383         QVERIFY(it.hasPrevious());
384         it.previous();
385         QCOMPARE(it.name(), QLatin1String("rab"));
386     }
387     {
388         // hasNext() and hasPrevious() cache their result; verify that the result is in sync
389         QScriptValue object = engine.newObject();
390         object.setProperty("foo", QScriptValue(&engine, "bar"));
391         object.setProperty("rab", QScriptValue(&engine, "oof"));
392         QScriptValueIterator it(object);
393         QVERIFY(it.hasNext());
394         it.next();
395         QCOMPARE(it.name(), QString::fromLatin1("foo"));
396         QVERIFY(it.hasNext());
397         it.previous();
398         QCOMPARE(it.name(), QString::fromLatin1("foo"));
399         QVERIFY(!it.hasPrevious());
400         it.next();
401         QCOMPARE(it.name(), QString::fromLatin1("foo"));
402         QVERIFY(it.hasPrevious());
403         it.next();
404         QCOMPARE(it.name(), QString::fromLatin1("rab"));
405     }
406 }
407
408 void tst_QScriptValueIterator::setValue()
409 {
410     QScriptEngine engine;
411     QScriptValue object = engine.newObject();
412     object.setProperty("foo", QScriptValue(&engine, "bar"));
413     QScriptValueIterator it(object);
414     it.next();
415     QCOMPARE(it.name(), QLatin1String("foo"));
416     it.setValue(QScriptValue(&engine, "baz"));
417     QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("baz"))), true);
418     QCOMPARE(object.property("foo").toString(), QLatin1String("baz"));
419     it.setValue(QScriptValue(&engine, "zab"));
420     QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("zab"))), true);
421     QCOMPARE(object.property("foo").toString(), QLatin1String("zab"));
422 }
423
424 void tst_QScriptValueIterator::remove()
425 {
426     QScriptEngine engine;
427     QScriptValue object = engine.newObject();
428     object.setProperty("foo", QScriptValue(&engine, "bar"),
429                        QScriptValue::SkipInEnumeration); // should not affect iterator
430     object.setProperty("rab", QScriptValue(&engine, "oof"));
431     QScriptValueIterator it(object);
432     it.next();
433     QCOMPARE(it.name(), QLatin1String("foo"));
434     it.remove();
435     QCOMPARE(it.hasPrevious(), false);
436     QCOMPARE(object.property("foo").isValid(), false);
437     QCOMPARE(object.property("rab").toString(), QLatin1String("oof"));
438     it.next();
439     QCOMPARE(it.name(), QLatin1String("rab"));
440     QCOMPARE(it.value().toString(), QLatin1String("oof"));
441     QCOMPARE(it.hasNext(), false);
442     it.remove();
443     QCOMPARE(object.property("rab").isValid(), false);
444     QCOMPARE(it.hasPrevious(), false);
445     QCOMPARE(it.hasNext(), false);
446 }
447
448 void tst_QScriptValueIterator::iterateString()
449 {
450     QScriptEngine engine;
451     QScriptValue str = QScriptValue(&engine, QString::fromLatin1("ciao"));
452     QVERIFY(str.isString());
453     QScriptValue obj = str.toObject();
454     QVERIFY(obj.property("length").isNumber());
455     int length = obj.property("length").toInt32();
456     QCOMPARE(length, 4);
457
458     QScriptValueIterator it(obj);
459     QHash<QString, QScriptValue> stringProperties;
460     bool iteratedThruLength = false;
461
462     while (it.hasNext()) {
463         it.next();
464         const QString name = it.name();
465
466         if (name == QString::fromLatin1("length")) {
467             QVERIFY(it.value().isNumber());
468             QCOMPARE(it.value().toInt32(), length);
469             QCOMPARE(it.flags(), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
470             QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration.");
471             iteratedThruLength = true;
472             continue;
473         }
474
475         QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration.");
476         stringProperties.insert(name, it.value());
477         QCOMPARE(it.flags(), obj.propertyFlags(name));
478         QVERIFY(it.value().strictlyEquals(obj.property(name)));
479     }
480
481     QVERIFY(iteratedThruLength);
482     QCOMPARE(stringProperties.size(), length);
483
484     // And going backwards
485     iteratedThruLength = false;
486     stringProperties.clear();
487     it.toBack();
488
489     while (it.hasPrevious()) {
490         it.previous();
491         const QString name = it.name();
492
493         if (name == QString::fromLatin1("length")) {
494             QVERIFY(it.value().isNumber());
495             QCOMPARE(it.value().toInt32(), length);
496             QCOMPARE(it.flags(), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
497             QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration.");
498             iteratedThruLength = true;
499             continue;
500         }
501
502         QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration.");
503         stringProperties.insert(name, it.value());
504         QCOMPARE(it.flags(), obj.propertyFlags(name));
505         QVERIFY(it.value().strictlyEquals(obj.property(name)));
506     }
507 }
508
509 static QScriptValue myGetterSetter(QScriptContext *ctx, QScriptEngine *)
510 {
511     if (ctx->argumentCount() == 1)
512         ctx->thisObject().setProperty("bar", ctx->argument(0));
513     return ctx->thisObject().property("bar");
514 }
515
516 static QScriptValue myGetter(QScriptContext *ctx, QScriptEngine *)
517 {
518     return ctx->thisObject().property("bar");
519 }
520
521 static QScriptValue mySetter(QScriptContext *ctx, QScriptEngine *)
522 {
523     ctx->thisObject().setProperty("bar", ctx->argument(0));
524     return ctx->argument(0);
525 }
526
527 void tst_QScriptValueIterator::iterateGetterSetter()
528 {
529     // unified getter/setter function
530     {
531         QScriptEngine eng;
532         QScriptValue obj = eng.newObject();
533         obj.setProperty("foo", eng.newFunction(myGetterSetter),
534                         QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
535         QScriptValue val(&eng, 123);
536         obj.setProperty("foo", val);
537         QVERIFY(obj.property("bar").strictlyEquals(val));
538         QVERIFY(obj.property("foo").strictlyEquals(val));
539
540         QScriptValueIterator it(obj);
541         QVERIFY(it.hasNext());
542         it.next();
543         QCOMPARE(it.name(), QString::fromLatin1("foo"));
544         QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter));
545         QVERIFY(it.value().strictlyEquals(val));
546         QScriptValue val2(&eng, 456);
547         it.setValue(val2);
548         QVERIFY(obj.property("bar").strictlyEquals(val2));
549         QVERIFY(obj.property("foo").strictlyEquals(val2));
550
551         QVERIFY(it.hasNext());
552         it.next();
553         QCOMPARE(it.name(), QString::fromLatin1("bar"));
554         QVERIFY(!it.hasNext());
555
556         QVERIFY(it.hasPrevious());
557         it.previous();
558         QCOMPARE(it.name(), QString::fromLatin1("bar"));
559         QVERIFY(it.hasPrevious());
560         it.previous();
561         QCOMPARE(it.name(), QString::fromLatin1("foo"));
562         QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter));
563         QVERIFY(it.value().strictlyEquals(val2));
564         it.setValue(val);
565         QVERIFY(obj.property("bar").strictlyEquals(val));
566         QVERIFY(obj.property("foo").strictlyEquals(val));
567     }
568     // separate getter/setter function
569     for (int x = 0; x < 2; ++x) {
570         QScriptEngine eng;
571         QScriptValue obj = eng.newObject();
572         if (x == 0) {
573             obj.setProperty("foo", eng.newFunction(myGetter), QScriptValue::PropertyGetter);
574             obj.setProperty("foo", eng.newFunction(mySetter), QScriptValue::PropertySetter);
575         } else {
576             obj.setProperty("foo", eng.newFunction(mySetter), QScriptValue::PropertySetter);
577             obj.setProperty("foo", eng.newFunction(myGetter), QScriptValue::PropertyGetter);
578         }
579         QScriptValue val(&eng, 123);
580         obj.setProperty("foo", val);
581         QVERIFY(obj.property("bar").strictlyEquals(val));
582         QVERIFY(obj.property("foo").strictlyEquals(val));
583
584         QScriptValueIterator it(obj);
585         QVERIFY(it.hasNext());
586         it.next();
587         QCOMPARE(it.name(), QString::fromLatin1("foo"));
588         QVERIFY(it.value().strictlyEquals(val));
589         QScriptValue val2(&eng, 456);
590         it.setValue(val2);
591         QVERIFY(obj.property("bar").strictlyEquals(val2));
592         QVERIFY(obj.property("foo").strictlyEquals(val2));
593
594         QVERIFY(it.hasNext());
595         it.next();
596         QCOMPARE(it.name(), QString::fromLatin1("bar"));
597         QVERIFY(!it.hasNext());
598
599         QVERIFY(it.hasPrevious());
600         it.previous();
601         QCOMPARE(it.name(), QString::fromLatin1("bar"));
602         QVERIFY(it.hasPrevious());
603         it.previous();
604         QCOMPARE(it.name(), QString::fromLatin1("foo"));
605         QVERIFY(it.value().strictlyEquals(val2));
606         it.setValue(val);
607         QVERIFY(obj.property("bar").strictlyEquals(val));
608         QVERIFY(obj.property("foo").strictlyEquals(val));
609     }
610 }
611
612 void tst_QScriptValueIterator::assignObjectToIterator()
613 {
614     QScriptEngine eng;
615     QScriptValue obj1 = eng.newObject();
616     obj1.setProperty("foo", 123);
617     QScriptValue obj2 = eng.newObject();
618     obj2.setProperty("bar", 456);
619
620     QScriptValueIterator it(obj1);
621     QVERIFY(it.hasNext());
622     it.next();
623     it = obj2;
624     QVERIFY(it.hasNext());
625     it.next();
626     QCOMPARE(it.name(), QString::fromLatin1("bar"));
627
628     it = obj1;
629     QVERIFY(it.hasNext());
630     it.next();
631     QCOMPARE(it.name(), QString::fromLatin1("foo"));
632
633     it = obj2;
634     QVERIFY(it.hasNext());
635     it.next();
636     QCOMPARE(it.name(), QString::fromLatin1("bar"));
637
638     it = obj2;
639     QVERIFY(it.hasNext());
640     it.next();
641     QCOMPARE(it.name(), QString::fromLatin1("bar"));
642 }
643
644 void tst_QScriptValueIterator::iterateNonObject()
645 {
646     QScriptValueIterator it(123);
647     QVERIFY(!it.hasNext());
648     it.next();
649     QVERIFY(!it.hasPrevious());
650     it.previous();
651     it.toFront();
652     it.toBack();
653     it.name();
654     it.scriptName();
655     it.flags();
656     it.value();
657     it.setValue(1);
658     it.remove();
659     QScriptValue num(5);
660     it = num;
661     QVERIFY(!it.hasNext());
662 }
663
664 void tst_QScriptValueIterator::iterateOverObjectFromDeletedEngine()
665 {
666     QScriptEngine *engine = new QScriptEngine;
667     QScriptValue objet = engine->newObject();
668
669     // populate object with properties
670     QHash<QString, int> properties;
671     properties.insert("foo",1235);
672     properties.insert("oof",5321);
673     properties.insert("ofo",3521);
674     QHash<QString, int>::const_iterator i = properties.constBegin();
675     for(; i != properties.constEnd(); ++i) {
676         objet.setProperty(i.key(), i.value());
677     }
678
679     // start iterating
680     QScriptValueIterator it(objet);
681     it.next();
682     QVERIFY(properties.contains(it.name()));
683
684     delete engine;
685
686     QVERIFY(!objet.isValid());
687     QVERIFY(it.name().isEmpty());
688     QVERIFY(!it.value().isValid());
689
690     QVERIFY(!it.hasNext());
691     it.next();
692
693     QVERIFY(it.name().isEmpty());
694     QVERIFY(!it.scriptName().isValid());
695     QVERIFY(!it.value().isValid());
696     it.setValue("1234567");
697     it.remove();
698
699     QVERIFY(!it.hasPrevious());
700     it.previous();
701
702     QVERIFY(it.name().isEmpty());
703     QVERIFY(!it.scriptName().isValid());
704     QVERIFY(!it.value().isValid());
705     it.setValue("1234567");
706     it.remove();
707 }
708
709 QTEST_MAIN(tst_QScriptValueIterator)
710 #include "tst_qscriptvalueiterator.moc"