diff options
Diffstat (limited to 'tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp')
-rw-r--r-- | tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp | 522 |
1 files changed, 522 insertions, 0 deletions
diff --git a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp new file mode 100644 index 0000000000..eade3de1a7 --- /dev/null +++ b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp @@ -0,0 +1,522 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <QJSEngine> +#include <QJSValue> +#include <QJSValueIterator> + +Q_DECLARE_METATYPE(QJSValue); + +class tst_QJSValueIterator : public QObject +{ + Q_OBJECT + +public: + tst_QJSValueIterator(); + virtual ~tst_QJSValueIterator(); + +private slots: + void iterateForward_data(); + void iterateForward(); + void iterateArray_data(); + void iterateArray(); + void iterateString(); +#if 0 + void iterateGetterSetter(); +#endif + void assignObjectToIterator(); + void iterateNonObject(); + void iterateOverObjectFromDeletedEngine(); +}; + +tst_QJSValueIterator::tst_QJSValueIterator() +{ +} + +tst_QJSValueIterator::~tst_QJSValueIterator() +{ +} + +void tst_QJSValueIterator::iterateForward_data() +{ + QTest::addColumn<QStringList>("propertyNames"); + QTest::addColumn<QStringList>("propertyValues"); + + QTest::newRow("no properties") + << QStringList() << QStringList(); + QTest::newRow("foo=bar") + << (QStringList() << "foo") + << (QStringList() << "bar"); + QTest::newRow("foo=bar, baz=123") + << (QStringList() << "foo" << "baz") + << (QStringList() << "bar" << "123"); + QTest::newRow("foo=bar, baz=123, rab=oof") + << (QStringList() << "foo" << "baz" << "rab") + << (QStringList() << "bar" << "123" << "oof"); +} + +void tst_QJSValueIterator::iterateForward() +{ + QFETCH(QStringList, propertyNames); + QFETCH(QStringList, propertyValues); + QMap<QString, QString> pmap; + QVERIFY(propertyNames.size() == propertyValues.size()); + + QJSEngine engine; + QJSValue object = engine.newObject(); + for (int i = 0; i < propertyNames.size(); ++i) { + QString name = propertyNames.at(i); + QString value = propertyValues.at(i); + pmap.insert(name, value); + object.setProperty(name, engine.toScriptValue(value)); + } + QJSValue otherObject = engine.newObject(); + otherObject.setProperty("foo", engine.toScriptValue(123456)); + otherObject.setProperty("protoProperty", engine.toScriptValue(654321)); + object.setPrototype(otherObject); // should not affect iterator + + QStringList lst; + QJSValueIterator it(object); + while (!pmap.isEmpty()) { + QCOMPARE(it.hasNext(), true); + QCOMPARE(it.hasNext(), true); + it.next(); + QString name = it.name(); + QCOMPARE(pmap.contains(name), true); + QCOMPARE(it.name(), name); + QCOMPARE(it.value().strictlyEquals(engine.toScriptValue(pmap.value(name))), true); + pmap.remove(name); + lst.append(name); + } + + QCOMPARE(it.hasNext(), false); + QCOMPARE(it.hasNext(), false); + + it = object; + for (int i = 0; i < lst.count(); ++i) { + QCOMPARE(it.hasNext(), true); + it.next(); + QCOMPARE(it.name(), lst.at(i)); + } +} + +void tst_QJSValueIterator::iterateArray_data() +{ + QTest::addColumn<QStringList>("propertyNames"); + QTest::addColumn<QStringList>("propertyValues"); + + QTest::newRow("no elements") << QStringList() << QStringList(); + + QTest::newRow("0=foo, 1=barr") + << (QStringList() << "0" << "1") + << (QStringList() << "foo" << "bar"); + + + QTest::newRow("0=foo, 3=barr") + << (QStringList() << "0" << "1" << "2" << "3") + << (QStringList() << "foo" << "" << "" << "bar"); +} + +void tst_QJSValueIterator::iterateArray() +{ + QFETCH(QStringList, propertyNames); + QFETCH(QStringList, propertyValues); + + QJSEngine engine; + QJSValue array = engine.newArray(); + + // Fill the array + for (int i = 0; i < propertyNames.size(); ++i) { + array.setProperty(propertyNames.at(i), propertyValues.at(i)); + } + + // Iterate thru array properties. Note that the QJSValueIterator doesn't guarantee + // any order on the iteration! + int length = array.property("length").toInt(); + QCOMPARE(length, propertyNames.size()); + + bool iteratedThruLength = false; + QHash<QString, QJSValue> arrayProperties; + QJSValueIterator it(array); + + // Iterate forward + while (it.hasNext()) { + it.next(); + + const QString name = it.name(); + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt(), length); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + // Storing the properties we iterate in a hash to compare with test data. + QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration."); + arrayProperties.insert(name, it.value()); + QVERIFY(it.value().strictlyEquals(array.property(name))); + } + + // Verify properties + QVERIFY(iteratedThruLength); + QCOMPARE(arrayProperties.size(), propertyNames.size()); + for (int i = 0; i < propertyNames.size(); ++i) { + QVERIFY(arrayProperties.contains(propertyNames.at(i))); + QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); + } + +#if 0 + + // Iterate backwards + arrayProperties.clear(); + iteratedThruLength = false; + it.toBack(); + + while (it.hasPrevious()) { + it.previous(); + + const QString name = it.name(); + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt(), length); + QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + // Storing the properties we iterate in a hash to compare with test data. + QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration."); + arrayProperties.insert(name, it.value()); + QCOMPARE(it.flags(), array.propertyFlags(name)); + QVERIFY(it.value().strictlyEquals(array.property(name))); + } + + // Verify properties + QVERIFY(iteratedThruLength); + QCOMPARE(arrayProperties.size(), propertyNames.size()); + for (int i = 0; i < propertyNames.size(); ++i) { + QVERIFY(arrayProperties.contains(propertyNames.at(i))); + QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); + } + + // ### Do we still need this test? + // Forward test again but as object + arrayProperties.clear(); + iteratedThruLength = false; + QJSValue arrayObject = engine.toObject(array); + QJSValueIterator it2(arrayObject); + + while (it2.hasNext()) { + it2.next(); + + const QString name = it2.name(); + if (name == QString::fromLatin1("length")) { + QVERIFY(it2.value().isNumber()); + QCOMPARE(it2.value().toInt(), length); + QCOMPARE(it2.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + // Storing the properties we iterate in a hash to compare with test data. + QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration."); + arrayProperties.insert(name, it2.value()); + QCOMPARE(it2.flags(), arrayObject.propertyFlags(name)); + QVERIFY(it2.value().strictlyEquals(arrayObject.property(name))); + } + + // Verify properties + QVERIFY(iteratedThruLength); + QCOMPARE(arrayProperties.size(), propertyNames.size()); + for (int i = 0; i < propertyNames.size(); ++i) { + QVERIFY(arrayProperties.contains(propertyNames.at(i))); + QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); + } +#endif +} + +void tst_QJSValueIterator::iterateString() +{ + QJSEngine engine; + QJSValue obj = engine.evaluate("new String('ciao')"); + QVERIFY(obj.property("length").isNumber()); + int length = obj.property("length").toInt(); + QCOMPARE(length, 4); + + QJSValueIterator it(obj); + QHash<QString, QJSValue> stringProperties; + bool iteratedThruLength = false; + + while (it.hasNext()) { + it.next(); + const QString name = it.name(); + + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt(), length); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration."); + stringProperties.insert(name, it.value()); + QVERIFY(it.value().strictlyEquals(obj.property(name))); + } + + QVERIFY(iteratedThruLength); + QCOMPARE(stringProperties.size(), length); +#if 0 + // And going backwards + iteratedThruLength = false; + stringProperties.clear(); + it.toBack(); + + while (it.hasPrevious()) { + it.previous(); + const QString name = it.name(); + + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt(), length); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration."); + stringProperties.insert(name, it.value()); + QVERIFY(it.value().strictlyEquals(obj.property(name))); + } +#endif +} + +#if 0 // FIXME what we should to keep from here? +static QJSValue myGetterSetter(QScriptContext *ctx, QJSEngine *) +{ + if (ctx->argumentCount() == 1) + ctx->thisObject().setProperty("bar", ctx->argument(0)); + return ctx->thisObject().property("bar"); +} + +static QJSValue myGetter(QScriptContext *ctx, QJSEngine *) +{ + return ctx->thisObject().property("bar"); +} + +static QJSValue mySetter(QScriptContext *ctx, QJSEngine *) +{ + ctx->thisObject().setProperty("bar", ctx->argument(0)); + return ctx->argument(0); +} + +void tst_QJSValueIterator::iterateGetterSetter() +{ + // unified getter/setter function + { + QJSEngine eng; + QJSValue obj = eng.newObject(); + obj.setProperty("foo", eng.newFunction(myGetterSetter), + QScriptValue::PropertyGetter | QScriptValue::PropertySetter); + QJSValue val(&eng, 123); + obj.setProperty("foo", val); + QVERIFY(obj.property("bar").strictlyEquals(val)); + QVERIFY(obj.property("foo").strictlyEquals(val)); + + QJSValueIterator it(obj); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter)); + QVERIFY(it.value().strictlyEquals(val)); + QJSValue val2(&eng, 456); + it.setValue(val2); + QVERIFY(obj.property("bar").strictlyEquals(val2)); + QVERIFY(obj.property("foo").strictlyEquals(val2)); + + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + QVERIFY(!it.hasNext()); + + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::PropertyGetter | QScriptValue::PropertySetter)); + QVERIFY(it.value().strictlyEquals(val2)); + it.setValue(val); + QVERIFY(obj.property("bar").strictlyEquals(val)); + QVERIFY(obj.property("foo").strictlyEquals(val)); + } + // separate getter/setter function + for (int x = 0; x < 2; ++x) { + QJSEngine eng; + QJSValue obj = eng.newObject(); + if (x == 0) { + obj.setProperty("foo", eng.newFunction(myGetter), QScriptValue::PropertyGetter); + obj.setProperty("foo", eng.newFunction(mySetter), QScriptValue::PropertySetter); + } else { + obj.setProperty("foo", eng.newFunction(mySetter), QScriptValue::PropertySetter); + obj.setProperty("foo", eng.newFunction(myGetter), QScriptValue::PropertyGetter); + } + QJSValue val(&eng, 123); + obj.setProperty("foo", val); + QVERIFY(obj.property("bar").strictlyEquals(val)); + QVERIFY(obj.property("foo").strictlyEquals(val)); + + QJSValueIterator it(obj); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QVERIFY(it.value().strictlyEquals(val)); + QJSValue val2(&eng, 456); + it.setValue(val2); + QVERIFY(obj.property("bar").strictlyEquals(val2)); + QVERIFY(obj.property("foo").strictlyEquals(val2)); + + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + QVERIFY(!it.hasNext()); + + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QVERIFY(it.value().strictlyEquals(val2)); + it.setValue(val); + QVERIFY(obj.property("bar").strictlyEquals(val)); + QVERIFY(obj.property("foo").strictlyEquals(val)); + } +} +#endif + +void tst_QJSValueIterator::assignObjectToIterator() +{ + QJSEngine eng; + QJSValue obj1 = eng.newObject(); + obj1.setProperty("foo", 123); + QJSValue obj2 = eng.newObject(); + obj2.setProperty("bar", 456); + + QJSValueIterator it(obj1); + QVERIFY(it.hasNext()); + it.next(); + it = obj2; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + + it = obj1; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + + it = obj2; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + + it = obj2; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); +} + +void tst_QJSValueIterator::iterateNonObject() +{ + QJSValueIterator it(123); + QVERIFY(!it.hasNext()); + it.next(); + it.name(); + it.value(); + QJSValue num(5); + it = num; + QVERIFY(!it.hasNext()); +} + +void tst_QJSValueIterator::iterateOverObjectFromDeletedEngine() +{ + QJSEngine *engine = new QJSEngine; + QJSValue objet = engine->newObject(); + + // populate object with properties + QHash<QString, int> properties; + properties.insert("foo",1235); + properties.insert("oof",5321); + properties.insert("ofo",3521); + QHash<QString, int>::const_iterator i = properties.constBegin(); + for (; i != properties.constEnd(); ++i) { + objet.setProperty(i.key(), i.value()); + } + + // start iterating + QJSValueIterator it(objet); + it.next(); + QVERIFY(properties.contains(it.name())); + + delete engine; + + QVERIFY(objet.isUndefined()); + QVERIFY(it.name().isEmpty()); + QVERIFY(it.value().isUndefined()); + + QVERIFY(!it.hasNext()); + it.next(); + + QVERIFY(it.name().isEmpty()); + QVERIFY(it.value().isUndefined()); + +} + +QTEST_MAIN(tst_QJSValueIterator) +#include "tst_qjsvalueiterator.moc" |