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