Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / benchmarks / declarative / js / qjsengine / tst_qjsengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qtest.h>
43 #include <QtDeclarative/qjsvalue.h>
44 #include <QtDeclarative/qjsengine.h>
45
46
47 Q_DECLARE_METATYPE(QJSValue)
48
49 class tst_QJSEngine : public QObject
50 {
51     Q_OBJECT
52
53 public:
54     tst_QJSEngine();
55     virtual ~tst_QJSEngine();
56
57 public slots:
58     void init();
59     void cleanup();
60
61 private slots:
62     void constructor();
63 #if 0 // No defaultPrototype for now
64     void defaultPrototype();
65     void setDefaultPrototype();
66 #endif
67     void evaluate_data();
68     void evaluate();
69 #if 0 // No program
70     void evaluateProgram_data();
71     void evaluateProgram();
72 #endif
73 #if 0 // no connections for now
74     void connectAndDisconnect();
75 #endif
76     void globalObject();
77     void hasUncaughtException();
78 #if 0  // no is Evaluating for now
79     void isEvaluating();
80 #endif
81     void newArray_data();
82     void newArray();
83     void newDate();
84     void newObject();
85 #if 0 // No ScriptClass
86     void newObjectWithScriptClass();
87 #endif
88 #if 0 // no qmetaobject
89     void newQMetaObject();
90 #endif
91     void newQObject();
92 #if 0 // no native functions for now
93     void newFunction();
94 #endif
95     void newRegExp();
96     void newVariant();
97     void undefinedValue();
98     void collectGarbage();
99 #if 0 // No extensions
100     void availableExtensions();
101     void importedExtensions();
102 #endif
103 #if 0 // no context
104     void currentContext();
105     void pushAndPopContext();
106 #endif
107 #if 0 // no stringhandle
108     void toStringHandle();
109 #endif
110     void castValueToQreal();
111 #if 0 // no native functions for now
112     void nativeCall();
113 #endif
114 #if 0 // no translations
115     void installTranslatorFunctions();
116     void translation_data();
117     void translation();
118 #endif
119 #if 0 // no declarative class
120     void readScopeProperty_data();
121     void readScopeProperty();
122 #endif
123 #if 0 // no context
124     void evaluateInNewContext();
125     void evaluateInNewContextWithScope();
126 #endif
127 #if 0 // no pushScope
128     void evaluateBindingExpression();
129 #endif
130
131 private:
132     void defineStandardTestValues();
133     void newEngine()
134     {
135         delete m_engine;
136         m_engine = new QJSEngine;
137     }
138
139     QJSEngine *m_engine;
140 };
141
142 tst_QJSEngine::tst_QJSEngine()
143     : m_engine(0)
144 {
145 }
146
147 tst_QJSEngine::~tst_QJSEngine()
148 {
149     delete m_engine;
150 }
151
152 void tst_QJSEngine::init()
153 {
154 }
155
156 void tst_QJSEngine::cleanup()
157 {
158 }
159
160 void tst_QJSEngine::constructor()
161 {
162     QBENCHMARK {
163         QJSEngine engine;
164         (void)engine.parent();
165     }
166 }
167
168 #if 0 // No defaultPrototype for now
169 void tst_QJSEngine::defaultPrototype()
170 {
171     newEngine();
172     int type = qMetaTypeId<int>();
173     m_engine->setDefaultPrototype(type, m_engine->newObject());
174     QBENCHMARK {
175         m_engine->defaultPrototype(type);
176     }
177 }
178
179 void tst_QJSEngine::setDefaultPrototype()
180 {
181     newEngine();
182     int type = qMetaTypeId<int>();
183     QJSValue proto = m_engine->newObject();
184     QBENCHMARK {
185         m_engine->setDefaultPrototype(type, proto);
186     }
187 }
188
189 #endif
190
191 void tst_QJSEngine::evaluate_data()
192 {
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)");
226 }
227
228 void tst_QJSEngine::evaluate()
229 {
230     QFETCH(QString, code);
231     newEngine();
232
233     QBENCHMARK {
234         (void)m_engine->evaluate(code);
235     }
236 }
237
238 #if 0
239 void tst_QJSEngine::connectAndDisconnect()
240 {
241     newEngine();
242     QJSValue fun = m_engine->evaluate("(function() { })");
243     QBENCHMARK {
244         qScriptConnect(m_engine, SIGNAL(destroyed()), QJSValue(), fun);
245         qScriptDisconnect(m_engine, SIGNAL(destroyed()), QJSValue(), fun);
246     }
247 }
248
249 void tst_QJSEngine::evaluateProgram_data()
250 {
251     evaluate_data();
252 }
253
254 void tst_QJSEngine::evaluateProgram()
255 {
256     QFETCH(QString, code);
257     QScriptProgram program(code);
258     newEngine();
259
260     QBENCHMARK {
261         (void)m_engine->evaluate(program);
262     }
263 }
264 #endif
265
266 void tst_QJSEngine::globalObject()
267 {
268     newEngine();
269     QBENCHMARK {
270         m_engine->globalObject();
271     }
272 }
273
274 void tst_QJSEngine::hasUncaughtException()
275 {
276     newEngine();
277     QBENCHMARK {
278         m_engine->hasUncaughtException();
279     }
280 }
281
282 #if 0
283 void tst_QJSEngine::isEvaluating()
284 {
285     newEngine();
286     QBENCHMARK {
287         m_engine->isEvaluating();
288     }
289 }
290 #endif
291
292 void tst_QJSEngine::newArray_data()
293 {
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;
301 }
302
303 void tst_QJSEngine::newArray()
304 {
305     QFETCH(int, size);
306     newEngine();
307     QBENCHMARK {
308         m_engine->newArray(size);
309     }
310 }
311
312 void tst_QJSEngine::newDate()
313 {
314     newEngine();
315     QDateTime dt = QDateTime::currentDateTime();
316     QBENCHMARK {
317         m_engine->toScriptValue(dt);
318     }
319 }
320
321 void tst_QJSEngine::newObject()
322 {
323     newEngine();
324     QBENCHMARK {
325         (void)m_engine->newObject();
326     }
327 }
328
329 #if 0
330 void tst_QJSEngine::newObjectWithScriptClass()
331 {
332     newEngine();
333     QScriptClass cls(m_engine);
334     QBENCHMARK {
335         m_engine->newObject(&cls);
336     }
337 }
338
339 void tst_QJSEngine::newQMetaObject()
340 {
341     newEngine();
342     QBENCHMARK {
343         m_engine->newQMetaObject(&QJSEngine::staticMetaObject);
344     }
345 }
346 #endif
347
348 void tst_QJSEngine::newQObject()
349 {
350     newEngine();
351     QBENCHMARK {
352         (void)m_engine->newQObject(QCoreApplication::instance());
353     }
354 }
355
356 #if 0
357 static QJSValue testFunction(QScriptContext *, QJSEngine *)
358 {
359     return 0;
360 }
361
362 void tst_QJSEngine::newFunction()
363 {
364     newEngine();
365     QBENCHMARK {
366         (void)m_engine->newFunction(testFunction);
367     }
368 }
369 #endif
370
371 void tst_QJSEngine::newRegExp()
372 {
373     newEngine();
374     QRegExp re = QRegExp("foo");
375     QBENCHMARK {
376         m_engine->toScriptValue(re);
377     }
378 }
379
380 void tst_QJSEngine::newVariant()
381 {
382     newEngine();
383     QVariant var(QPoint(10, 20));
384     QBENCHMARK {
385         (void)m_engine->toScriptValue(var);
386     }
387 }
388
389 void tst_QJSEngine::undefinedValue()
390 {
391     newEngine();
392     QVariant var;
393     QBENCHMARK {
394         m_engine->toScriptValue(var);
395     }
396 }
397
398 void tst_QJSEngine::collectGarbage()
399 {
400     newEngine();
401     QBENCHMARK {
402         m_engine->collectGarbage();
403     }
404 }
405
406 #if 0
407 void tst_QJSEngine::availableExtensions()
408 {
409     newEngine();
410     QBENCHMARK {
411         m_engine->availableExtensions();
412     }
413 }
414
415 void tst_QJSEngine::importedExtensions()
416 {
417     newEngine();
418     QBENCHMARK {
419         m_engine->importedExtensions();
420     }
421 }
422
423 void tst_QJSEngine::currentContext()
424 {
425     newEngine();
426     QBENCHMARK {
427         m_engine->currentContext();
428     }
429 }
430
431 void tst_QJSEngine::pushAndPopContext()
432 {
433     newEngine();
434     QBENCHMARK {
435         (void)m_engine->pushContext();
436         m_engine->popContext();
437     }
438 }
439 #endif
440
441 #if 0
442 void tst_QJSEngine::toStringHandle()
443 {
444     newEngine();
445     QString str = QString::fromLatin1("foobarbaz");
446     QBENCHMARK {
447         (void)m_engine->toStringHandle(str);
448     }
449 }
450 #endif
451
452 void tst_QJSEngine::castValueToQreal()
453 {
454     QJSValue val(123);
455     QBENCHMARK {
456         (void)qjsvalue_cast<qreal>(val);
457     }
458 }
459
460 #if 0
461 static QJSValue native_function(QScriptContext *, QJSEngine *)
462 {
463     return 42;
464 }
465
466 void tst_QJSEngine::nativeCall()
467 {
468     newEngine();
469     m_engine->globalObject().setProperty("fun", m_engine->newFunction(native_function));
470     QBENCHMARK{
471         m_engine->evaluate("var w = 0; for (i = 0; i < 100000; ++i) {\n"
472                      "  w += fun() + fun(); w -= fun(); fun(); w -= fun(); }");
473     }
474 }
475
476 void tst_QJSEngine::installTranslatorFunctions()
477 {
478     newEngine();
479     QBENCHMARK {
480         m_engine->installTranslatorFunctions();
481     }
482 }
483
484 void tst_QJSEngine::translation_data()
485 {
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";
492 }
493
494 void tst_QJSEngine::translation()
495 {
496     QFETCH(QString, text);
497     QFETCH(QString, fileName);
498     newEngine();
499     m_engine->installTranslatorFunctions();
500
501     QBENCHMARK {
502         (void)m_engine->evaluate(text, fileName);
503     }
504 }
505 #endif
506
507 #if 0
508 void tst_QJSEngine::readScopeProperty_data()
509 {
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;
516 }
517
518 void tst_QJSEngine::readScopeProperty()
519 {
520     QFETCH(bool, staticScope);
521     QFETCH(bool, nestedScope);
522
523     newEngine();
524     QScriptContext *ctx = m_engine->pushContext();
525
526     QJSValue scope;
527     if (staticScope)
528         scope = QScriptDeclarativeClass::newStaticScopeObject(m_engine);
529     else
530         scope = m_engine->newObject();
531     scope.setProperty("foo", 123);
532     ctx->pushScope(scope);
533
534     if (nestedScope) {
535         QJSValue scope2;
536         if (staticScope)
537             scope2 = QScriptDeclarativeClass::newStaticScopeObject(m_engine);
538         else
539             scope2 = m_engine->newObject();
540         scope2.setProperty("bar", 456); // ensure a miss in inner scope
541         ctx->pushScope(scope2);
542     }
543
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"
547                                        "  }\n"
548                                        "})");
549     m_engine->popContext();
550     QVERIFY(fun.isFunction());
551     QBENCHMARK {
552         fun.call();
553     }
554 }
555
556 void tst_QJSEngine::evaluateInNewContext()
557 {
558     QJSEngine engine;
559     QBENCHMARK {
560         engine.pushContext();
561         engine.evaluate("var a = 10");
562         engine.popContext();
563     }
564 }
565
566 void tst_QJSEngine::evaluateInNewContextWithScope()
567 {
568     QJSEngine engine;
569     QJSValue scope = engine.newObject();
570     scope.setProperty("foo", 123);
571     QBENCHMARK {
572         QScriptContext *ctx = engine.pushContext();
573         ctx->pushScope(scope);
574         engine.evaluate("foo");
575         engine.popContext();
576     }
577 }
578
579 // Binding expressions in QML are implemented as anonymous functions
580 // with custom scopes.
581 void tst_QJSEngine::evaluateBindingExpression()
582 {
583     QJSEngine engine;
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());
590     engine.popContext();
591     QVERIFY(fun.call().equals(scope.property("foo")));
592     QJSValue receiver = engine.globalObject();
593     QBENCHMARK {
594         fun.call(receiver);
595     }
596 }
597 #endif
598
599 QTEST_MAIN(tst_QJSEngine)
600 #include "tst_qjsengine.moc"