Fix QScriptValueIterator::hasNext and QScriptValueIterator::hasPrevious
[qt:qt.git] / tests / auto / qscriptvalueiterator / tst_qscriptvalueiterator.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
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     Q_ASSERT(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     Q_ASSERT(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>("inputPropertyNames");
216     QTest::addColumn<QStringList>("inputPropertyValues");
217     QTest::addColumn<QStringList>("propertyNames");
218     QTest::addColumn<QStringList>("propertyValues");
219     QTest::newRow("no elements") << QStringList() << QStringList() << QStringList() << QStringList();
220
221
222     QTest::newRow("0=foo, 1=barr")
223         << (QStringList() << "0" << "1")
224         << (QStringList() << "foo" << "bar")
225         << (QStringList() << "0" << "1")
226         << (QStringList() << "foo" << "bar");
227
228
229     QTest::newRow("0=foo, 3=barr")
230         << (QStringList() << "0" << "1" << "2" << "3")
231         << (QStringList() << "foo" << "" << "" << "bar")
232         << (QStringList() << "0" << "1" << "2" << "3")
233         << (QStringList() << "foo" << "" << "" << "bar");
234 }
235
236 void tst_QScriptValueIterator::iterateArray()
237 {
238     QFETCH(QStringList, inputPropertyNames);
239     QFETCH(QStringList, inputPropertyValues);
240     QFETCH(QStringList, propertyNames);
241     QFETCH(QStringList, propertyValues);
242
243     QScriptEngine engine;
244     QScriptValue array = engine.newArray();
245     for (int i = 0; i < inputPropertyNames.size(); ++i) {
246         array.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i));
247     }
248
249     int length = array.property("length").toInt32();
250     QCOMPARE(length, propertyNames.size());
251     QScriptValueIterator it(array);
252     for (int i = 0; i < length; ++i) {
253         QCOMPARE(it.hasNext(), true);
254         it.next();
255         QCOMPARE(it.name(), propertyNames.at(i));
256         QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
257         QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
258         QCOMPARE(it.value().toString(), propertyValues.at(i));
259     }
260     QVERIFY(it.hasNext());
261     it.next();
262     QCOMPARE(it.name(), QString::fromLatin1("length"));
263     QVERIFY(it.value().isNumber());
264     QCOMPARE(it.value().toInt32(), length);
265     QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
266
267     it.previous();
268     QCOMPARE(it.hasPrevious(), length > 0);
269     for (int i = length - 1; i >= 0; --i) {
270         it.previous();
271         QCOMPARE(it.name(), propertyNames.at(i));
272         QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
273         QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
274         QCOMPARE(it.value().toString(), propertyValues.at(i));
275         QCOMPARE(it.hasPrevious(), i > 0);
276     }
277     QCOMPARE(it.hasPrevious(), false);
278
279     // hasNext() and hasPrevious() cache their result; verify that the result is in sync
280     if (length > 1) {
281         QVERIFY(it.hasNext());
282         it.next();
283         QCOMPARE(it.name(), QString::fromLatin1("0"));
284         QVERIFY(it.hasNext());
285         it.previous();
286         QCOMPARE(it.name(), QString::fromLatin1("0"));
287         QVERIFY(!it.hasPrevious());
288         it.next();
289         QCOMPARE(it.name(), QString::fromLatin1("0"));
290         QVERIFY(it.hasPrevious());
291         it.next();
292         QCOMPARE(it.name(), QString::fromLatin1("1"));
293     }
294     {
295         // same test as object:
296         QScriptValue originalArray = engine.newArray();
297         for (int i = 0; i < inputPropertyNames.size(); ++i) {
298             originalArray.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i));
299         }
300         QScriptValue array = originalArray.toObject();
301         int length = array.property("length").toInt32();
302         QCOMPARE(length, propertyNames.size());
303         QScriptValueIterator it(array);
304         for (int i = 0; i < length; ++i) {
305             QCOMPARE(it.hasNext(), true);
306             it.next();
307             QCOMPARE(it.name(), propertyNames.at(i));
308             QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
309             QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
310             QCOMPARE(it.value().toString(), propertyValues.at(i));
311         }
312         QCOMPARE(it.hasNext(), true);
313         it.next();
314         QCOMPARE(it.name(), QString::fromLatin1("length"));
315     }
316 }
317
318 void tst_QScriptValueIterator::iterateBackAndForth()
319 {
320     QScriptEngine engine;
321     {
322         QScriptValue object = engine.newObject();
323         object.setProperty("foo", QScriptValue(&engine, "bar"));
324         object.setProperty("rab", QScriptValue(&engine, "oof"),
325                            QScriptValue::SkipInEnumeration); // should not affect iterator
326         QScriptValueIterator it(object);
327         QVERIFY(it.hasNext());
328         it.next();
329         QCOMPARE(it.name(), QLatin1String("foo"));
330         QVERIFY(it.hasPrevious());
331         it.previous();
332         QCOMPARE(it.name(), QLatin1String("foo"));
333         QVERIFY(it.hasNext());
334         it.next();
335         QCOMPARE(it.name(), QLatin1String("foo"));
336         QVERIFY(it.hasPrevious());
337         it.previous();
338         QCOMPARE(it.name(), QLatin1String("foo"));
339         QVERIFY(it.hasNext());
340         it.next();
341         QCOMPARE(it.name(), QLatin1String("foo"));
342         QVERIFY(it.hasNext());
343         it.next();
344         QCOMPARE(it.name(), QLatin1String("rab"));
345         QVERIFY(it.hasPrevious());
346         it.previous();
347         QCOMPARE(it.name(), QLatin1String("rab"));
348         QVERIFY(it.hasNext());
349         it.next();
350         QCOMPARE(it.name(), QLatin1String("rab"));
351         QVERIFY(it.hasPrevious());
352         it.previous();
353         QCOMPARE(it.name(), QLatin1String("rab"));
354     }
355     {
356         // hasNext() and hasPrevious() cache their result; verify that the result is in sync
357         QScriptValue object = engine.newObject();
358         object.setProperty("foo", QScriptValue(&engine, "bar"));
359         object.setProperty("rab", QScriptValue(&engine, "oof"));
360         QScriptValueIterator it(object);
361         QVERIFY(it.hasNext());
362         it.next();
363         QCOMPARE(it.name(), QString::fromLatin1("foo"));
364         QVERIFY(it.hasNext());
365         it.previous();
366         QCOMPARE(it.name(), QString::fromLatin1("foo"));
367         QVERIFY(!it.hasPrevious());
368         it.next();
369         QCOMPARE(it.name(), QString::fromLatin1("foo"));
370         QVERIFY(it.hasPrevious());
371         it.next();
372         QCOMPARE(it.name(), QString::fromLatin1("rab"));
373     }
374 }
375
376 void tst_QScriptValueIterator::setValue()
377 {
378     QScriptEngine engine;
379     QScriptValue object = engine.newObject();
380     object.setProperty("foo", QScriptValue(&engine, "bar"));
381     QScriptValueIterator it(object);
382     it.next();
383     QCOMPARE(it.name(), QLatin1String("foo"));
384     it.setValue(QScriptValue(&engine, "baz"));
385     QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("baz"))), true);
386     QCOMPARE(object.property("foo").toString(), QLatin1String("baz"));
387     it.setValue(QScriptValue(&engine, "zab"));
388     QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("zab"))), true);
389     QCOMPARE(object.property("foo").toString(), QLatin1String("zab"));
390 }
391
392 void tst_QScriptValueIterator::remove()
393 {
394     QScriptEngine engine;
395     QScriptValue object = engine.newObject();
396     object.setProperty("foo", QScriptValue(&engine, "bar"),
397                        QScriptValue::SkipInEnumeration); // should not affect iterator
398     object.setProperty("rab", QScriptValue(&engine, "oof"));
399     QScriptValueIterator it(object);
400     it.next();
401     QCOMPARE(it.name(), QLatin1String("foo"));
402     it.remove();
403     QCOMPARE(it.hasPrevious(), false);
404     QCOMPARE(object.property("foo").isValid(), false);
405     QCOMPARE(object.property("rab").toString(), QLatin1String("oof"));
406     it.next();
407     QCOMPARE(it.name(), QLatin1String("rab"));
408     QCOMPARE(it.value().toString(), QLatin1String("oof"));
409     QCOMPARE(it.hasNext(), false);
410     it.remove();
411     QCOMPARE(object.property("rab").isValid(), false);
412     QCOMPARE(it.hasPrevious(), false);
413     QCOMPARE(it.hasNext(), false);
414 }
415
416 void tst_QScriptValueIterator::iterateString()
417 {
418     QScriptEngine engine;
419     QScriptValue str = QScriptValue(&engine, QString::fromLatin1("ciao"));
420     QVERIFY(str.isString());
421     QScriptValue obj = str.toObject();
422     int length = obj.property("length").toInt32();
423     QCOMPARE(length, 4);
424     QScriptValueIterator it(obj);
425     for (int i = 0; i < length; ++i) {
426         QCOMPARE(it.hasNext(), true);
427         QString indexStr = QScriptValue(&engine, i).toString();
428         it.next();
429         QCOMPARE(it.name(), indexStr);
430         QCOMPARE(it.flags(), obj.propertyFlags(indexStr));
431         QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true);
432     }
433     QVERIFY(it.hasNext());
434     it.next();
435     QCOMPARE(it.name(), QString::fromLatin1("length"));
436     QVERIFY(it.value().isNumber());
437     QCOMPARE(it.value().toInt32(), length);
438     QCOMPARE(it.flags(), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
439
440     it.previous();
441     QCOMPARE(it.hasPrevious(), length > 0);
442     for (int i = length - 1; i >= 0; --i) {
443         it.previous();
444         QString indexStr = QScriptValue(&engine, i).toString();
445         QCOMPARE(it.name(), indexStr);
446         QCOMPARE(it.flags(), obj.propertyFlags(indexStr));
447         QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true);
448         QCOMPARE(it.hasPrevious(), i > 0);
449     }
450     QCOMPARE(it.hasPrevious(), false);
451 }
452
453 static QScriptValue myGetterSetter(QScriptContext *ctx, QScriptEngine *)
454 {
455     if (ctx->argumentCount() == 1)
456         ctx->thisObject().setProperty("bar", ctx->argument(0));
457     return ctx->thisObject().property("bar");
458 }
459
460 static QScriptValue myGetter(QScriptContext *ctx, QScriptEngine *)
461 {
462     return ctx->thisObject().property("bar");
463 }
464
465 static QScriptValue mySetter(QScriptContext *ctx, QScriptEngine *)
466 {
467     ctx->thisObject().setProperty("bar", ctx->argument(0));
468     return ctx->argument(0);
469 }
470
471 void tst_QScriptValueIterator::iterateGetterSetter()
472 {
473     // unified getter/setter function
474     {
475         QScriptEngine eng;
476         QScriptValue obj = eng.newObject();
477         obj.setProperty("foo", eng.newFunction(myGetterSetter),
478                         QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
479         QScriptValue val(&eng, 123);
480         obj.setProperty("foo", val);
481         QVERIFY(obj.property("bar").strictlyEquals(val));
482         QVERIFY(obj.property("foo").strictlyEquals(val));
483
484         QScriptValueIterator it(obj);
485         QVERIFY(it.hasNext());
486         it.next();
487         QCOMPARE(it.name(), QString::fromLatin1("foo"));
488         QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter));
489         QVERIFY(it.value().strictlyEquals(val));
490         QScriptValue val2(&eng, 456);
491         it.setValue(val2);
492         QVERIFY(obj.property("bar").strictlyEquals(val2));
493         QVERIFY(obj.property("foo").strictlyEquals(val2));
494
495         QVERIFY(it.hasNext());
496         it.next();
497         QCOMPARE(it.name(), QString::fromLatin1("bar"));
498         QVERIFY(!it.hasNext());
499
500         QVERIFY(it.hasPrevious());
501         it.previous();
502         QCOMPARE(it.name(), QString::fromLatin1("bar"));
503         QVERIFY(it.hasPrevious());
504         it.previous();
505         QCOMPARE(it.name(), QString::fromLatin1("foo"));
506         QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter));
507         QVERIFY(it.value().strictlyEquals(val2));
508         it.setValue(val);
509         QVERIFY(obj.property("bar").strictlyEquals(val));
510         QVERIFY(obj.property("foo").strictlyEquals(val));
511     }
512     // separate getter/setter function
513     for (int x = 0; x < 2; ++x) {
514         QScriptEngine eng;
515         QScriptValue obj = eng.newObject();
516         if (x == 0) {
517             obj.setProperty("foo", eng.newFunction(myGetter), QScriptValue::PropertyGetter);
518             obj.setProperty("foo", eng.newFunction(mySetter), QScriptValue::PropertySetter);
519         } else {
520             obj.setProperty("foo", eng.newFunction(mySetter), QScriptValue::PropertySetter);
521             obj.setProperty("foo", eng.newFunction(myGetter), QScriptValue::PropertyGetter);
522         }
523         QScriptValue val(&eng, 123);
524         obj.setProperty("foo", val);
525         QVERIFY(obj.property("bar").strictlyEquals(val));
526         QVERIFY(obj.property("foo").strictlyEquals(val));
527
528         QScriptValueIterator it(obj);
529         QVERIFY(it.hasNext());
530         it.next();
531         QCOMPARE(it.name(), QString::fromLatin1("foo"));
532         QVERIFY(it.value().strictlyEquals(val));
533         QScriptValue val2(&eng, 456);
534         it.setValue(val2);
535         QVERIFY(obj.property("bar").strictlyEquals(val2));
536         QVERIFY(obj.property("foo").strictlyEquals(val2));
537
538         QVERIFY(it.hasNext());
539         it.next();
540         QCOMPARE(it.name(), QString::fromLatin1("bar"));
541         QVERIFY(!it.hasNext());
542
543         QVERIFY(it.hasPrevious());
544         it.previous();
545         QCOMPARE(it.name(), QString::fromLatin1("bar"));
546         QVERIFY(it.hasPrevious());
547         it.previous();
548         QCOMPARE(it.name(), QString::fromLatin1("foo"));
549         QVERIFY(it.value().strictlyEquals(val2));
550         it.setValue(val);
551         QVERIFY(obj.property("bar").strictlyEquals(val));
552         QVERIFY(obj.property("foo").strictlyEquals(val));
553     }
554 }
555
556 void tst_QScriptValueIterator::assignObjectToIterator()
557 {
558     QScriptEngine eng;
559     QScriptValue obj1 = eng.newObject();
560     obj1.setProperty("foo", 123);
561     QScriptValue obj2 = eng.newObject();
562     obj2.setProperty("bar", 456);
563
564     QScriptValueIterator it(obj1);
565     QVERIFY(it.hasNext());
566     it.next();
567     it = obj2;
568     QVERIFY(it.hasNext());
569     it.next();
570     QCOMPARE(it.name(), QString::fromLatin1("bar"));
571
572     it = obj1;
573     QVERIFY(it.hasNext());
574     it.next();
575     QCOMPARE(it.name(), QString::fromLatin1("foo"));
576
577     it = obj2;
578     QVERIFY(it.hasNext());
579     it.next();
580     QCOMPARE(it.name(), QString::fromLatin1("bar"));
581
582     it = obj2;
583     QVERIFY(it.hasNext());
584     it.next();
585     QCOMPARE(it.name(), QString::fromLatin1("bar"));
586 }
587
588 void tst_QScriptValueIterator::iterateNonObject()
589 {
590     QScriptValueIterator it(123);
591     QVERIFY(!it.hasNext());
592     it.next();
593     QVERIFY(!it.hasPrevious());
594     it.previous();
595     it.toFront();
596     it.toBack();
597     it.name();
598     it.scriptName();
599     it.flags();
600     it.value();
601     it.setValue(1);
602     it.remove();
603     QScriptValue num(5);
604     it = num;
605     QVERIFY(!it.hasNext());
606 }
607
608 void tst_QScriptValueIterator::iterateOverObjectFromDeletedEngine()
609 {
610     QScriptEngine *engine = new QScriptEngine;
611     QScriptValue objet = engine->newObject();
612
613     // populate object with properties
614     QHash<QString, int> properties;
615     properties.insert("foo",1235);
616     properties.insert("oof",5321);
617     properties.insert("ofo",3521);
618     QHash<QString, int>::const_iterator i = properties.constBegin();
619     for(; i != properties.constEnd(); ++i) {
620         objet.setProperty(i.key(), i.value());
621     }
622
623     // start iterating
624     QScriptValueIterator it(objet);
625     it.next();
626     QVERIFY(properties.contains(it.name()));
627
628     delete engine;
629
630     QVERIFY(!objet.isValid());
631     QVERIFY(it.name().isEmpty());
632     QVERIFY(!it.value().isValid());
633
634     QVERIFY(!it.hasNext());
635     it.next();
636
637     QVERIFY(it.name().isEmpty());
638     QVERIFY(!it.scriptName().isValid());
639     QVERIFY(!it.value().isValid());
640     it.setValue("1234567");
641     it.remove();
642
643     QVERIFY(!it.hasPrevious());
644     it.previous();
645
646     QVERIFY(it.name().isEmpty());
647     QVERIFY(!it.scriptName().isValid());
648     QVERIFY(!it.value().isValid());
649     it.setValue("1234567");
650     it.remove();
651 }
652
653 QTEST_MAIN(tst_QScriptValueIterator)
654 #include "tst_qscriptvalueiterator.moc"