1
/****************************************************************************
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/
6
** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40
****************************************************************************/
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
#include <QtCore/qnumeric.h>
51
#include <private/qv4compiler_p.h>
53
#include "../../shared/util.h"
54
#include "testtypes.h"
56
class tst_v4 : public QQmlDataTest
65
void unnecessaryReeval();
67
void nestedLogicalOr();
69
void nestedLogicalAnd();
70
void conditionalExpr();
73
void nestedObjectAccess();
74
void subscriptionsInConditionalExpressions();
77
void stringComparison();
87
void conversions_data();
91
void debuggingDumpInstructions(); // this test should be last.
97
void tst_v4::initTestCase()
99
QQmlDataTest::initTestCase();
103
static int v4ErrorsMsgCount = 0;
104
static void v4ErrorsMsgHandler(QtMsgType, const char *message)
106
QByteArray m(message);
107
if (m.contains("QV4"))
111
void tst_v4::qtscript()
113
QFETCH(QString, file);
114
QV4Compiler::enableBindingsTest(true);
116
QQmlComponent component(&engine, testFileUrl(file));
118
v4ErrorsMsgCount = 0;
119
QtMsgHandler old = qInstallMsgHandler(v4ErrorsMsgHandler);
121
QObject *o = component.create();
124
qInstallMsgHandler(old);
126
QCOMPARE(v4ErrorsMsgCount, 0);
128
QV4Compiler::enableBindingsTest(false);
131
void tst_v4::qtscript_data()
133
QTest::addColumn<QString>("file");
135
QTest::newRow("equals") << "equals.qml";
136
QTest::newRow("strict equals") << "strictEquals.qml";
137
QTest::newRow("qreal -> int rounding") << "qrealToIntRounding.qml";
138
QTest::newRow("exception on fetch") << "fetchException.qml";
139
QTest::newRow("logical or") << "logicalOr.qml";
140
QTest::newRow("conditional expressions") << "conditionalExpr.qml";
141
QTest::newRow("double bool jump") << "doubleBoolJump.qml";
142
QTest::newRow("unary minus") << "unaryMinus.qml";
143
QTest::newRow("null qobject") << "nullQObject.qml";
144
QTest::newRow("qobject -> bool") << "objectToBool.qml";
145
QTest::newRow("conversion from bool") << "conversions.1.qml"; // QTBUG-24706
146
QTest::newRow("conversion from int") << "conversions.2.qml"; // QTBUG-24706
147
QTest::newRow("conversion from float") << "conversions.3.qml";
148
QTest::newRow("conversion from double") << "conversions.4.qml"; // QTBUG-24706
149
QTest::newRow("conversion from real") << "conversions.5.qml"; // QTBUG-24706
150
QTest::newRow("conversion from string") << "conversions.6.qml"; // QTBUG-24706
151
QTest::newRow("conversion from url") << "conversions.7.qml"; // QTBUG-24706
152
QTest::newRow("conversion from vec3") << "conversions.8.qml";
153
QTest::newRow("variantHandling") << "variantHandling.qml";
156
void tst_v4::unnecessaryReeval()
158
QQmlComponent component(&engine, testFileUrl("unnecessaryReeval.qml"));
160
QObject *o = component.create();
163
ResultObject *ro = qobject_cast<ResultObject *>(o);
166
QCOMPARE(ro->resultCounter(), 1);
167
QCOMPARE(ro->result(), 19);
168
ro->resetResultCounter();
170
ro->setProperty("b", 6);
172
QCOMPARE(ro->resultCounter(), 1);
173
QCOMPARE(ro->result(), 6);
174
ro->resetResultCounter();
176
ro->setProperty("a", 14);
178
QCOMPARE(ro->resultCounter(), 1);
179
QCOMPARE(ro->result(), 7);
180
ro->resetResultCounter();
182
ro->setProperty("b", 14);
183
QCOMPARE(ro->resultCounter(), 0);
184
QCOMPARE(ro->result(), 7);
189
void tst_v4::logicalOr()
192
QQmlComponent component(&engine, testFileUrl("logicalOr.qml"));
194
QObject *o = component.create();
197
ResultObject *ro = qobject_cast<ResultObject *>(o);
200
QCOMPARE(ro->result(), 0);
205
QQmlComponent component(&engine, testFileUrl("logicalOr.2.qml"));
207
QObject *o = component.create();
210
ResultObject *ro = qobject_cast<ResultObject *>(o);
213
QCOMPARE(ro->result(), 1);
218
void tst_v4::nestedLogicalOr()
220
//we are primarily testing that v4 does not get caught in a loop (QTBUG-24038)
221
QQmlComponent component(&engine, testFileUrl("nestedLogicalOr.qml"));
223
QObject *o = component.create();
226
ResultObject *ro = qobject_cast<ResultObject *>(o);
229
QCOMPARE(ro->result(), 1);
233
void tst_v4::logicalAnd()
236
QQmlComponent component(&engine, testFileUrl("logicalAnd.qml"));
238
QObject *o = component.create();
241
ResultObject *ro = qobject_cast<ResultObject *>(o);
244
QCOMPARE(ro->result(), 0);
249
QQmlComponent component(&engine, testFileUrl("logicalAnd.2.qml"));
251
QObject *o = component.create();
254
ResultObject *ro = qobject_cast<ResultObject *>(o);
257
QCOMPARE(ro->result(), 1);
262
QQmlComponent component(&engine, testFileUrl("logicalAnd.3.qml"));
264
QObject *o = component.create();
267
ResultObject *ro = qobject_cast<ResultObject *>(o);
270
QCOMPARE(ro->result(), 1);
276
QQmlComponent component(&engine, testFileUrl("logicalAnd.4.qml"));
278
QObject *o = component.create();
281
ResultObject *ro = qobject_cast<ResultObject *>(o);
284
QCOMPARE(ro->result(), 1);
289
QQmlComponent component(&engine, testFileUrl("logicalAnd.5.qml"));
291
QObject *o = component.create();
294
ResultObject *ro = qobject_cast<ResultObject *>(o);
297
QCOMPARE(ro->result(), 1);
302
QQmlComponent component(&engine, testFileUrl("logicalAnd.6.qml"));
304
QObject *o = component.create();
307
ResultObject *ro = qobject_cast<ResultObject *>(o);
310
QCOMPARE(ro->result(), 1);
315
QQmlComponent component(&engine, testFileUrl("logicalAnd.7.qml"));
317
QObject *o = component.create();
320
ResultObject *ro = qobject_cast<ResultObject *>(o);
323
QCOMPARE(ro->result(), 1);
328
void tst_v4::nestedLogicalAnd()
330
QQmlComponent component(&engine, testFileUrl("nestedLogicalAnd.qml"));
332
QObject *o = component.create();
335
ResultObject *ro = qobject_cast<ResultObject *>(o);
338
QCOMPARE(ro->result(), 1);
342
void tst_v4::conditionalExpr()
345
QQmlComponent component(&engine, testFileUrl("conditionalExpr.qml"));
347
QObject *o = component.create();
350
ResultObject *ro = qobject_cast<ResultObject *>(o);
353
QCOMPARE(ro->result(), 0);
358
// This would previously use the metaObject of the root element to result the nested access.
359
// That is, the index for accessing "result" would have been RootObject::result, instead of
360
// NestedObject::result.
361
void tst_v4::nestedObjectAccess()
364
QQmlComponent component(&engine, testFileUrl("nestedObjectAccess.qml"));
366
QObject *o = component.create();
369
ResultObject *ro = qobject_cast<ResultObject *>(o);
372
QCOMPARE(ro->result(), 37);
378
QQmlComponent component(&engine, testFileUrl("nestedObjectAccess2.qml"));
380
QObject *o = component.create();
383
ResultObject *ro = qobject_cast<ResultObject *>(o);
386
QCOMPARE(ro->result(), 37);
392
void tst_v4::subscriptionsInConditionalExpressions()
394
QQmlComponent component(&engine, testFileUrl("subscriptionsInConditionalExpressions.qml"));
396
QObject *o = component.create();
399
QObject *ro = qobject_cast<QObject *>(o);
402
QCOMPARE(ro->property("result").toReal(), qreal(2));
408
void tst_v4::qtbug_21883()
410
QQmlComponent component(&engine, testFileUrl("qtbug_21883.qml"));
412
QString warning = component.url().toString() + ":4: Unable to assign null to ResultObject*";
413
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
415
QObject *o = component.create();
420
void tst_v4::qtbug_22816()
422
QQmlComponent component(&engine, testFileUrl("qtbug_22816.qml"));
424
QObject *o = component.create();
426
QCOMPARE(o->property("test1").toBool(), false);
427
QCOMPARE(o->property("test2").toBool(), false);
431
void tst_v4::stringComparison()
433
QQmlComponent component(&engine, testFileUrl("stringComparison.qml"));
435
QObject *o = component.create();
437
QCOMPARE(o->property("test1").toBool(), true);
438
QCOMPARE(o->property("test2").toBool(), true);
439
QCOMPARE(o->property("test3").toBool(), true);
440
QCOMPARE(o->property("test4").toBool(), true);
441
QCOMPARE(o->property("test5").toBool(), true);
442
QCOMPARE(o->property("test6").toBool(), true);
443
QCOMPARE(o->property("test7").toBool(), true);
444
QCOMPARE(o->property("test8").toBool(), true);
445
QCOMPARE(o->property("test9").toBool(), true);
446
QCOMPARE(o->property("test10").toBool(), true);
447
QCOMPARE(o->property("test11").toBool(), true);
448
QCOMPARE(o->property("test12").toBool(), true);
449
QCOMPARE(o->property("test13").toBool(), true);
450
QCOMPARE(o->property("test14").toBool(), true);
451
QCOMPARE(o->property("test15").toBool(), true);
452
QCOMPARE(o->property("test16").toBool(), true);
453
QCOMPARE(o->property("test17").toBool(), true);
454
QCOMPARE(o->property("test18").toBool(), true);
455
QCOMPARE(o->property("test19").toBool(), true);
456
QCOMPARE(o->property("test20").toBool(), true);
457
QCOMPARE(o->property("test21").toBool(), true);
458
QCOMPARE(o->property("test22").toBool(), true);
462
void tst_v4::unaryMinus()
464
QQmlComponent component(&engine, testFileUrl("unaryMinus.qml"));
466
QObject *o = component.create();
469
QCOMPARE(o->property("test1").toReal(), qreal(-18));
470
QCOMPARE(o->property("test2").toInt(), -18);
471
QCOMPARE(o->property("test3").toReal(), qreal(3.7));
472
QCOMPARE(o->property("test4").toInt(), 4);
473
QCOMPARE(o->property("test5").toReal(), qreal(3.3));
474
QCOMPARE(o->property("test6").toInt(), 3);
475
QCOMPARE(o->property("test7").toReal(), qreal(7));
476
QCOMPARE(o->property("test8").toInt(), 7);
477
QCOMPARE(o->property("test9").toReal(), qreal(-4.4));
478
QCOMPARE(o->property("test10").toInt(), -4);
483
void tst_v4::unaryPlus()
485
QQmlComponent component(&engine, testFileUrl("unaryPlus.qml"));
487
QObject *o = component.create();
490
QCOMPARE(o->property("test1").toReal(), qreal(18));
491
QCOMPARE(o->property("test2").toInt(), 18);
492
QCOMPARE(o->property("test3").toReal(), qreal(-3.7));
493
QCOMPARE(o->property("test4").toInt(), -4);
494
QCOMPARE(o->property("test5").toReal(), qreal(-3.3));
495
QCOMPARE(o->property("test6").toInt(), -3);
496
QCOMPARE(o->property("test7").toReal(), qreal(-7));
497
QCOMPARE(o->property("test8").toInt(), -7);
498
QCOMPARE(o->property("test9").toReal(), qreal(4.4));
499
QCOMPARE(o->property("test10").toInt(), 4);
504
void tst_v4::colorType()
506
QQmlComponent component(&engine, testFileUrl("colorType.qml"));
508
QObject *o = component.create();
510
QCOMPARE(o->property("test1").value<QColor>(), QColor("red"));
511
QCOMPARE(o->property("test2").value<QColor>(), QColor("red"));
512
QCOMPARE(o->property("test3").value<QColor>(), QColor("red"));
513
QCOMPARE(o->property("test4").toBool(), true);
514
QCOMPARE(o->property("test5").toBool(), true);
515
QCOMPARE(o->property("test6").toBool(), true);
516
QCOMPARE(o->property("test7").toBool(), true);
520
void tst_v4::mathAbs()
522
QQmlComponent component(&engine, testFileUrl("mathAbs.qml"));
524
QObject *o = component.create();
527
QCOMPARE(o->property("test1").toReal(), qreal(3.7));
528
QCOMPARE(o->property("test2").toReal(), qreal(4.5));
529
QCOMPARE(o->property("test3").toInt(), 18);
530
QCOMPARE(o->property("test4").toInt(), 72);
531
QCOMPARE(o->property("test5").toBool(), true);
532
QCOMPARE(o->property("test6").toBool(), true);
533
QCOMPARE(o->property("test7").toBool(), true);
534
QCOMPARE(o->property("test8").toInt(), 82);
535
QCOMPARE(o->property("test9").toBool(), true);
536
QCOMPARE(o->property("test10").toBool(), true);
537
QCOMPARE(o->property("test11").toInt(), 0);
538
//QCOMPARE(o->property("test12").toBool(), true); //QTBUG-24706
543
void tst_v4::mathCeil()
545
QQmlComponent component(&engine, testFileUrl("mathCeil.qml"));
547
QObject *o = component.create();
550
QCOMPARE(o->property("test1").toReal(), qreal(-3));
551
QCOMPARE(o->property("test2").toReal(), qreal(5));
552
QCOMPARE(o->property("test3").toBool(), true);
553
//QCOMPARE(o->property("test4").toBool(), true); //QTBUG-24706
554
QCOMPARE(o->property("test5").toBool(), true);
555
QCOMPARE(o->property("test6").toReal(), qreal(83));
556
//QCOMPARE(o->property("test7").toBool(), true); //QTBUG-24706
557
//QCOMPARE(o->property("test8").toBool(), true); //QTBUG-24706
558
QCOMPARE(o->property("test9").toInt(), 0);
559
//QCOMPARE(o->property("test10").toBool(), true); //QTBUG-24706
564
void tst_v4::mathMax()
566
QQmlComponent component(&engine, testFileUrl("mathMax.qml"));
568
QObject *o = component.create();
571
QCOMPARE(o->property("test1").toReal(), qreal(4.4));
572
QCOMPARE(o->property("test2").toReal(), qreal(7));
573
QCOMPARE(o->property("test3").toBool(), true);
574
QCOMPARE(o->property("test4").toBool(), true);
575
QCOMPARE(o->property("test5").toBool(), true);
576
QCOMPARE(o->property("test6").toReal(), qreal(82.6));
577
QCOMPARE(o->property("test7").toReal(), qreal(4.4));
578
QCOMPARE(o->property("test8").toBool(), true);
579
//QCOMPARE(o->property("test9").toBool(), true); //QTBUG-24706
580
QCOMPARE(o->property("test10").toReal(), qreal(0));
581
QCOMPARE(o->property("test11").toReal(), qreal(4.4));
582
QCOMPARE(o->property("test12").toReal(), qreal(7));
587
void tst_v4::mathMin()
589
QQmlComponent component(&engine, testFileUrl("mathMin.qml"));
591
QObject *o = component.create();
594
QCOMPARE(o->property("test1").toReal(), qreal(-3.7));
595
QCOMPARE(o->property("test2").toReal(), qreal(4.4));
596
QCOMPARE(o->property("test3").toBool(), true);
597
QCOMPARE(o->property("test4").toBool(), true);
598
QCOMPARE(o->property("test5").toBool(), true);
599
QCOMPARE(o->property("test6").toReal(), qreal(82.6));
600
QCOMPARE(o->property("test7").toBool(), true);
601
QCOMPARE(o->property("test8").toReal(), qreal(4.4));
602
//QCOMPARE(o->property("test9").toBool(), true); //QTBUG-24706
603
QCOMPARE(o->property("test10").toReal(), qreal(-3.7));
604
QCOMPARE(o->property("test11").toReal(), qreal(0));
605
QCOMPARE(o->property("test12").toReal(), qreal(-3.7));
609
class V4ModuleApi : public QObject
612
Q_PROPERTY(int ip READ ip WRITE setIp NOTIFY ipChanged FINAL)
614
V4ModuleApi() : m_ip(12) {}
617
Q_INVOKABLE int random() { static int prng = 3; prng++; m_ip++; emit ipChanged(); return prng; }
619
int ip() const { return m_ip; }
620
void setIp(int v) { m_ip = v; emit ipChanged(); }
629
static QObject *v4_module_api_factory(QQmlEngine*, QJSEngine*)
631
return new V4ModuleApi;
634
void tst_v4::moduleApi()
636
// register module api, providing typeinfo via template
637
qmlRegisterModuleApi<V4ModuleApi>("Qt.test", 1, 0, v4_module_api_factory);
638
QQmlComponent component(&engine, testFileUrl("moduleApi.qml"));
639
QObject *o = component.create();
641
QCOMPARE(o->property("testProp").toInt(), 12);
642
QCOMPARE(o->property("testProp2").toInt(), 2);
643
QMetaObject::invokeMethod(o, "getRandom");
644
QCOMPARE(o->property("testProp").toInt(), 13);
645
QCOMPARE(o->property("testProp2").toInt(), 4);
649
void tst_v4::conversions_data()
651
QTest::addColumn<QUrl>("file");
652
QTest::addColumn<QStringList>("warnings");
653
QTest::addColumn<bool>("boolProp");
654
QTest::addColumn<int>("intProp");
655
QTest::addColumn<float>("floatProp");
656
QTest::addColumn<double>("doubleProp");
657
QTest::addColumn<qreal>("qrealProp");
658
QTest::addColumn<QString>("qstringProp");
659
QTest::addColumn<QUrl>("qurlProp");
660
QTest::addColumn<QVector3D>("vec3Prop");
662
QTest::newRow("from bool") << testFileUrl("conversions.1.qml")
663
<< (QStringList() << (testFileUrl("conversions.1.qml").toString() + QLatin1String(":11:15: Unable to assign bool to QUrl")))
669
<< QString(QLatin1String("true"))
670
<< QUrl() // cannot assign bool to url.
671
<< QVector3D(1, 1, 1);
673
QTest::newRow("from integer") << testFileUrl("conversions.2.qml")
674
<< (QStringList() << (testFileUrl("conversions.2.qml").toString() + QLatin1String(":11:15: Unable to assign int to QUrl")))
680
<< QString(QLatin1String("4"))
681
<< QUrl() // cannot assign int to url.
682
<< QVector3D(4, 4, 4);
684
QTest::newRow("from float") << testFileUrl("conversions.3.qml")
685
<< (QStringList() << (testFileUrl("conversions.3.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
689
<< (double)((float)4.4)
690
<< (qreal)((float)4.4)
691
<< QString::number((double)((float)4.4), 'g', 16)
692
<< QUrl() // cannot assign number to url.
693
<< QVector3D(4.4, 4.4, 4.4);
695
QTest::newRow("from double") << testFileUrl("conversions.4.qml")
696
<< (QStringList() << (testFileUrl("conversions.4.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
699
<< (float)4.444444444
700
<< (double)4.444444444
701
<< (qreal)4.444444444
702
<< QString::number((double)4.444444444, 'g', 16)
703
<< QUrl() // cannot assign number to url.
704
<< QVector3D(4.444444444, 4.444444444, 4.444444444);
706
QTest::newRow("from qreal") << testFileUrl("conversions.5.qml")
707
<< (QStringList() << (testFileUrl("conversions.5.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
713
<< QString(QLatin1String("4.44"))
714
<< QUrl() // cannot assign number to url.
715
<< QVector3D(4.44, 4.44, 4.44);
717
QTest::newRow("from string") << testFileUrl("conversions.6.qml")
724
<< QString(QLatin1String("4"))
725
<< QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
726
<< QVector3D(4, 4, 4);
729
QTest::newRow("from url") << testFileUrl("conversions.7.qml")
730
<< (QStringList() << (testFileUrl("conversions.7.qml").toString() + QLatin1String(":6:14: Unable to assign QUrl to int"))
731
<< (testFileUrl("conversions.7.qml").toString() + QLatin1String(":7:16: Unable to assign QUrl to number"))
732
<< (testFileUrl("conversions.7.qml").toString() + QLatin1String(":8:17: Unable to assign QUrl to number"))
733
<< (testFileUrl("conversions.7.qml").toString() + QLatin1String(":9:16: Unable to assign QUrl to number")))
739
<< QString(testFileUrl("").toString() + QString(QLatin1String("4")))
740
<< QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
741
<< QVector3D(qQNaN(), qQNaN(), qQNaN());
743
QTest::newRow("from vector") << testFileUrl("conversions.8.qml")
744
<< (QStringList() << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":11: Unable to assign QVector3D to QUrl"))
745
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":10: Unable to assign QVector3D to QString"))
746
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":9: Unable to assign QVector3D to double"))
747
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":8: Unable to assign QVector3D to double"))
748
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":7: Unable to assign QVector3D to float"))
749
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":6: Unable to assign QVector3D to int")))
750
<< true // non-null therefore true
751
<< (int)0 // the other values should be the default-ctor values.
757
<< QVector3D(4, 4, 4); // except this one.
760
#define COMPARE_NUMBER(type, prop, expected) \
761
if (qIsNaN(expected)) \
762
QVERIFY(qIsNaN(qvariant_cast<type>(prop))); \
764
QCOMPARE((prop), QVariant::fromValue<type>(expected));
766
void tst_v4::conversions()
769
QFETCH(QStringList, warnings);
770
QFETCH(bool, boolProp);
771
QFETCH(int, intProp);
772
QFETCH(float, floatProp);
773
QFETCH(double, doubleProp);
774
QFETCH(qreal, qrealProp);
775
QFETCH(QString, qstringProp);
776
QFETCH(QUrl, qurlProp);
777
QFETCH(QVector3D, vec3Prop);
779
foreach (const QString &w, warnings)
780
QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
782
QQmlComponent component(&engine, file);
783
QObject *o = component.create();
785
QCOMPARE(o->property("boolProp"), QVariant::fromValue<bool>(boolProp));
786
QCOMPARE(o->property("intProp"), QVariant::fromValue<int>(intProp));
787
COMPARE_NUMBER(float, o->property("floatProp"), floatProp);
788
COMPARE_NUMBER(double, o->property("doubleProp"), doubleProp);
789
COMPARE_NUMBER(qreal, o->property("qrealProp"), qrealProp);
790
QCOMPARE(o->property("qstringProp"), QVariant::fromValue<QString>(qstringProp));
791
QCOMPARE(o->property("qurlProp"), QVariant::fromValue<QUrl>(qurlProp));
793
QVector3D vec3 = qvariant_cast<QVector3D>(o->property("vec3Prop"));
794
COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.x()), vec3Prop.x());
795
COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.y()), vec3Prop.y());
796
COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.z()), vec3Prop.z());
800
void tst_v4::subscriptions()
803
QQmlComponent component(&engine, testFileUrl("subscriptions.1.qml"));
805
QObject *o = component.create();
808
QObject *ro = qobject_cast<QObject *>(o);
811
QCOMPARE(ro->property("targetHeight"), QVariant::fromValue<qreal>(201));
817
static QStringList messages;
818
static void msgHandler(QtMsgType, const char *msg)
820
messages << QLatin1String(msg);
823
static QByteArray getAddress(int address)
825
return QByteArray::number(address);
828
static QByteArray getLeading(int address)
832
leading = getAddress(address);
833
leading.prepend(QByteArray(8 - leading.count(), ' '));
838
#include <private/qv4instruction_p.h>
839
void tst_v4::debuggingDumpInstructions()
841
QStringList expectedPreAddress;
842
expectedPreAddress << "\t\tNoop";
843
expectedPreAddress << "\t0:0:";
844
expectedPreAddress << "\t\tSubscribe\t\tObject_Reg(0) Notify_Signal(0) -> Subscribe_Slot(0)";
845
expectedPreAddress << "\t\tSubscribeId\t\tId_Offset(0) -> Subscribe_Slot(0)";
846
expectedPreAddress << "\t\tFetchAndSubscribe\tObject_Reg(0) Fast_Accessor(0x0) -> Output_Reg(0) Subscription_Slot(0)";
847
expectedPreAddress << "\t\tLoadId\t\t\tId_Offset(0) -> Output_Reg(0)";
848
expectedPreAddress << "\t\tLoadScope\t\t-> Output_Reg(0)";
849
expectedPreAddress << "\t\tLoadRoot\t\t-> Output_Reg(0)";
850
expectedPreAddress << "\t\tLoadModuleObject\t\t) -> Output_Reg(0)";
851
expectedPreAddress << "\t\tLoadAttached\t\tObject_Reg(0) Attached_Index(0) -> Output_Reg(0)";
852
expectedPreAddress << "\t\tUnaryNot\t\tInput_Reg(0) -> Output_Reg(0)";
853
expectedPreAddress << "\t\tUnaryMinusNumber\t\tInput_Reg(0) -> Output_Reg(0)";
854
expectedPreAddress << "\t\tUnaryMinusInt\t\tInput_Reg(0) -> Output_Reg(0)";
855
expectedPreAddress << "\t\tUnaryPlusNumber\t\tInput_Reg(0) -> Output_Reg(0)";
856
expectedPreAddress << "\t\tUnaryPlusInt\t\tInput_Reg(0) -> Output_Reg(0)";
857
expectedPreAddress << "\t\tConvertBoolToInt\tInput_Reg(0) -> Output_Reg(0)";
858
expectedPreAddress << "\t\tConvertBoolToNumber\tInput_Reg(0) -> Output_Reg(0)";
859
expectedPreAddress << "\t\tConvertBoolToString\tInput_Reg(0) -> Output_Reg(0)";
860
expectedPreAddress << "\t\tConvertBoolToVariant\tInput_Reg(0) -> Output_Reg(0)";
861
expectedPreAddress << "\t\tConvertIntToBool\tInput_Reg(0) -> Output_Reg(0)";
862
expectedPreAddress << "\t\tConvertIntToNumber\tInput_Reg(0) -> Output_Reg(0)";
863
expectedPreAddress << "\t\tConvertIntToString\tInput_Reg(0) -> Output_Reg(0)";
864
expectedPreAddress << "\t\tConvertIntToVariant\tInput_Reg(0) -> Output_Reg(0)";
865
expectedPreAddress << "\t\tConvertNumberToBool\tInput_Reg(0) -> Output_Reg(0)";
866
expectedPreAddress << "\t\tConvertNumberToInt\tInput_Reg(0) -> Output_Reg(0)";
867
expectedPreAddress << "\t\tConvertNumberToString\tInput_Reg(0) -> Output_Reg(0)";
868
expectedPreAddress << "\t\tConvertNumberToVariant\tInput_Reg(0) -> Output_Reg(0)";
869
expectedPreAddress << "\t\tConvertStringToBool\tInput_Reg(0) -> Output_Reg(0)";
870
expectedPreAddress << "\t\tConvertStringToInt\tInput_Reg(0) -> Output_Reg(0)";
871
expectedPreAddress << "\t\tConvertStringToNumber\tInput_Reg(0) -> Output_Reg(0)";
872
expectedPreAddress << "\t\tConvertStringToUrl\tInput_Reg(0) -> Output_Reg(0)";
873
expectedPreAddress << "\t\tConvertStringToColor\tInput_Reg(0) -> Output_Reg(0)";
874
expectedPreAddress << "\t\tConvertStringToVariant\tInput_Reg(0) -> Output_Reg(0)";
875
expectedPreAddress << "\t\tConvertUrlToBool\tInput_Reg(0) -> Output_Reg(0)";
876
expectedPreAddress << "\t\tConvertUrlToString\tInput_Reg(0) -> Output_Reg(0)";
877
expectedPreAddress << "\t\tConvertUrlToVariant\tInput_Reg(0) -> Output_Reg(0)";
878
expectedPreAddress << "\t\tConvertColorToBool\tInput_Reg(0) -> Output_Reg(0)";
879
expectedPreAddress << "\t\tConvertColorToString\tInput_Reg(0) -> Output_Reg(0)";
880
expectedPreAddress << "\t\tConvertColorToVariant\tInput_Reg(0) -> Output_Reg(0)";
881
expectedPreAddress << "\t\tConvertObjectToBool\tInput_Reg(0) -> Output_Reg(0)";
882
expectedPreAddress << "\t\tConvertObjectToVariant\tInput_Reg(0) -> Output_Reg(0)";
883
expectedPreAddress << "\t\tConvertNullToObject\tInput_Reg(0) -> Output_Reg(0)";
884
expectedPreAddress << "\t\tConvertNullToVariant\tInput_Reg(0) -> Output_Reg(0)";
885
expectedPreAddress << "\t\tResolveUrl\t\tInput_Reg(0) -> Output_Reg(0)";
886
expectedPreAddress << "\t\tMathSinNumber\t\tInput_Reg(0) -> Output_Reg(0)";
887
expectedPreAddress << "\t\tMathCosNumber\t\tInput_Reg(0) -> Output_Reg(0)";
888
expectedPreAddress << "\t\tMathAbsNumber\t\tInput_Reg(0) -> Output_Reg(0)";
889
expectedPreAddress << "\t\tMathRoundNumber\t\tInput_Reg(0) -> Output_Reg(0)";
890
expectedPreAddress << "\t\tMathFloorNumber\t\tInput_Reg(0) -> Output_Reg(0)";
891
expectedPreAddress << "\t\tMathCeilNumber\t\tInput_Reg(0) -> Output_Reg(0)";
892
expectedPreAddress << "\t\tMathPINumber\t\tInput_Reg(0) -> Output_Reg(0)";
893
expectedPreAddress << "\t\tLoadNull\t\tConstant(null) -> Output_Reg(0)";
894
expectedPreAddress << "\t\tLoadNumber\t\tConstant(0) -> Output_Reg(0)";
895
expectedPreAddress << "\t\tLoadInt\t\t\tConstant(0) -> Output_Reg(0)";
896
expectedPreAddress << "\t\tLoadBool\t\tConstant(false) -> Output_Reg(0)";
897
expectedPreAddress << "\t\tLoadString\t\tString_DataIndex(0) String_Length(0) -> Output_Register(0)";
898
expectedPreAddress << "\t\tEnableV4Test\t\tString_DataIndex(0) String_Length(0)";
899
expectedPreAddress << "\t\tTestV4Store\t\tInput_Reg(0) Reg_Type(0)";
900
expectedPreAddress << "\t\tBitAndInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
901
expectedPreAddress << "\t\tBitOrInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
902
expectedPreAddress << "\t\tBitXorInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
903
expectedPreAddress << "\t\tAddNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
904
expectedPreAddress << "\t\tAddString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
905
expectedPreAddress << "\t\tSubNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
906
expectedPreAddress << "\t\tMulNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
907
expectedPreAddress << "\t\tDivNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
908
expectedPreAddress << "\t\tModNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
909
expectedPreAddress << "\t\tLShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
910
expectedPreAddress << "\t\tRShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
911
expectedPreAddress << "\t\tURShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
912
expectedPreAddress << "\t\tGtNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
913
expectedPreAddress << "\t\tLtNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
914
expectedPreAddress << "\t\tGeNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
915
expectedPreAddress << "\t\tLeNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
916
expectedPreAddress << "\t\tEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
917
expectedPreAddress << "\t\tNotEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
918
expectedPreAddress << "\t\tStrictEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
919
expectedPreAddress << "\t\tStrictNotEqualNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
920
expectedPreAddress << "\t\tGtString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
921
expectedPreAddress << "\t\tLtString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
922
expectedPreAddress << "\t\tGeString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
923
expectedPreAddress << "\t\tLeString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
924
expectedPreAddress << "\t\tEqualString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
925
expectedPreAddress << "\t\tNotEqualString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
926
expectedPreAddress << "\t\tStrictEqualString\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
927
expectedPreAddress << "\t\tStrictNotEqualString\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
928
expectedPreAddress << "\t\tEqualObject\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
929
expectedPreAddress << "\t\tNotEqualObject\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
930
expectedPreAddress << "\t\tStrictEqualObject\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
931
expectedPreAddress << "\t\tStrictNotEqualObject\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
932
expectedPreAddress << "\t\tMathMaxNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
933
expectedPreAddress << "\t\tMathMinNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
934
expectedPreAddress << "\t\tNewString\t\tRegister(0)";
935
expectedPreAddress << "\t\tNewUrl\t\t\tRegister(0)";
936
expectedPreAddress << "\t\tCleanupRegister\t\tRegister(0)";
937
expectedPreAddress << "\t\tCopy\t\t\tInput_Reg(0) -> Output_Reg(0)";
938
expectedPreAddress << "\t\tFetch\t\t\tObject_Reg(0) Property_Index(0) -> Output_Reg(0)";
939
expectedPreAddress << "\t\tStore\t\t\tInput_Reg(0) -> Object_Reg(0) Property_Index(0)";
940
expectedPreAddress << "\t\tJump\t\t\tAddress(UNIT_TEST_JUMP_ADDRESS) [if false == Input_Reg(0)]"; //(address + size() + i->jump.count)
941
expectedPreAddress << "\t\tBranchTrue\t\tAddress(UNIT_TEST_BRANCH_ADDRESS) [if true == Input_Reg(0)]"; //(address + size() + i->branchop.offset)
942
expectedPreAddress << "\t\tBranchFalse\t\tAddress(UNIT_TEST_BRANCH_ADDRESS) [if false == Input_Reg(0)]"; //(address + size() + i->branchop.offset)
943
expectedPreAddress << "\t\tBranch\t\t\tAddress(UNIT_TEST_BRANCH_ADDRESS)"; //(address + size() + i->branchop.offset)
944
expectedPreAddress << "\t\tBlock\t\t\tMask(0)";
945
expectedPreAddress << "\t\tThrow\t\t\tInputReg(0)";
946
expectedPreAddress << "\t\tInitString\t\tString_DataIndex(0) -> String_Slot(0)";
947
QStringList expected;
949
messages = QStringList();
950
QtMsgHandler old = qInstallMsgHandler(msgHandler);
953
#define DUMP_INSTR_IN_UNIT_TEST(I, FMT) { QQmlJS::V4InstrData<QQmlJS::V4Instr::I> i; memset(&i, 0, sizeof(i)); bc.append(i); }
954
FOR_EACH_V4_INSTR(DUMP_INSTR_IN_UNIT_TEST);
955
#undef DUMP_INSTR_IN_UNIT_TEST // NOTE: we memset in order to ensure stable output.
956
const char *start = bc.constData();
957
const char *end = start + bc.size();
958
const char *codeAddr = start;
959
int whichExpected = 0;
960
#define DUMP_INSTR_SIZE_IN_UNIT_TEST(I, FMT) { \
961
QString currExpected = whichExpected < expectedPreAddress.size() ? expectedPreAddress.at(whichExpected++) : QString(); \
962
currExpected.prepend(getLeading(codeAddr - start)); \
963
expected.append(currExpected); \
964
codeAddr += QQmlJS::V4Instr::size(static_cast<QQmlJS::V4Instr::Type>(QQmlJS::V4Instr::I)); \
966
FOR_EACH_V4_INSTR(DUMP_INSTR_SIZE_IN_UNIT_TEST);
967
#undef DUMP_INSTR_SIZE_IN_UNIT_TEST // so that we generate the correct address for each instruction comparison
970
// ensure that the output was expected.
971
qInstallMsgHandler(old);
972
QCOMPARE(messages.count(), expected.count());
973
for (int ii = 0; ii < messages.count(); ++ii) {
974
// Calculating the destination address of a null jump/branch instruction is tricky
975
// so instead we simply don't compare that part of those instructions.
976
QRegExp ignoreAddress("\\bAddress\\((\\w*)\\)");
977
ignoreAddress.setMinimal(true);
978
QString expectOut = expected.at(ii); expectOut.replace(ignoreAddress, "");
979
QString actualOut = messages.at(ii); actualOut.replace(ignoreAddress, "");
980
QCOMPARE(actualOut, expectOut);
987
#include "tst_v4.moc"