Fix bug in v4 strict equality.
[profile/ivi/qtdeclarative.git] / tests / auto / qml / v4 / tst_v4.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QtCore/qobject.h>
43 #include <QtCore/qfileinfo.h>
44 #include <QtCore/qdir.h>
45 #include <QtQml/qqmlengine.h>
46 #include <QtQml/qqmlcomponent.h>
47 #include <QtCore/qdebug.h>
48 #include <QtGui/qcolor.h>
49
50 #include <private/qv4compiler_p.h>
51
52 #include "../../shared/util.h"
53 #include "testtypes.h"
54
55 class tst_v4 : public QQmlDataTest
56 {
57     Q_OBJECT
58 public:
59     tst_v4() {}
60
61 private slots:
62     void initTestCase();
63
64     void unnecessaryReeval();
65     void logicalOr();
66     void nestedLogicalOr();
67     void logicalAnd();
68     void nestedLogicalAnd();
69     void conditionalExpr();
70     void qtscript();
71     void qtscript_data();
72     void nestedObjectAccess();
73     void subscriptionsInConditionalExpressions();
74     void qtbug_21883();
75     void qtbug_22816();
76     void stringComparison();
77     void unaryMinus();
78     void unaryPlus();
79     void colorType();
80     void mathAbs();
81     void mathCeil();
82     void mathMax();
83     void mathMin();
84
85 private:
86     QQmlEngine engine;
87 };
88
89 void tst_v4::initTestCase()
90 {
91     QQmlDataTest::initTestCase();
92     registerTypes();
93 }
94
95 static int v4ErrorsMsgCount = 0;
96 static void v4ErrorsMsgHandler(QtMsgType, const char *message)
97 {
98     QByteArray m(message);
99     if (m.contains("QV4"))
100         v4ErrorsMsgCount++;
101 }
102
103 void tst_v4::qtscript()
104 {
105     QFETCH(QString, file);
106     QV4Compiler::enableBindingsTest(true);
107
108     QQmlComponent component(&engine, testFileUrl(file));
109
110     v4ErrorsMsgCount = 0;
111     QtMsgHandler old = qInstallMsgHandler(v4ErrorsMsgHandler);
112
113     QObject *o = component.create();
114     delete o;
115
116     qInstallMsgHandler(old);
117
118     QCOMPARE(v4ErrorsMsgCount, 0);
119
120     QV4Compiler::enableBindingsTest(false);
121 }
122
123 void tst_v4::qtscript_data()
124 {
125     QTest::addColumn<QString>("file");
126
127     QTest::newRow("equals") << "equals.qml";
128     QTest::newRow("strict equals") << "strictEquals.qml";
129     QTest::newRow("qreal -> int rounding") << "qrealToIntRounding.qml";
130     QTest::newRow("exception on fetch") << "fetchException.qml";
131     QTest::newRow("logical or") << "logicalOr.qml";
132     QTest::newRow("conditional expressions") << "conditionalExpr.qml";
133     QTest::newRow("double bool jump") << "doubleBoolJump.qml";
134     QTest::newRow("unary minus") << "unaryMinus.qml";
135     QTest::newRow("null qobject") << "nullQObject.qml";
136 }
137
138 void tst_v4::unnecessaryReeval()
139 {
140     QQmlComponent component(&engine, testFileUrl("unnecessaryReeval.qml"));
141
142     QObject *o = component.create();
143     QVERIFY(o != 0);
144
145     ResultObject *ro = qobject_cast<ResultObject *>(o);
146     QVERIFY(ro != 0);
147
148     QCOMPARE(ro->resultCounter(),  1);
149     QCOMPARE(ro->result(), 19);
150     ro->resetResultCounter();
151
152     ro->setProperty("b", 6);
153
154     QCOMPARE(ro->resultCounter(),  1);
155     QCOMPARE(ro->result(), 6);
156     ro->resetResultCounter();
157
158     ro->setProperty("a", 14);
159
160     QCOMPARE(ro->resultCounter(),  1);
161     QCOMPARE(ro->result(), 7);
162     ro->resetResultCounter();
163
164     ro->setProperty("b", 14);
165     QCOMPARE(ro->resultCounter(),  0);
166     QCOMPARE(ro->result(), 7);
167
168     delete o;
169 }
170
171 void tst_v4::logicalOr()
172 {
173     {
174         QQmlComponent component(&engine, testFileUrl("logicalOr.qml"));
175
176         QObject *o = component.create();
177         QVERIFY(o != 0);
178
179         ResultObject *ro = qobject_cast<ResultObject *>(o);
180         QVERIFY(ro != 0);
181
182         QCOMPARE(ro->result(), 0);
183         delete o;
184     }
185
186     {
187         QQmlComponent component(&engine, testFileUrl("logicalOr.2.qml"));
188
189         QObject *o = component.create();
190         QVERIFY(o != 0);
191
192         ResultObject *ro = qobject_cast<ResultObject *>(o);
193         QVERIFY(ro != 0);
194
195         QCOMPARE(ro->result(), 1);
196         delete o;
197     }
198 }
199
200 void tst_v4::nestedLogicalOr()
201 {
202     //we are primarily testing that v4 does not get caught in a loop (QTBUG-24038)
203     QQmlComponent component(&engine, testFileUrl("nestedLogicalOr.qml"));
204
205     QObject *o = component.create();
206     QVERIFY(o != 0);
207
208     ResultObject *ro = qobject_cast<ResultObject *>(o);
209     QVERIFY(ro != 0);
210
211     QCOMPARE(ro->result(), 1);
212     delete o;
213 }
214
215 void tst_v4::logicalAnd()
216 {
217     {
218         QQmlComponent component(&engine, testFileUrl("logicalAnd.qml"));
219
220         QObject *o = component.create();
221         QVERIFY(o != 0);
222
223         ResultObject *ro = qobject_cast<ResultObject *>(o);
224         QVERIFY(ro != 0);
225
226         QCOMPARE(ro->result(), 0);
227         delete o;
228     }
229
230     {
231         QQmlComponent component(&engine, testFileUrl("logicalAnd.2.qml"));
232
233         QObject *o = component.create();
234         QVERIFY(o != 0);
235
236         ResultObject *ro = qobject_cast<ResultObject *>(o);
237         QVERIFY(ro != 0);
238
239         QCOMPARE(ro->result(), 1);
240         delete o;
241     }
242
243     {
244         QQmlComponent component(&engine, testFileUrl("logicalAnd.3.qml"));
245
246         QObject *o = component.create();
247         QVERIFY(o != 0);
248
249         ResultObject *ro = qobject_cast<ResultObject *>(o);
250         QVERIFY(ro != 0);
251
252         QCOMPARE(ro->result(), 1);
253         delete o;
254     }
255
256     {
257         // QTBUG-24660
258         QQmlComponent component(&engine, testFileUrl("logicalAnd.4.qml"));
259
260         QObject *o = component.create();
261         QVERIFY(o != 0);
262
263         ResultObject *ro = qobject_cast<ResultObject *>(o);
264         QVERIFY(ro != 0);
265
266         QCOMPARE(ro->result(), 1);
267         delete o;
268     }
269
270     {
271         QQmlComponent component(&engine, testFileUrl("logicalAnd.5.qml"));
272
273         QObject *o = component.create();
274         QVERIFY(o != 0);
275
276         ResultObject *ro = qobject_cast<ResultObject *>(o);
277         QVERIFY(ro != 0);
278
279         QCOMPARE(ro->result(), 1);
280         delete o;
281     }
282
283     {
284         QQmlComponent component(&engine, testFileUrl("logicalAnd.6.qml"));
285
286         QObject *o = component.create();
287         QVERIFY(o != 0);
288
289         ResultObject *ro = qobject_cast<ResultObject *>(o);
290         QVERIFY(ro != 0);
291
292         QCOMPARE(ro->result(), 1);
293         delete o;
294     }
295
296     {
297         QQmlComponent component(&engine, testFileUrl("logicalAnd.7.qml"));
298
299         QObject *o = component.create();
300         QVERIFY(o != 0);
301
302         ResultObject *ro = qobject_cast<ResultObject *>(o);
303         QVERIFY(ro != 0);
304
305         QCOMPARE(ro->result(), 1);
306         delete o;
307     }
308 }
309
310 void tst_v4::nestedLogicalAnd()
311 {
312     QQmlComponent component(&engine, testFileUrl("nestedLogicalAnd.qml"));
313
314     QObject *o = component.create();
315     QVERIFY(o != 0);
316
317     ResultObject *ro = qobject_cast<ResultObject *>(o);
318     QVERIFY(ro != 0);
319
320     QCOMPARE(ro->result(), 1);
321     delete o;
322 }
323
324 void tst_v4::conditionalExpr()
325 {
326     {
327         QQmlComponent component(&engine, testFileUrl("conditionalExpr.qml"));
328
329         QObject *o = component.create();
330         QVERIFY(o != 0);
331
332         ResultObject *ro = qobject_cast<ResultObject *>(o);
333         QVERIFY(ro != 0);
334
335         QCOMPARE(ro->result(), 0);
336         delete o;
337     }
338 }
339
340 // This would previously use the metaObject of the root element to result the nested access.
341 // That is, the index for accessing "result" would have been RootObject::result, instead of
342 // NestedObject::result.
343 void tst_v4::nestedObjectAccess()
344 {
345     {
346         QQmlComponent component(&engine, testFileUrl("nestedObjectAccess.qml"));
347
348         QObject *o = component.create();
349         QVERIFY(o != 0);
350
351         ResultObject *ro = qobject_cast<ResultObject *>(o);
352         QVERIFY(ro != 0);
353
354         QCOMPARE(ro->result(), 37);
355
356         delete o;
357     }
358
359     {
360         QQmlComponent component(&engine, testFileUrl("nestedObjectAccess2.qml"));
361
362         QObject *o = component.create();
363         QVERIFY(o != 0);
364
365         ResultObject *ro = qobject_cast<ResultObject *>(o);
366         QVERIFY(ro != 0);
367
368         QCOMPARE(ro->result(), 37);
369
370         delete o;
371     }
372 }
373
374 void tst_v4::subscriptionsInConditionalExpressions()
375 {
376     QQmlComponent component(&engine, testFileUrl("subscriptionsInConditionalExpressions.qml"));
377
378     QObject *o = component.create();
379     QVERIFY(o != 0);
380
381     QObject *ro = qobject_cast<QObject *>(o);
382     QVERIFY(ro != 0);
383
384     QCOMPARE(ro->property("result").toReal(), qreal(2));
385
386     delete o;
387 }
388
389 // Crash test
390 void tst_v4::qtbug_21883()
391 {
392     QQmlComponent component(&engine, testFileUrl("qtbug_21883.qml"));
393
394     QString warning = component.url().toString() + ":4: Unable to assign null to ResultObject*";
395     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
396
397     QObject *o = component.create();
398     QVERIFY(o != 0);
399     delete o;
400 }
401
402 void tst_v4::qtbug_22816()
403 {
404     QQmlComponent component(&engine, testFileUrl("qtbug_22816.qml"));
405
406     QObject *o = component.create();
407     QVERIFY(o != 0);
408     QCOMPARE(o->property("test1").toBool(), false);
409     QCOMPARE(o->property("test2").toBool(), false);
410     delete o;
411 }
412
413 void tst_v4::stringComparison()
414 {
415     QQmlComponent component(&engine, testFileUrl("stringComparison.qml"));
416
417     QObject *o = component.create();
418     QVERIFY(o != 0);
419     QCOMPARE(o->property("test1").toBool(), true);
420     QCOMPARE(o->property("test2").toBool(), true);
421     QCOMPARE(o->property("test3").toBool(), true);
422     QCOMPARE(o->property("test4").toBool(), true);
423     QCOMPARE(o->property("test5").toBool(), true);
424     QCOMPARE(o->property("test6").toBool(), true);
425     QCOMPARE(o->property("test7").toBool(), true);
426     QCOMPARE(o->property("test8").toBool(), true);
427     QCOMPARE(o->property("test9").toBool(), true);
428     QCOMPARE(o->property("test10").toBool(), true);
429     QCOMPARE(o->property("test11").toBool(), true);
430     QCOMPARE(o->property("test12").toBool(), true);
431     QCOMPARE(o->property("test13").toBool(), true);
432     QCOMPARE(o->property("test14").toBool(), true);
433     QCOMPARE(o->property("test15").toBool(), true);
434     QCOMPARE(o->property("test16").toBool(), true);
435     QCOMPARE(o->property("test17").toBool(), true);
436     QCOMPARE(o->property("test18").toBool(), true);
437     QCOMPARE(o->property("test19").toBool(), true);
438     QCOMPARE(o->property("test20").toBool(), true);
439     QCOMPARE(o->property("test21").toBool(), true);
440     QCOMPARE(o->property("test22").toBool(), true);
441     delete o;
442 }
443
444 void tst_v4::unaryMinus()
445 {
446     QQmlComponent component(&engine, testFileUrl("unaryMinus.qml"));
447
448     QObject *o = component.create();
449     QVERIFY(o != 0);
450
451     QCOMPARE(o->property("test1").toReal(), qreal(-18));
452     QCOMPARE(o->property("test2").toInt(), -18);
453     QCOMPARE(o->property("test3").toReal(), qreal(3.7));
454     QCOMPARE(o->property("test4").toInt(), 4);
455     QCOMPARE(o->property("test5").toReal(), qreal(3.3));
456     QCOMPARE(o->property("test6").toInt(), 3);
457     QCOMPARE(o->property("test7").toReal(), qreal(7));
458     QCOMPARE(o->property("test8").toInt(), 7);
459     QCOMPARE(o->property("test9").toReal(), qreal(-4.4));
460     QCOMPARE(o->property("test10").toInt(), -4);
461
462     delete o;
463 }
464
465 void tst_v4::unaryPlus()
466 {
467     QQmlComponent component(&engine, testFileUrl("unaryPlus.qml"));
468
469     QObject *o = component.create();
470     QVERIFY(o != 0);
471
472     QCOMPARE(o->property("test1").toReal(), qreal(18));
473     QCOMPARE(o->property("test2").toInt(), 18);
474     QCOMPARE(o->property("test3").toReal(), qreal(-3.7));
475     QCOMPARE(o->property("test4").toInt(), -4);
476     QCOMPARE(o->property("test5").toReal(), qreal(-3.3));
477     QCOMPARE(o->property("test6").toInt(), -3);
478     QCOMPARE(o->property("test7").toReal(), qreal(-7));
479     QCOMPARE(o->property("test8").toInt(), -7);
480     QCOMPARE(o->property("test9").toReal(), qreal(4.4));
481     QCOMPARE(o->property("test10").toInt(), 4);
482
483     delete o;
484 }
485
486 void tst_v4::colorType()
487 {
488     QQmlComponent component(&engine, testFileUrl("colorType.qml"));
489
490     QObject *o = component.create();
491     QVERIFY(o != 0);
492     QCOMPARE(o->property("test1").value<QColor>(), QColor("red"));
493     QCOMPARE(o->property("test2").value<QColor>(), QColor("red"));
494     QCOMPARE(o->property("test3").value<QColor>(), QColor("red"));
495     QCOMPARE(o->property("test4").toBool(), true);
496     QCOMPARE(o->property("test5").toBool(), true);
497     QCOMPARE(o->property("test6").toBool(), true);
498     QCOMPARE(o->property("test7").toBool(), true);
499     delete o;
500 }
501
502 void tst_v4::mathAbs()
503 {
504     QQmlComponent component(&engine, testFileUrl("mathAbs.qml"));
505
506     QObject *o = component.create();
507     QVERIFY(o != 0);
508
509     QCOMPARE(o->property("test1").toReal(), qreal(3.7));
510     QCOMPARE(o->property("test2").toReal(), qreal(4.5));
511     QCOMPARE(o->property("test3").toInt(), 18);
512     QCOMPARE(o->property("test4").toInt(), 72);
513     QCOMPARE(o->property("test5").toBool(), true);
514     QCOMPARE(o->property("test6").toBool(), true);
515     QCOMPARE(o->property("test7").toBool(), true);
516     QCOMPARE(o->property("test8").toInt(), 82);
517     QCOMPARE(o->property("test9").toBool(), true);
518     QCOMPARE(o->property("test10").toBool(), true);
519     QCOMPARE(o->property("test11").toInt(), 0);
520     //QCOMPARE(o->property("test12").toBool(), true);   //QTBUG-24706
521
522     delete o;
523 }
524
525 void tst_v4::mathCeil()
526 {
527     QQmlComponent component(&engine, testFileUrl("mathCeil.qml"));
528
529     QObject *o = component.create();
530     QVERIFY(o != 0);
531
532     QCOMPARE(o->property("test1").toReal(), qreal(-3));
533     QCOMPARE(o->property("test2").toReal(), qreal(5));
534     QCOMPARE(o->property("test3").toBool(), true);
535     //QCOMPARE(o->property("test4").toBool(), true);    //QTBUG-24706
536     QCOMPARE(o->property("test5").toBool(), true);
537     QCOMPARE(o->property("test6").toReal(), qreal(83));
538     //QCOMPARE(o->property("test7").toBool(), true);    //QTBUG-24706
539     //QCOMPARE(o->property("test8").toBool(), true);    //QTBUG-24706
540     QCOMPARE(o->property("test9").toInt(), 0);
541     //QCOMPARE(o->property("test10").toBool(), true);   //QTBUG-24706
542
543     delete o;
544 }
545
546 void tst_v4::mathMax()
547 {
548     QQmlComponent component(&engine, testFileUrl("mathMax.qml"));
549
550     QObject *o = component.create();
551     QVERIFY(o != 0);
552
553     QCOMPARE(o->property("test1").toReal(), qreal(4.4));
554     QCOMPARE(o->property("test2").toReal(), qreal(7));
555     QCOMPARE(o->property("test3").toBool(), true);
556     QCOMPARE(o->property("test4").toBool(), true);
557     QCOMPARE(o->property("test5").toBool(), true);
558     QCOMPARE(o->property("test6").toReal(), qreal(82.6));
559     QCOMPARE(o->property("test7").toReal(), qreal(4.4));
560     QCOMPARE(o->property("test8").toBool(), true);
561     //QCOMPARE(o->property("test9").toBool(), true);    //QTBUG-24706
562     QCOMPARE(o->property("test10").toReal(), qreal(0));
563     QCOMPARE(o->property("test11").toReal(), qreal(4.4));
564     QCOMPARE(o->property("test12").toReal(), qreal(7));
565
566     delete o;
567 }
568
569 void tst_v4::mathMin()
570 {
571     QQmlComponent component(&engine, testFileUrl("mathMin.qml"));
572
573     QObject *o = component.create();
574     QVERIFY(o != 0);
575
576     QCOMPARE(o->property("test1").toReal(), qreal(-3.7));
577     QCOMPARE(o->property("test2").toReal(), qreal(4.4));
578     QCOMPARE(o->property("test3").toBool(), true);
579     QCOMPARE(o->property("test4").toBool(), true);
580     QCOMPARE(o->property("test5").toBool(), true);
581     QCOMPARE(o->property("test6").toReal(), qreal(82.6));
582     QCOMPARE(o->property("test7").toBool(), true);
583     QCOMPARE(o->property("test8").toReal(), qreal(4.4));
584     //QCOMPARE(o->property("test9").toBool(), true);    //QTBUG-24706
585     QCOMPARE(o->property("test10").toReal(), qreal(-3.7));
586     QCOMPARE(o->property("test11").toReal(), qreal(0));
587     QCOMPARE(o->property("test12").toReal(), qreal(-3.7));
588     delete o;
589 }
590
591 QTEST_MAIN(tst_v4)
592
593 #include "tst_v4.moc"