Fixed rounding errors in QtQuick1 to int conversions
[qt:qt.git] / tests / auto / declarative / qdeclarativevaluetypes / tst_qdeclarativevaluetypes.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qtest.h>
43 #include <QDeclarativeEngine>
44 #include <QDeclarativeComponent>
45 #include <QDebug>
46 #include <private/qdeclarativevaluetype_p.h>
47 #include "testtypes.h"
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 QT_BEGIN_NAMESPACE
55 extern Q_GUI_EXPORT int qt_defaultDpi();
56 QT_END_NAMESPACE
57
58 class tst_qdeclarativevaluetypes : public QObject
59 {
60     Q_OBJECT
61 public:
62     tst_qdeclarativevaluetypes() {}
63
64 private slots:
65     void initTestCase();
66
67     void point();
68     void pointf();
69     void size();
70     void sizef();
71     void sizereadonly();
72     void rect();
73     void rectf();
74     void vector2d();
75     void vector3d();
76     void vector4d();
77     void quaternion();
78     void matrix4x4();
79     void font();
80     void variant();
81
82     void bindingAssignment();
83     void bindingRead();
84     void staticAssignment();
85     void scriptAccess();
86     void autoBindingRemoval();
87     void valueSources();
88     void valueInterceptors();
89     void bindingConflict();
90     void deletedObject();
91     void bindingVariantCopy();
92     void scriptVariantCopy();
93     void cppClasses();
94     void enums();
95     void conflictingBindings();
96     void returnValues();
97     void varAssignment();
98     void bindingsSpliceCorrectly();
99     void qtbug_33625();
100
101 private:
102     QDeclarativeEngine engine;
103 };
104
105 void tst_qdeclarativevaluetypes::initTestCase()
106 {
107     registerTypes();
108 }
109
110 inline QUrl TEST_FILE(const QString &filename)
111 {
112     return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
113 }
114
115 void tst_qdeclarativevaluetypes::point()
116 {
117     {
118         QDeclarativeComponent component(&engine, TEST_FILE("point_read.qml"));
119         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
120         QVERIFY(object != 0);
121
122         QCOMPARE(object->property("p_x").toInt(), 10);
123         QCOMPARE(object->property("p_y").toInt(), 4);
124         QCOMPARE(object->property("copy"), QVariant(QPoint(10, 4)));
125
126         delete object;
127     }
128
129     {
130         QDeclarativeComponent component(&engine, TEST_FILE("point_write.qml"));
131         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
132         QVERIFY(object != 0);
133
134         QCOMPARE(object->point(), QPoint(11, 12));
135
136         delete object;
137     }
138 }
139
140 void tst_qdeclarativevaluetypes::pointf()
141 {
142     {
143         QDeclarativeComponent component(&engine, TEST_FILE("pointf_read.qml"));
144         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
145         QVERIFY(object != 0);
146
147         QCOMPARE(float(object->property("p_x").toDouble()), float(11.3));
148         QCOMPARE(float(object->property("p_y").toDouble()), float(-10.9));
149         QCOMPARE(object->property("copy"), QVariant(QPointF(11.3, -10.9)));
150
151         delete object;
152     }
153
154     {
155         QDeclarativeComponent component(&engine, TEST_FILE("pointf_write.qml"));
156         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
157         QVERIFY(object != 0);
158
159         QCOMPARE(object->pointf(), QPointF(6.8, 9.3));
160
161         delete object;
162     }
163 }
164
165 void tst_qdeclarativevaluetypes::size()
166 {
167     {
168         QDeclarativeComponent component(&engine, TEST_FILE("size_read.qml"));
169         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
170         QVERIFY(object != 0);
171
172         QCOMPARE(object->property("s_width").toInt(), 1912);
173         QCOMPARE(object->property("s_height").toInt(), 1913);
174         QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
175
176         delete object;
177     }
178
179     {
180         QDeclarativeComponent component(&engine, TEST_FILE("size_write.qml"));
181         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
182         QVERIFY(object != 0);
183
184         QCOMPARE(object->size(), QSize(13, 88));
185
186         delete object;
187     }
188 }
189
190 void tst_qdeclarativevaluetypes::sizef()
191 {
192     {
193         QDeclarativeComponent component(&engine, TEST_FILE("sizef_read.qml"));
194         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
195         QVERIFY(object != 0);
196
197         QCOMPARE(float(object->property("s_width").toDouble()), float(0.1));
198         QCOMPARE(float(object->property("s_height").toDouble()), float(100923.2));
199         QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
200
201         delete object;
202     }
203
204     {
205         QDeclarativeComponent component(&engine, TEST_FILE("sizef_write.qml"));
206         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
207         QVERIFY(object != 0);
208
209         QCOMPARE(object->sizef(), QSizeF(44.3, 92.8));
210
211         delete object;
212     }
213 }
214
215 void tst_qdeclarativevaluetypes::variant()
216 {
217     QDeclarativeComponent component(&engine, TEST_FILE("variant_read.qml"));
218     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
219     QVERIFY(object != 0);
220
221     QCOMPARE(float(object->property("s_width").toDouble()), float(0.1));
222     QCOMPARE(float(object->property("s_height").toDouble()), float(100923.2));
223     QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
224
225     delete object;
226 }
227
228 void tst_qdeclarativevaluetypes::sizereadonly()
229 {
230     {
231         QDeclarativeComponent component(&engine, TEST_FILE("sizereadonly_read.qml"));
232         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
233         QVERIFY(object != 0);
234
235         QCOMPARE(object->property("s_width").toInt(), 1912);
236         QCOMPARE(object->property("s_height").toInt(), 1913);
237         QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
238
239         delete object;
240     }
241
242     {
243         QDeclarativeComponent component(&engine, TEST_FILE("sizereadonly_writeerror.qml"));
244         QVERIFY(component.isError());
245         QCOMPARE(component.errors().at(0).description(), QLatin1String("Invalid property assignment: \"sizereadonly\" is a read-only property"));
246     }
247
248     {
249         QDeclarativeComponent component(&engine, TEST_FILE("sizereadonly_writeerror2.qml"));
250         QVERIFY(component.isError());
251         QCOMPARE(component.errors().at(0).description(), QLatin1String("Invalid property assignment: \"sizereadonly\" is a read-only property"));
252     }
253
254     {
255         QDeclarativeComponent component(&engine, TEST_FILE("sizereadonly_writeerror3.qml"));
256         QVERIFY(component.isError());
257         QCOMPARE(component.errors().at(0).description(), QLatin1String("Invalid property assignment: \"sizereadonly\" is a read-only property"));
258     }
259
260     {
261         QDeclarativeComponent component(&engine, TEST_FILE("sizereadonly_writeerror4.qml"));
262
263         QObject *object = component.create();
264         QVERIFY(object);
265
266         QCOMPARE(object->property("sizereadonly").toSize(), QSize(1912, 1913));
267
268         delete object;
269     }
270 }
271
272 void tst_qdeclarativevaluetypes::rect()
273 {
274     {
275         QDeclarativeComponent component(&engine, TEST_FILE("rect_read.qml"));
276         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
277         QVERIFY(object != 0);
278
279         QCOMPARE(object->property("r_x").toInt(), 2);
280         QCOMPARE(object->property("r_y").toInt(), 3);
281         QCOMPARE(object->property("r_width").toInt(), 109);
282         QCOMPARE(object->property("r_height").toInt(), 102);
283         QCOMPARE(object->property("copy"), QVariant(QRect(2, 3, 109, 102)));
284
285         delete object;
286     }
287
288     {
289         QDeclarativeComponent component(&engine, TEST_FILE("rect_write.qml"));
290         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
291         QVERIFY(object != 0);
292
293         QCOMPARE(object->rect(), QRect(1234, 7, 56, 63));
294
295         delete object;
296     }
297 }
298
299 void tst_qdeclarativevaluetypes::rectf()
300 {
301     {
302         QDeclarativeComponent component(&engine, TEST_FILE("rectf_read.qml"));
303         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
304         QVERIFY(object != 0);
305
306         QCOMPARE(float(object->property("r_x").toDouble()), float(103.8));
307         QCOMPARE(float(object->property("r_y").toDouble()), float(99.2));
308         QCOMPARE(float(object->property("r_width").toDouble()), float(88.1));
309         QCOMPARE(float(object->property("r_height").toDouble()), float(77.6));
310         QCOMPARE(object->property("copy"), QVariant(QRectF(103.8, 99.2, 88.1, 77.6)));
311
312         delete object;
313     }
314
315     {
316         QDeclarativeComponent component(&engine, TEST_FILE("rectf_write.qml"));
317         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
318         QVERIFY(object != 0);
319
320         QCOMPARE(object->rectf(), QRectF(70.1, -113.2, 80924.8, 99.2));
321
322         delete object;
323     }
324 }
325
326 void tst_qdeclarativevaluetypes::vector2d()
327 {
328     {
329         QDeclarativeComponent component(&engine, TEST_FILE("vector2d_read.qml"));
330         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
331         QVERIFY(object != 0);
332
333         QCOMPARE((float)object->property("v_x").toDouble(), (float)32.88);
334         QCOMPARE((float)object->property("v_y").toDouble(), (float)1.3);
335         QCOMPARE(object->property("copy"), QVariant(QVector2D(32.88, 1.3)));
336
337         delete object;
338     }
339
340     {
341         QDeclarativeComponent component(&engine, TEST_FILE("vector2d_write.qml"));
342         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
343         QVERIFY(object != 0);
344
345         QCOMPARE(object->vector2(), QVector2D(-0.3, -12.9));
346
347         delete object;
348     }
349 }
350
351 void tst_qdeclarativevaluetypes::vector3d()
352 {
353     {
354         QDeclarativeComponent component(&engine, TEST_FILE("vector3d_read.qml"));
355         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
356         QVERIFY(object != 0);
357
358         QCOMPARE((float)object->property("v_x").toDouble(), (float)23.88);
359         QCOMPARE((float)object->property("v_y").toDouble(), (float)3.1);
360         QCOMPARE((float)object->property("v_z").toDouble(), (float)4.3);
361         QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88, 3.1, 4.3)));
362
363         delete object;
364     }
365
366     {
367         QDeclarativeComponent component(&engine, TEST_FILE("vector3d_write.qml"));
368         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
369         QVERIFY(object != 0);
370
371         QCOMPARE(object->vector(), QVector3D(-0.3, -12.9, 907.4));
372
373         delete object;
374     }
375 }
376
377 void tst_qdeclarativevaluetypes::vector4d()
378 {
379     {
380         QDeclarativeComponent component(&engine, TEST_FILE("vector4d_read.qml"));
381         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
382         QVERIFY(object != 0);
383
384         QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
385         QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
386         QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
387         QCOMPARE((float)object->property("v_w").toDouble(), (float)4.3);
388         QCOMPARE(object->property("copy"), QVariant(QVector4D(54.2, 23.88, 3.1, 4.3)));
389
390         delete object;
391     }
392
393     {
394         QDeclarativeComponent component(&engine, TEST_FILE("vector4d_write.qml"));
395         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
396         QVERIFY(object != 0);
397
398         QCOMPARE(object->vector4(), QVector4D(-0.3, -12.9, 907.4, 88.5));
399
400         delete object;
401     }
402 }
403
404 void tst_qdeclarativevaluetypes::quaternion()
405 {
406     {
407         QDeclarativeComponent component(&engine, TEST_FILE("quaternion_read.qml"));
408         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
409         QVERIFY(object != 0);
410
411         QCOMPARE((float)object->property("v_scalar").toDouble(), (float)4.3);
412         QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
413         QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
414         QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
415         QCOMPARE(object->property("copy"), QVariant(QQuaternion(4.3, 54.2, 23.88, 3.1)));
416
417         delete object;
418     }
419
420     {
421         QDeclarativeComponent component(&engine, TEST_FILE("quaternion_write.qml"));
422         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
423         QVERIFY(object != 0);
424
425         QCOMPARE(object->quaternion(), QQuaternion(88.5, -0.3, -12.9, 907.4));
426
427         delete object;
428     }
429 }
430
431 void tst_qdeclarativevaluetypes::matrix4x4()
432 {
433     {
434         QDeclarativeComponent component(&engine, TEST_FILE("matrix4x4_read.qml"));
435         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
436         QVERIFY(object != 0);
437
438         QCOMPARE((float)object->property("v_m11").toDouble(), (float)1);
439         QCOMPARE((float)object->property("v_m12").toDouble(), (float)2);
440         QCOMPARE((float)object->property("v_m13").toDouble(), (float)3);
441         QCOMPARE((float)object->property("v_m14").toDouble(), (float)4);
442         QCOMPARE((float)object->property("v_m21").toDouble(), (float)5);
443         QCOMPARE((float)object->property("v_m22").toDouble(), (float)6);
444         QCOMPARE((float)object->property("v_m23").toDouble(), (float)7);
445         QCOMPARE((float)object->property("v_m24").toDouble(), (float)8);
446         QCOMPARE((float)object->property("v_m31").toDouble(), (float)9);
447         QCOMPARE((float)object->property("v_m32").toDouble(), (float)10);
448         QCOMPARE((float)object->property("v_m33").toDouble(), (float)11);
449         QCOMPARE((float)object->property("v_m34").toDouble(), (float)12);
450         QCOMPARE((float)object->property("v_m41").toDouble(), (float)13);
451         QCOMPARE((float)object->property("v_m42").toDouble(), (float)14);
452         QCOMPARE((float)object->property("v_m43").toDouble(), (float)15);
453         QCOMPARE((float)object->property("v_m44").toDouble(), (float)16);
454         QCOMPARE(object->property("copy"),
455                  QVariant(QMatrix4x4(1, 2, 3, 4,
456                                      5, 6, 7, 8,
457                                      9, 10, 11, 12,
458                                      13, 14, 15, 16)));
459
460         delete object;
461     }
462
463     {
464         QDeclarativeComponent component(&engine, TEST_FILE("matrix4x4_write.qml"));
465         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
466         QVERIFY(object != 0);
467
468         QCOMPARE(object->matrix(), QMatrix4x4(11, 12, 13, 14,
469                                               21, 22, 23, 24,
470                                               31, 32, 33, 34,
471                                               41, 42, 43, 44));
472
473         delete object;
474     }
475 }
476
477 void tst_qdeclarativevaluetypes::font()
478 {
479     {
480         QDeclarativeComponent component(&engine, TEST_FILE("font_read.qml"));
481         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
482         QVERIFY(object != 0);
483
484         QCOMPARE(object->property("f_family").toString(), object->font().family());
485         QCOMPARE(object->property("f_bold").toBool(), object->font().bold());
486         QCOMPARE(object->property("f_weight").toInt(), object->font().weight());
487         QCOMPARE(object->property("f_italic").toBool(), object->font().italic());
488         QCOMPARE(object->property("f_underline").toBool(), object->font().underline());
489         QCOMPARE(object->property("f_overline").toBool(), object->font().overline());
490         QCOMPARE(object->property("f_strikeout").toBool(), object->font().strikeOut());
491         QCOMPARE(object->property("f_pointSize").toDouble(), object->font().pointSizeF());
492         QCOMPARE(object->property("f_pixelSize").toInt(), int((object->font().pointSizeF() * qt_defaultDpi()) / qreal(72.)));
493         QCOMPARE(object->property("f_capitalization").toInt(), (int)object->font().capitalization());
494         QCOMPARE(object->property("f_letterSpacing").toDouble(), object->font().letterSpacing());
495         QCOMPARE(object->property("f_wordSpacing").toDouble(), object->font().wordSpacing());
496
497         QCOMPARE(object->property("copy"), QVariant(object->font()));
498
499         delete object;
500     }
501
502     {
503         QDeclarativeComponent component(&engine, TEST_FILE("font_write.qml"));
504         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
505         QVERIFY(object != 0);
506
507         QFont font;
508         font.setFamily("Helvetica");
509         font.setBold(false);
510         font.setWeight(QFont::Normal);
511         font.setItalic(false);
512         font.setUnderline(false);
513         font.setStrikeOut(false);
514         font.setPointSize(15);
515         font.setCapitalization(QFont::AllLowercase);
516         font.setLetterSpacing(QFont::AbsoluteSpacing, 9.7);
517         font.setWordSpacing(11.2);
518
519         QFont f = object->font();
520         QCOMPARE(f.family(), font.family());
521         QCOMPARE(f.bold(), font.bold());
522         QCOMPARE(f.weight(), font.weight());
523         QCOMPARE(f.italic(), font.italic());
524         QCOMPARE(f.underline(), font.underline());
525         QCOMPARE(f.strikeOut(), font.strikeOut());
526         QCOMPARE(f.pointSize(), font.pointSize());
527         QCOMPARE(f.capitalization(), font.capitalization());
528         QCOMPARE(f.letterSpacing(), font.letterSpacing());
529         QCOMPARE(f.wordSpacing(), font.wordSpacing());
530
531         delete object;
532     }
533
534     // Test pixelSize
535     {
536         QDeclarativeComponent component(&engine, TEST_FILE("font_write.2.qml"));
537         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
538         QVERIFY(object != 0);
539
540         QCOMPARE(object->font().pixelSize(), 10);
541
542         delete object;
543     }
544
545     // Test pixelSize and pointSize
546     {
547         QDeclarativeComponent component(&engine, TEST_FILE("font_write.3.qml"));
548         QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
549         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
550         QVERIFY(object != 0);
551
552         QCOMPARE(object->font().pixelSize(), 10);
553
554         delete object;
555     }
556     {
557         QDeclarativeComponent component(&engine, TEST_FILE("font_write.4.qml"));
558         QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
559         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
560         QVERIFY(object != 0);
561
562         QCOMPARE(object->font().pixelSize(), 10);
563
564         delete object;
565     }
566     {
567         QDeclarativeComponent component(&engine, TEST_FILE("font_write.5.qml"));
568         QObject *object = qobject_cast<QObject *>(component.create());
569         QVERIFY(object != 0);
570         MyTypeObject *object1 = object->findChild<MyTypeObject *>("object1");
571         QVERIFY(object1 != 0);
572         MyTypeObject *object2 = object->findChild<MyTypeObject *>("object2");
573         QVERIFY(object2 != 0);
574
575         QCOMPARE(object1->font().pixelSize(), 19);
576         QCOMPARE(object2->font().pointSize(), 14);
577
578         delete object;
579     }
580 }
581
582 // Test bindings can write to value types
583 void tst_qdeclarativevaluetypes::bindingAssignment()
584 {
585     QDeclarativeComponent component(&engine, TEST_FILE("bindingAssignment.qml"));
586     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
587     QVERIFY(object != 0);
588
589     QCOMPARE(object->rect().x(), 10);
590
591     object->setProperty("value", QVariant(92));
592
593     QCOMPARE(object->rect().x(), 92);
594
595     delete object;
596 }
597
598 // Test bindings can read from value types
599 void tst_qdeclarativevaluetypes::bindingRead()
600 {
601     QDeclarativeComponent component(&engine, TEST_FILE("bindingRead.qml"));
602     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
603     QVERIFY(object != 0);
604
605     QCOMPARE(object->property("value").toInt(), 2);
606
607     object->setRect(QRect(19, 3, 88, 2));
608
609     QCOMPARE(object->property("value").toInt(), 19);
610
611     delete object;
612 }
613
614 // Test static values can assign to value types
615 void tst_qdeclarativevaluetypes::staticAssignment()
616 {
617     QDeclarativeComponent component(&engine, TEST_FILE("staticAssignment.qml"));
618     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
619     QVERIFY(object != 0);
620
621     QCOMPARE(object->rect().x(), 9);
622
623     delete object;
624 }
625
626 // Test scripts can read/write value types
627 void tst_qdeclarativevaluetypes::scriptAccess()
628 {
629     QDeclarativeComponent component(&engine, TEST_FILE("scriptAccess.qml"));
630     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
631     QVERIFY(object != 0);
632
633     QCOMPARE(object->property("valuePre").toInt(), 2);
634     QCOMPARE(object->rect().x(), 19);
635     QCOMPARE(object->property("valuePost").toInt(), 19);
636
637     delete object;
638 }
639
640 // Test that assigning a constant from script removes any binding
641 void tst_qdeclarativevaluetypes::autoBindingRemoval()
642 {
643     {
644         QDeclarativeComponent component(&engine, TEST_FILE("autoBindingRemoval.qml"));
645         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
646         QVERIFY(object != 0);
647
648         QCOMPARE(object->rect().x(), 10);
649
650         object->setProperty("value", QVariant(13));
651
652         QCOMPARE(object->rect().x(), 13);
653
654         object->emitRunScript();
655
656         QCOMPARE(object->rect().x(), 42);
657
658         object->setProperty("value", QVariant(92));
659
660         QCOMPARE(object->rect().x(), 42);
661
662         delete object;
663     }
664
665     /*
666     {
667         QDeclarativeComponent component(&engine, TEST_FILE("autoBindingRemoval.2.qml"));
668         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
669         QVERIFY(object != 0);
670
671         QCOMPARE(object->rect().x(), 10);
672
673         object->setProperty("value", QVariant(13));
674
675         QCOMPARE(object->rect().x(), 13);
676
677         object->emitRunScript();
678
679         QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
680
681         object->setProperty("value", QVariant(92));
682
683         QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
684
685         delete object;
686     }
687
688     {
689         QDeclarativeComponent component(&engine, TEST_FILE("autoBindingRemoval.3.qml"));
690         MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
691         QVERIFY(object != 0);
692
693         object->setProperty("value", QVariant(QRect(9, 22, 33, 44)));
694
695         QCOMPARE(object->rect(), QRect(9, 22, 33, 44));
696
697         object->emitRunScript();
698
699         QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
700
701         object->setProperty("value", QVariant(QRect(19, 3, 4, 8)));
702
703         QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
704
705         delete object;
706     }
707 */
708 }
709
710 // Test that property value sources assign to value types
711 void tst_qdeclarativevaluetypes::valueSources()
712 {
713     QDeclarativeComponent component(&engine, TEST_FILE("valueSources.qml"));
714     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
715     QVERIFY(object != 0);
716
717     QCOMPARE(object->rect().x(), 3345);
718
719     delete object;
720 }
721
722 static void checkNoErrors(QDeclarativeComponent& component)
723 {
724     QList<QDeclarativeError> errors = component.errors();
725     if (errors.isEmpty())
726         return;
727     for (int ii = 0; ii < errors.count(); ++ii) {
728         const QDeclarativeError &error = errors.at(ii);
729         qWarning("%d:%d:%s",error.line(),error.column(),error.description().toUtf8().constData());
730     }
731 }
732
733 // Test that property value interceptors can be applied to value types
734 void tst_qdeclarativevaluetypes::valueInterceptors()
735 {
736     QDeclarativeComponent component(&engine, TEST_FILE("valueInterceptors.qml"));
737     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
738     checkNoErrors(component);
739     QVERIFY(object != 0);
740
741     QCOMPARE(object->rect().x(), 13);
742
743     object->setProperty("value", 99);
744
745     QCOMPARE(object->rect().x(), 112);
746
747     delete object;
748 }
749
750 // Test that you can't assign a binding to the "root" value type, and a sub-property
751 void tst_qdeclarativevaluetypes::bindingConflict()
752 {
753     QDeclarativeComponent component(&engine, TEST_FILE("bindingConflict.qml"));
754     QCOMPARE(component.isError(), true);
755 }
756
757 #define CPP_TEST(type, v) \
758 { \
759     type *t = new type; \
760     QVariant value(v); \
761     t->setValue(value); \
762     QCOMPARE(t->value(), value); \
763     delete t; \
764 }
765
766 // Test that accessing a reference to a valuetype after the owning object is deleted
767 // doesn't crash
768 void tst_qdeclarativevaluetypes::deletedObject()
769 {
770     QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
771     QTest::ignoreMessage(QtDebugMsg, "Test: 2");
772     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
773     QVERIFY(object != 0);
774
775     QObject *dObject = qvariant_cast<QObject *>(object->property("object"));
776     QVERIFY(dObject != 0);
777     delete dObject;
778
779     QTest::ignoreMessage(QtDebugMsg, "Test: undefined");
780     object->emitRunScript();
781
782     delete object;
783 }
784
785 // Test that value types can be assigned to another value type property in a binding
786 void tst_qdeclarativevaluetypes::bindingVariantCopy()
787 {
788     QDeclarativeComponent component(&engine, TEST_FILE("bindingVariantCopy.qml"));
789     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
790     QVERIFY(object != 0);
791
792     QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
793
794     delete object;
795 }
796
797 // Test that value types can be assigned to another value type property in script
798 void tst_qdeclarativevaluetypes::scriptVariantCopy()
799 {
800     QDeclarativeComponent component(&engine, TEST_FILE("scriptVariantCopy.qml"));
801     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
802     QVERIFY(object != 0);
803
804     QCOMPARE(object->rect(), QRect(2, 3, 109, 102));
805
806     object->emitRunScript();
807
808     QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
809
810     delete object;
811 }
812
813
814 // Test that the value type classes can be used manually
815 void tst_qdeclarativevaluetypes::cppClasses()
816 {
817     CPP_TEST(QDeclarativePointValueType, QPoint(19, 33));
818     CPP_TEST(QDeclarativePointFValueType, QPointF(33.6, -23));
819     CPP_TEST(QDeclarativeSizeValueType, QSize(-100, 18));
820     CPP_TEST(QDeclarativeSizeFValueType, QSizeF(-100.7, 18.2));
821     CPP_TEST(QDeclarativeRectValueType, QRect(13, 39, 10928, 88));
822     CPP_TEST(QDeclarativeRectFValueType, QRectF(88.2, -90.1, 103.2, 118));
823     CPP_TEST(QDeclarativeVector2DValueType, QVector2D(19.7, 1002));
824     CPP_TEST(QDeclarativeVector3DValueType, QVector3D(18.2, 19.7, 1002));
825     CPP_TEST(QDeclarativeVector4DValueType, QVector4D(18.2, 19.7, 1002, 54));
826     CPP_TEST(QDeclarativeQuaternionValueType, QQuaternion(18.2, 19.7, 1002, 54));
827     CPP_TEST(QDeclarativeMatrix4x4ValueType,
828              QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
829     CPP_TEST(QDeclarativeFontValueType, QFont("Helvetica"));
830
831 }
832
833 void tst_qdeclarativevaluetypes::enums()
834 {
835     {
836     QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
837     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
838     QVERIFY(object != 0);
839     QVERIFY(object->font().capitalization() == QFont::AllUppercase);
840     delete object;
841     }
842
843     {
844     QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
845     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
846     QVERIFY(object != 0);
847     QVERIFY(object->font().capitalization() == QFont::AllUppercase);
848     delete object;
849     }
850
851     {
852     QDeclarativeComponent component(&engine, TEST_FILE("enums.3.qml"));
853     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
854     QVERIFY(object != 0);
855     QVERIFY(object->font().capitalization() == QFont::AllUppercase);
856     delete object;
857     }
858
859     {
860     QDeclarativeComponent component(&engine, TEST_FILE("enums.4.qml"));
861     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
862     QVERIFY(object != 0);
863     QVERIFY(object->font().capitalization() == QFont::AllUppercase);
864     delete object;
865     }
866
867     {
868     QDeclarativeComponent component(&engine, TEST_FILE("enums.5.qml"));
869     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
870     QVERIFY(object != 0);
871     QVERIFY(object->font().capitalization() == QFont::AllUppercase);
872     delete object;
873     }
874 }
875
876 // Tests switching between "conflicting" bindings (eg. a binding on the core
877 // property, to a binding on the value-type sub-property)
878 void tst_qdeclarativevaluetypes::conflictingBindings()
879 {
880     {
881     QDeclarativeComponent component(&engine, TEST_FILE("conflicting.1.qml"));
882     QObject *object = component.create();
883     QVERIFY(object != 0);
884
885     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
886
887     QMetaObject::invokeMethod(object, "toggle");
888
889     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
890
891     QMetaObject::invokeMethod(object, "toggle");
892
893     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
894
895     delete object;
896     }
897
898     {
899     QDeclarativeComponent component(&engine, TEST_FILE("conflicting.2.qml"));
900     QObject *object = component.create();
901     QVERIFY(object != 0);
902
903     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
904
905     QMetaObject::invokeMethod(object, "toggle");
906
907     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
908
909     QMetaObject::invokeMethod(object, "toggle");
910
911     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
912
913     delete object;
914     }
915
916     {
917     QDeclarativeComponent component(&engine, TEST_FILE("conflicting.3.qml"));
918     QObject *object = component.create();
919     QVERIFY(object != 0);
920
921     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
922
923     QMetaObject::invokeMethod(object, "toggle");
924
925     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 24);
926
927     QMetaObject::invokeMethod(object, "toggle");
928
929     QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
930
931     delete object;
932     }
933 }
934
935 void tst_qdeclarativevaluetypes::returnValues()
936 {
937     QDeclarativeComponent component(&engine, TEST_FILE("returnValues.qml"));
938     QObject *object = component.create();
939     QVERIFY(object != 0);
940
941     QCOMPARE(object->property("test1").toBool(), true);
942     QCOMPARE(object->property("test2").toBool(), true);
943     QCOMPARE(object->property("size").toSize(), QSize(13, 14));
944
945     delete object;
946 }
947
948 void tst_qdeclarativevaluetypes::varAssignment()
949 {
950     QDeclarativeComponent component(&engine, TEST_FILE("varAssignment.qml"));
951     QObject *object = component.create();
952     QVERIFY(object != 0);
953
954     QCOMPARE(object->property("x").toInt(), 1);
955     QCOMPARE(object->property("y").toInt(), 2);
956     QCOMPARE(object->property("z").toInt(), 3);
957
958     delete object;
959 }
960
961 // Test bindings splice together correctly
962 void tst_qdeclarativevaluetypes::bindingsSpliceCorrectly()
963 {
964     {
965     QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.1.qml"));
966     QObject *object = component.create();
967     QVERIFY(object != 0);
968
969     QCOMPARE(object->property("test").toBool(), true);
970
971     delete object;
972     }
973
974     {
975     QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.2.qml"));
976     QObject *object = component.create();
977     QVERIFY(object != 0);
978
979     QCOMPARE(object->property("test").toBool(), true);
980
981     delete object;
982     }
983
984
985     {
986     QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.3.qml"));
987     QObject *object = component.create();
988     QVERIFY(object != 0);
989
990     QCOMPARE(object->property("test").toBool(), true);
991
992     delete object;
993     }
994
995     {
996     QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.4.qml"));
997     QObject *object = component.create();
998     QVERIFY(object != 0);
999
1000     QCOMPARE(object->property("test").toBool(), true);
1001
1002     delete object;
1003     }
1004
1005     {
1006     QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.5.qml"));
1007     QObject *object = component.create();
1008     QVERIFY(object != 0);
1009
1010     QCOMPARE(object->property("test").toBool(), true);
1011
1012     delete object;
1013     }
1014 }
1015
1016 //qreal as float should not limit int to single precision.
1017 void tst_qdeclarativevaluetypes::qtbug_33625()
1018 {
1019    QDeclarativeComponent component(&engine, TEST_FILE("qtbug-33625.qml"));
1020    QObject *object = component.create();
1021    QVERIFY(object != 0);
1022
1023    QCOMPARE(object->property("intint").toInt(), 16777237);
1024    QCOMPARE(object->property("stringint").toInt(), 16777237);
1025
1026    delete object;
1027 }
1028
1029 QTEST_MAIN(tst_qdeclarativevaluetypes)
1030
1031 #include "tst_qdeclarativevaluetypes.moc"