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