1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "testtypes.h"
45 #include <QDeclarativeEngine>
46 #include <QDeclarativeComponent>
47 #include <QDeclarativeContext>
48 #include <QDeclarativeProperty>
53 // In Symbian OS test data is located in applications private dir
57 // Conceptually, there are several different "holistic" areas to benchmark:
59 // - read file from disk
61 // - handle nested imports
63 // - create meta object templates etc
64 // - compile to bytecode and cache it
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)
69 // - bindings evaluation
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)
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.
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);
98 class tst_holistic : public QObject
109 qRegisterMetaType<PropertyNameList>("PropertyNameList");
110 qRegisterMetaType<PropertyValueList>("PropertyValueList");
113 void compilation_data();
115 void instantiation_data() { compilation_data(); }
116 void instantiation();
117 void creation_data() { compilation_data(); }
119 void dynamicity_data();
122 void cppToJsDirect_data();
123 void cppToJsDirect();
124 void cppToJsIndirect();
126 void typeResolution_data();
127 void typeResolution();
130 QDeclarativeEngine engine;
133 tst_holistic::tst_holistic()
137 inline QUrl TEST_FILE(const QString &filename)
139 return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
143 void tst_holistic::compilation_data()
145 QTest::addColumn<QStringList>("files");
146 QTest::addColumn<int>("repetitions");
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;
154 // Benchmarks: a single, small component ten times with caching.
155 QTest::newRow("single small component cached") << f << 10; f.clear();
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;
161 // Benchmarks: a single, large component ten times with caching.
162 QTest::newRow("single large component cached") << f << 10; f.clear();
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;
171 // Benchmarks: 4 small components ten times each with caching
172 QTest::newRow("multiple small components cached") << f << 10; f.clear();
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;
180 // Benchmarks: 3 large components ten times each with caching.
181 QTest::newRow("multiple large components cached") << f << 10; f.clear();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
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;
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();
261 void tst_holistic::compilation()
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.
267 QFETCH(QStringList, files);
268 QFETCH(int, repetitions);
269 Q_ASSERT(files.size() > 0);
270 Q_ASSERT(repetitions > 0);
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)));
282 void tst_holistic::instantiation()
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.
288 QFETCH(QStringList, files);
289 QFETCH(int, repetitions);
290 Q_ASSERT(files.size() > 0);
291 Q_ASSERT(repetitions > 0);
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);
300 // XXX TODO: clear each component's instantiation cache
302 for (int i = 0; i < repetitions; ++i) {
303 for (int j = 0; j < components.size(); ++j) {
304 QObject *obj = components.at(j)->create();
311 for (int i = 0; i < components.size(); ++i) {
312 delete components.at(i);
316 void tst_holistic::creation()
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.
322 QFETCH(QStringList, files);
323 QFETCH(int, repetitions);
324 Q_ASSERT(files.size() > 0);
325 Q_ASSERT(repetitions > 0);
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();
339 void tst_holistic::dynamicity_data()
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");
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"));
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"));
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"));
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"));
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"));
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"));
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"));
378 void tst_holistic::dynamicity()
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.
384 QFETCH(QString, file);
385 QFETCH(QString, writeProperty);
386 QFETCH(QVariant, writeValueOne);
387 QFETCH(QVariant, writeValueTwo);
388 QFETCH(QString, readProperty);
390 QDeclarativeComponent c(&engine, file);
391 QObject *obj = c.create();
395 bool usedFirst = false;
399 writeValue = writeValueTwo;
402 writeValue = writeValueOne;
406 obj->setProperty(writeProperty.toAscii().constData(), writeValue);
407 readValue = obj->property(readProperty.toAscii().constData());
419 void tst_holistic::cppToJsDirect_data()
421 QTest::addColumn<QString>("file");
422 QTest::addColumn<QString>("methodName");
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"));
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"));
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"));
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"));
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"));
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"));
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"));
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"));
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"));
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"));
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"));
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"));
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"));
491 void tst_holistic::cppToJsDirect()
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).
496 QFETCH(QString, file);
497 QFETCH(QString, methodName);
499 QDeclarativeComponent c(&engine, file);
500 QObject *obj = c.create();
503 QMetaObject::invokeMethod(obj, methodName.toLatin1().constData());
510 void tst_holistic::cppToJsIndirect()
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.
518 QDeclarativeComponent c(&engine, QString(SRCDIR + QLatin1String("/data/scopeSwitching/ScarceTwo.qml")));
519 QObject *obj = c.create();
521 ScarceResourceProvider *srp = 0;
522 srp = qobject_cast<ScarceResourceProvider*>(QDeclarativeProperty::read(obj, "a").value<QObject*>());
525 srp->changeResources(); // will cause small+large scarce resources changed signals to be emitted.
535 void tst_holistic::typeResolution_data()
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");
545 PropertyNameList pn1;
546 PropertyValueList pv1;
547 PropertyNameList pn2;
548 PropertyValueList pv2;
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;
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();
563 void tst_holistic::typeResolution()
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.
570 QFETCH(QString, file);
571 QFETCH(PropertyNameList, propertyNameOne);
572 QFETCH(PropertyValueList, propertyValueOne);
573 QFETCH(PropertyNameList, propertyNameTwo);
574 QFETCH(PropertyValueList, propertyValueTwo);
575 QFETCH(int, repetitions);
577 Q_ASSERT(propertyNameOne.size() == propertyValueOne.size());
578 Q_ASSERT(propertyNameTwo.size() == propertyValueTwo.size());
579 Q_ASSERT(repetitions > 0);
581 QDeclarativeComponent c(&engine, file);
582 QObject *obj = c.create();
584 PropertyNameList writeProperty;
585 PropertyValueList writeValue;
586 bool usedFirst = false;
589 for (int i = 0; i < repetitions; ++i) {
591 writeProperty = propertyNameOne;
592 writeValue = propertyValueOne;
595 writeProperty = propertyNameTwo;
596 writeValue = propertyValueTwo;
600 for (int j = 0; j < writeProperty.size(); ++j) {
601 obj->setProperty(writeProperty.at(j).toAscii().constData(), writeValue.at(j));
610 QTEST_MAIN(tst_holistic)
612 #include "tst_holistic.moc"