1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtDeclarative/qjsvalue.h>
44 #include <QtDeclarative/qjsengine.h>
47 Q_DECLARE_METATYPE(QJSValue)
49 class tst_QJSEngine : public QObject
55 virtual ~tst_QJSEngine();
63 #if 0 // No defaultPrototype for now
64 void defaultPrototype();
65 void setDefaultPrototype();
70 void evaluateProgram_data();
71 void evaluateProgram();
73 #if 0 // no connections for now
74 void connectAndDisconnect();
77 void hasUncaughtException();
78 #if 0 // no is Evaluating for now
85 #if 0 // No ScriptClass
86 void newObjectWithScriptClass();
88 #if 0 // no qmetaobject
89 void newQMetaObject();
92 #if 0 // no native functions for now
97 void undefinedValue();
98 void collectGarbage();
99 #if 0 // No extensions
100 void availableExtensions();
101 void importedExtensions();
104 void currentContext();
105 void pushAndPopContext();
107 #if 0 // no stringhandle
108 void toStringHandle();
110 void castValueToQreal();
111 #if 0 // no native functions for now
114 #if 0 // no translations
115 void installTranslatorFunctions();
116 void translation_data();
119 #if 0 // no declarative class
120 void readScopeProperty_data();
121 void readScopeProperty();
124 void evaluateInNewContext();
125 void evaluateInNewContextWithScope();
127 #if 0 // no pushScope
128 void evaluateBindingExpression();
132 void defineStandardTestValues();
136 m_engine = new QJSEngine;
142 tst_QJSEngine::tst_QJSEngine()
147 tst_QJSEngine::~tst_QJSEngine()
152 void tst_QJSEngine::init()
156 void tst_QJSEngine::cleanup()
160 void tst_QJSEngine::constructor()
164 (void)engine.parent();
168 #if 0 // No defaultPrototype for now
169 void tst_QJSEngine::defaultPrototype()
172 int type = qMetaTypeId<int>();
173 m_engine->setDefaultPrototype(type, m_engine->newObject());
175 m_engine->defaultPrototype(type);
179 void tst_QJSEngine::setDefaultPrototype()
182 int type = qMetaTypeId<int>();
183 QJSValue proto = m_engine->newObject();
185 m_engine->setDefaultPrototype(type, proto);
191 void tst_QJSEngine::evaluate_data()
193 QTest::addColumn<QString>("code");
194 QTest::newRow("empty script") << QString::fromLatin1("");
195 QTest::newRow("number literal") << QString::fromLatin1("123");
196 QTest::newRow("string literal") << QString::fromLatin1("'ciao'");
197 QTest::newRow("regexp literal") << QString::fromLatin1("/foo/gim");
198 QTest::newRow("null literal") << QString::fromLatin1("null");
199 QTest::newRow("undefined literal") << QString::fromLatin1("undefined");
200 QTest::newRow("null literal") << QString::fromLatin1("null");
201 QTest::newRow("empty object literal") << QString::fromLatin1("{}");
202 QTest::newRow("this") << QString::fromLatin1("this");
203 QTest::newRow("object literal with one property") << QString::fromLatin1("{ foo: 123 }");
204 QTest::newRow("object literal with two properties") << QString::fromLatin1("{ foo: 123, bar: 456 }");
205 QTest::newRow("object literal with many properties") << QString::fromLatin1("{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }");
206 QTest::newRow("empty array literal") << QString::fromLatin1("[]");
207 QTest::newRow("array literal with one element") << QString::fromLatin1("[1]");
208 QTest::newRow("array literal with two elements") << QString::fromLatin1("[1,2]");
209 QTest::newRow("array literal with many elements") << QString::fromLatin1("[1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1]");
210 QTest::newRow("empty function definition") << QString::fromLatin1("function foo() { }");
211 QTest::newRow("function definition") << QString::fromLatin1("function foo() { return 123; }");
212 QTest::newRow("for loop with empty body (1000 iterations)") << QString::fromLatin1("for (i = 0; i < 1000; ++i) {}");
213 QTest::newRow("for loop with empty body (10000 iterations)") << QString::fromLatin1("for (i = 0; i < 10000; ++i) {}");
214 QTest::newRow("for loop with empty body (100000 iterations)") << QString::fromLatin1("for (i = 0; i < 100000; ++i) {}");
215 QTest::newRow("for loop with empty body (1000000 iterations)") << QString::fromLatin1("for (i = 0; i < 1000000; ++i) {}");
216 QTest::newRow("for loop (1000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 1000; ++i) { j += i; }; j");
217 QTest::newRow("for loop (10000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 10000; ++i) { j += i; }; j");
218 QTest::newRow("for loop (100000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 100000; ++i) { j += i; }; j");
219 QTest::newRow("for loop (1000000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 1000000; ++i) { j += i; }; j");
220 QTest::newRow("assignments") << QString::fromLatin1("a = 1; b = 2; c = 3; d = 4");
221 QTest::newRow("while loop (1000 iterations)") << QString::fromLatin1("i = 0; while (i < 1000) { ++i; }; i");
222 QTest::newRow("while loop (10000 iterations)") << QString::fromLatin1("i = 0; while (i < 10000) { ++i; }; i");
223 QTest::newRow("while loop (100000 iterations)") << QString::fromLatin1("i = 0; while (i < 100000) { ++i; }; i");
224 QTest::newRow("while loop (1000000 iterations)") << QString::fromLatin1("i = 0; while (i < 1000000) { ++i; }; i");
225 QTest::newRow("function expression") << QString::fromLatin1("(function(a, b, c){ return a + b + c; })(1, 2, 3)");
228 void tst_QJSEngine::evaluate()
230 QFETCH(QString, code);
234 (void)m_engine->evaluate(code);
239 void tst_QJSEngine::connectAndDisconnect()
242 QJSValue fun = m_engine->evaluate("(function() { })");
244 qScriptConnect(m_engine, SIGNAL(destroyed()), QJSValue(), fun);
245 qScriptDisconnect(m_engine, SIGNAL(destroyed()), QJSValue(), fun);
249 void tst_QJSEngine::evaluateProgram_data()
254 void tst_QJSEngine::evaluateProgram()
256 QFETCH(QString, code);
257 QScriptProgram program(code);
261 (void)m_engine->evaluate(program);
266 void tst_QJSEngine::globalObject()
270 m_engine->globalObject();
274 void tst_QJSEngine::hasUncaughtException()
278 m_engine->hasUncaughtException();
283 void tst_QJSEngine::isEvaluating()
287 m_engine->isEvaluating();
292 void tst_QJSEngine::newArray_data()
294 QTest::addColumn<int>("size");
295 QTest::newRow("size=0") << 0;
296 QTest::newRow("size=10") << 10;
297 QTest::newRow("size=100") << 0;
298 QTest::newRow("size=1000") << 0;
299 QTest::newRow("size=10000") << 0;
300 QTest::newRow("size=50000") << 0;
303 void tst_QJSEngine::newArray()
308 m_engine->newArray(size);
312 void tst_QJSEngine::newDate()
315 QDateTime dt = QDateTime::currentDateTime();
317 m_engine->toScriptValue(dt);
321 void tst_QJSEngine::newObject()
325 (void)m_engine->newObject();
330 void tst_QJSEngine::newObjectWithScriptClass()
333 QScriptClass cls(m_engine);
335 m_engine->newObject(&cls);
339 void tst_QJSEngine::newQMetaObject()
343 m_engine->newQMetaObject(&QJSEngine::staticMetaObject);
348 void tst_QJSEngine::newQObject()
352 (void)m_engine->newQObject(QCoreApplication::instance());
357 static QJSValue testFunction(QScriptContext *, QJSEngine *)
362 void tst_QJSEngine::newFunction()
366 (void)m_engine->newFunction(testFunction);
371 void tst_QJSEngine::newRegExp()
374 QRegExp re = QRegExp("foo");
376 m_engine->toScriptValue(re);
380 void tst_QJSEngine::newVariant()
383 QVariant var(QPoint(10, 20));
385 (void)m_engine->toScriptValue(var);
389 void tst_QJSEngine::undefinedValue()
394 m_engine->toScriptValue(var);
398 void tst_QJSEngine::collectGarbage()
402 m_engine->collectGarbage();
407 void tst_QJSEngine::availableExtensions()
411 m_engine->availableExtensions();
415 void tst_QJSEngine::importedExtensions()
419 m_engine->importedExtensions();
423 void tst_QJSEngine::currentContext()
427 m_engine->currentContext();
431 void tst_QJSEngine::pushAndPopContext()
435 (void)m_engine->pushContext();
436 m_engine->popContext();
442 void tst_QJSEngine::toStringHandle()
445 QString str = QString::fromLatin1("foobarbaz");
447 (void)m_engine->toStringHandle(str);
452 void tst_QJSEngine::castValueToQreal()
456 (void)qjsvalue_cast<qreal>(val);
461 static QJSValue native_function(QScriptContext *, QJSEngine *)
466 void tst_QJSEngine::nativeCall()
469 m_engine->globalObject().setProperty("fun", m_engine->newFunction(native_function));
471 m_engine->evaluate("var w = 0; for (i = 0; i < 100000; ++i) {\n"
472 " w += fun() + fun(); w -= fun(); fun(); w -= fun(); }");
476 void tst_QJSEngine::installTranslatorFunctions()
480 m_engine->installTranslatorFunctions();
484 void tst_QJSEngine::translation_data()
486 QTest::addColumn<QString>("text");
487 QTest::addColumn<QString>("fileName");
488 QTest::newRow("no translation") << "\"hello world\"" << "";
489 QTest::newRow("qsTr") << "qsTr(\"hello world\")" << "";
490 QTest::newRow("qsTranslate") << "qsTranslate(\"\", \"hello world\")" << "";
491 QTest::newRow("qsTr:script.js") << "qsTr(\"hello world\")" << "script.js";
494 void tst_QJSEngine::translation()
496 QFETCH(QString, text);
497 QFETCH(QString, fileName);
499 m_engine->installTranslatorFunctions();
502 (void)m_engine->evaluate(text, fileName);
508 void tst_QJSEngine::readScopeProperty_data()
510 QTest::addColumn<bool>("staticScope");
511 QTest::addColumn<bool>("nestedScope");
512 QTest::newRow("single dynamic scope") << false << false;
513 QTest::newRow("single static scope") << true << false;
514 QTest::newRow("double dynamic scope") << false << true;
515 QTest::newRow("double static scope") << true << true;
518 void tst_QJSEngine::readScopeProperty()
520 QFETCH(bool, staticScope);
521 QFETCH(bool, nestedScope);
524 QScriptContext *ctx = m_engine->pushContext();
528 scope = QScriptDeclarativeClass::newStaticScopeObject(m_engine);
530 scope = m_engine->newObject();
531 scope.setProperty("foo", 123);
532 ctx->pushScope(scope);
537 scope2 = QScriptDeclarativeClass::newStaticScopeObject(m_engine);
539 scope2 = m_engine->newObject();
540 scope2.setProperty("bar", 456); // ensure a miss in inner scope
541 ctx->pushScope(scope2);
544 QJSValue fun = m_engine->evaluate("(function() {\n"
545 " for (var i = 0; i < 10000; ++i) {\n"
546 " foo; foo; foo; foo; foo; foo; foo; foo;\n"
549 m_engine->popContext();
550 QVERIFY(fun.isFunction());
556 void tst_QJSEngine::evaluateInNewContext()
560 engine.pushContext();
561 engine.evaluate("var a = 10");
566 void tst_QJSEngine::evaluateInNewContextWithScope()
569 QJSValue scope = engine.newObject();
570 scope.setProperty("foo", 123);
572 QScriptContext *ctx = engine.pushContext();
573 ctx->pushScope(scope);
574 engine.evaluate("foo");
579 // Binding expressions in QML are implemented as anonymous functions
580 // with custom scopes.
581 void tst_QJSEngine::evaluateBindingExpression()
584 QScriptContext *ctx = engine.pushContext();
585 QJSValue scope = engine.newObject();
586 scope.setProperty("foo", 123);
587 ctx->pushScope(scope);
588 QJSValue fun = engine.evaluate("(function() { return foo; })");
589 QVERIFY(fun.isFunction());
591 QVERIFY(fun.call().equals(scope.property("foo")));
592 QJSValue receiver = engine.globalObject();
599 QTEST_MAIN(tst_QJSEngine)
600 #include "tst_qjsengine.moc"