292f4727a6e9be2151d2c866a0de74563e56a91d
[profile/ivi/qtdeclarative.git] / tests / benchmarks / declarative / script / tst_script.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qtest.h>
43 #include <QDeclarativeEngine>
44 #include <QDeclarativeComponent>
45 #include <private/qdeclarativeengine_p.h>
46 #include <private/qdeclarativeobjectscriptclass_p.h>
47 #include <private/qdeclarativerectangle_p.h>
48 #include <QScriptEngine>
49 #include <QScriptValue>
50
51 class tst_script : public QObject
52 {
53     Q_OBJECT
54 public:
55     tst_script() {}
56
57 private slots:
58     void initTestCase();
59
60     void property_js();
61     void property_getter();
62     void property_getter_js();
63     void property_getter_qobject();
64     void property_getter_qmetaproperty();
65     void property_qobject();
66     void property_qmlobject();
67
68     void setproperty_js();
69     void setproperty_qmlobject();
70
71     void function_js();
72     void function_cpp();
73     void function_qobject();
74     void function_qmlobject();
75
76     void function_args_js();
77     void function_args_cpp();
78     void function_args_qobject();
79     void function_args_qmlobject();
80
81     void signal_unconnected();
82     void signal_qml();
83     void signal_args();
84     void signal_unusedArgs();
85
86     void slot_simple();
87     void slot_simple_js();
88     void slot_complex();
89     void slot_complex_js();
90
91     void block_data();
92     void block();
93
94     void global_property_js();
95     void global_property_qml();
96     void global_property_qml_js();
97
98     void scriptfile_property();
99
100     void enums();
101     void namespacedEnums();
102     void scriptCall();
103 };
104
105 inline QUrl TEST_FILE(const QString &filename)
106 {
107     return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
108 }
109
110 class TestObject : public QObject
111 {
112     Q_OBJECT
113     Q_PROPERTY(int x READ x WRITE setX)
114
115 public:
116     TestObject(QObject *parent = 0);
117
118     int x();
119     void setX(int x) { m_x = x; }
120
121     void emitMySignal() { emit mySignal(); }
122     void emitMySignalWithArgs(int n) { emit mySignalWithArgs(n); }
123
124 signals:
125     void mySignal();
126     void mySignalWithArgs(int n);
127
128 public slots:
129     int method() {
130         return x();
131     }
132
133     int methodArgs(int val) {
134         return val + x();
135     }
136
137 private:
138     int m_x;
139 };
140 QML_DECLARE_TYPE(TestObject);
141
142 TestObject::TestObject(QObject *parent)
143 : QObject(parent), m_x(0)
144 {
145 }
146
147 int TestObject::x() 
148 {
149     return m_x++;
150 }
151
152 void tst_script::initTestCase()
153 {
154     qmlRegisterType<TestObject>("Qt.test", 1, 0, "TestObject");
155 }
156
157
158 #define PROPERTY_PROGRAM \
159     "(function(testObject) { return (function() { " \
160     "    var test = 0; " \
161     "    for (var ii = 0; ii < 10000; ++ii) { " \
162     "        test += testObject.x; " \
163     "    } " \
164     "    return test; " \
165     "}); })"
166
167 void tst_script::property_js()
168 {
169     QScriptEngine engine;
170
171     QScriptValue v = engine.newObject();
172     v.setProperty(QLatin1String("x"), 10);
173
174     QScriptValueList args;
175     args << v;
176     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
177     prog.call();
178
179     QBENCHMARK {
180         prog.call().toNumber();
181     }
182 }
183
184 static QScriptValue property_getter_method(QScriptContext *, QScriptEngine *engine) 
185 {
186     static int x = 0;
187     return QScriptValue(engine,x++);
188 }
189
190 void tst_script::property_getter()
191 {
192     QScriptEngine engine;
193
194     QScriptValue v = engine.newObject();
195     v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_method), 
196                   QScriptValue::PropertyGetter);
197
198     QScriptValueList args;
199     args << v;
200     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
201     prog.call();
202
203     QBENCHMARK {
204         prog.call();
205     }
206 }
207
208 static TestObject *property_getter_qobject_object = 0;
209 static QScriptValue property_getter_qobject_method(QScriptContext *, QScriptEngine *) 
210 {
211     static int idx = -1;
212     if (idx == -1) 
213         idx = TestObject::staticMetaObject.indexOfProperty("x");
214
215     int value = 0;
216     void *args[] = { &value, 0 };
217     QMetaObject::metacall(property_getter_qobject_object, QMetaObject::ReadProperty, idx, args);
218
219     return QScriptValue(value);
220 }
221
222 static QScriptValue property_getter_qmetaproperty_method(QScriptContext *, QScriptEngine *) 
223 {
224     static int idx = -1;
225     if (idx == -1) 
226         idx = TestObject::staticMetaObject.indexOfProperty("x");
227
228     int value = 0;
229     value = property_getter_qobject_object->metaObject()->property(idx).read(property_getter_qobject_object).toInt();
230
231     return QScriptValue(value);
232 }
233
234 void tst_script::property_getter_qobject()
235 {
236     QScriptEngine engine;
237
238     TestObject to;
239     property_getter_qobject_object = &to;
240     QScriptValue v = engine.newObject();
241     v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qobject_method), 
242                   QScriptValue::PropertyGetter);
243
244     QScriptValueList args;
245     args << v;
246     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
247     prog.call();
248
249     QBENCHMARK {
250         prog.call();
251     }
252     property_getter_qobject_object = 0;
253 }
254
255 void tst_script::property_getter_qmetaproperty()
256 {
257     QScriptEngine engine;
258
259     TestObject to;
260     property_getter_qobject_object = &to;
261     QScriptValue v = engine.newObject();
262     v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qmetaproperty_method), 
263                   QScriptValue::PropertyGetter);
264
265     QScriptValueList args;
266     args << v;
267     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
268     prog.call();
269
270     QBENCHMARK {
271         prog.call();
272     }
273     property_getter_qobject_object = 0;
274 }
275
276
277 void tst_script::property_getter_js()
278 {
279     QScriptEngine engine;
280     
281     QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.__defineGetter__(\"x\", function() { return this._x++; }); return o; })").call();
282
283     QScriptValueList args;
284     args << v;
285     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
286     prog.call();
287
288     QBENCHMARK {
289         prog.call();
290     }
291 }
292
293 void tst_script::property_qobject()
294 {
295     QScriptEngine engine;
296
297     TestObject to;
298     QScriptValue v = engine.newQObject(&to);
299
300     QScriptValueList args;
301     args << v;
302     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
303     prog.call();
304
305     QBENCHMARK {
306         prog.call();
307     }
308 }
309
310 void tst_script::property_qmlobject()
311 {
312     QDeclarativeEngine qmlengine;
313
314     QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(&qmlengine);
315     TestObject to;
316
317     QScriptValue v = QDeclarativeEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
318
319     QScriptValueList args;
320     args << v;
321     QScriptValue prog = engine->evaluate(PROPERTY_PROGRAM).call(engine->globalObject(), args);
322     prog.call();
323
324     QBENCHMARK {
325         prog.call();
326     }
327 }
328
329 #define SETPROPERTY_PROGRAM \
330     "(function(testObject) { return (function() { " \
331     "    for (var ii = 0; ii < 10000; ++ii) { " \
332     "        testObject.x = ii; " \
333     "    } " \
334     "}); })"
335
336 void tst_script::setproperty_js()
337 {
338     QScriptEngine engine;
339
340     QScriptValue v = engine.newObject();
341     v.setProperty(QLatin1String("x"), 0);
342
343     QScriptValueList args;
344     args << v;
345     QScriptValue prog = engine.evaluate(SETPROPERTY_PROGRAM).call(engine.globalObject(), args);
346     prog.call();
347
348     QBENCHMARK {
349         prog.call();
350     }
351 }
352
353 void tst_script::setproperty_qmlobject()
354 {
355     QDeclarativeEngine qmlengine;
356
357     QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(&qmlengine);
358     TestObject to;
359
360     QScriptValue v = QDeclarativeEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
361
362     QScriptValueList args;
363     args << v;
364     QScriptValue prog = engine->evaluate(SETPROPERTY_PROGRAM).call(engine->globalObject(), args);
365     prog.call();
366
367     QBENCHMARK {
368         prog.call();
369     }
370 }
371
372 #define FUNCTION_PROGRAM \
373     "(function(testObject) { return (function() { " \
374     "    var test = 0; " \
375     "    for (var ii = 0; ii < 10000; ++ii) { " \
376     "        test += testObject.method(); " \
377     "    } " \
378     "    return test; " \
379     "}); })"
380
381 void tst_script::function_js()
382 {
383     QScriptEngine engine;
384     
385     QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.method = (function() { return this._x++; }); return o; })").call();
386
387     QScriptValueList args;
388     args << v;
389     QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
390     prog.call();
391
392     QBENCHMARK {
393         prog.call();
394     }
395 }
396
397 static QScriptValue function_method(QScriptContext *, QScriptEngine *) 
398 {
399     static int x = 0;
400     return QScriptValue(x++);
401 }
402
403 void tst_script::function_cpp()
404 {
405     QScriptEngine engine;
406
407     QScriptValue v = engine.newObject();
408     v.setProperty(QLatin1String("method"), engine.newFunction(function_method));
409
410     QScriptValueList args;
411     args << v;
412     QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
413     prog.call();
414
415     QBENCHMARK {
416         prog.call();
417     }
418 }
419
420 void tst_script::function_qobject()
421 {
422     QScriptEngine engine;
423
424     TestObject to;
425     QScriptValue v = engine.newQObject(&to);
426
427     QScriptValueList args;
428     args << v;
429     QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
430     prog.call();
431
432     QBENCHMARK {
433         prog.call();
434     }
435 }
436
437 void tst_script::function_qmlobject()
438 {
439     QDeclarativeEngine qmlengine;
440
441     QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(&qmlengine);
442     TestObject to;
443
444     QScriptValue v = QDeclarativeEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
445
446     QScriptValueList args;
447     args << v;
448     QScriptValue prog = engine->evaluate(FUNCTION_PROGRAM).call(engine->globalObject(), args);
449     prog.call();
450
451     QBENCHMARK {
452         prog.call();
453     }
454 }
455
456 #define FUNCTION_ARGS_PROGRAM \
457     "(function(testObject) { return (function() { " \
458     "    var test = 0; " \
459     "    for (var ii = 0; ii < 10000; ++ii) { " \
460     "        test += testObject.methodArgs(ii); " \
461     "    } " \
462     "    return test; " \
463     "}); })"
464
465 void tst_script::function_args_js()
466 {
467     QScriptEngine engine;
468     
469     QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.methodArgs = (function(a) { return a + this._x++; }); return o; })").call();
470
471     QScriptValueList args;
472     args << v;
473     QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
474     prog.call();
475
476     QBENCHMARK {
477         prog.call();
478     }
479 }
480
481 static QScriptValue function_args_method(QScriptContext *ctxt, QScriptEngine *) 
482 {
483     static int x = 0;
484     return QScriptValue(ctxt->argument(0).toNumber() + x++);
485 }
486
487 void tst_script::function_args_cpp()
488 {
489     QScriptEngine engine;
490
491     QScriptValue v = engine.newObject();
492     v.setProperty(QLatin1String("methodArgs"), engine.newFunction(function_args_method));
493
494     QScriptValueList args;
495     args << v;
496     QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
497     prog.call();
498
499     QBENCHMARK {
500         prog.call();
501     }
502 }
503
504 void tst_script::function_args_qobject()
505 {
506     QScriptEngine engine;
507
508     TestObject to;
509     QScriptValue v = engine.newQObject(&to);
510
511     QScriptValueList args;
512     args << v;
513     QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
514     prog.call();
515
516     QBENCHMARK {
517         prog.call();
518     }
519 }
520
521 void tst_script::function_args_qmlobject()
522 {
523     QDeclarativeEngine qmlengine;
524
525     QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(&qmlengine);
526     TestObject to;
527
528     QScriptValue v = QDeclarativeEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
529
530     QScriptValueList args;
531     args << v;
532     QScriptValue prog = engine->evaluate(FUNCTION_ARGS_PROGRAM).call(engine->globalObject(), args);
533     prog.call();
534
535     QBENCHMARK {
536         prog.call();
537     }
538 }
539
540 void tst_script::signal_unconnected()
541 {
542     QDeclarativeEngine engine;
543     QDeclarativeComponent component(&engine, TEST_FILE("signal_unconnected.qml"));
544     TestObject *object = qobject_cast<TestObject *>(component.create());
545     QVERIFY(object != 0);
546
547     QBENCHMARK {
548         object->emitMySignal();
549     }
550
551     delete object;
552 }
553
554 void tst_script::signal_qml()
555 {
556     QDeclarativeEngine engine;
557     QDeclarativeComponent component(&engine, TEST_FILE("signal_qml.qml"));
558     TestObject *object = qobject_cast<TestObject *>(component.create());
559     QVERIFY(object != 0);
560
561     QBENCHMARK {
562         object->emitMySignal();
563     }
564
565     delete object;
566 }
567
568 void tst_script::signal_args()
569 {
570     QDeclarativeEngine engine;
571     QDeclarativeComponent component(&engine, TEST_FILE("signal_args.qml"));
572     TestObject *object = qobject_cast<TestObject *>(component.create());
573     QVERIFY(object != 0);
574
575     QBENCHMARK {
576         object->emitMySignalWithArgs(11);
577     }
578
579     delete object;
580 }
581
582 void tst_script::signal_unusedArgs()
583 {
584     QDeclarativeEngine engine;
585     QDeclarativeComponent component(&engine, TEST_FILE("signal_unusedArgs.qml"));
586     TestObject *object = qobject_cast<TestObject *>(component.create());
587     QVERIFY(object != 0);
588
589     QBENCHMARK {
590         object->emitMySignalWithArgs(11);
591     }
592
593     delete object;
594 }
595
596 void tst_script::slot_simple()
597 {
598     QDeclarativeEngine engine;
599     QDeclarativeComponent component(&engine, TEST_FILE("slot_simple.qml"));
600     TestObject *object = qobject_cast<TestObject *>(component.create());
601     QVERIFY(object != 0);
602
603     QBENCHMARK {
604         object->emitMySignal();
605     }
606
607     delete object;
608 }
609
610 void tst_script::slot_simple_js()
611 {
612     QDeclarativeEngine engine;
613     QDeclarativeComponent component(&engine, TEST_FILE("slot_simple_js.qml"));
614     TestObject *object = qobject_cast<TestObject *>(component.create());
615     QVERIFY(object != 0);
616
617     QBENCHMARK {
618         object->emitMySignal();
619     }
620
621     delete object;
622 }
623
624 void tst_script::slot_complex()
625 {
626     QDeclarativeEngine engine;
627     QDeclarativeComponent component(&engine, TEST_FILE("slot_complex.qml"));
628     TestObject *object = qobject_cast<TestObject *>(component.create());
629     QVERIFY(object != 0);
630
631     QBENCHMARK {
632         object->emitMySignal();
633     }
634
635     delete object;
636 }
637
638 void tst_script::slot_complex_js()
639 {
640     QDeclarativeEngine engine;
641     QDeclarativeComponent component(&engine, TEST_FILE("slot_complex_js.qml"));
642     TestObject *object = qobject_cast<TestObject *>(component.create());
643     QVERIFY(object != 0);
644
645     QBENCHMARK {
646         object->emitMySignal();
647     }
648
649     delete object;
650 }
651
652 void tst_script::block_data()
653 {
654     QTest::addColumn<QString>("methodName");
655     QTest::newRow("direct") << "doSomethingDirect()";
656     QTest::newRow("localObj") << "doSomethingLocalObj()";
657     QTest::newRow("local") << "doSomethingLocal()";
658 }
659
660 void tst_script::block()
661 {
662     QFETCH(QString, methodName);
663     QDeclarativeEngine engine;
664     QDeclarativeComponent component(&engine, TEST_FILE("block.qml"));
665     QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle *>(component.create());
666     QVERIFY(rect != 0);
667
668     int index = rect->metaObject()->indexOfMethod(methodName.toUtf8());
669     QVERIFY(index != -1);
670     QMetaMethod method = rect->metaObject()->method(index);
671
672     QBENCHMARK {
673         method.invoke(rect, Qt::DirectConnection);
674     }
675
676     delete rect;
677 }
678
679 #define GLOBALPROPERTY_PROGRAM \
680     "(function() { " \
681     "    for (var ii = 0; ii < 10000; ++ii) { " \
682     "        Math.sin(90); " \
683     "    } " \
684     "})"
685
686 void tst_script::global_property_js()
687 {
688     QScriptEngine engine;
689
690     QScriptValue prog = engine.evaluate(GLOBALPROPERTY_PROGRAM);
691     prog.call();
692
693     QBENCHMARK {
694         prog.call();
695     }
696 }
697
698 void tst_script::global_property_qml()
699 {
700     QDeclarativeEngine qmlengine;
701
702     QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(&qmlengine);
703     QScriptValue prog = engine->evaluate(GLOBALPROPERTY_PROGRAM);
704     prog.call();
705
706     QBENCHMARK {
707         prog.call();
708     }
709 }
710
711 void tst_script::global_property_qml_js()
712 {
713     QDeclarativeEngine engine;
714     QDeclarativeComponent component(&engine, TEST_FILE("global_prop.qml"));
715     QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle *>(component.create());
716     QVERIFY(rect != 0);
717
718     int index = rect->metaObject()->indexOfMethod("triggered()");
719     QVERIFY(index != -1);
720     QMetaMethod method = rect->metaObject()->method(index);
721
722     QBENCHMARK {
723         method.invoke(rect, Qt::DirectConnection);
724     }
725
726     delete rect;
727 }
728
729 void tst_script::scriptfile_property()
730 {
731     QDeclarativeEngine engine;
732     QDeclarativeComponent component(&engine, TEST_FILE("global_prop.qml"));
733     QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle *>(component.create());
734     QVERIFY(rect != 0);
735
736     int index = rect->metaObject()->indexOfMethod("incrementTriggered()");
737     QVERIFY(index != -1);
738     QMetaMethod method = rect->metaObject()->method(index);
739
740     QBENCHMARK {
741         method.invoke(rect, Qt::DirectConnection);
742     }
743
744     delete rect;
745 }
746
747 void tst_script::enums()
748 {
749     QDeclarativeEngine engine;
750     QDeclarativeComponent component(&engine, TEST_FILE("enums.qml"));
751     QObject *o = component.create();
752     QVERIFY(o != 0);
753
754     int index = o->metaObject()->indexOfMethod("runtest()");
755     QVERIFY(index != -1);
756     QMetaMethod method = o->metaObject()->method(index);
757
758     QBENCHMARK {
759         method.invoke(o, Qt::DirectConnection);
760     }
761
762     delete o;
763 }
764
765 void tst_script::namespacedEnums()
766 {
767     QDeclarativeEngine engine;
768     QDeclarativeComponent component(&engine, TEST_FILE("namespacedEnums.qml"));
769     QObject *o = component.create();
770     QVERIFY(o != 0);
771
772     int index = o->metaObject()->indexOfMethod("runtest()");
773     QVERIFY(index != -1);
774     QMetaMethod method = o->metaObject()->method(index);
775
776     QBENCHMARK {
777         method.invoke(o, Qt::DirectConnection);
778     }
779
780     delete o;
781 }
782
783 void tst_script::scriptCall()
784 {
785     QDeclarativeEngine engine;
786     QDeclarativeComponent component(&engine, TEST_FILE("scriptCall.qml"));
787     QObject *o = component.create();
788     QVERIFY(o != 0);
789
790     int index = o->metaObject()->indexOfMethod("runtest()");
791     QVERIFY(index != -1);
792     QMetaMethod method = o->metaObject()->method(index);
793
794     QBENCHMARK {
795         method.invoke(o, Qt::DirectConnection);
796     }
797
798     delete o;
799 }
800
801 QTEST_MAIN(tst_script)
802
803 #include "tst_script.moc"