1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtDeclarative/private/qdeclarativedom_p.h>
45 
46 #include <QtCore/QDebug>
47 #include <QtCore/QFile>
48 
49 #ifdef Q_OS_SYMBIAN
50 // In Symbian OS test data is located in applications private dir
51 #define SRCDIR "."
52 #endif
53 
54 class tst_qdeclarativedom : public QObject
55 {
56     Q_OBJECT
57 public:
tst_qdeclarativedom()58     tst_qdeclarativedom() {}
59 
60 private slots:
61     void loadSimple();
62     void loadProperties();
63     void loadGroupedProperties();
64     void loadChildObject();
65     void loadComposite();
66     void loadImports();
67     void loadErrors();
68     void loadSyntaxErrors();
69     void loadRemoteErrors();
70     void loadDynamicProperty();
71     void loadComponent();
72 
73     void testValueSource();
74     void testValueInterceptor();
75 
76     void object_dynamicProperty();
77     void object_property();
78     void object_url();
79 
80     void copy();
81     void position();
82 private:
83     QDeclarativeEngine engine;
84 };
85 
86 
loadSimple()87 void tst_qdeclarativedom::loadSimple()
88 {
89     QByteArray qml = "import QtQuick 1.0\n"
90                       "Item {}";
91 
92     QDeclarativeDomDocument document;
93     QVERIFY(document.load(&engine, qml));
94     QVERIFY(document.errors().isEmpty());
95 
96     QDeclarativeDomObject rootObject = document.rootObject();
97     QVERIFY(rootObject.isValid());
98     QVERIFY(!rootObject.isComponent());
99     QVERIFY(!rootObject.isCustomType());
100     QVERIFY(rootObject.objectType() == "QtQuick/Item");
101     QVERIFY(rootObject.objectTypeMajorVersion() == 1);
102     QVERIFY(rootObject.objectTypeMinorVersion() == 0);
103 }
104 
105 // Test regular properties
loadProperties()106 void tst_qdeclarativedom::loadProperties()
107 {
108     QByteArray qml = "import QtQuick 1.0\n"
109                      "Item { id : item; x : 300; visible : true }";
110 
111     QDeclarativeDomDocument document;
112     QVERIFY(document.load(&engine, qml));
113 
114     QDeclarativeDomObject rootObject = document.rootObject();
115     QVERIFY(rootObject.isValid());
116     QVERIFY(rootObject.objectId() == "item");
117     QCOMPARE(rootObject.properties().size(), 3);
118 
119     QDeclarativeDomProperty xProperty = rootObject.property("x");
120     QVERIFY(xProperty.propertyName() == "x");
121     QCOMPARE(xProperty.propertyNameParts().count(), 1);
122     QVERIFY(xProperty.propertyNameParts().at(0) == "x");
123     QCOMPARE(xProperty.position(), 37);
124     QCOMPARE(xProperty.length(), 1);
125     QVERIFY(xProperty.value().isLiteral());
126     QVERIFY(xProperty.value().toLiteral().literal() == "300");
127 
128     QDeclarativeDomProperty visibleProperty = rootObject.property("visible");
129     QVERIFY(visibleProperty.propertyName() == "visible");
130     QCOMPARE(visibleProperty.propertyNameParts().count(), 1);
131     QVERIFY(visibleProperty.propertyNameParts().at(0) == "visible");
132     QCOMPARE(visibleProperty.position(), 46);
133     QCOMPARE(visibleProperty.length(), 7);
134     QVERIFY(visibleProperty.value().isLiteral());
135     QVERIFY(visibleProperty.value().toLiteral().literal() == "true");
136 }
137 
138 // Test grouped properties
loadGroupedProperties()139 void tst_qdeclarativedom::loadGroupedProperties()
140 {
141     {
142         QByteArray qml = "import QtQuick 1.0\n"
143                          "Item { anchors.left: parent.left; anchors.right: parent.right }";
144 
145         QDeclarativeDomDocument document;
146         QVERIFY(document.load(&engine, qml));
147 
148         QDeclarativeDomObject rootItem = document.rootObject();
149         QVERIFY(rootItem.isValid());
150         QVERIFY(rootItem.properties().size() == 2);
151 
152         // Order is not deterministic
153         QDeclarativeDomProperty p0 = rootItem.properties().at(0);
154         QDeclarativeDomProperty p1 = rootItem.properties().at(1);
155         QDeclarativeDomProperty leftProperty;
156         QDeclarativeDomProperty rightProperty;
157         if (p0.propertyName() == "anchors.left") {
158             leftProperty = p0;
159             rightProperty = p1;
160         } else {
161             leftProperty = p1;
162             rightProperty = p0;
163         }
164 
165         QVERIFY(leftProperty.propertyName() == "anchors.left");
166         QCOMPARE(leftProperty.propertyNameParts().count(), 2);
167         QVERIFY(leftProperty.propertyNameParts().at(0) == "anchors");
168         QVERIFY(leftProperty.propertyNameParts().at(1) == "left");
169         QCOMPARE(leftProperty.position(), 26);
170         QCOMPARE(leftProperty.length(), 12);
171         QVERIFY(leftProperty.value().isBinding());
172         QVERIFY(leftProperty.value().toBinding().binding() == "parent.left");
173 
174         QVERIFY(rightProperty.propertyName() == "anchors.right");
175         QCOMPARE(rightProperty.propertyNameParts().count(), 2);
176         QVERIFY(rightProperty.propertyNameParts().at(0) == "anchors");
177         QVERIFY(rightProperty.propertyNameParts().at(1) == "right");
178         QCOMPARE(rightProperty.position(), 53);
179         QCOMPARE(rightProperty.length(), 13);
180         QVERIFY(rightProperty.value().isBinding());
181         QVERIFY(rightProperty.value().toBinding().binding() == "parent.right");
182     }
183 
184     {
185         QByteArray qml = "import QtQuick 1.0\n"
186                          "Item { \n"
187                          "    anchors {\n"
188                          "        left: parent.left\n"
189                          "        right: parent.right\n"
190                          "    }\n"
191                          "}";
192 
193         QDeclarativeDomDocument document;
194         QVERIFY(document.load(&engine, qml));
195 
196         QDeclarativeDomObject rootItem = document.rootObject();
197         QVERIFY(rootItem.isValid());
198         QVERIFY(rootItem.properties().size() == 2);
199 
200         // Order is not deterministic
201         QDeclarativeDomProperty p0 = rootItem.properties().at(0);
202         QDeclarativeDomProperty p1 = rootItem.properties().at(1);
203         QDeclarativeDomProperty leftProperty;
204         QDeclarativeDomProperty rightProperty;
205         if (p0.propertyName() == "anchors.left") {
206             leftProperty = p0;
207             rightProperty = p1;
208         } else {
209             leftProperty = p1;
210             rightProperty = p0;
211         }
212 
213         QVERIFY(leftProperty.propertyName() == "anchors.left");
214         QCOMPARE(leftProperty.propertyNameParts().count(), 2);
215         QVERIFY(leftProperty.propertyNameParts().at(0) == "anchors");
216         QVERIFY(leftProperty.propertyNameParts().at(1) == "left");
217         QCOMPARE(leftProperty.position(), 49);
218         QCOMPARE(leftProperty.length(), 4);
219         QVERIFY(leftProperty.value().isBinding());
220         QVERIFY(leftProperty.value().toBinding().binding() == "parent.left");
221 
222         QVERIFY(rightProperty.propertyName() == "anchors.right");
223         QCOMPARE(rightProperty.propertyNameParts().count(), 2);
224         QVERIFY(rightProperty.propertyNameParts().at(0) == "anchors");
225         QVERIFY(rightProperty.propertyNameParts().at(1) == "right");
226         QCOMPARE(rightProperty.position(), 75);
227         QCOMPARE(rightProperty.length(), 5);
228         QVERIFY(rightProperty.value().isBinding());
229         QVERIFY(rightProperty.value().toBinding().binding() == "parent.right");
230     }
231 
232 }
233 
loadChildObject()234 void tst_qdeclarativedom::loadChildObject()
235 {
236     QByteArray qml = "import QtQuick 1.0\n"
237                      "Item { Item {} }";
238 
239     QDeclarativeDomDocument document;
240     QVERIFY(document.load(&engine, qml));
241 
242     QDeclarativeDomObject rootItem = document.rootObject();
243     QVERIFY(rootItem.isValid());
244     QVERIFY(rootItem.properties().size() == 1);
245 
246     QDeclarativeDomProperty listProperty = rootItem.properties().at(0);
247     QVERIFY(listProperty.isDefaultProperty());
248     QVERIFY(listProperty.value().isList());
249 
250     QDeclarativeDomList list = listProperty.value().toList();
251     QVERIFY(list.values().size() == 1);
252 
253     QDeclarativeDomObject childItem = list.values().first().toObject();
254     QVERIFY(childItem.isValid());
255     QVERIFY(childItem.objectType() == "QtQuick/Item");
256 }
257 
loadComposite()258 void tst_qdeclarativedom::loadComposite()
259 {
260     QFile file(SRCDIR  "/data/top.qml");
261     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
262 
263     QDeclarativeDomDocument document;
264     QVERIFY(document.load(&engine, file.readAll(), QUrl::fromLocalFile(file.fileName())));
265     QVERIFY(document.errors().isEmpty());
266 
267     QDeclarativeDomObject rootItem = document.rootObject();
268     QVERIFY(rootItem.isValid());
269     QCOMPARE(rootItem.objectType(), QByteArray("MyComponent"));
270     QCOMPARE(rootItem.properties().size(), 2);
271 
272     QDeclarativeDomProperty widthProperty = rootItem.property("width");
273     QVERIFY(widthProperty.value().isLiteral());
274 
275     QDeclarativeDomProperty heightProperty = rootItem.property("height");
276     QVERIFY(heightProperty.value().isLiteral());
277 }
278 
testValueSource()279 void tst_qdeclarativedom::testValueSource()
280 {
281     QByteArray qml = "import QtQuick 1.0\n"
282                      "Rectangle { SpringAnimation on height { spring: 1.4; damping: .15; to: Math.min(Math.max(-130, value*2.2 - 130), 133); }}";
283 
284     QDeclarativeEngine freshEngine;
285     QDeclarativeDomDocument document;
286     QVERIFY(document.load(&freshEngine, qml));
287 
288     QDeclarativeDomObject rootItem = document.rootObject();
289     QVERIFY(rootItem.isValid());
290     QDeclarativeDomProperty heightProperty = rootItem.properties().at(0);
291     QVERIFY(heightProperty.propertyName() == "height");
292     QVERIFY(heightProperty.value().isValueSource());
293 
294     const QDeclarativeDomValueValueSource valueSource = heightProperty.value().toValueSource();
295     QDeclarativeDomObject valueSourceObject = valueSource.object();
296     QVERIFY(valueSourceObject.isValid());
297 
298     QVERIFY(valueSourceObject.objectType() == "QtQuick/SpringAnimation");
299 
300     const QDeclarativeDomValue springValue = valueSourceObject.property("spring").value();
301     QVERIFY(!springValue.isInvalid());
302     QVERIFY(springValue.isLiteral());
303     QVERIFY(springValue.toLiteral().literal() == "1.4");
304 
305     const QDeclarativeDomValue sourceValue = valueSourceObject.property("to").value();
306     QVERIFY(!sourceValue.isInvalid());
307     QVERIFY(sourceValue.isBinding());
308     QVERIFY(sourceValue.toBinding().binding() == "Math.min(Math.max(-130, value*2.2 - 130), 133)");
309 }
310 
testValueInterceptor()311 void tst_qdeclarativedom::testValueInterceptor()
312 {
313     QByteArray qml = "import QtQuick 1.0\n"
314                      "Rectangle { Behavior on height { NumberAnimation { duration: 100 } } }";
315 
316     QDeclarativeEngine freshEngine;
317     QDeclarativeDomDocument document;
318     QVERIFY(document.load(&freshEngine, qml));
319 
320     QDeclarativeDomObject rootItem = document.rootObject();
321     QVERIFY(rootItem.isValid());
322     QDeclarativeDomProperty heightProperty = rootItem.properties().at(0);
323     QVERIFY(heightProperty.propertyName() == "height");
324     QVERIFY(heightProperty.value().isValueInterceptor());
325 
326     const QDeclarativeDomValueValueInterceptor valueInterceptor = heightProperty.value().toValueInterceptor();
327     QDeclarativeDomObject valueInterceptorObject = valueInterceptor.object();
328     QVERIFY(valueInterceptorObject.isValid());
329 
330     QVERIFY(valueInterceptorObject.objectType() == "QtQuick/Behavior");
331 
332     const QDeclarativeDomValue animationValue = valueInterceptorObject.property("animation").value();
333     QVERIFY(!animationValue.isInvalid());
334     QVERIFY(animationValue.isObject());
335 }
336 
337 // Test QDeclarativeDomDocument::imports()
loadImports()338 void tst_qdeclarativedom::loadImports()
339 {
340     QByteArray qml = "import QtQuick 1.0\n"
341                      "import importlib.sublib 1.1\n"
342                      "import importlib.sublib 1.0 as NewFoo\n"
343                      "import 'import'\n"
344                      "import 'import' as X\n"
345                      "Item {}";
346 
347     QDeclarativeEngine engine;
348     engine.addImportPath(SRCDIR "/data");
349     QDeclarativeDomDocument document;
350     QVERIFY(document.load(&engine, qml, QUrl::fromLocalFile(SRCDIR "/data/dummy.qml")));
351 
352     QCOMPARE(document.imports().size(), 5);
353 
354     QDeclarativeDomImport import = document.imports().at(0);
355     QCOMPARE(import.type(), QDeclarativeDomImport::Library);
356     QCOMPARE(import.uri(), QLatin1String("QtQuick"));
357     QCOMPARE(import.qualifier(), QString());
358     QCOMPARE(import.version(), QLatin1String("1.0"));
359 
360     import = document.imports().at(1);
361     QCOMPARE(import.type(), QDeclarativeDomImport::Library);
362     QCOMPARE(import.uri(), QLatin1String("importlib.sublib"));
363     QCOMPARE(import.qualifier(), QString());
364     QCOMPARE(import.version(), QLatin1String("1.1"));
365 
366     import = document.imports().at(2);
367     QCOMPARE(import.type(), QDeclarativeDomImport::Library);
368     QCOMPARE(import.uri(), QLatin1String("importlib.sublib"));
369     QCOMPARE(import.qualifier(), QLatin1String("NewFoo"));
370     QCOMPARE(import.version(), QLatin1String("1.0"));
371 
372     import = document.imports().at(3);
373     QCOMPARE(import.type(), QDeclarativeDomImport::File);
374     QCOMPARE(import.uri(), QLatin1String("import"));
375     QCOMPARE(import.qualifier(), QLatin1String(""));
376     QCOMPARE(import.version(), QLatin1String(""));
377 
378     import = document.imports().at(4);
379     QCOMPARE(import.type(), QDeclarativeDomImport::File);
380     QCOMPARE(import.uri(), QLatin1String("import"));
381     QCOMPARE(import.qualifier(), QLatin1String("X"));
382     QCOMPARE(import.version(), QLatin1String(""));
383 }
384 
385 // Test loading a file with errors
loadErrors()386 void tst_qdeclarativedom::loadErrors()
387 {
388     QByteArray qml = "import QtQuick 1.0\n"
389                      "Item {\n"
390                      "  foo: 12\n"
391                      "}";
392 
393     QDeclarativeDomDocument document;
394     QVERIFY(false == document.load(&engine, qml));
395 
396     QCOMPARE(document.errors().count(), 1);
397     QDeclarativeError error = document.errors().first();
398 
399     QCOMPARE(error.url(), QUrl());
400     QCOMPARE(error.line(), 3);
401     QCOMPARE(error.column(), 3);
402     QCOMPARE(error.description(), QString("Cannot assign to non-existent property \"foo\""));
403 }
404 
405 // Test loading a file with syntax errors
loadSyntaxErrors()406 void tst_qdeclarativedom::loadSyntaxErrors()
407 {
408     QByteArray qml = "import QtQuick 1.0\n"
409                      "asdf";
410 
411     QDeclarativeDomDocument document;
412     QVERIFY(false == document.load(&engine, qml));
413 
414     QCOMPARE(document.errors().count(), 1);
415     QDeclarativeError error = document.errors().first();
416 
417     QCOMPARE(error.url(), QUrl());
418     QCOMPARE(error.line(), 2);
419     QCOMPARE(error.column(), 1);
420     QCOMPARE(error.description(), QString("Syntax error"));
421 }
422 
423 // Test attempting to load a file with remote references
loadRemoteErrors()424 void tst_qdeclarativedom::loadRemoteErrors()
425 {
426     QByteArray qml = "import QtQuick 1.0\n"
427                      "import \"http://localhost/exampleQmlScript.js\" as Script\n"
428                      "Item {\n"
429                      "}";
430     QDeclarativeDomDocument document;
431     QVERIFY(false == document.load(&engine, qml));
432 
433     QCOMPARE(document.errors().count(), 1);
434     QDeclarativeError error = document.errors().first();
435 
436     QCOMPARE(error.url(), QUrl());
437     QCOMPARE(error.line(), -1);
438     QCOMPARE(error.column(), -1);
439     QCOMPARE(error.description(), QString("QDeclarativeDomDocument supports local types only"));
440 }
441 
442 // Test dynamic property declarations
loadDynamicProperty()443 void tst_qdeclarativedom::loadDynamicProperty()
444 {
445     {
446         QByteArray qml = "import QtQuick 1.0\n"
447                          "Item {\n"
448                          "    property int a\n"
449                          "    property bool b\n"
450                          "    property double c\n"
451                          "    property real d\n"
452                          "    property string e\n"
453                          "    property url f\n"
454                          "    property color g\n"
455                          "    property date h\n"
456                          "    property variant i\n"
457                          "    property QtObject j\n"
458                          "}";
459 
460         QDeclarativeDomDocument document;
461         QVERIFY(document.load(&engine, qml));
462 
463         QDeclarativeDomObject rootObject = document.rootObject();
464         QVERIFY(rootObject.isValid());
465 
466         QCOMPARE(rootObject.dynamicProperties().count(), 10);
467 
468 #define DP_TEST(index, name, type, test_position, test_length, propTypeName) \
469     { \
470         QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(index); \
471         QVERIFY(d.isValid()); \
472         QVERIFY(d.propertyName() == # name ); \
473         QVERIFY(d.propertyType() == type); \
474         QVERIFY(d.propertyTypeName() == propTypeName); \
475         QVERIFY(d.isDefaultProperty() == false); \
476         QVERIFY(d.defaultValue().isValid() == false); \
477         QCOMPARE(d.position(), test_position); \
478         QCOMPARE(d.length(), test_length); \
479     } \
480 
481         DP_TEST(0, a, QVariant::Int, 30, 14, "int");
482         DP_TEST(1, b, QVariant::Bool, 49, 15, "bool");
483         DP_TEST(2, c, QMetaType::QReal, 69, 17, "double");
484         DP_TEST(3, d, QMetaType::QReal, 91, 15, "real");
485         DP_TEST(4, e, QVariant::String, 111, 17, "string");
486         DP_TEST(5, f, QVariant::Url, 133, 14, "url");
487         DP_TEST(6, g, QVariant::Color, 152, 16, "color");
488         DP_TEST(7, h, QVariant::DateTime, 173, 15, "date");
489         DP_TEST(8, i, qMetaTypeId<QVariant>(), 193, 18, "variant");
490         DP_TEST(9, j, -1, 216, 19, "QtObject");
491     }
492 
493     {
494         QByteArray qml = "import QtQuick 1.0\n"
495                          "Item {\n"
496                          "    id: item\n"
497                          "    property int a: 12\n"
498                          "    property int b: a + 6\n"
499                          "    default property QtObject c\n"
500                          "    property alias d: item.a\n"
501                          "}\n";
502 
503         QDeclarativeDomDocument document;
504         QVERIFY(document.load(&engine, qml));
505 
506         QDeclarativeDomObject rootObject = document.rootObject();
507         QVERIFY(rootObject.isValid());
508 
509         QCOMPARE(rootObject.dynamicProperties().count(), 4);
510 
511         {
512             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(0);
513             QVERIFY(d.isDefaultProperty() == false);
514             QVERIFY(d.isAlias() == false);
515             QVERIFY(d.defaultValue().isValid());
516             QVERIFY(d.defaultValue().propertyName() == "a");
517             QVERIFY(d.defaultValue().value().isLiteral());
518         }
519 
520         {
521             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(1);
522             QVERIFY(d.isDefaultProperty() == false);
523             QVERIFY(d.isAlias() == false);
524             QVERIFY(d.defaultValue().isValid());
525             QVERIFY(d.defaultValue().propertyName() == "b");
526             QVERIFY(d.defaultValue().value().isBinding());
527         }
528 
529         {
530             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(2);
531             QVERIFY(d.isDefaultProperty() == true);
532             QVERIFY(d.isAlias() == false);
533             QVERIFY(d.defaultValue().isValid() == false);
534         }
535 
536         {
537             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(3);
538             QVERIFY(d.isDefaultProperty() == false);
539             QVERIFY(d.isAlias() == true);
540         }
541     }
542 }
543 
544 // Test inline components
loadComponent()545 void tst_qdeclarativedom::loadComponent()
546 {
547     // Explicit component
548     {
549         QByteArray qml = "import QtQuick 1.0\n"
550                          "Item {\n"
551                          "    Component {\n"
552                          "        id: myComponent\n"
553                          "        Item {}\n"
554                          "    }\n"
555                          "}";
556 
557         QDeclarativeDomDocument document;
558         QVERIFY(document.load(&engine, qml));
559 
560         QDeclarativeDomObject rootItem = document.rootObject();
561         QVERIFY(rootItem.isValid());
562         QVERIFY(rootItem.properties().size() == 1);
563 
564         QDeclarativeDomProperty listProperty = rootItem.properties().at(0);
565         QVERIFY(listProperty.isDefaultProperty());
566         QVERIFY(listProperty.value().isList());
567 
568         QDeclarativeDomList list = listProperty.value().toList();
569         QVERIFY(list.values().size() == 1);
570 
571         QDeclarativeDomObject componentObject = list.values().first().toObject();
572         QVERIFY(componentObject.isValid());
573         QVERIFY(componentObject.objectClassName() == "Component");
574         QVERIFY(componentObject.isComponent());
575 
576         QDeclarativeDomComponent component = componentObject.toComponent();
577         QVERIFY(component.isValid());
578         QVERIFY(component.objectType() == "QtQuick/Component");
579         QVERIFY(component.objectTypeMajorVersion() == 1);
580         QVERIFY(component.objectTypeMinorVersion() == 0);
581         QVERIFY(component.objectClassName() == "Component");
582         QVERIFY(component.objectId() == "myComponent");
583         QVERIFY(component.properties().isEmpty());
584         QVERIFY(component.dynamicProperties().isEmpty());
585         QVERIFY(component.isCustomType() == false);
586         QVERIFY(component.customTypeData() == "");
587         QVERIFY(component.isComponent());
588         QCOMPARE(component.position(), 30);
589         QCOMPARE(component.length(), 57);
590 
591         QVERIFY(component.componentRoot().isValid());
592         QVERIFY(component.componentRoot().objectClassName() == "Item");
593     }
594 
595     // Implicit component
596     {
597         QByteArray qml = "import QtQuick 1.0\n"
598                          "ListView {\n"
599                          "    delegate: Item {}\n"
600                          "}";
601 
602         QDeclarativeDomDocument document;
603         QVERIFY(document.load(&engine, qml));
604 
605         QDeclarativeDomObject rootItem = document.rootObject();
606         QVERIFY(rootItem.isValid());
607         QVERIFY(rootItem.properties().size() == 1);
608 
609         QDeclarativeDomProperty delegate = rootItem.property("delegate");
610 
611         QDeclarativeDomObject componentObject = delegate.value().toObject();
612         QVERIFY(componentObject.isValid());
613         QVERIFY(componentObject.objectClassName() == "Component");
614         QVERIFY(componentObject.isComponent());
615 
616         QDeclarativeDomComponent component = componentObject.toComponent();
617         QVERIFY(component.isValid());
618         QVERIFY(component.objectType() == "QtQuick/Component");
619         QVERIFY(component.objectClassName() == "Component");
620         QVERIFY(component.objectId() == "");
621         QVERIFY(component.properties().isEmpty());
622         QVERIFY(component.dynamicProperties().isEmpty());
623         QVERIFY(component.isCustomType() == false);
624         QVERIFY(component.customTypeData() == "");
625         QVERIFY(component.isComponent());
626         QCOMPARE(component.position(), 44);
627         QCOMPARE(component.length(), 7);
628 
629         QVERIFY(component.componentRoot().isValid());
630         QVERIFY(component.componentRoot().objectClassName() == "Item");
631     }
632 }
633 
634 // Test QDeclarativeDomObject::dynamicProperty() method
object_dynamicProperty()635 void tst_qdeclarativedom::object_dynamicProperty()
636 {
637     // Invalid object
638     {
639         QDeclarativeDomObject object;
640         QVERIFY(object.dynamicProperty("").isValid() == false);
641         QVERIFY(object.dynamicProperty("foo").isValid() == false);
642     }
643 
644 
645     // Valid object, no dynamic properties
646     {
647         QByteArray qml = "import QtQuick 1.0\n"
648                          "Item {}";
649 
650         QDeclarativeDomDocument document;
651         QVERIFY(document.load(&engine, qml));
652 
653         QDeclarativeDomObject rootObject = document.rootObject();
654         QVERIFY(rootObject.isValid());
655 
656         QVERIFY(rootObject.dynamicProperty("").isValid() == false);
657         QVERIFY(rootObject.dynamicProperty("foo").isValid() == false);
658     }
659 
660     // Valid object, dynamic properties
661     {
662         QByteArray qml = "import QtQuick 1.0\n"
663                          "Item {\n"
664                          "    property int a\n"
665                          "}";
666 
667         QDeclarativeDomDocument document;
668         QVERIFY(document.load(&engine, qml));
669 
670         QDeclarativeDomObject rootObject = document.rootObject();
671         QVERIFY(rootObject.isValid());
672 
673         QVERIFY(rootObject.dynamicProperty("").isValid() == false);
674         QVERIFY(rootObject.dynamicProperty("foo").isValid() == false);
675 
676         QDeclarativeDomDynamicProperty p = rootObject.dynamicProperty("a");
677         QVERIFY(p.isValid());
678         QVERIFY(p.propertyName() == "a");
679         QVERIFY(p.propertyType() == QVariant::Int);
680         QVERIFY(p.propertyTypeName() == "int");
681         QVERIFY(p.isDefaultProperty() == false);
682         QCOMPARE(p.position(), 30);
683         QCOMPARE(p.length(), 14);
684     }
685 
686 }
687 
688 // Test QDeclarativeObject::property() method
object_property()689 void tst_qdeclarativedom::object_property()
690 {
691     // Invalid object
692     {
693         QDeclarativeDomObject object;
694         QVERIFY(object.property("").isValid() == false);
695         QVERIFY(object.property("foo").isValid() == false);
696     }
697 
698     // Valid object - no default
699     {
700         QByteArray qml = "import QtQuick 1.0\n"
701                          "Item {\n"
702                          "    x: 10\n"
703                          "    y: 12\n"
704                          "}\n";
705 
706         QDeclarativeDomDocument document;
707         QVERIFY(document.load(&engine, qml));
708 
709         QDeclarativeDomObject rootObject = document.rootObject();
710         QVERIFY(rootObject.isValid());
711 
712         QVERIFY(rootObject.property("").isValid() == false);
713         QVERIFY(rootObject.property("foo").isValid() == false);
714 
715         QDeclarativeDomProperty x = rootObject.property("x");
716         QVERIFY(x.isValid());
717         QVERIFY(x.propertyName() == "x");
718         QVERIFY(x.propertyNameParts().count() == 1);
719         QVERIFY(x.propertyNameParts().at(0) == "x");
720         QVERIFY(x.isDefaultProperty() == false);
721         QVERIFY(x.value().isLiteral());
722         QVERIFY(x.value().toLiteral().literal() == "10");
723         QCOMPARE(x.position(), 30);
724         QCOMPARE(x.length(), 1);
725 
726         QDeclarativeDomProperty y = rootObject.property("y");
727         QVERIFY(y.isValid());
728         QVERIFY(y.propertyName() == "y");
729         QVERIFY(y.propertyNameParts().count() == 1);
730         QVERIFY(y.propertyNameParts().at(0) == "y");
731         QVERIFY(y.isDefaultProperty() == false);
732         QVERIFY(y.value().isLiteral());
733         QVERIFY(y.value().toLiteral().literal() == "12");
734         QCOMPARE(y.position(), 40);
735         QCOMPARE(y.length(), 1);
736     }
737 
738     // Valid object - with default
739     {
740         QByteArray qml = "import QtQuick 1.0\n"
741                          "Item {\n"
742                          "    x: 10\n"
743                          "    y: 12\n"
744                          "    Item {}\n"
745                          "}\n";
746 
747         QDeclarativeDomDocument document;
748         QVERIFY(document.load(&engine, qml));
749 
750         QDeclarativeDomObject rootObject = document.rootObject();
751         QVERIFY(rootObject.isValid());
752 
753         QVERIFY(rootObject.property("").isValid() == false);
754         QVERIFY(rootObject.property("foo").isValid() == false);
755 
756         QDeclarativeDomProperty x = rootObject.property("x");
757         QVERIFY(x.isValid());
758         QVERIFY(x.propertyName() == "x");
759         QVERIFY(x.propertyNameParts().count() == 1);
760         QVERIFY(x.propertyNameParts().at(0) == "x");
761         QVERIFY(x.isDefaultProperty() == false);
762         QVERIFY(x.value().isLiteral());
763         QVERIFY(x.value().toLiteral().literal() == "10");
764         QCOMPARE(x.position(), 30);
765         QCOMPARE(x.length(), 1);
766 
767         QDeclarativeDomProperty y = rootObject.property("y");
768         QVERIFY(y.isValid());
769         QVERIFY(y.propertyName() == "y");
770         QVERIFY(y.propertyNameParts().count() == 1);
771         QVERIFY(y.propertyNameParts().at(0) == "y");
772         QVERIFY(y.isDefaultProperty() == false);
773         QVERIFY(y.value().isLiteral());
774         QVERIFY(y.value().toLiteral().literal() == "12");
775         QCOMPARE(y.position(), 40);
776         QCOMPARE(y.length(), 1);
777 
778         QDeclarativeDomProperty data = rootObject.property("data");
779         QVERIFY(data.isValid());
780         QVERIFY(data.propertyName() == "data");
781         QVERIFY(data.propertyNameParts().count() == 1);
782         QVERIFY(data.propertyNameParts().at(0) == "data");
783         QVERIFY(data.isDefaultProperty() == true);
784         QVERIFY(data.value().isList());
785         QCOMPARE(data.position(), 50);
786         QCOMPARE(data.length(), 0);
787     }
788 }
789 
790 // Tests the QDeclarativeDomObject::url() method
object_url()791 void tst_qdeclarativedom::object_url()
792 {
793     // Invalid object
794     {
795         QDeclarativeDomObject object;
796         QCOMPARE(object.url(), QUrl());
797     }
798 
799     // Valid builtin object
800     {
801         QByteArray qml = "import QtQuick 1.0\n"
802                          "Item {}";
803 
804         QDeclarativeDomDocument document;
805         QVERIFY(document.load(&engine, qml));
806 
807         QDeclarativeDomObject rootObject = document.rootObject();
808         QVERIFY(rootObject.isValid());
809         QCOMPARE(rootObject.url(), QUrl());
810     }
811 
812     // Valid composite object
813     {
814         QByteArray qml = "import QtQuick 1.0\n"
815                          "MyItem {}";
816 
817         QUrl myUrl = QUrl::fromLocalFile(SRCDIR "/data/main.qml");
818         QUrl subUrl = QUrl::fromLocalFile(SRCDIR "/data/MyItem.qml");
819 
820         QDeclarativeDomDocument document;
821         QVERIFY(document.load(&engine, qml, myUrl));
822 
823         QDeclarativeDomObject rootObject = document.rootObject();
824         QVERIFY(rootObject.isValid());
825         QCOMPARE(rootObject.url(), subUrl);
826     }
827 }
828 
829 // Test copy constructors and operators
copy()830 void tst_qdeclarativedom::copy()
831 {
832     QByteArray qml = "import QtQuick 1.0\n"
833                      "MyItem {\n"
834                      "    id: myItem\n"
835                      "    property int a: 10\n"
836                      "    x: 10\n"
837                      "    y: x + 10\n"
838                      "    NumberAnimation on z {}\n"
839                      "    Behavior on opacity {}\n"
840                      "    Component {\n"
841                      "        Item{}\n"
842                      "    }\n"
843                      "    children: [ Item{}, Item{} ]\n"
844                      "}\n";
845 
846     QUrl myUrl = QUrl::fromLocalFile(SRCDIR "/data/main.qml");
847 
848     QDeclarativeDomDocument document;
849     QVERIFY(document.load(&engine, qml, myUrl));
850 
851     // QDeclarativeDomDocument
852     {
853         QDeclarativeDomDocument document2(document);
854         QDeclarativeDomDocument document3;
855         document3 = document;
856 
857         QCOMPARE(document.imports().count(), document2.imports().count());
858         QCOMPARE(document.errors().count(), document2.errors().count());
859         QCOMPARE(document.rootObject().objectClassName(), document2.rootObject().objectClassName());
860 
861         QCOMPARE(document.imports().count(), document3.imports().count());
862         QCOMPARE(document.errors().count(), document3.errors().count());
863         QCOMPARE(document.rootObject().objectClassName(), document3.rootObject().objectClassName());
864     }
865 
866     // QDeclarativeDomImport
867     {
868         QCOMPARE(document.imports().count(), 1);
869         QDeclarativeDomImport import = document.imports().at(0);
870 
871         QDeclarativeDomImport import2(import);
872         QDeclarativeDomImport import3;
873         import3 = import2;
874 
875         QCOMPARE(import.type(), import2.type());
876         QCOMPARE(import.uri(), import2.uri());
877         QCOMPARE(import.version(), import2.version());
878         QCOMPARE(import.qualifier(), import2.qualifier());
879 
880         QCOMPARE(import.type(), import3.type());
881         QCOMPARE(import.uri(), import3.uri());
882         QCOMPARE(import.version(), import3.version());
883         QCOMPARE(import.qualifier(), import3.qualifier());
884     }
885 
886     // QDeclarativeDomObject
887     {
888         QDeclarativeDomObject object = document.rootObject();
889         QVERIFY(object.isValid());
890 
891         QDeclarativeDomObject object2(object);
892         QDeclarativeDomObject object3;
893         object3 = object;
894 
895         QCOMPARE(object.isValid(), object2.isValid());
896         QCOMPARE(object.objectType(), object2.objectType());
897         QCOMPARE(object.objectClassName(), object2.objectClassName());
898         QCOMPARE(object.objectTypeMajorVersion(), object2.objectTypeMajorVersion());
899         QCOMPARE(object.objectTypeMinorVersion(), object2.objectTypeMinorVersion());
900         QCOMPARE(object.objectId(), object2.objectId());
901         QCOMPARE(object.properties().count(), object2.properties().count());
902         QCOMPARE(object.dynamicProperties().count(), object2.dynamicProperties().count());
903         QCOMPARE(object.isCustomType(), object2.isCustomType());
904         QCOMPARE(object.customTypeData(), object2.customTypeData());
905         QCOMPARE(object.isComponent(), object2.isComponent());
906         QCOMPARE(object.position(), object2.position());
907         QCOMPARE(object.length(), object2.length());
908         QCOMPARE(object.url(), object2.url());
909 
910         QCOMPARE(object.isValid(), object3.isValid());
911         QCOMPARE(object.objectType(), object3.objectType());
912         QCOMPARE(object.objectClassName(), object3.objectClassName());
913         QCOMPARE(object.objectTypeMajorVersion(), object3.objectTypeMajorVersion());
914         QCOMPARE(object.objectTypeMinorVersion(), object3.objectTypeMinorVersion());
915         QCOMPARE(object.objectId(), object3.objectId());
916         QCOMPARE(object.properties().count(), object3.properties().count());
917         QCOMPARE(object.dynamicProperties().count(), object3.dynamicProperties().count());
918         QCOMPARE(object.isCustomType(), object3.isCustomType());
919         QCOMPARE(object.customTypeData(), object3.customTypeData());
920         QCOMPARE(object.isComponent(), object3.isComponent());
921         QCOMPARE(object.position(), object3.position());
922         QCOMPARE(object.length(), object3.length());
923         QCOMPARE(object.url(), object3.url());
924     }
925 
926     // QDeclarativeDomDynamicProperty
927     {
928         QDeclarativeDomObject object = document.rootObject();
929         QDeclarativeDomDynamicProperty property = object.dynamicProperty("a");
930 
931         QDeclarativeDomDynamicProperty property2(property);
932         QDeclarativeDomDynamicProperty property3;
933         property3 = property;
934 
935         QCOMPARE(property.isValid(), property2.isValid());
936         QCOMPARE(property.propertyName(), property2.propertyName());
937         QCOMPARE(property.propertyType(), property2.propertyType());
938         QCOMPARE(property.propertyTypeName(), property2.propertyTypeName());
939         QCOMPARE(property.isDefaultProperty(), property2.isDefaultProperty());
940         QCOMPARE(property.defaultValue().propertyName(), property2.defaultValue().propertyName());
941         QCOMPARE(property.position(), property2.position());
942         QCOMPARE(property.length(), property2.length());
943 
944         QCOMPARE(property.isValid(), property3.isValid());
945         QCOMPARE(property.propertyName(), property3.propertyName());
946         QCOMPARE(property.propertyType(), property3.propertyType());
947         QCOMPARE(property.propertyTypeName(), property3.propertyTypeName());
948         QCOMPARE(property.isDefaultProperty(), property3.isDefaultProperty());
949         QCOMPARE(property.defaultValue().propertyName(), property3.defaultValue().propertyName());
950         QCOMPARE(property.position(), property3.position());
951         QCOMPARE(property.length(), property3.length());
952     }
953 
954     // QDeclarativeDomProperty
955     {
956         QDeclarativeDomObject object = document.rootObject();
957         QDeclarativeDomProperty property = object.property("opacity");
958 
959         QDeclarativeDomProperty property2(property);
960         QDeclarativeDomProperty property3;
961         property3 = property;
962 
963         QCOMPARE(property.isValid(), property2.isValid());
964         QCOMPARE(property.propertyName(), property2.propertyName());
965         QCOMPARE(property.propertyNameParts(), property2.propertyNameParts());
966         QCOMPARE(property.isDefaultProperty(), property2.isDefaultProperty());
967         QCOMPARE(property.value().type(), property2.value().type());
968         QCOMPARE(property.position(), property2.position());
969         QCOMPARE(property.length(), property2.length());
970 
971         QCOMPARE(property.isValid(), property3.isValid());
972         QCOMPARE(property.propertyName(), property3.propertyName());
973         QCOMPARE(property.propertyNameParts(), property3.propertyNameParts());
974         QCOMPARE(property.isDefaultProperty(), property3.isDefaultProperty());
975         QCOMPARE(property.value().type(), property3.value().type());
976         QCOMPARE(property.position(), property3.position());
977         QCOMPARE(property.length(), property3.length());
978     }
979 
980     // QDeclarativeDomValueLiteral
981     {
982         QDeclarativeDomObject object = document.rootObject();
983         QDeclarativeDomProperty property = object.property("x");
984         QDeclarativeDomValueLiteral literal = property.value().toLiteral();
985         QCOMPARE(literal.literal(), QString("10"));
986 
987         QDeclarativeDomValueLiteral literal2(literal);
988         QDeclarativeDomValueLiteral literal3;
989         literal3 = literal2;
990 
991         QCOMPARE(literal2.literal(), QString("10"));
992         QCOMPARE(literal3.literal(), QString("10"));
993     }
994 
995 
996     // QDeclarativeDomValueBinding
997     {
998         QDeclarativeDomObject object = document.rootObject();
999         QDeclarativeDomProperty property = object.property("y");
1000         QDeclarativeDomValueBinding binding = property.value().toBinding();
1001         QCOMPARE(binding.binding(), QString("x + 10"));
1002 
1003         QDeclarativeDomValueBinding binding2(binding);
1004         QDeclarativeDomValueBinding binding3;
1005         binding3 = binding2;
1006 
1007         QCOMPARE(binding2.binding(), QString("x + 10"));
1008         QCOMPARE(binding3.binding(), QString("x + 10"));
1009     }
1010 
1011     // QDeclarativeDomValueValueSource
1012     {
1013         QDeclarativeDomObject object = document.rootObject();
1014         QDeclarativeDomProperty property = object.property("z");
1015         QDeclarativeDomValueValueSource source = property.value().toValueSource();
1016         QCOMPARE(source.object().objectClassName(), QByteArray("NumberAnimation"));
1017 
1018         QDeclarativeDomValueValueSource source2(source);
1019         QDeclarativeDomValueValueSource source3;
1020         source3 = source;
1021 
1022         QCOMPARE(source2.object().objectClassName(), QByteArray("NumberAnimation"));
1023         QCOMPARE(source3.object().objectClassName(), QByteArray("NumberAnimation"));
1024     }
1025 
1026     // QDeclarativeDomValueValueInterceptor
1027     {
1028         QDeclarativeDomObject object = document.rootObject();
1029         QDeclarativeDomProperty property = object.property("opacity");
1030         QDeclarativeDomValueValueInterceptor interceptor = property.value().toValueInterceptor();
1031         QCOMPARE(interceptor.object().objectClassName(), QByteArray("Behavior"));
1032 
1033         QDeclarativeDomValueValueInterceptor interceptor2(interceptor);
1034         QDeclarativeDomValueValueInterceptor interceptor3;
1035         interceptor3 = interceptor;
1036 
1037         QCOMPARE(interceptor2.object().objectClassName(), QByteArray("Behavior"));
1038         QCOMPARE(interceptor3.object().objectClassName(), QByteArray("Behavior"));
1039     }
1040 
1041     // QDeclarativeDomComponent
1042     {
1043         QDeclarativeDomObject object = document.rootObject();
1044         QDeclarativeDomProperty property = object.property("data");
1045         QCOMPARE(property.value().toList().values().count(), 1);
1046         QDeclarativeDomComponent component =
1047             property.value().toList().values().at(0).toObject().toComponent();
1048         QCOMPARE(component.componentRoot().objectClassName(), QByteArray("Item"));
1049 
1050         QDeclarativeDomComponent component2(component);
1051         QDeclarativeDomComponent component3;
1052         component3 = component;
1053 
1054         QCOMPARE(component.componentRoot().objectClassName(), component2.componentRoot().objectClassName());
1055         QCOMPARE(component.isValid(), component2.isValid());
1056         QCOMPARE(component.objectType(), component2.objectType());
1057         QCOMPARE(component.objectClassName(), component2.objectClassName());
1058         QCOMPARE(component.objectTypeMajorVersion(), component2.objectTypeMajorVersion());
1059         QCOMPARE(component.objectTypeMinorVersion(), component2.objectTypeMinorVersion());
1060         QCOMPARE(component.objectId(), component2.objectId());
1061         QCOMPARE(component.properties().count(), component2.properties().count());
1062         QCOMPARE(component.dynamicProperties().count(), component2.dynamicProperties().count());
1063         QCOMPARE(component.isCustomType(), component2.isCustomType());
1064         QCOMPARE(component.customTypeData(), component2.customTypeData());
1065         QCOMPARE(component.isComponent(), component2.isComponent());
1066         QCOMPARE(component.position(), component2.position());
1067         QCOMPARE(component.length(), component2.length());
1068         QCOMPARE(component.url(), component2.url());
1069 
1070         QCOMPARE(component.componentRoot().objectClassName(), component3.componentRoot().objectClassName());
1071         QCOMPARE(component.isValid(), component3.isValid());
1072         QCOMPARE(component.objectType(), component3.objectType());
1073         QCOMPARE(component.objectClassName(), component3.objectClassName());
1074         QCOMPARE(component.objectTypeMajorVersion(), component3.objectTypeMajorVersion());
1075         QCOMPARE(component.objectTypeMinorVersion(), component3.objectTypeMinorVersion());
1076         QCOMPARE(component.objectId(), component3.objectId());
1077         QCOMPARE(component.properties().count(), component3.properties().count());
1078         QCOMPARE(component.dynamicProperties().count(), component3.dynamicProperties().count());
1079         QCOMPARE(component.isCustomType(), component3.isCustomType());
1080         QCOMPARE(component.customTypeData(), component3.customTypeData());
1081         QCOMPARE(component.isComponent(), component3.isComponent());
1082         QCOMPARE(component.position(), component3.position());
1083         QCOMPARE(component.length(), component3.length());
1084         QCOMPARE(component.url(), component3.url());
1085     }
1086 
1087     // QDeclarativeDomValue
1088     {
1089         QDeclarativeDomObject object = document.rootObject();
1090         QDeclarativeDomProperty property = object.property("data");
1091         QDeclarativeDomValue value = property.value();
1092 
1093         QDeclarativeDomValue value2(value);
1094         QDeclarativeDomValue value3;
1095         value3 = value;
1096 
1097         QCOMPARE(value.type(), value2.type());
1098         QCOMPARE(value.isInvalid(), value2.isInvalid());
1099         QCOMPARE(value.isLiteral(), value2.isLiteral());
1100         QCOMPARE(value.isBinding(), value2.isBinding());
1101         QCOMPARE(value.isValueSource(), value2.isValueSource());
1102         QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
1103         QCOMPARE(value.isObject(), value2.isObject());
1104         QCOMPARE(value.isList(), value2.isList());
1105         QCOMPARE(value.position(), value2.position());
1106         QCOMPARE(value.length(), value2.length());
1107 
1108         QCOMPARE(value.type(), value3.type());
1109         QCOMPARE(value.isInvalid(), value3.isInvalid());
1110         QCOMPARE(value.isLiteral(), value3.isLiteral());
1111         QCOMPARE(value.isBinding(), value3.isBinding());
1112         QCOMPARE(value.isValueSource(), value3.isValueSource());
1113         QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
1114         QCOMPARE(value.isObject(), value3.isObject());
1115         QCOMPARE(value.isList(), value3.isList());
1116         QCOMPARE(value.position(), value3.position());
1117         QCOMPARE(value.length(), value3.length());
1118     }
1119     {
1120         QDeclarativeDomObject object = document.rootObject();
1121         QDeclarativeDomProperty property = object.property("x");
1122         QDeclarativeDomValue value = property.value();
1123 
1124         QDeclarativeDomValue value2(value);
1125         QDeclarativeDomValue value3;
1126         value3 = value;
1127 
1128         QCOMPARE(value.type(), value2.type());
1129         QCOMPARE(value.isInvalid(), value2.isInvalid());
1130         QCOMPARE(value.isLiteral(), value2.isLiteral());
1131         QCOMPARE(value.isBinding(), value2.isBinding());
1132         QCOMPARE(value.isValueSource(), value2.isValueSource());
1133         QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
1134         QCOMPARE(value.isObject(), value2.isObject());
1135         QCOMPARE(value.isList(), value2.isList());
1136         QCOMPARE(value.position(), value2.position());
1137         QCOMPARE(value.length(), value2.length());
1138 
1139         QCOMPARE(value.type(), value3.type());
1140         QCOMPARE(value.isInvalid(), value3.isInvalid());
1141         QCOMPARE(value.isLiteral(), value3.isLiteral());
1142         QCOMPARE(value.isBinding(), value3.isBinding());
1143         QCOMPARE(value.isValueSource(), value3.isValueSource());
1144         QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
1145         QCOMPARE(value.isObject(), value3.isObject());
1146         QCOMPARE(value.isList(), value3.isList());
1147         QCOMPARE(value.position(), value3.position());
1148         QCOMPARE(value.length(), value3.length());
1149     }
1150     {
1151         QDeclarativeDomValue value;
1152 
1153         QDeclarativeDomValue value2(value);
1154         QDeclarativeDomValue value3;
1155         value3 = value;
1156 
1157         QCOMPARE(value.type(), value2.type());
1158         QCOMPARE(value.isInvalid(), value2.isInvalid());
1159         QCOMPARE(value.isLiteral(), value2.isLiteral());
1160         QCOMPARE(value.isBinding(), value2.isBinding());
1161         QCOMPARE(value.isValueSource(), value2.isValueSource());
1162         QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
1163         QCOMPARE(value.isObject(), value2.isObject());
1164         QCOMPARE(value.isList(), value2.isList());
1165         QCOMPARE(value.position(), value2.position());
1166         QCOMPARE(value.length(), value2.length());
1167 
1168         QCOMPARE(value.type(), value3.type());
1169         QCOMPARE(value.isInvalid(), value3.isInvalid());
1170         QCOMPARE(value.isLiteral(), value3.isLiteral());
1171         QCOMPARE(value.isBinding(), value3.isBinding());
1172         QCOMPARE(value.isValueSource(), value3.isValueSource());
1173         QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
1174         QCOMPARE(value.isObject(), value3.isObject());
1175         QCOMPARE(value.isList(), value3.isList());
1176         QCOMPARE(value.position(), value3.position());
1177         QCOMPARE(value.length(), value3.length());
1178     }
1179 
1180     // QDeclarativeDomList
1181     {
1182         QDeclarativeDomObject object = document.rootObject();
1183         QDeclarativeDomProperty property = object.property("children");
1184         QDeclarativeDomList list = property.value().toList();
1185         QCOMPARE(list.values().count(), 2);
1186 
1187         QDeclarativeDomList list2(list);
1188         QDeclarativeDomList list3;
1189         list3 = list2;
1190 
1191         QCOMPARE(list.values().count(), list2.values().count());
1192         QCOMPARE(list.position(), list2.position());
1193         QCOMPARE(list.length(), list2.length());
1194         QCOMPARE(list.commaPositions(), list2.commaPositions());
1195 
1196         QCOMPARE(list.values().count(), list3.values().count());
1197         QCOMPARE(list.position(), list3.position());
1198         QCOMPARE(list.length(), list3.length());
1199         QCOMPARE(list.commaPositions(), list3.commaPositions());
1200 
1201     }
1202 }
1203 
1204 // Tests the position/length of various elements
position()1205 void tst_qdeclarativedom::position()
1206 {
1207     QByteArray qml = "import QtQuick 1.0\n"
1208                      "Item {\n"
1209                      "    id: myItem\n"
1210                      "    property int a: 10\n"
1211                      "    x: 10\n"
1212                      "    y: x + 10\n"
1213                      "    NumberAnimation on z {}\n"
1214                      "    Behavior on opacity {}\n"
1215                      "    Component {\n"
1216                      "        Item{}\n"
1217                      "    }\n"
1218                      "    children: [ Item{}, Item{} ]\n"
1219                      "}\n";
1220 
1221 
1222     QDeclarativeDomDocument document;
1223     QVERIFY(document.load(&engine, qml));
1224 
1225     QDeclarativeDomObject root = document.rootObject();
1226 
1227     // All QDeclarativeDomDynamicProperty
1228     QDeclarativeDomDynamicProperty dynProp = root.dynamicProperty("a");
1229     QCOMPARE(dynProp.position(), 45);
1230     QCOMPARE(dynProp.length(), 18);
1231 
1232     // All QDeclarativeDomProperty
1233     QDeclarativeDomProperty x = root.property("x");
1234     QCOMPARE(x.position(), 68);
1235     QCOMPARE(x.length(), 1);
1236 
1237     QDeclarativeDomProperty y = root.property("y");
1238     QCOMPARE(y.position(), 78);
1239     QCOMPARE(y.length(), 1);
1240 
1241     QDeclarativeDomProperty z = root.property("z");
1242     QCOMPARE(z.position(), 111);
1243     QCOMPARE(z.length(), 1);
1244 
1245     QDeclarativeDomProperty opacity = root.property("opacity");
1246     QCOMPARE(opacity.position(), 132);
1247     QCOMPARE(opacity.length(), 7);
1248 
1249     QDeclarativeDomProperty data = root.property("data");
1250     QCOMPARE(data.position(), 147);
1251     QCOMPARE(data.length(), 0);
1252 
1253     QDeclarativeDomProperty children = root.property("children");
1254     QCOMPARE(children.position(), 184);
1255     QCOMPARE(children.length(), 8);
1256 
1257     QDeclarativeDomList dataList = data.value().toList();
1258     QCOMPARE(dataList.values().count(), 1);
1259     QDeclarativeDomList childrenList = children.value().toList();
1260     QCOMPARE(childrenList.values().count(), 2);
1261 
1262     // All QDeclarativeDomObject
1263     QCOMPARE(root.position(), 19);
1264     QCOMPARE(root.length(), 195);
1265 
1266     QDeclarativeDomObject numberAnimation = z.value().toValueSource().object();
1267     QCOMPARE(numberAnimation.position(), 92);
1268     QCOMPARE(numberAnimation.length(), 23);
1269 
1270     QDeclarativeDomObject behavior = opacity.value().toValueInterceptor().object();
1271     QCOMPARE(behavior.position(), 120);
1272     QCOMPARE(behavior.length(), 22);
1273 
1274     QDeclarativeDomObject component = dataList.values().at(0).toObject();
1275     QCOMPARE(component.position(), 147);
1276     QCOMPARE(component.length(), 32);
1277 
1278     QDeclarativeDomObject componentRoot = component.toComponent().componentRoot();
1279     QCOMPARE(componentRoot.position(), 167);
1280     QCOMPARE(componentRoot.length(), 6);
1281 
1282     QDeclarativeDomObject child1 = childrenList.values().at(0).toObject();
1283     QCOMPARE(child1.position(), 196);
1284     QCOMPARE(child1.length(), 6);
1285 
1286     QDeclarativeDomObject child2 = childrenList.values().at(1).toObject();
1287     QCOMPARE(child2.position(), 204);
1288     QCOMPARE(child2.length(), 6);
1289 
1290     // All QDeclarativeDomValue
1291     QDeclarativeDomValue xValue = x.value();
1292     QCOMPARE(xValue.position(), 71);
1293     QCOMPARE(xValue.length(), 2);
1294 
1295     QDeclarativeDomValue yValue = y.value();
1296     QCOMPARE(yValue.position(), 81);
1297     QCOMPARE(yValue.length(), 6);
1298 
1299     QDeclarativeDomValue zValue = z.value();
1300     QCOMPARE(zValue.position(), 92);
1301     QCOMPARE(zValue.length(), 23);
1302 
1303     QDeclarativeDomValue opacityValue = opacity.value();
1304     QCOMPARE(opacityValue.position(), 120);
1305     QCOMPARE(opacityValue.length(), 22);
1306 
1307     QDeclarativeDomValue dataValue = data.value();
1308     QCOMPARE(dataValue.position(), 147);
1309     QCOMPARE(dataValue.length(), 32);
1310 
1311     QDeclarativeDomValue child1Value = childrenList.values().at(0);
1312     QCOMPARE(child1Value.position(), 196);
1313     QCOMPARE(child1Value.length(), 6);
1314 
1315     QDeclarativeDomValue child2Value = childrenList.values().at(1);
1316     QCOMPARE(child2Value.position(), 204);
1317     QCOMPARE(child2Value.length(), 6);
1318 
1319     // All QDeclarativeDomList
1320     QCOMPARE(childrenList.position(), 194);
1321     QCOMPARE(childrenList.length(), 18);
1322 }
1323 
1324 QTEST_MAIN(tst_qdeclarativedom)
1325 
1326 #include "tst_qdeclarativedom.moc"
1327