a4d6b09083458d64646e6fa40cf5b91e4c99bc74
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeproperty / tst_qdeclarativeproperty.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtDeclarative/qdeclarativecontext.h>
45 #include <QtDeclarative/qdeclarativeproperty.h>
46 #include <QtDeclarative/private/qdeclarativeproperty_p.h>
47 #include <private/qdeclarativebinding_p.h>
48 #include <QtWidgets/QLineEdit>
49 #include <QtCore/qfileinfo.h>
50 #include <QtCore/qdir.h>
51 #include "../../shared/util.h"
52
53 #include <QDebug>
54 class MyQmlObject : public QObject
55 {
56     Q_OBJECT
57 public:
58     MyQmlObject() {}
59 };
60
61 QML_DECLARE_TYPE(MyQmlObject);
62
63 class MyAttached : public QObject
64 {
65     Q_OBJECT
66     Q_PROPERTY(int foo READ foo WRITE setFoo)
67 public:
68     MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
69
70     int foo() const { return m_foo; }
71     void setFoo(int f) { m_foo = f; }
72
73 private:
74     int m_foo;
75 };
76
77 class MyContainer : public QObject
78 {
79     Q_OBJECT
80     Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children)
81 public:
82     MyContainer() {}
83
84     QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); }
85
86     static MyAttached *qmlAttachedProperties(QObject *o) {
87         return new MyAttached(o);
88     }
89
90 private:
91     QList<MyQmlObject*> m_children;
92 };
93
94 QML_DECLARE_TYPE(MyContainer);
95 QML_DECLARE_TYPEINFO(MyContainer, QML_HAS_ATTACHED_PROPERTIES)
96
97 class tst_qdeclarativeproperty : public QDeclarativeDataTest
98 {
99     Q_OBJECT
100 public:
101     tst_qdeclarativeproperty() {}
102
103 private slots:
104     void initTestCase();
105
106     // Constructors
107     void qmlmetaproperty();
108     void qmlmetaproperty_object();
109     void qmlmetaproperty_object_string();
110     void qmlmetaproperty_object_context();
111     void qmlmetaproperty_object_string_context();
112
113     // Methods
114     void name();
115     void read();
116     void write();
117     void reset();
118
119     // Functionality
120     void writeObjectToList();
121     void writeListToList();
122
123     //writeToReadOnly();
124
125     void urlHandling_data();
126     void urlHandling();
127
128     void variantMapHandling_data();
129     void variantMapHandling();
130
131     // Bugs
132     void crashOnValueProperty();
133     void aliasPropertyBindings();
134     void noContext();
135     void assignEmptyVariantMap();
136
137     void copy();
138 private:
139     QDeclarativeEngine engine;
140 };
141
142 void tst_qdeclarativeproperty::qmlmetaproperty()
143 {
144     QDeclarativeProperty prop;
145
146     QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
147     QVERIFY(binding != 0);
148     QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
149     QVERIFY(expression != 0);
150
151     QObject *obj = new QObject;
152
153     QCOMPARE(prop.name(), QString());
154     QCOMPARE(prop.read(), QVariant());
155     QCOMPARE(prop.write(QVariant()), false);
156     QCOMPARE(prop.hasNotifySignal(), false);
157     QCOMPARE(prop.needsNotifySignal(), false);
158     QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
159     QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
160     QCOMPARE(prop.connectNotifySignal(obj, 0), false);
161     QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
162     QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
163     QCOMPARE(prop.connectNotifySignal(obj, -1), false);
164     QVERIFY(prop.method().signature() == 0);
165     QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
166     QCOMPARE(prop.isProperty(), false);
167     QCOMPARE(prop.isWritable(), false);
168     QCOMPARE(prop.isDesignable(), false);
169     QCOMPARE(prop.isResettable(), false);
170     QCOMPARE(prop.isSignalProperty(), false);
171     QCOMPARE(prop.isValid(), false);
172     QCOMPARE(prop.object(), (QObject *)0);
173     QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
174     QCOMPARE(prop.propertyType(), 0);
175     QCOMPARE(prop.propertyTypeName(), (const char *)0);
176     QVERIFY(prop.property().name() == 0);
177     QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
178     QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
179     QVERIFY(binding == 0);
180     QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
181     QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
182     QVERIFY(expression == 0);
183     QCOMPARE(prop.index(), -1);
184     QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
185
186     delete obj;
187 }
188
189 class PropertyObject : public QObject
190 {
191     Q_OBJECT
192     Q_PROPERTY(int defaultProperty READ defaultProperty)
193     Q_PROPERTY(QRect rectProperty READ rectProperty)
194     Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty)
195     Q_PROPERTY(QUrl url READ url WRITE setUrl)
196     Q_PROPERTY(QVariantMap variantMap READ variantMap WRITE setVariantMap)
197     Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
198     Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
199     Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
200
201     Q_CLASSINFO("DefaultProperty", "defaultProperty")
202 public:
203     PropertyObject() : m_resetProperty(9) {}
204
205     int defaultProperty() { return 10; }
206     QRect rectProperty() { return QRect(10, 10, 1, 209); }
207
208     QRect wrectProperty() { return m_rect; }
209     void setWRectProperty(const QRect &r) { m_rect = r; }
210
211     QUrl url() { return m_url; }
212     void setUrl(const QUrl &u) { m_url = u; }
213
214     QVariantMap variantMap() const { return m_variantMap; }
215     void setVariantMap(const QVariantMap &variantMap) { m_variantMap = variantMap; }
216
217     int resettableProperty() const { return m_resetProperty; }
218     void setResettableProperty(int r) { m_resetProperty = r; }
219     void resetProperty() { m_resetProperty = 9; }
220
221     int propertyWithNotify() const { return m_propertyWithNotify; }
222     void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
223
224     MyQmlObject *qmlObject() { return &m_qmlObject; }
225
226 signals:
227     void clicked();
228     void oddlyNamedNotifySignal();
229
230 private:
231     int m_resetProperty;
232     QRect m_rect;
233     QUrl m_url;
234     QVariantMap m_variantMap;
235     int m_propertyWithNotify;
236     MyQmlObject m_qmlObject;
237 };
238
239 QML_DECLARE_TYPE(PropertyObject);
240
241 void tst_qdeclarativeproperty::qmlmetaproperty_object()
242 {
243     QObject object; // Has no default property
244     PropertyObject dobject; // Has default property
245
246     {
247         QDeclarativeProperty prop(&object);
248
249         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
250         QVERIFY(binding != 0);
251         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
252         QVERIFY(expression != 0);
253
254         QObject *obj = new QObject;
255
256         QCOMPARE(prop.name(), QString());
257         QCOMPARE(prop.read(), QVariant());
258         QCOMPARE(prop.write(QVariant()), false);
259         QCOMPARE(prop.hasNotifySignal(), false);
260         QCOMPARE(prop.needsNotifySignal(), false);
261         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
262         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
263         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
264         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
265         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
266         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
267         QVERIFY(prop.method().signature() == 0);
268         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
269         QCOMPARE(prop.isProperty(), false);
270         QCOMPARE(prop.isWritable(), false);
271         QCOMPARE(prop.isDesignable(), false);
272         QCOMPARE(prop.isResettable(), false);
273         QCOMPARE(prop.isSignalProperty(), false);
274         QCOMPARE(prop.isValid(), false);
275         QCOMPARE(prop.object(), (QObject *)0);
276         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
277         QCOMPARE(prop.propertyType(), 0);
278         QCOMPARE(prop.propertyTypeName(), (const char *)0);
279         QVERIFY(prop.property().name() == 0);
280         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
281         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
282         QVERIFY(binding == 0);
283         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
284         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
285         QVERIFY(expression == 0);
286         QCOMPARE(prop.index(), -1);
287         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
288
289         delete obj;
290     }
291
292     {
293         QDeclarativeProperty prop(&dobject);
294
295         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
296         binding.data()->setTarget(prop);
297         QVERIFY(binding != 0);
298         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
299         QVERIFY(expression != 0);
300
301         QObject *obj = new QObject;
302
303         QCOMPARE(prop.name(), QString("defaultProperty"));
304         QCOMPARE(prop.read(), QVariant(10));
305         QCOMPARE(prop.write(QVariant()), false);
306         QCOMPARE(prop.hasNotifySignal(), false);
307         QCOMPARE(prop.needsNotifySignal(), true);
308         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
309         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
310         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
311         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
312         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
313         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
314         QVERIFY(prop.method().signature() == 0);
315         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
316         QCOMPARE(prop.isProperty(), true);
317         QCOMPARE(prop.isWritable(), false);
318         QCOMPARE(prop.isDesignable(), true);
319         QCOMPARE(prop.isResettable(), false);
320         QCOMPARE(prop.isSignalProperty(), false);
321         QCOMPARE(prop.isValid(), true);
322         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
323         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
324         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
325         QCOMPARE(prop.propertyTypeName(), "int");
326         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
327         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
328         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
329         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
330         QVERIFY(binding != 0);
331         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
332         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
333         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
334         QVERIFY(expression == 0);
335         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
336         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
337
338         delete obj;
339     }
340 }
341
342 void tst_qdeclarativeproperty::qmlmetaproperty_object_string()
343 {
344     QObject object; 
345     PropertyObject dobject; 
346
347     {
348         QDeclarativeProperty prop(&object, QString("defaultProperty"));
349
350         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
351         QVERIFY(binding != 0);
352         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
353         QVERIFY(expression != 0);
354
355         QObject *obj = new QObject;
356
357         QCOMPARE(prop.name(), QString());
358         QCOMPARE(prop.read(), QVariant());
359         QCOMPARE(prop.write(QVariant()), false);
360         QCOMPARE(prop.hasNotifySignal(), false);
361         QCOMPARE(prop.needsNotifySignal(), false);
362         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
363         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
364         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
365         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
366         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
367         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
368         QVERIFY(prop.method().signature() == 0);
369         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
370         QCOMPARE(prop.isProperty(), false);
371         QCOMPARE(prop.isWritable(), false);
372         QCOMPARE(prop.isDesignable(), false);
373         QCOMPARE(prop.isResettable(), false);
374         QCOMPARE(prop.isSignalProperty(), false);
375         QCOMPARE(prop.isValid(), false);
376         QCOMPARE(prop.object(), (QObject *)0);
377         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
378         QCOMPARE(prop.propertyType(), 0);
379         QCOMPARE(prop.propertyTypeName(), (const char *)0);
380         QVERIFY(prop.property().name() == 0);
381         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
382         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
383         QVERIFY(binding == 0);
384         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
385         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
386         QVERIFY(expression == 0);
387         QCOMPARE(prop.index(), -1);
388         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
389
390         delete obj;
391     }
392
393     {
394         QDeclarativeProperty prop(&dobject, QString("defaultProperty"));
395
396         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
397         binding.data()->setTarget(prop);
398         QVERIFY(binding != 0);
399         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
400         QVERIFY(expression != 0);
401
402         QObject *obj = new QObject;
403
404         QCOMPARE(prop.name(), QString("defaultProperty"));
405         QCOMPARE(prop.read(), QVariant(10));
406         QCOMPARE(prop.write(QVariant()), false);
407         QCOMPARE(prop.hasNotifySignal(), false);
408         QCOMPARE(prop.needsNotifySignal(), true);
409         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
410         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
411         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
412         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
413         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
414         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
415         QVERIFY(prop.method().signature() == 0);
416         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
417         QCOMPARE(prop.isProperty(), true);
418         QCOMPARE(prop.isWritable(), false);
419         QCOMPARE(prop.isDesignable(), true);
420         QCOMPARE(prop.isResettable(), false);
421         QCOMPARE(prop.isSignalProperty(), false);
422         QCOMPARE(prop.isValid(), true);
423         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
424         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
425         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
426         QCOMPARE(prop.propertyTypeName(), "int");
427         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
428         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
429         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
430         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
431         QVERIFY(binding != 0);
432         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
433         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
434         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
435         QVERIFY(expression == 0);
436         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
437         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
438
439         delete obj;
440     }
441
442     {
443         QDeclarativeProperty prop(&dobject, QString("onClicked"));
444
445         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
446         binding.data()->setTarget(prop);
447         QVERIFY(binding != 0);
448         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
449         QVERIFY(expression != 0);
450
451         QObject *obj = new QObject;
452
453         QCOMPARE(prop.name(), QString("onClicked"));
454         QCOMPARE(prop.read(), QVariant());
455         QCOMPARE(prop.write(QVariant("Hello")), false);
456         QCOMPARE(prop.hasNotifySignal(), false);
457         QCOMPARE(prop.needsNotifySignal(), false);
458         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
459         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
460         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
461         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
462         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
463         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
464         QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
465         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
466         QCOMPARE(prop.isProperty(), false);
467         QCOMPARE(prop.isWritable(), false);
468         QCOMPARE(prop.isDesignable(), false);
469         QCOMPARE(prop.isResettable(), false);
470         QCOMPARE(prop.isSignalProperty(), true);
471         QCOMPARE(prop.isValid(), true);
472         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
473         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
474         QCOMPARE(prop.propertyType(), 0);
475         QCOMPARE(prop.propertyTypeName(), (const char *)0);
476         QCOMPARE(prop.property().name(), (const char *)0);
477         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
478         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
479         QVERIFY(binding == 0);
480         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
481         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
482         QVERIFY(expression != 0);
483         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
484         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
485         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
486
487         delete obj;
488     }
489
490     {
491         QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
492
493         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
494         binding.data()->setTarget(prop);
495         QVERIFY(binding != 0);
496         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
497         QVERIFY(expression != 0);
498
499         QObject *obj = new QObject;
500
501         QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
502         QCOMPARE(prop.read(), QVariant());
503         QCOMPARE(prop.write(QVariant("Hello")), false);
504         QCOMPARE(prop.hasNotifySignal(), false);
505         QCOMPARE(prop.needsNotifySignal(), false);
506         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
507         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
508         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
509         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
510         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
511         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
512         QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
513         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
514         QCOMPARE(prop.isProperty(), false);
515         QCOMPARE(prop.isWritable(), false);
516         QCOMPARE(prop.isDesignable(), false);
517         QCOMPARE(prop.isResettable(), false);
518         QCOMPARE(prop.isSignalProperty(), true);
519         QCOMPARE(prop.isValid(), true);
520         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
521         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
522         QCOMPARE(prop.propertyType(), 0);
523         QCOMPARE(prop.propertyTypeName(), (const char *)0);
524         QCOMPARE(prop.property().name(), (const char *)0);
525         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
526         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
527         QVERIFY(binding == 0);
528         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
529         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
530         QVERIFY(expression != 0);
531         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
532         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
533         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
534
535         delete obj;
536     }
537 }
538
539 void tst_qdeclarativeproperty::qmlmetaproperty_object_context()
540 {
541     QObject object; // Has no default property
542     PropertyObject dobject; // Has default property
543
544     {
545         QDeclarativeProperty prop(&object, engine.rootContext());
546
547         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
548         QVERIFY(binding != 0);
549         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
550         QVERIFY(expression != 0);
551
552         QObject *obj = new QObject;
553
554         QCOMPARE(prop.name(), QString());
555         QCOMPARE(prop.read(), QVariant());
556         QCOMPARE(prop.write(QVariant()), false);
557         QCOMPARE(prop.hasNotifySignal(), false);
558         QCOMPARE(prop.needsNotifySignal(), false);
559         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
560         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
561         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
562         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
563         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
564         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
565         QVERIFY(prop.method().signature() == 0);
566         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
567         QCOMPARE(prop.isProperty(), false);
568         QCOMPARE(prop.isWritable(), false);
569         QCOMPARE(prop.isDesignable(), false);
570         QCOMPARE(prop.isResettable(), false);
571         QCOMPARE(prop.isSignalProperty(), false);
572         QCOMPARE(prop.isValid(), false);
573         QCOMPARE(prop.object(), (QObject *)0);
574         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
575         QCOMPARE(prop.propertyType(), 0);
576         QCOMPARE(prop.propertyTypeName(), (const char *)0);
577         QVERIFY(prop.property().name() == 0);
578         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
579         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
580         QVERIFY(binding == 0);
581         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
582         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
583         QVERIFY(expression == 0);
584         QCOMPARE(prop.index(), -1);
585         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
586
587         delete obj;
588     }
589
590     {
591         QDeclarativeProperty prop(&dobject, engine.rootContext());
592
593         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
594         binding.data()->setTarget(prop);
595         QVERIFY(binding != 0);
596         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
597         QVERIFY(expression != 0);
598
599         QObject *obj = new QObject;
600
601         QCOMPARE(prop.name(), QString("defaultProperty"));
602         QCOMPARE(prop.read(), QVariant(10));
603         QCOMPARE(prop.write(QVariant()), false);
604         QCOMPARE(prop.hasNotifySignal(), false);
605         QCOMPARE(prop.needsNotifySignal(), true);
606         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
607         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
608         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
609         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
610         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
611         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
612         QVERIFY(prop.method().signature() == 0);
613         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
614         QCOMPARE(prop.isProperty(), true);
615         QCOMPARE(prop.isWritable(), false);
616         QCOMPARE(prop.isDesignable(), true);
617         QCOMPARE(prop.isResettable(), false);
618         QCOMPARE(prop.isSignalProperty(), false);
619         QCOMPARE(prop.isValid(), true);
620         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
621         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
622         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
623         QCOMPARE(prop.propertyTypeName(), "int");
624         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
625         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
626         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
627         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
628         QVERIFY(binding != 0);
629         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
630         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
631         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
632         QVERIFY(expression == 0);
633         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
634         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
635
636         delete obj;
637     }
638 }
639
640 void tst_qdeclarativeproperty::qmlmetaproperty_object_string_context()
641 {
642     QObject object; 
643     PropertyObject dobject; 
644
645     {
646         QDeclarativeProperty prop(&object, QString("defaultProperty"), engine.rootContext());
647
648         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
649         QVERIFY(binding != 0);
650         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
651         QVERIFY(expression != 0);
652
653         QObject *obj = new QObject;
654
655         QCOMPARE(prop.name(), QString());
656         QCOMPARE(prop.read(), QVariant());
657         QCOMPARE(prop.write(QVariant()), false);
658         QCOMPARE(prop.hasNotifySignal(), false);
659         QCOMPARE(prop.needsNotifySignal(), false);
660         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
661         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
662         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
663         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
664         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
665         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
666         QVERIFY(prop.method().signature() == 0);
667         QCOMPARE(prop.type(), QDeclarativeProperty::Invalid);
668         QCOMPARE(prop.isProperty(), false);
669         QCOMPARE(prop.isWritable(), false);
670         QCOMPARE(prop.isDesignable(), false);
671         QCOMPARE(prop.isResettable(), false);
672         QCOMPARE(prop.isSignalProperty(), false);
673         QCOMPARE(prop.isValid(), false);
674         QCOMPARE(prop.object(), (QObject *)0);
675         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
676         QCOMPARE(prop.propertyType(), 0);
677         QCOMPARE(prop.propertyTypeName(), (const char *)0);
678         QVERIFY(prop.property().name() == 0);
679         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
680         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
681         QVERIFY(binding == 0);
682         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
683         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
684         QVERIFY(expression == 0);
685         QCOMPARE(prop.index(), -1);
686         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
687
688         delete obj;
689     }
690
691     {
692         QDeclarativeProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
693
694         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
695         binding.data()->setTarget(prop);
696         QVERIFY(binding != 0);
697         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
698         QVERIFY(expression != 0);
699
700         QObject *obj = new QObject;
701
702         QCOMPARE(prop.name(), QString("defaultProperty"));
703         QCOMPARE(prop.read(), QVariant(10));
704         QCOMPARE(prop.write(QVariant()), false);
705         QCOMPARE(prop.hasNotifySignal(), false);
706         QCOMPARE(prop.needsNotifySignal(), true);
707         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
708         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
709         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
710         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
711         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
712         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
713         QVERIFY(prop.method().signature() == 0);
714         QCOMPARE(prop.type(), QDeclarativeProperty::Property);
715         QCOMPARE(prop.isProperty(), true);
716         QCOMPARE(prop.isWritable(), false);
717         QCOMPARE(prop.isDesignable(), true);
718         QCOMPARE(prop.isResettable(), false);
719         QCOMPARE(prop.isSignalProperty(), false);
720         QCOMPARE(prop.isValid(), true);
721         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
722         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::Normal);
723         QCOMPARE(prop.propertyType(), (int)QVariant::Int);
724         QCOMPARE(prop.propertyTypeName(), "int");
725         QCOMPARE(QString(prop.property().name()), QString("defaultProperty"));
726         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
727         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Unable to assign null to int");
728         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
729         QVERIFY(binding != 0);
730         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == binding.data());
731         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
732         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
733         QVERIFY(expression == 0);
734         QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
735         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
736
737         delete obj;
738     }
739
740     {
741         QDeclarativeProperty prop(&dobject, QString("onClicked"), engine.rootContext());
742
743         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
744         binding.data()->setTarget(prop);
745         QVERIFY(binding != 0);
746         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
747         QVERIFY(expression != 0);
748
749         QObject *obj = new QObject;
750
751         QCOMPARE(prop.name(), QString("onClicked"));
752         QCOMPARE(prop.read(), QVariant());
753         QCOMPARE(prop.write(QVariant("Hello")), false);
754         QCOMPARE(prop.hasNotifySignal(), false);
755         QCOMPARE(prop.needsNotifySignal(), false);
756         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
757         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
758         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
759         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
760         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
761         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
762         QCOMPARE(QString(prop.method().signature()), QString("clicked()"));
763         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
764         QCOMPARE(prop.isProperty(), false);
765         QCOMPARE(prop.isWritable(), false);
766         QCOMPARE(prop.isDesignable(), false);
767         QCOMPARE(prop.isResettable(), false);
768         QCOMPARE(prop.isSignalProperty(), true);
769         QCOMPARE(prop.isValid(), true);
770         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
771         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
772         QCOMPARE(prop.propertyType(), 0);
773         QCOMPARE(prop.propertyTypeName(), (const char *)0);
774         QCOMPARE(prop.property().name(), (const char *)0);
775         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
776         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
777         QVERIFY(binding == 0);
778         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
779         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
780         QVERIFY(expression != 0);
781         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
782         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
783         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
784
785         delete obj;
786     }
787
788     {
789         QDeclarativeProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
790
791         QWeakPointer<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
792         binding.data()->setTarget(prop);
793         QVERIFY(binding != 0);
794         QWeakPointer<QDeclarativeExpression> expression(new QDeclarativeExpression());
795         QVERIFY(expression != 0);
796
797         QObject *obj = new QObject;
798
799         QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
800         QCOMPARE(prop.read(), QVariant());
801         QCOMPARE(prop.write(QVariant("Hello")), false);
802         QCOMPARE(prop.hasNotifySignal(), false);
803         QCOMPARE(prop.needsNotifySignal(), false);
804         QCOMPARE(prop.connectNotifySignal(0, SLOT(deleteLater())), false);
805         QCOMPARE(prop.connectNotifySignal(obj, SLOT(deleteLater())), false);
806         QCOMPARE(prop.connectNotifySignal(obj, 0), false);
807         QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
808         QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
809         QCOMPARE(prop.connectNotifySignal(obj, -1), false);
810         QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
811         QCOMPARE(prop.type(), QDeclarativeProperty::SignalProperty);
812         QCOMPARE(prop.isProperty(), false);
813         QCOMPARE(prop.isWritable(), false);
814         QCOMPARE(prop.isDesignable(), false);
815         QCOMPARE(prop.isResettable(), false);
816         QCOMPARE(prop.isSignalProperty(), true);
817         QCOMPARE(prop.isValid(), true);
818         QCOMPARE(prop.object(), qobject_cast<QObject*>(&dobject));
819         QCOMPARE(prop.propertyTypeCategory(), QDeclarativeProperty::InvalidCategory);
820         QCOMPARE(prop.propertyType(), 0);
821         QCOMPARE(prop.propertyTypeName(), (const char *)0);
822         QCOMPARE(prop.property().name(), (const char *)0);
823         QVERIFY(QDeclarativePropertyPrivate::binding(prop) == 0);
824         QVERIFY(QDeclarativePropertyPrivate::setBinding(prop, binding.data()) == 0);
825         QVERIFY(binding == 0);
826         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == 0);
827         QVERIFY(QDeclarativePropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
828         QVERIFY(expression != 0);
829         QVERIFY(QDeclarativePropertyPrivate::signalExpression(prop) == expression.data());
830         QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
831         QCOMPARE(QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), -1);
832
833         delete obj;
834     }
835 }
836
837 void tst_qdeclarativeproperty::name()
838 {
839     { 
840         QDeclarativeProperty p;
841         QCOMPARE(p.name(), QString());
842     }
843
844     {
845         PropertyObject o;
846         QDeclarativeProperty p(&o);
847         QCOMPARE(p.name(), QString("defaultProperty"));
848     }
849
850     {
851         QObject o;
852         QDeclarativeProperty p(&o, QString("objectName"));
853         QCOMPARE(p.name(), QString("objectName"));
854     }
855
856     {
857         PropertyObject o;
858         QDeclarativeProperty p(&o, "onClicked");
859         QCOMPARE(p.name(), QString("onClicked"));
860     }
861
862     {
863         QObject o;
864         QDeclarativeProperty p(&o, "onClicked");
865         QCOMPARE(p.name(), QString());
866     }
867
868     {
869         PropertyObject o;
870         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
871         QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
872     }
873
874     {
875         QObject o;
876         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
877         QCOMPARE(p.name(), QString());
878     }
879
880     {
881         QObject o;
882         QDeclarativeProperty p(&o, "foo");
883         QCOMPARE(p.name(), QString());
884     }
885
886     {
887         QDeclarativeProperty p(0, "foo");
888         QCOMPARE(p.name(), QString());
889     }
890
891     {
892         PropertyObject o;
893         QDeclarativeProperty p(&o, "rectProperty");
894         QCOMPARE(p.name(), QString("rectProperty"));
895     }
896
897     {
898         PropertyObject o;
899         QDeclarativeProperty p(&o, "rectProperty.x");
900         QCOMPARE(p.name(), QString("rectProperty.x"));
901     }
902
903     {
904         PropertyObject o;
905         QDeclarativeProperty p(&o, "rectProperty.foo");
906         QCOMPARE(p.name(), QString());
907     }
908 }
909
910 void tst_qdeclarativeproperty::read()
911 {
912     // Invalid 
913     {
914         QDeclarativeProperty p;
915         QCOMPARE(p.read(), QVariant());
916     }
917
918     // Default prop
919     {
920         PropertyObject o;
921         QDeclarativeProperty p(&o);
922         QCOMPARE(p.read(), QVariant(10));
923     }
924
925     // Invalid default prop
926     {
927         QObject o;
928         QDeclarativeProperty p(&o);
929         QCOMPARE(p.read(), QVariant());
930     }
931
932     // Value prop by name
933     {
934         QObject o;
935
936         QDeclarativeProperty p(&o, "objectName");
937         QCOMPARE(p.read(), QVariant(QString()));
938
939         o.setObjectName("myName");
940
941         QCOMPARE(p.read(), QVariant("myName"));
942     }
943
944     // Value prop by name (static)
945     {
946         QObject o;
947
948         QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant(QString()));
949
950         o.setObjectName("myName");
951
952         QCOMPARE(QDeclarativeProperty::read(&o, "objectName"), QVariant("myName"));
953     }
954
955     // Value-type prop
956     {
957         PropertyObject o;
958         QDeclarativeProperty p(&o, "rectProperty.x");
959         QCOMPARE(p.read(), QVariant(10));
960     }
961
962     // Invalid value-type prop
963     {
964         PropertyObject o;
965         QDeclarativeProperty p(&o, "rectProperty.foo");
966         QCOMPARE(p.read(), QVariant());
967     }
968
969     // Signal property
970     {
971         PropertyObject o;
972         QDeclarativeProperty p(&o, "onClicked");
973         QCOMPARE(p.read(), QVariant());
974
975         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
976         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
977
978         QCOMPARE(p.read(), QVariant());
979     }
980
981     // Automatic signal property 
982     {
983         PropertyObject o;
984         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
985         QCOMPARE(p.read(), QVariant());
986
987         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
988         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
989
990         QCOMPARE(p.read(), QVariant());
991     }
992
993     // Deleted object
994     {
995         PropertyObject *o = new PropertyObject;
996         QDeclarativeProperty p(o, "rectProperty.x");
997         QCOMPARE(p.read(), QVariant(10));
998         delete o;
999         QCOMPARE(p.read(), QVariant());
1000     }
1001
1002     // Object property
1003     {
1004         PropertyObject o;
1005         QDeclarativeProperty p(&o, "qmlObject");
1006         QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1007         QCOMPARE(p.propertyType(), qMetaTypeId<MyQmlObject*>());
1008         QVariant v = p.read();
1009         QVERIFY(v.userType() == QMetaType::QObjectStar);
1010         QVERIFY(qvariant_cast<QObject *>(v) == o.qmlObject());
1011     }
1012     {
1013         QDeclarativeComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1014         QObject *object = component.create();
1015         QVERIFY(object != 0);
1016
1017         QDeclarativeProperty p(object, "test", &engine);
1018
1019         QCOMPARE(p.propertyTypeCategory(), QDeclarativeProperty::Object);
1020         QVERIFY(p.propertyType() != QMetaType::QObjectStar);
1021
1022         QVariant v = p.read();
1023         QVERIFY(v.userType() == QMetaType::QObjectStar);
1024         QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1025         QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1026     }
1027     {   // static
1028         QDeclarativeComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
1029         QObject *object = component.create();
1030         QVERIFY(object != 0);
1031
1032         QVariant v = QDeclarativeProperty::read(object, "test", &engine);
1033         QVERIFY(v.userType() == QMetaType::QObjectStar);
1034         QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
1035         QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
1036     }
1037
1038     // Attached property
1039     {
1040         QDeclarativeComponent component(&engine);
1041         component.setData("import Test 1.0\nMyContainer { }", QUrl());
1042         QObject *object = component.create();
1043         QVERIFY(object != 0);
1044
1045         QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1046         QCOMPARE(p.read(), QVariant(13));
1047         delete object;
1048     }
1049     {
1050         QDeclarativeComponent component(&engine);
1051         component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
1052         QObject *object = component.create();
1053         QVERIFY(object != 0);
1054
1055         QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1056         QCOMPARE(p.read(), QVariant(10));
1057         delete object;
1058     }
1059     {
1060         QDeclarativeComponent component(&engine);
1061         component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1062         QObject *object = component.create();
1063         QVERIFY(object != 0);
1064
1065         QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1066         QCOMPARE(p.read(), QVariant(10));
1067         delete object;
1068     }
1069     {   // static
1070         QDeclarativeComponent component(&engine);
1071         component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1072         QObject *object = component.create();
1073         QVERIFY(object != 0);
1074
1075         QCOMPARE(QDeclarativeProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
1076         delete object;
1077     }
1078 }
1079
1080 void tst_qdeclarativeproperty::write()
1081 {
1082     // Invalid
1083     {
1084         QDeclarativeProperty p;
1085         QCOMPARE(p.write(QVariant(10)), false);
1086     }
1087
1088     // Read-only default prop
1089     {
1090         PropertyObject o;
1091         QDeclarativeProperty p(&o);
1092         QCOMPARE(p.write(QVariant(10)), false);
1093     }
1094
1095     // Invalid default prop
1096     {
1097         QObject o;
1098         QDeclarativeProperty p(&o);
1099         QCOMPARE(p.write(QVariant(10)), false);
1100     }
1101
1102     // Read-only prop by name
1103     {
1104         PropertyObject o;
1105         QDeclarativeProperty p(&o, QString("defaultProperty"));
1106         QCOMPARE(p.write(QVariant(10)), false);
1107     }
1108
1109     // Writable prop by name
1110     {
1111         PropertyObject o;
1112         QDeclarativeProperty p(&o, QString("objectName"));
1113         QCOMPARE(o.objectName(), QString());
1114         QCOMPARE(p.write(QVariant(QString("myName"))), true);
1115         QCOMPARE(o.objectName(), QString("myName"));
1116     }
1117
1118     // Writable prop by name (static)
1119     {
1120         PropertyObject o;
1121         QCOMPARE(QDeclarativeProperty::write(&o, QString("objectName"), QVariant(QString("myName"))), true);
1122         QCOMPARE(o.objectName(), QString("myName"));
1123     }
1124
1125     // Deleted object
1126     {
1127         PropertyObject *o = new PropertyObject;
1128         QDeclarativeProperty p(o, QString("objectName"));
1129         QCOMPARE(p.write(QVariant(QString("myName"))), true);
1130         QCOMPARE(o->objectName(), QString("myName"));
1131
1132         delete o;
1133
1134         QCOMPARE(p.write(QVariant(QString("myName"))), false);
1135     }
1136
1137     // Signal property
1138     {
1139         PropertyObject o;
1140         QDeclarativeProperty p(&o, "onClicked");
1141         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1142
1143         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1144         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1145
1146         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1147
1148         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1149     }
1150
1151     // Automatic signal property
1152     {
1153         PropertyObject o;
1154         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1155         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1156
1157         QVERIFY(0 == QDeclarativePropertyPrivate::setSignalExpression(p, new QDeclarativeExpression()));
1158         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1159
1160         QCOMPARE(p.write(QVariant("console.log(1921)")), false);
1161
1162         QVERIFY(0 != QDeclarativePropertyPrivate::signalExpression(p));
1163     }
1164
1165     // Value-type property
1166     {
1167         PropertyObject o;
1168         QDeclarativeProperty p(&o, "wrectProperty");
1169
1170         QCOMPARE(o.wrectProperty(), QRect());
1171         QCOMPARE(p.write(QRect(1, 13, 99, 8)), true);
1172         QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8));
1173
1174         QDeclarativeProperty p2(&o, "wrectProperty.x");
1175         QCOMPARE(p2.read(), QVariant(1));
1176         QCOMPARE(p2.write(QVariant(6)), true);
1177         QCOMPARE(p2.read(), QVariant(6));
1178         QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8));
1179     }
1180
1181     // URL-property
1182     {
1183         PropertyObject o;
1184         QDeclarativeProperty p(&o, "url");
1185
1186         QCOMPARE(p.write(QUrl("main.qml")), true);
1187         QCOMPARE(o.url(), QUrl("main.qml"));
1188
1189         QDeclarativeProperty p2(&o, "url", engine.rootContext());
1190
1191         QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1192         QVERIFY(result != QUrl("main.qml"));
1193
1194         QCOMPARE(p2.write(QUrl("main.qml")), true);
1195         QCOMPARE(o.url(), result);
1196     }
1197     {   // static
1198         PropertyObject o;
1199
1200         QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml")), true);
1201         QCOMPARE(o.url(), QUrl("main.qml"));
1202
1203         QUrl result = engine.baseUrl().resolved(QUrl("main.qml"));
1204         QVERIFY(result != QUrl("main.qml"));
1205
1206         QCOMPARE(QDeclarativeProperty::write(&o, "url", QUrl("main.qml"), engine.rootContext()), true);
1207         QCOMPARE(o.url(), result);
1208     }
1209
1210     // VariantMap-property
1211     QVariantMap vm;
1212     vm.insert("key", "value");
1213
1214     {
1215         PropertyObject o;
1216         QDeclarativeProperty p(&o, "variantMap");
1217
1218         QCOMPARE(p.write(vm), true);
1219         QCOMPARE(o.variantMap(), vm);
1220
1221         QDeclarativeProperty p2(&o, "variantMap", engine.rootContext());
1222
1223         QCOMPARE(p2.write(vm), true);
1224         QCOMPARE(o.variantMap(), vm);
1225     }
1226     {   // static
1227         PropertyObject o;
1228
1229         QCOMPARE(QDeclarativeProperty::write(&o, "variantMap", vm), true);
1230         QCOMPARE(o.variantMap(), vm);
1231
1232         QCOMPARE(QDeclarativeProperty::write(&o, "variantMap", vm, engine.rootContext()), true);
1233         QCOMPARE(o.variantMap(), vm);
1234     }
1235
1236     // Attached property
1237     {
1238         QDeclarativeComponent component(&engine);
1239         component.setData("import Test 1.0\nMyContainer { }", QUrl());
1240         QObject *object = component.create();
1241         QVERIFY(object != 0);
1242
1243         QDeclarativeProperty p(object, "MyContainer.foo", qmlContext(object));
1244         p.write(QVariant(99));
1245         QCOMPARE(p.read(), QVariant(99));
1246         delete object;
1247     }
1248     {
1249         QDeclarativeComponent component(&engine);
1250         component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
1251         QObject *object = component.create();
1252         QVERIFY(object != 0);
1253
1254         QDeclarativeProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
1255         p.write(QVariant(99));
1256         QCOMPARE(p.read(), QVariant(99));
1257         delete object;
1258     }
1259 }
1260
1261 void tst_qdeclarativeproperty::reset()
1262 {
1263     // Invalid
1264     {
1265         QDeclarativeProperty p;
1266         QCOMPARE(p.isResettable(), false);
1267         QCOMPARE(p.reset(), false);
1268     }
1269
1270     // Read-only default prop
1271     {
1272         PropertyObject o;
1273         QDeclarativeProperty p(&o);
1274         QCOMPARE(p.isResettable(), false);
1275         QCOMPARE(p.reset(), false);
1276     }
1277
1278     // Invalid default prop
1279     {
1280         QObject o;
1281         QDeclarativeProperty p(&o);
1282         QCOMPARE(p.isResettable(), false);
1283         QCOMPARE(p.reset(), false);
1284     }
1285
1286     // Non-resettable-only prop by name
1287     {
1288         PropertyObject o;
1289         QDeclarativeProperty p(&o, QString("defaultProperty"));
1290         QCOMPARE(p.isResettable(), false);
1291         QCOMPARE(p.reset(), false);
1292     }
1293
1294     // Resettable prop by name
1295     {
1296         PropertyObject o;
1297         QDeclarativeProperty p(&o, QString("resettableProperty"));
1298
1299         QCOMPARE(p.read(), QVariant(9));
1300         QCOMPARE(p.write(QVariant(11)), true);
1301         QCOMPARE(p.read(), QVariant(11));
1302
1303         QCOMPARE(p.isResettable(), true);
1304         QCOMPARE(p.reset(), true);
1305
1306         QCOMPARE(p.read(), QVariant(9));
1307     }
1308
1309     // Deleted object
1310     {
1311         PropertyObject *o = new PropertyObject;
1312
1313         QDeclarativeProperty p(o, QString("resettableProperty"));
1314
1315         QCOMPARE(p.isResettable(), true);
1316         QCOMPARE(p.reset(), true);
1317
1318         delete o;
1319
1320         QCOMPARE(p.isResettable(), false);
1321         QCOMPARE(p.reset(), false);
1322     }
1323
1324     // Signal property
1325     {
1326         PropertyObject o;
1327         QDeclarativeProperty p(&o, "onClicked");
1328
1329         QCOMPARE(p.isResettable(), false);
1330         QCOMPARE(p.reset(), false);
1331     }
1332
1333     // Automatic signal property
1334     {
1335         PropertyObject o;
1336         QDeclarativeProperty p(&o, "onPropertyWithNotifyChanged");
1337
1338         QCOMPARE(p.isResettable(), false);
1339         QCOMPARE(p.reset(), false);
1340     }
1341 }
1342
1343 void tst_qdeclarativeproperty::writeObjectToList()
1344 {
1345     QDeclarativeComponent containerComponent(&engine);
1346     containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1347     MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1348     QVERIFY(container != 0);
1349     QDeclarativeListReference list(container, "children");
1350     QVERIFY(list.count() == 1);
1351
1352     MyQmlObject *object = new MyQmlObject;
1353     QDeclarativeProperty prop(container, "children");
1354     prop.write(qVariantFromValue(object));
1355     QCOMPARE(list.count(), 1);
1356     QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
1357 }
1358
1359 void tst_qdeclarativeproperty::writeListToList()
1360 {
1361     QDeclarativeComponent containerComponent(&engine);
1362     containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
1363     MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
1364     QVERIFY(container != 0);
1365     QDeclarativeListReference list(container, "children");
1366     QVERIFY(list.count() == 1);
1367
1368     QList<QObject*> objList;
1369     objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
1370     QDeclarativeProperty prop(container, "children");
1371     prop.write(qVariantFromValue(objList));
1372     QCOMPARE(list.count(), 4);
1373
1374     //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
1375     /*QList<MyQmlObject*> typedObjList;
1376     typedObjList << new MyQmlObject();
1377     prop.write(qVariantFromValue(&typedObjList));
1378     QCOMPARE(container->children()->size(), 1);*/
1379 }
1380
1381 void tst_qdeclarativeproperty::urlHandling_data()
1382 {
1383     QTest::addColumn<QByteArray>("input");
1384     QTest::addColumn<QString>("scheme");
1385     QTest::addColumn<QString>("path");
1386     QTest::addColumn<QByteArray>("encoded");
1387
1388     QTest::newRow("unspecifiedFile")
1389         << QByteArray("main.qml")
1390         << QString("")
1391         << QString("main.qml")
1392         << QByteArray("main.qml");
1393
1394     QTest::newRow("specifiedFile")
1395         << QByteArray("file:///main.qml")
1396         << QString("file")
1397         << QString("/main.qml")
1398         << QByteArray("file:///main.qml");
1399
1400     QTest::newRow("httpFile")
1401         << QByteArray("http://www.example.com/main.qml")
1402         << QString("http")
1403         << QString("/main.qml")
1404         << QByteArray("http://www.example.com/main.qml");
1405
1406     QTest::newRow("pathFile")
1407         << QByteArray("http://www.example.com/resources/main.qml")
1408         << QString("http")
1409         << QString("/resources/main.qml")
1410         << QByteArray("http://www.example.com/resources/main.qml");
1411
1412     QTest::newRow("encodableName")
1413         << QByteArray("http://www.example.com/main file.qml")
1414         << QString("http")
1415         << QString("/main file.qml")
1416         << QByteArray("http://www.example.com/main%20file.qml");
1417
1418     QTest::newRow("preencodedName")
1419         << QByteArray("http://www.example.com/resources%7cmain%20file.qml")
1420         << QString("http")
1421         << QString("/resources|main file.qml")
1422         << QByteArray("http://www.example.com/resources%7cmain%20file.qml");
1423
1424     QTest::newRow("encodableQuery")
1425         << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now working?")
1426         << QString("http")
1427         << QString("/main.qml")
1428         << QByteArray("http://www.example.com/main.qml?type=text/qml&comment=now%20working?");
1429
1430     QTest::newRow("preencodedQuery")
1431         << QByteArray("http://www.example.com/main.qml?type=text%2fqml&comment=now working%3f")
1432         << QString("http")
1433         << QString("/main.qml")
1434         << QByteArray("http://www.example.com/main.qml?type=text%2fqml&comment=now%20working%3f");
1435
1436     QTest::newRow("encodableFragment")
1437         << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000|volume+50%")
1438         << QString("http")
1439         << QString("/main.qml")
1440         << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7Cvolume+50%25");
1441
1442     QTest::newRow("preencodedFragment")
1443         << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7cvolume%2b50%")
1444         << QString("http")
1445         << QString("/main.qml")
1446         << QByteArray("http://www.example.com/main.qml?type=text/qml#start+30000%7cvolume%2b50%25");
1447 }
1448
1449 void tst_qdeclarativeproperty::urlHandling()
1450 {
1451     QFETCH(QByteArray, input);
1452     QFETCH(QString, scheme);
1453     QFETCH(QString, path);
1454     QFETCH(QByteArray, encoded);
1455
1456     QString inputString(QString::fromUtf8(input));
1457
1458     {
1459         PropertyObject o;
1460         QDeclarativeProperty p(&o, "url");
1461
1462         // Test url written as QByteArray
1463         QCOMPARE(p.write(input), true);
1464         QUrl byteArrayResult(o.url());
1465
1466         QCOMPARE(byteArrayResult.scheme(), scheme);
1467         QCOMPARE(byteArrayResult.path(), path);
1468         QCOMPARE(byteArrayResult.toEncoded(), encoded);
1469     }
1470
1471     {
1472         PropertyObject o;
1473         QDeclarativeProperty p(&o, "url");
1474
1475         // Test url written as QString
1476         QCOMPARE(p.write(inputString), true);
1477         QUrl stringResult(o.url());
1478
1479         QCOMPARE(stringResult.scheme(), scheme);
1480         QCOMPARE(stringResult.path(), path);
1481         QCOMPARE(stringResult.toEncoded(), encoded);
1482     }
1483 }
1484
1485 void tst_qdeclarativeproperty::variantMapHandling_data()
1486 {
1487     QTest::addColumn<QVariantMap>("vm");
1488
1489     // Object literals
1490     {
1491         QVariantMap m;
1492         QTest::newRow("{}") << m;
1493     }
1494     {
1495         QVariantMap m;
1496         m["a"] = QVariantMap();
1497         QTest::newRow("{ a:{} }") << m;
1498     }
1499     {
1500         QVariantMap m, m2;
1501         m2["b"] = 10;
1502         m2["c"] = 20;
1503         m["a"] = m2;
1504         QTest::newRow("{ a:{b:10, c:20} }") << m;
1505     }
1506     {
1507         QVariantMap m;
1508         m["a"] = 10;
1509         m["b"] = QVariantList() << 20 << 30;
1510         QTest::newRow("{ a:10, b:[20, 30]}") << m;
1511     }
1512
1513     // Cyclic objects
1514     {
1515         QVariantMap m;
1516         m["p"] = QVariantMap();
1517         QTest::newRow("var o={}; o.p=o") << m;
1518     }
1519     {
1520         QVariantMap m;
1521         m["p"] = 123;
1522         m["q"] = QVariantMap();
1523         QTest::newRow("var o={}; o.p=123; o.q=o") << m;
1524     }
1525 }
1526
1527 void tst_qdeclarativeproperty::variantMapHandling()
1528 {
1529     QFETCH(QVariantMap, vm);
1530
1531     PropertyObject o;
1532     QDeclarativeProperty p(&o, "variantMap");
1533
1534     QCOMPARE(p.write(vm), true);
1535     QCOMPARE(o.variantMap(), vm);
1536 }
1537
1538 void tst_qdeclarativeproperty::crashOnValueProperty()
1539 {
1540     QDeclarativeEngine *engine = new QDeclarativeEngine;
1541     QDeclarativeComponent component(engine);
1542
1543     component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
1544     PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
1545     QVERIFY(obj != 0);
1546
1547     QDeclarativeProperty p(obj, "wrectProperty.x", qmlContext(obj));
1548     QCOMPARE(p.name(), QString("wrectProperty.x"));
1549
1550     QCOMPARE(p.read(), QVariant(10));
1551
1552     //don't crash once the engine is deleted
1553     delete engine;
1554     engine = 0;
1555
1556     QCOMPARE(p.propertyTypeName(), "int");
1557     QCOMPARE(p.read(), QVariant(10));
1558     p.write(QVariant(20));
1559     QCOMPARE(p.read(), QVariant(20));
1560 }
1561
1562 // QTBUG-13719
1563 void tst_qdeclarativeproperty::aliasPropertyBindings()
1564 {
1565     QDeclarativeComponent component(&engine, testFileUrl("aliasPropertyBindings.qml"));
1566
1567     QObject *object = component.create();
1568     QVERIFY(object != 0);
1569
1570     QCOMPARE(object->property("realProperty").toReal(), 90.);
1571     QCOMPARE(object->property("aliasProperty").toReal(), 90.);
1572
1573     object->setProperty("test", 10);
1574
1575     QCOMPARE(object->property("realProperty").toReal(), 110.);
1576     QCOMPARE(object->property("aliasProperty").toReal(), 110.);
1577
1578     QDeclarativeProperty realProperty(object, QLatin1String("realProperty"));
1579     QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty"));
1580
1581     // Check there is a binding on these two properties
1582     QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1583     QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1584
1585     // Check that its the same binding on these two properties
1586     QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1587              QDeclarativePropertyPrivate::binding(aliasProperty));
1588
1589     // Change the binding
1590     object->setProperty("state", QString("switch"));
1591
1592     QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1593     QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1594     QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1595              QDeclarativePropertyPrivate::binding(aliasProperty));
1596
1597     QCOMPARE(object->property("realProperty").toReal(), 96.);
1598     QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1599
1600     // Check the old binding really has not effect any more
1601     object->setProperty("test", 4);
1602
1603     QCOMPARE(object->property("realProperty").toReal(), 96.);
1604     QCOMPARE(object->property("aliasProperty").toReal(), 96.);
1605
1606     object->setProperty("test2", 9);
1607
1608     QCOMPARE(object->property("realProperty").toReal(), 288.);
1609     QCOMPARE(object->property("aliasProperty").toReal(), 288.);
1610
1611     // Revert
1612     object->setProperty("state", QString(""));
1613
1614     QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0);
1615     QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0);
1616     QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty),
1617              QDeclarativePropertyPrivate::binding(aliasProperty));
1618
1619     QCOMPARE(object->property("realProperty").toReal(), 20.);
1620     QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1621
1622     object->setProperty("test2", 3);
1623
1624     QCOMPARE(object->property("realProperty").toReal(), 20.);
1625     QCOMPARE(object->property("aliasProperty").toReal(), 20.);
1626
1627     delete object;
1628 }
1629
1630 void tst_qdeclarativeproperty::copy()
1631 {
1632     PropertyObject object;
1633
1634     QDeclarativeProperty *property = new QDeclarativeProperty(&object, QLatin1String("defaultProperty"));
1635     QCOMPARE(property->name(), QString("defaultProperty"));
1636     QCOMPARE(property->read(), QVariant(10));
1637     QCOMPARE(property->type(), QDeclarativeProperty::Property);
1638     QCOMPARE(property->propertyTypeCategory(), QDeclarativeProperty::Normal);
1639     QCOMPARE(property->propertyType(), (int)QVariant::Int);
1640
1641     QDeclarativeProperty p1(*property);
1642     QCOMPARE(p1.name(), QString("defaultProperty"));
1643     QCOMPARE(p1.read(), QVariant(10));
1644     QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1645     QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1646     QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1647
1648     QDeclarativeProperty p2(&object, QLatin1String("url"));
1649     QCOMPARE(p2.name(), QString("url"));
1650     p2 = *property;
1651     QCOMPARE(p2.name(), QString("defaultProperty"));
1652     QCOMPARE(p2.read(), QVariant(10));
1653     QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1654     QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1655     QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1656
1657     delete property; property = 0;
1658
1659     QCOMPARE(p1.name(), QString("defaultProperty"));
1660     QCOMPARE(p1.read(), QVariant(10));
1661     QCOMPARE(p1.type(), QDeclarativeProperty::Property);
1662     QCOMPARE(p1.propertyTypeCategory(), QDeclarativeProperty::Normal);
1663     QCOMPARE(p1.propertyType(), (int)QVariant::Int);
1664
1665     QCOMPARE(p2.name(), QString("defaultProperty"));
1666     QCOMPARE(p2.read(), QVariant(10));
1667     QCOMPARE(p2.type(), QDeclarativeProperty::Property);
1668     QCOMPARE(p2.propertyTypeCategory(), QDeclarativeProperty::Normal);
1669     QCOMPARE(p2.propertyType(), (int)QVariant::Int);
1670 }
1671
1672 void tst_qdeclarativeproperty::noContext()
1673 {
1674     QDeclarativeComponent compA(&engine, testFileUrl("NoContextTypeA.qml"));
1675     QDeclarativeComponent compB(&engine, testFileUrl("NoContextTypeB.qml"));
1676
1677     QObject *a = compA.create();
1678     QVERIFY(a != 0);
1679     QObject *b = compB.create();
1680     QVERIFY(b != 0);
1681
1682     QVERIFY(QDeclarativeProperty::write(b, "myTypeA", QVariant::fromValue(a), &engine));
1683
1684     delete a;
1685     delete b;
1686 }
1687
1688 void tst_qdeclarativeproperty::assignEmptyVariantMap()
1689 {
1690     PropertyObject o;
1691
1692     QVariantMap map;
1693     map.insert("key", "value");
1694     o.setVariantMap(map);
1695     QCOMPARE(o.variantMap().count(), 1);
1696     QCOMPARE(o.variantMap().isEmpty(), false);
1697
1698     QDeclarativeContext context(&engine);
1699     context.setContextProperty("o", &o);
1700
1701     QDeclarativeComponent component(&engine, testFileUrl("assignEmptyVariantMap.qml"));
1702     QObject *obj = component.create(&context);
1703     QVERIFY(obj);
1704
1705     QCOMPARE(o.variantMap().count(), 0);
1706     QCOMPARE(o.variantMap().isEmpty(), true);
1707
1708     delete obj;
1709 }
1710
1711 void tst_qdeclarativeproperty::initTestCase()
1712 {
1713     QDeclarativeDataTest::initTestCase();
1714     qmlRegisterType<MyQmlObject>("Test",1,0,"MyQmlObject");
1715     qmlRegisterType<PropertyObject>("Test",1,0,"PropertyObject");
1716     qmlRegisterType<MyContainer>("Test",1,0,"MyContainer");
1717 }
1718
1719 QTEST_MAIN(tst_qdeclarativeproperty)
1720
1721 #include "tst_qdeclarativeproperty.moc"