2 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #ifndef tst_qscriptvalueiterator_h
21 #define tst_qscriptvalueiterator_h
23 #include "qscriptengine.h"
24 #include "qscriptvalue.h"
25 #include "qscriptvalueiterator.h"
26 #include <QtCore/qhash.h>
27 #include <QtTest/QtTest>
29 class tst_QScriptValueIterator
: public QObject
{
33 tst_QScriptValueIterator();
34 virtual ~tst_QScriptValueIterator();
37 void iterateForward_data();
38 void iterateForward();
39 void iterateBackward_data();
40 void iterateBackward();
41 void iterateArray_data();
43 void iterateBackAndForth();
47 void removeUndeletable();
49 void assignObjectToIterator();
52 tst_QScriptValueIterator::tst_QScriptValueIterator()
56 tst_QScriptValueIterator::~tst_QScriptValueIterator()
60 void tst_QScriptValueIterator::iterateForward_data()
62 QTest::addColumn
<QStringList
>("propertyNames");
63 QTest::addColumn
<QStringList
>("propertyValues");
65 QTest::newRow("no properties")
66 << QStringList() << QStringList();
67 QTest::newRow("foo=bar")
68 << (QStringList() << "foo")
69 << (QStringList() << "bar");
70 QTest::newRow("foo=bar, baz=123")
71 << (QStringList() << "foo" << "baz")
72 << (QStringList() << "bar" << "123");
73 QTest::newRow("foo=bar, baz=123, rab=oof")
74 << (QStringList() << "foo" << "baz" << "rab")
75 << (QStringList() << "bar" << "123" << "oof");
78 void tst_QScriptValueIterator::iterateForward()
80 QFETCH(QStringList
, propertyNames
);
81 QFETCH(QStringList
, propertyValues
);
82 QMap
<QString
, QString
> pmap
;
83 Q_ASSERT(propertyNames
.size() == propertyValues
.size());
86 QScriptValue object
= engine
.newObject();
87 for (int i
= 0; i
< propertyNames
.size(); ++i
) {
88 QString name
= propertyNames
.at(i
);
89 QString value
= propertyValues
.at(i
);
90 pmap
.insert(name
, value
);
91 object
.setProperty(name
, QScriptValue(&engine
, value
));
93 QScriptValue otherObject
= engine
.newObject();
94 otherObject
.setProperty("foo", QScriptValue(&engine
, 123456));
95 otherObject
.setProperty("protoProperty", QScriptValue(&engine
, 654321));
96 object
.setPrototype(otherObject
); // should not affect iterator
99 QScriptValueIterator
it(object
);
100 while (!pmap
.isEmpty()) {
101 QCOMPARE(it
.hasNext(), true);
102 QCOMPARE(it
.hasNext(), true);
104 QString name
= it
.name();
105 QCOMPARE(pmap
.contains(name
), true);
106 QCOMPARE(it
.name(), name
);
107 QCOMPARE(it
.flags(), object
.propertyFlags(name
));
108 QCOMPARE(it
.value().strictlyEquals(QScriptValue(&engine
, pmap
.value(name
))), true);
109 QCOMPARE(it
.scriptName(), engine
.toStringHandle(name
));
114 QCOMPARE(it
.hasNext(), false);
115 QCOMPARE(it
.hasNext(), false);
118 for (int i
= 0; i
< lst
.count(); ++i
) {
119 QCOMPARE(it
.hasNext(), true);
121 QCOMPARE(it
.name(), lst
.at(i
));
124 for (int i
= 0; i
< lst
.count(); ++i
) {
125 QCOMPARE(it
.hasPrevious(), true);
127 QCOMPARE(it
.name(), lst
.at(lst
.count()-1-i
));
129 QCOMPARE(it
.hasPrevious(), false);
132 void tst_QScriptValueIterator::iterateBackward_data()
134 iterateForward_data();
137 void tst_QScriptValueIterator::iterateBackward()
139 QFETCH(QStringList
, propertyNames
);
140 QFETCH(QStringList
, propertyValues
);
141 QMap
<QString
, QString
> pmap
;
142 Q_ASSERT(propertyNames
.size() == propertyValues
.size());
144 QScriptEngine engine
;
145 QScriptValue object
= engine
.newObject();
146 for (int i
= 0; i
< propertyNames
.size(); ++i
) {
147 QString name
= propertyNames
.at(i
);
148 QString value
= propertyValues
.at(i
);
149 pmap
.insert(name
, value
);
150 object
.setProperty(name
, QScriptValue(&engine
, value
));
154 QScriptValueIterator
it(object
);
156 while (!pmap
.isEmpty()) {
157 QCOMPARE(it
.hasPrevious(), true);
158 QCOMPARE(it
.hasPrevious(), true);
160 QString name
= it
.name();
161 QCOMPARE(pmap
.contains(name
), true);
162 QCOMPARE(it
.name(), name
);
163 QCOMPARE(it
.flags(), object
.propertyFlags(name
));
164 QCOMPARE(it
.value().strictlyEquals(QScriptValue(&engine
, pmap
.value(name
))), true);
169 QCOMPARE(it
.hasPrevious(), false);
170 QCOMPARE(it
.hasPrevious(), false);
173 for (int i
= 0; i
< lst
.count(); ++i
) {
174 QCOMPARE(it
.hasPrevious(), true);
176 QCOMPARE(it
.name(), lst
.at(i
));
179 for (int i
= 0; i
< lst
.count(); ++i
) {
180 QCOMPARE(it
.hasNext(), true);
182 QCOMPARE(it
.name(), lst
.at(lst
.count()-1-i
));
184 QCOMPARE(it
.hasNext(), false);
187 void tst_QScriptValueIterator::iterateArray_data()
189 QTest::addColumn
<QStringList
>("inputPropertyNames");
190 QTest::addColumn
<QStringList
>("inputPropertyValues");
191 QTest::addColumn
<QStringList
>("propertyNames");
192 QTest::addColumn
<QStringList
>("propertyValues");
193 QTest::newRow("no elements") << QStringList() << QStringList() << QStringList() << QStringList();
195 QTest::newRow("0=foo, 1=barr")
196 << (QStringList() << "0" << "1")
197 << (QStringList() << "foo" << "bar")
198 << (QStringList() << "0" << "1")
199 << (QStringList() << "foo" << "bar");
201 QTest::newRow("0=foo, 3=barr")
202 << (QStringList() << "0" << "1" << "2" << "3")
203 << (QStringList() << "foo" << "" << "" << "bar")
204 << (QStringList() << "0" << "1" << "2" << "3")
205 << (QStringList() << "foo" << "" << "" << "bar");
208 void tst_QScriptValueIterator::iterateArray()
210 QFETCH(QStringList
, inputPropertyNames
);
211 QFETCH(QStringList
, inputPropertyValues
);
212 QFETCH(QStringList
, propertyNames
);
213 QFETCH(QStringList
, propertyValues
);
215 QScriptEngine engine
;
216 QScriptValue array
= engine
.newArray();
217 for (int i
= 0; i
< inputPropertyNames
.size(); ++i
)
218 array
.setProperty(inputPropertyNames
.at(i
), inputPropertyValues
.at(i
));
220 int length
= array
.property("length").toInt32();
221 QCOMPARE(length
, propertyNames
.size());
222 QScriptValueIterator
it(array
);
223 for (int i
= 0; i
< length
; ++i
) {
224 QCOMPARE(it
.hasNext(), true);
226 QCOMPARE(it
.name(), propertyNames
.at(i
));
227 QCOMPARE(it
.flags(), array
.propertyFlags(propertyNames
.at(i
)));
228 QVERIFY(it
.value().strictlyEquals(array
.property(propertyNames
.at(i
))));
229 QCOMPARE(it
.value().toString(), propertyValues
.at(i
));
231 QVERIFY(it
.hasNext());
233 QCOMPARE(it
.name(), QString::fromLatin1("length"));
234 QVERIFY(it
.value().isNumber());
235 QCOMPARE(it
.value().toInt32(), length
);
236 QCOMPARE(it
.flags(), QScriptValue::PropertyFlags(QScriptValue::SkipInEnumeration
| QScriptValue::Undeletable
));
239 QCOMPARE(it
.hasPrevious(), length
> 0);
240 for (int i
= length
- 1; i
>= 0; --i
) {
242 QCOMPARE(it
.name(), propertyNames
.at(i
));
243 QCOMPARE(it
.flags(), array
.propertyFlags(propertyNames
.at(i
)));
244 QVERIFY(it
.value().strictlyEquals(array
.property(propertyNames
.at(i
))));
245 QCOMPARE(it
.value().toString(), propertyValues
.at(i
));
246 QCOMPARE(it
.hasPrevious(), i
> 0);
248 QCOMPARE(it
.hasPrevious(), false);
250 // hasNext() and hasPrevious() cache their result; verify that the result is in sync
252 QVERIFY(it
.hasNext());
254 QCOMPARE(it
.name(), QString::fromLatin1("0"));
255 QVERIFY(it
.hasNext());
257 QCOMPARE(it
.name(), QString::fromLatin1("0"));
258 QVERIFY(!it
.hasPrevious());
260 QCOMPARE(it
.name(), QString::fromLatin1("0"));
261 QVERIFY(it
.hasPrevious());
263 QCOMPARE(it
.name(), QString::fromLatin1("1"));
266 // same test as object:
267 QScriptValue originalArray
= engine
.newArray();
268 for (int i
= 0; i
< inputPropertyNames
.size(); ++i
)
269 originalArray
.setProperty(inputPropertyNames
.at(i
), inputPropertyValues
.at(i
));
271 QScriptValue array
= originalArray
.toObject();
272 int length
= array
.property("length").toInt32();
273 QCOMPARE(length
, propertyNames
.size());
274 QScriptValueIterator
it(array
);
275 for (int i
= 0; i
< length
; ++i
) {
276 QCOMPARE(it
.hasNext(), true);
278 QCOMPARE(it
.name(), propertyNames
.at(i
));
279 QCOMPARE(it
.flags(), array
.propertyFlags(propertyNames
.at(i
)));
280 QVERIFY(it
.value().strictlyEquals(array
.property(propertyNames
.at(i
))));
281 QCOMPARE(it
.value().toString(), propertyValues
.at(i
));
283 QCOMPARE(it
.hasNext(), true);
285 QCOMPARE(it
.name(), QString::fromLatin1("length"));
289 void tst_QScriptValueIterator::iterateBackAndForth()
291 QScriptEngine engine
;
293 QScriptValue object
= engine
.newObject();
294 object
.setProperty("foo", QScriptValue(&engine
, "bar"));
295 object
.setProperty("rab", QScriptValue(&engine
, "oof"),
296 QScriptValue::SkipInEnumeration
); // should not affect iterator
297 QScriptValueIterator
it(object
);
298 QVERIFY(it
.hasNext());
300 QCOMPARE(it
.name(), QLatin1String("foo"));
301 QVERIFY(it
.hasPrevious());
303 QCOMPARE(it
.name(), QLatin1String("foo"));
304 QVERIFY(it
.hasNext());
306 QCOMPARE(it
.name(), QLatin1String("foo"));
307 QVERIFY(it
.hasPrevious());
309 QCOMPARE(it
.name(), QLatin1String("foo"));
310 QVERIFY(it
.hasNext());
312 QCOMPARE(it
.name(), QLatin1String("foo"));
313 QVERIFY(it
.hasNext());
315 QCOMPARE(it
.name(), QLatin1String("rab"));
316 QVERIFY(it
.hasPrevious());
318 QCOMPARE(it
.name(), QLatin1String("rab"));
319 QVERIFY(it
.hasNext());
321 QCOMPARE(it
.name(), QLatin1String("rab"));
322 QVERIFY(it
.hasPrevious());
324 QCOMPARE(it
.name(), QLatin1String("rab"));
327 // hasNext() and hasPrevious() cache their result; verify that the result is in sync
328 QScriptValue object
= engine
.newObject();
329 object
.setProperty("foo", QScriptValue(&engine
, "bar"));
330 object
.setProperty("rab", QScriptValue(&engine
, "oof"));
331 QScriptValueIterator
it(object
);
332 QVERIFY(it
.hasNext());
334 QCOMPARE(it
.name(), QString::fromLatin1("foo"));
335 QVERIFY(it
.hasNext());
337 QCOMPARE(it
.name(), QString::fromLatin1("foo"));
338 QVERIFY(!it
.hasPrevious());
340 QCOMPARE(it
.name(), QString::fromLatin1("foo"));
341 QVERIFY(it
.hasPrevious());
343 QCOMPARE(it
.name(), QString::fromLatin1("rab"));
347 void tst_QScriptValueIterator::setValue()
349 QScriptEngine engine
;
350 QScriptValue object
= engine
.newObject();
351 object
.setProperty("foo", QScriptValue(&engine
, "bar"));
352 QScriptValueIterator
it(object
);
354 QCOMPARE(it
.name(), QLatin1String("foo"));
355 it
.setValue(QScriptValue(&engine
, "baz"));
356 QCOMPARE(it
.value().strictlyEquals(QScriptValue(&engine
, QLatin1String("baz"))), true);
357 QCOMPARE(object
.property("foo").toString(), QLatin1String("baz"));
358 it
.setValue(QScriptValue(&engine
, "zab"));
359 QCOMPARE(it
.value().strictlyEquals(QScriptValue(&engine
, QLatin1String("zab"))), true);
360 QCOMPARE(object
.property("foo").toString(), QLatin1String("zab"));
363 void tst_QScriptValueIterator::remove()
365 QScriptEngine engine
;
366 QScriptValue object
= engine
.newObject();
367 object
.setProperty("foo", QScriptValue(&engine
, "bar"),
368 QScriptValue::SkipInEnumeration
); // should not affect iterator
369 object
.setProperty("rab", QScriptValue(&engine
, "oof"));
370 QScriptValueIterator
it(object
);
372 QCOMPARE(it
.name(), QLatin1String("foo"));
374 QCOMPARE(it
.hasPrevious(), false);
375 QCOMPARE(object
.property("foo").isValid(), false);
376 QCOMPARE(object
.property("rab").toString(), QLatin1String("oof"));
378 QCOMPARE(it
.name(), QLatin1String("rab"));
379 QCOMPARE(it
.value().toString(), QLatin1String("oof"));
380 QCOMPARE(it
.hasNext(), false);
382 QCOMPARE(object
.property("rab").isValid(), false);
383 QCOMPARE(it
.hasPrevious(), false);
384 QCOMPARE(it
.hasNext(), false);
387 void tst_QScriptValueIterator::removeMixed()
389 // This test checks if QScriptValueIterator behaives correctly if an object's property got deleted
391 QScriptEngine engine
;
392 QScriptValue object
= engine
.evaluate("o = new Object; o");
393 object
.setProperty("a", QScriptValue(124), QScriptValue::SkipInEnumeration
);
394 object
.setProperty("b", QScriptValue(816));
395 object
.setProperty("c", QScriptValue(3264));
396 QScriptValueIterator
it(object
);
399 QCOMPARE(it
.name(), QLatin1String("b"));
400 QCOMPARE(it
.hasPrevious(), true);
401 QCOMPARE(it
.hasNext(), true);
403 object
.setProperty("a", QScriptValue());
404 QEXPECT_FAIL("", "That would be a significant behavioral and performance change, new QtScript API should be developed (QTBUG-12087)", Abort
);
405 QCOMPARE(it
.hasPrevious(), false);
406 QCOMPARE(it
.hasNext(), true);
408 engine
.evaluate("delete o.c");
409 QCOMPARE(it
.hasPrevious(), false);
410 QCOMPARE(it
.hasNext(), false);
412 object
.setProperty("b", QScriptValue());
413 QCOMPARE(it
.hasPrevious(), false);
414 QCOMPARE(it
.hasNext(), false);
415 QCOMPARE(it
.name(), QString());
416 QCOMPARE(it
.value().toString(), QString());
418 // Try to remove a removed property.
420 QCOMPARE(it
.hasPrevious(), false);
421 QCOMPARE(it
.hasNext(), false);
422 QCOMPARE(it
.name(), QString());
423 QCOMPARE(it
.value().toString(), QString());
425 for (int i
= 0; i
< 2; ++i
) {
427 QCOMPARE(it
.hasPrevious(), false);
428 QCOMPARE(it
.hasNext(), false);
429 QCOMPARE(it
.name(), QString());
430 QCOMPARE(it
.value().toString(), QString());
433 for (int i
= 0; i
< 2; ++i
) {
435 QCOMPARE(it
.hasPrevious(), false);
436 QCOMPARE(it
.hasNext(), false);
437 QCOMPARE(it
.name(), QString());
438 QCOMPARE(it
.value().toString(), QString());
442 void tst_QScriptValueIterator::removeUndeletable()
444 // Undeletable property can't be deleted via iterator.
445 QScriptEngine engine
;
446 QScriptValue object
= engine
.evaluate("o = new Object; o");
447 object
.setProperty("a", QScriptValue(&engine
, 124));
448 object
.setProperty("b", QScriptValue(&engine
, 816), QScriptValue::Undeletable
);
449 QVERIFY(object
.property("b").isValid());
450 QScriptValueIterator
it(object
);
455 QVERIFY(it
.hasNext());
456 QVERIFY(object
.property("b").isValid());
459 void tst_QScriptValueIterator::iterateString()
461 QScriptEngine engine
;
462 QScriptValue str
= QScriptValue(&engine
, QString::fromLatin1("ciao"));
463 QVERIFY(str
.isString());
464 QScriptValue obj
= str
.toObject();
465 int length
= obj
.property("length").toInt32();
467 QScriptValueIterator
it(obj
);
468 for (int i
= 0; i
< length
; ++i
) {
469 QCOMPARE(it
.hasNext(), true);
470 QString indexStr
= QScriptValue(&engine
, i
).toString();
472 QCOMPARE(it
.name(), indexStr
);
473 QCOMPARE(it
.flags(), obj
.propertyFlags(indexStr
));
474 QCOMPARE(it
.value().strictlyEquals(obj
.property(indexStr
)), true);
476 QVERIFY(it
.hasNext());
478 QCOMPARE(it
.name(), QString::fromLatin1("length"));
479 QVERIFY(it
.value().isNumber());
480 QCOMPARE(it
.value().toInt32(), length
);
481 QCOMPARE(it
.flags(), QScriptValue::PropertyFlags(QScriptValue::ReadOnly
| QScriptValue::SkipInEnumeration
| QScriptValue::Undeletable
));
484 QCOMPARE(it
.hasPrevious(), length
> 0);
485 for (int i
= length
- 1; i
>= 0; --i
) {
487 QString indexStr
= QScriptValue(&engine
, i
).toString();
488 QCOMPARE(it
.name(), indexStr
);
489 QCOMPARE(it
.flags(), obj
.propertyFlags(indexStr
));
490 QCOMPARE(it
.value().strictlyEquals(obj
.property(indexStr
)), true);
491 QCOMPARE(it
.hasPrevious(), i
> 0);
493 QCOMPARE(it
.hasPrevious(), false);
496 void tst_QScriptValueIterator::assignObjectToIterator()
499 QScriptValue obj1
= eng
.newObject();
500 obj1
.setProperty("foo", 123);
501 QScriptValue obj2
= eng
.newObject();
502 obj2
.setProperty("bar", 456);
504 QScriptValueIterator
it(obj1
);
505 QVERIFY(it
.hasNext());
508 QVERIFY(it
.hasNext());
510 QCOMPARE(it
.name(), QString::fromLatin1("bar"));
513 QVERIFY(it
.hasNext());
515 QCOMPARE(it
.name(), QString::fromLatin1("foo"));
518 QVERIFY(it
.hasNext());
520 QCOMPARE(it
.name(), QString::fromLatin1("bar"));
523 QVERIFY(it
.hasNext());
525 QCOMPARE(it
.name(), QString::fromLatin1("bar"));
528 QTEST_MAIN(tst_QScriptValueIterator
)
529 #include "tst_qscriptvalueiterator.moc"
531 #endif // tst_qscriptvalueiterator_h