102a91cb255837de9d40362bff427e4c39ce53ab
[profile/ivi/qtdeclarative.git] / tests / benchmarks / declarative / holistic / tst_holistic.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 ** 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 "testtypes.h"
43
44 #include <qtest.h>
45 #include <QDeclarativeEngine>
46 #include <QDeclarativeComponent>
47 #include <QDeclarativeContext>
48 #include <QDeclarativeProperty>
49 #include <QFile>
50 #include <QDebug>
51
52 #ifdef Q_OS_SYMBIAN
53 // In Symbian OS test data is located in applications private dir
54 #define SRCDIR "."
55 #endif
56
57 // Conceptually, there are several different "holistic" areas to benchmark:
58 // 1) Loading
59 //     - read file from disk
60 //     - parse/lex file
61 //     - handle nested imports
62 // 2) Compilation
63 //     - create meta object templates etc
64 //     - compile to bytecode and cache it
65 // 3) Instantiation
66 //     - running the bytecode to create an object tree, assign properties, etc
67 //     - and, importantly, to evaluate bindings for the first time (incl. js expressions)
68 // 4) Dynamicism
69 //     - bindings evaluation
70 //     - signal handlers
71 //
72 // Aside from this, we also need to determine:
73 // 1) JavaScript Metrics
74 //     - simple expressions
75 //     - complex expressions
76 //     - instantiation vs evaluation time
77 //     - imports and nested imports
78 // 2) Context-switch costs
79 //     - how expensive is it to call a cpp function from QML
80 //     - how expensive is it to call a js function from cpp via QML
81 //     - how expensive is it to pass around objects between them
82 // 3) Complete creation time.
83 //     - loading + compilation + instantiation (for "application startup time" metric)
84 //
85 // In some cases, we want to include "initialization costs";
86 // i.e., we need to tell the engine not to cache type data resulting
87 // in compilation between rounds, and we need to tell the engine not
88 // to cache whatever it caches between instantiations of components.
89 // The reason for this is that it is often the "first start of application"
90 // performance which we're attempting to benchmark.
91
92 // define some custom types we use in test data functions.
93 typedef QList<QString> PropertyNameList;
94 Q_DECLARE_METATYPE(PropertyNameList);
95 typedef QList<QVariant> PropertyValueList;
96 Q_DECLARE_METATYPE(PropertyValueList);
97
98 class tst_holistic : public QObject
99 {
100     Q_OBJECT
101
102 public:
103     tst_holistic();
104
105 private slots:
106     void initTestCase()
107     {
108         registerTypes();
109         qRegisterMetaType<PropertyNameList>("PropertyNameList");
110         qRegisterMetaType<PropertyValueList>("PropertyValueList");
111     }
112
113     void compilation_data();
114     void compilation();
115     void instantiation_data() { compilation_data(); }
116     void instantiation();
117     void creation_data() { compilation_data(); }
118     void creation();
119     void dynamicity_data();
120     void dynamicity();
121
122     void cppToJsDirect_data();
123     void cppToJsDirect();
124     void cppToJsIndirect();
125
126     void typeResolution_data();
127     void typeResolution();
128
129 private:
130     QDeclarativeEngine engine;
131 };
132
133 tst_holistic::tst_holistic()
134 {
135 }
136
137 inline QUrl TEST_FILE(const QString &filename)
138 {
139     return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
140 }
141
142
143 void tst_holistic::compilation_data()
144 {
145     QTest::addColumn<QStringList>("files");
146     QTest::addColumn<int>("repetitions");
147
148     QStringList f;
149
150     // Benchmarks: a single, small component once with no caching.
151     f << QString(SRCDIR + QLatin1String("/data/smallTargets/SmallOne.qml"));
152     QTest::newRow("single small component") << f << 1;
153
154     // Benchmarks: a single, small component ten times with caching.
155     QTest::newRow("single small component cached") << f << 10; f.clear();
156
157     // Benchmarks: a single, large component once with no caching.
158     f << QString(SRCDIR + QLatin1String("/data/largeTargets/mousearea-example.qml"));
159     QTest::newRow("single large component") << f << 1;
160
161     // Benchmarks: a single, large component ten times with caching.
162     QTest::newRow("single large component cached") << f << 10; f.clear();
163
164     // Benchmarks: 4 small components once each with no caching
165     f << QString(SRCDIR + QLatin1String("/data/smallTargets/SmallOne.qml"));
166     f << QString(SRCDIR + QLatin1String("/data/smallTargets/SmallTwo.qml"));
167     f << QString(SRCDIR + QLatin1String("/data/smallTargets/SmallThree.qml"));
168     f << QString(SRCDIR + QLatin1String("/data/smallTargets/SmallFour.qml"));
169     QTest::newRow("multiple small components") << f << 1;
170
171     // Benchmarks: 4 small components ten times each with caching
172     QTest::newRow("multiple small components cached") << f << 10; f.clear();
173
174     // Benchmarks: 3 large components once each with no caching.
175     f << QString(SRCDIR + QLatin1String("/data/largeTargets/mousearea-example.qml"));
176     f << QString(SRCDIR + QLatin1String("/data/largeTargets/gridview-example.qml"));
177     f << QString(SRCDIR + QLatin1String("/data/largeTargets/layoutdirection.qml"));
178     QTest::newRow("multiple large components") << f << 1;
179
180     // Benchmarks: 3 large components ten times each with caching.
181     QTest::newRow("multiple large components cached") << f << 10; f.clear();
182
183     // Benchmarks: single small component which imports a single small js file, no caching
184     f << QString(SRCDIR + QLatin1String("/data/jsImports/Sssi.qml"));
185     QTest::newRow("single small js import") << f << 1;
186
187     // Benchmarks: single small component which imports a single small js file, 10 reps, with caching
188     QTest::newRow("single small js import, cached") << f << 10; f.clear();
189
190     // Benchmarks: single small component which imports multiple small js files (no deep nesting), no caching
191     f << QString(SRCDIR + QLatin1String("/data/jsImports/Msbsi.qml"));
192     QTest::newRow("multiple small js imports, shallow") << f << 1;
193
194     // Benchmarks: single small component which imports multiple small js files (no deep nesting), 10 reps, with caching
195     QTest::newRow("multiple small js imports, shallow, cached") << f << 10; f.clear();
196
197     // Benchmarks: single small component which imports multiple small js files (with deep nesting), no caching
198     f << QString(SRCDIR + QLatin1String("/data/jsImports/Msdsi.qml"));
199     QTest::newRow("multiple small js imports, deeply nested") << f << 1;
200
201     // Benchmarks: single small component which imports multiple small js files (with deep nesting), 10 reps, with caching
202     QTest::newRow("multiple small js imports, deeply nested, cached") << f << 10; f.clear();
203
204     // Benchmarks: single small component which imports multiple small js files (nested and unnested), no caching
205     f << QString(SRCDIR + QLatin1String("/data/jsImports/Mssi.qml"));
206     QTest::newRow("muliple small js imports, both") << f << 1;
207
208     // Benchmarks: single small component which imports multiple small js files (nested and unnested), 10 reps, with caching
209     QTest::newRow("muliple small js imports, both, cached") << f << 10; f.clear();
210
211     // Benchmarks: single small component which imports a single large js file, no caching
212     f << QString(SRCDIR + QLatin1String("/data/jsImports/Slsi.qml"));
213     QTest::newRow("single large js import") << f << 1;
214
215     // Benchmarks: single small component which imports a single large js file, 10 reps, with caching
216     QTest::newRow("single large js import, cached") << f << 10; f.clear();
217
218     // Benchmarks: single small component which imports multiple large js files (no deep nesting), no caching
219     f << QString(SRCDIR + QLatin1String("/data/jsImports/Mlbsi.qml"));
220     QTest::newRow("multiple large js imports, shallow") << f << 1;
221
222     // Benchmarks: single small component which imports multiple large js files (no deep nesting), 10 reps, with caching
223     QTest::newRow("multiple large js imports, shallow, cached") << f << 10; f.clear();
224
225     // Benchmarks: single small component which imports multiple large js files (with deep nesting), no caching
226     f << QString(SRCDIR + QLatin1String("/data/jsImports/Mldsi.qml"));
227     QTest::newRow("multiple large js imports, deeply nested") << f << 1;
228
229     // Benchmarks: single small component which imports multiple large js files (with deep nesting), 10 reps, with caching
230     QTest::newRow("multiple large js imports, deeply nested, cached") << f << 10; f.clear();
231
232     // Benchmarks: single small component which imports multiple large js files (nested and unnested), no caching
233     f << QString(SRCDIR + QLatin1String("/data/jsImports/Mlsi.qml"));
234     QTest::newRow("multiple large js imports, both") << f << 1;
235
236     // Benchmarks: single small component which imports multiple large js files (nested and unnested), 10 reps, with caching
237     QTest::newRow("multiple large js imports, both, cached") << f << 10; f.clear();
238
239     // Benchmarks: single small component which imports multiple js files which all import a .pragma library js file, no caching
240     f << QString(SRCDIR + QLatin1String("/data/jsImports/PragmaBm.qml"));
241     QTest::newRow(".pragma library js import") << f << 1;
242
243     // Benchmarks: single small component which imports multiple js files which all import a .pragma library js file, 10 reps, with caching
244     QTest::newRow(".pragma library js import, cached") << f << 10; f.clear();
245
246     // Benchmarks: single small component which imports a js file which imports a QML module, no caching
247     f << QString(SRCDIR + QLatin1String("/data/jsImports/ModuleBm.qml"));
248     QTest::newRow("import js with QML import") << f << 1;
249
250     // Benchmarks: single small component which imports a js file which imports a QML module, 10 reps, with caching
251     QTest::newRow("import js with QML import, cached") << f << 10; f.clear();
252
253     // Benchmarks: single small component which imports multiple js files which all import a .pragma library js file and a QML module, no caching
254     f << QString(SRCDIR + QLatin1String("/data/jsImports/PragmaModuleBm.qml"));
255     QTest::newRow("import js with QML import and .pragma library") << f << 1;
256
257     // Benchmarks: single small component which imports multiple js files which all import a .pragma library js file and a QML module, 10 reps, with caching
258     QTest::newRow("import js with QML import and .pragma library, cached") << f << 10; f.clear();
259 }
260
261 void tst_holistic::compilation()
262 {
263     // This function benchmarks the cost of loading and compiling specified QML files.
264     // If "repetitions" is non-zero, each file from "files" will be compiled "repetitions"
265     // times, without clearing the engine's component cache between compilations.
266
267     QFETCH(QStringList, files);
268     QFETCH(int, repetitions);
269     Q_ASSERT(files.size() > 0);
270     Q_ASSERT(repetitions > 0);
271
272     QBENCHMARK {
273         engine.clearComponentCache();
274         for (int i = 0; i < repetitions; ++i) {
275             for (int j = 0; j < files.size(); ++j) {
276                 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(files.at(j)));
277             }
278         }
279     }
280 }
281
282 void tst_holistic::instantiation()
283 {
284     // This function benchmarks the cost of instantiating components compiled from specified QML files.
285     // If "repetitions" is non-zero, each component compiled from "files" will be instantiated "repetitions"
286     // times, without clearing the component's instantiation cache between instantiations.
287
288     QFETCH(QStringList, files);
289     QFETCH(int, repetitions);
290     Q_ASSERT(files.size() > 0);
291     Q_ASSERT(repetitions > 0);
292
293     QList<QDeclarativeComponent*> components;
294     for (int i = 0; i < files.size(); ++i) {
295         QDeclarativeComponent *c = new QDeclarativeComponent(&engine, QUrl::fromLocalFile(files.at(i)));
296         components.append(c);
297     }
298
299     QBENCHMARK {
300         // XXX TODO: clear each component's instantiation cache
301
302         for (int i = 0; i < repetitions; ++i) {
303             for (int j = 0; j < components.size(); ++j) {
304                 QObject *obj = components.at(j)->create();
305                 delete obj;
306             }
307         }
308     }
309
310     // cleanup
311     for (int i = 0; i < components.size(); ++i) {
312         delete components.at(i);
313     }
314 }
315
316 void tst_holistic::creation()
317 {
318     // This function benchmarks the cost of loading, compiling  and instantiating specified QML files.
319     // If "repetitions" is non-zero, each file from "files" will be created "repetitions"
320     // times, without clearing the engine's component cache between component creation.
321
322     QFETCH(QStringList, files);
323     QFETCH(int, repetitions);
324     Q_ASSERT(files.size() > 0);
325     Q_ASSERT(repetitions > 0);
326
327     QBENCHMARK {
328         engine.clearComponentCache();
329         for (int i = 0; i < repetitions; ++i) {
330             for (int j = 0; j < files.size(); ++j) {
331                 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(files.at(j)));
332                 QObject *obj = c.create();
333                 delete obj;
334             }
335         }
336     }
337 }
338
339 void tst_holistic::dynamicity_data()
340 {
341     QTest::addColumn<QString>("file");
342     QTest::addColumn<QString>("writeProperty");
343     QTest::addColumn<QVariant>("writeValueOne");
344     QTest::addColumn<QVariant>("writeValueTwo");
345     QTest::addColumn<QString>("readProperty");
346
347     QString f;
348
349     // Benchmarks: single simple property binding
350     f = QString(SRCDIR + QLatin1String("/data/dynamicTargets/DynamicOne.qml"));
351     QTest::newRow("single simple property binding") << f << QString(QLatin1String("dynamicWidth")) << QVariant(300) << QVariant(500) << QString(QLatin1String("height"));
352
353     // Benchmarks: multiple simple property bindings in one component
354     f = QString(SRCDIR + QLatin1String("/data/dynamicTargets/DynamicTwo.qml"));
355     QTest::newRow("multiple simple property bindings") << f << QString(QLatin1String("dynamicWidth")) << QVariant(300) << QVariant(500) << QString(QLatin1String("dynamicWidth"));
356
357     // Benchmarks: single simple property binding plus onPropertyChanged slot
358     f = QString(SRCDIR + QLatin1String("/data/dynamicTargets/DynamicThree.qml"));
359     QTest::newRow("single simple plus slot") << f << QString(QLatin1String("dynamicWidth")) << QVariant(300) << QVariant(500) << QString(QLatin1String("dynamicWidth"));
360
361     // Benchmarks: multiple simple property bindings plus multiple onPropertyChanged slots in one component
362     f = QString(SRCDIR + QLatin1String("/data/dynamicTargets/DynamicFour.qml"));
363     QTest::newRow("multiple simple plus slots") << f << QString(QLatin1String("dynamicWidth")) << QVariant(300) << QVariant(500) << QString(QLatin1String("dynamicHeight"));
364
365     // Benchmarks: single simple js expression in a slot
366     f = QString(SRCDIR + QLatin1String("/data/jsTargets/JsOne.qml"));
367     QTest::newRow("single simple js expression slot") << f << QString(QLatin1String("dynamicWidth")) << QVariant(300) << QVariant(500) << QString(QLatin1String("dynamicWidth"));
368
369     // Benchmarks: single complex js expression in a slot
370     f = QString(SRCDIR + QLatin1String("/data/jsTargets/JsTwo.qml"));
371     QTest::newRow("single complex js expression slot") << f << QString(QLatin1String("dynamicWidth")) << QVariant(300) << QVariant(500) << QString(QLatin1String("dynamicWidth"));
372
373     // Benchmarks: simple property assignment and bindings update
374     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/CppToQml.qml"));
375     QTest::newRow("single simple property binding") << f << QString(QLatin1String("arbitrary")) << QVariant(36) << QVariant(35) << QString(QLatin1String("arbitrary"));
376 }
377
378 void tst_holistic::dynamicity()
379 {
380     // This function benchmarks the cost of "continued operation" - signal invocation,
381     // updating bindings, etc.  Note that we take two different writeValues in order
382     // to force updates to occur, and we read to force lazy evaluation to occur.
383
384     QFETCH(QString, file);
385     QFETCH(QString, writeProperty);
386     QFETCH(QVariant, writeValueOne);
387     QFETCH(QVariant, writeValueTwo);
388     QFETCH(QString, readProperty);
389
390     QDeclarativeComponent c(&engine, file);
391     QObject *obj = c.create();
392
393     QVariant readValue;
394     QVariant writeValue;
395     bool usedFirst = false;
396
397     QBENCHMARK {
398         if (usedFirst) {
399             writeValue = writeValueTwo;
400             usedFirst = false;
401         } else {
402             writeValue = writeValueOne;
403             usedFirst = true;
404         }
405
406         obj->setProperty(writeProperty.toAscii().constData(), writeValue);
407         readValue = obj->property(readProperty.toAscii().constData());
408     }
409
410     delete obj;
411 }
412
413
414
415
416
417
418
419 void tst_holistic::cppToJsDirect_data()
420 {
421     QTest::addColumn<QString>("file");
422     QTest::addColumn<QString>("methodName");
423
424     QString f;
425
426     // Benchmarks: cost of calling a js function from cpp directly
427     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/CppToJs.qml"));
428     QTest::newRow("cpp-to-js") << f << QString(QLatin1String("callJsFunction"));
429
430     // Benchmarks: cost of calling js function which calls cpp function:
431     // const CPP function with no return value and no arguments.
432     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppOne.qml"));
433     QTest::newRow("cpp-to-js-to-cpp: no retn, no args") << f << QString(QLatin1String("callCppFunction"));
434
435     // Benchmarks: cost of calling js function which calls cpp function:
436     // nonconst CPP function with no return value and no arguments.
437     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppTwo.qml"));
438     QTest::newRow("cpp-to-js-to-cpp: nonconst, no retn, no args") << f << QString(QLatin1String("callCppFunction"));
439
440     // Benchmarks: cost of calling js function which calls cpp function:
441     // const CPP function with no return value and a single integer argument.
442     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppThree.qml"));
443     QTest::newRow("cpp-to-js-to-cpp: const, no retn, int arg") << f << QString(QLatin1String("callCppFunction"));
444
445     // Benchmarks: cost of calling js function which calls cpp function:
446     // nonconst CPP function with no return value and a single integer argument.
447     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppFour.qml"));
448     QTest::newRow("cpp-to-js-to-cpp: nonconst, no retn, int arg") << f << QString(QLatin1String("callCppFunction"));
449
450     // Benchmarks: cost of calling js function which calls cpp function:
451     // const CPP function with an integer return value and no arguments.
452     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppFive.qml"));
453     QTest::newRow("cpp-to-js-to-cpp: const, int retn, no args") << f << QString(QLatin1String("callCppFunction"));
454
455     // Benchmarks: cost of calling js function which calls cpp function:
456     // nonconst CPP function with an integer return value and no arguments.
457     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppSix.qml"));
458     QTest::newRow("cpp-to-js-to-cpp: nonconst, int retn, no args") << f << QString(QLatin1String("callCppFunction"));
459
460     // Benchmarks: cost of calling js function which calls cpp function:
461     // const CPP function with an integer return value and a single integer argument.
462     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppSeven.qml"));
463     QTest::newRow("cpp-to-js-to-cpp: const, int retn, int arg") << f << QString(QLatin1String("callCppFunction"));
464
465     // Benchmarks: cost of calling js function which calls cpp function:
466     // nonconst CPP function with an integer return value and a single integer argument.
467     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppEight.qml"));
468     QTest::newRow("cpp-to-js-to-cpp: nonconst, int retn, int arg") << f << QString(QLatin1String("callCppFunction"));
469
470     // Benchmarks: cost of calling js function which calls cpp function:
471     // const CPP function with a variant return value and multiple integer arguments.
472     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppNine.qml"));
473     QTest::newRow("cpp-to-js-to-cpp: const, variant retn, int args") << f << QString(QLatin1String("callCppFunction"));
474
475     // Benchmarks: cost of calling js function which calls cpp function:
476     // nonconst CPP function with a variant return value and multiple integer arguments.
477     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppTen.qml"));
478     QTest::newRow("cpp-to-js-to-cpp: nonconst, variant retn, int args") << f << QString(QLatin1String("callCppFunction"));
479
480     // Benchmarks: cost of calling js function which calls cpp function:
481     // nonconst CPP function with a variant return value and multiple integer arguments.
482     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/JsToCppEleven.qml"));
483     QTest::newRow("cpp-to-js-to-cpp: nonconst, variant retn, variant + int args") << f << QString(QLatin1String("callCppFunction"));
484
485     // Benchmarks: calling js function which copies scarce resources by calling back into cpp scope
486     f = QString(SRCDIR + QLatin1String("/data/scopeSwitching/ScarceOne.qml"));
487     QTest::newRow("cpp-to-js-to-coo: copy scarce resources") << f << QString(QLatin1String("copyScarceResources"));
488 }
489
490
491 void tst_holistic::cppToJsDirect()
492 {
493     // This function benchmarks the cost of calling from CPP scope to JS scope
494     // (and possibly vice versa, if the invoked js method then calls to cpp).
495
496     QFETCH(QString, file);
497     QFETCH(QString, methodName);
498
499     QDeclarativeComponent c(&engine, file);
500     QObject *obj = c.create();
501
502     QBENCHMARK {
503         QMetaObject::invokeMethod(obj, methodName.toLatin1().constData());
504     }
505
506     delete obj;
507 }
508
509
510 void tst_holistic::cppToJsIndirect()
511 {
512     // This function benchmarks the cost of binding scarce resources
513     // to properties of a QML component.  The engine should automatically release such
514     // resources when they are no longer used.
515     // The benchmark deliberately causes change signals to be emitted (and
516     // modifies the scarce resources) so that the properties are updated.
517
518     QDeclarativeComponent c(&engine, QString(SRCDIR + QLatin1String("/data/scopeSwitching/ScarceTwo.qml")));
519     QObject *obj = c.create();
520
521     ScarceResourceProvider *srp = 0;
522     srp = qobject_cast<ScarceResourceProvider*>(QDeclarativeProperty::read(obj, "a").value<QObject*>());
523
524     QBENCHMARK {
525         srp->changeResources(); // will cause small+large scarce resources changed signals to be emitted.
526     }
527
528     delete obj;
529 }
530
531
532
533
534
535 void tst_holistic::typeResolution_data()
536 {
537     QTest::addColumn<QString>("file");
538     QTest::addColumn<PropertyNameList>("propertyNameOne");
539     QTest::addColumn<PropertyValueList>("propertyValueOne");
540     QTest::addColumn<PropertyNameList>("propertyNameTwo");
541     QTest::addColumn<PropertyValueList>("propertyValueTwo");
542     QTest::addColumn<int>("repetitions");
543
544     QString f;
545     PropertyNameList pn1;
546     PropertyValueList pv1;
547     PropertyNameList pn2;
548     PropertyValueList pv2;
549
550     // Benchmarks: resolving nested ids and types, no caching
551     f = QString(SRCDIR + QLatin1String("/data/resolutionTargets/ResolveOne.qml"));
552     pn1 << QString(QLatin1String("baseWidth")) << QString(QLatin1String("baseHeight")) << QString(QLatin1String("baseColor"));
553     pv1 << QVariant(401) << QVariant(402) << QVariant(QString(QLatin1String("brown")));
554     pn2 << QString(QLatin1String("baseWidth")) << QString(QLatin1String("baseHeight")) << QString(QLatin1String("baseColor"));
555     pv2 << QVariant(403) << QVariant(404) << QVariant(QString(QLatin1String("orange")));
556     QTest::newRow("nested id resolution") << f << pn1 << pv1 << pn2 << pv2 << 1;
557
558     // Benchmarks: resolving nested ids and types, 10 reps with caching
559     QTest::newRow("nested id resolution, cached") << f << pn1 << pv1 << pn2 << pv2 << 10;
560     pn1.clear(); pn2.clear(); pv1.clear(); pv2.clear();
561 }
562
563 void tst_holistic::typeResolution()
564 {
565     // This function benchmarks the cost of "continued operation" (signal invocation,
566     // updating bindings, etc) where the component has lots of nested items with
567     // lots of resolving required.  Note that we take two different writeValues in order
568     // to force updates to occur.
569
570     QFETCH(QString, file);
571     QFETCH(PropertyNameList, propertyNameOne);
572     QFETCH(PropertyValueList, propertyValueOne);
573     QFETCH(PropertyNameList, propertyNameTwo);
574     QFETCH(PropertyValueList, propertyValueTwo);
575     QFETCH(int, repetitions);
576
577     Q_ASSERT(propertyNameOne.size() == propertyValueOne.size());
578     Q_ASSERT(propertyNameTwo.size() == propertyValueTwo.size());
579     Q_ASSERT(repetitions > 0);
580
581     QDeclarativeComponent c(&engine, file);
582     QObject *obj = c.create();
583
584     PropertyNameList writeProperty;
585     PropertyValueList writeValue;
586     bool usedFirst = false;
587
588     QBENCHMARK {
589         for (int i = 0; i < repetitions; ++i) {
590             if (usedFirst) {
591                 writeProperty = propertyNameOne;
592                 writeValue = propertyValueOne;
593                 usedFirst = false;
594             } else {
595                 writeProperty = propertyNameTwo;
596                 writeValue = propertyValueTwo;
597                 usedFirst = true;
598             }
599
600             for (int j = 0; j < writeProperty.size(); ++j) {
601                 obj->setProperty(writeProperty.at(j).toAscii().constData(), writeValue.at(j));
602             }
603         }
604     }
605
606     delete obj;
607 }
608
609
610 QTEST_MAIN(tst_holistic)
611
612 #include "tst_holistic.moc"