1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
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();
89
void integerOperations();
91
void conversions_data();
95
void debuggingDumpInstructions(); // this test should be last.
101
void tst_v4::initTestCase()
103
QQmlDataTest::initTestCase();
107
void tst_v4::qtscript()
109
QFETCH(QString, file);
110
QV4Compiler::enableBindingsTest(true);
112
QQmlComponent component(&engine, testFileUrl(file));
114
QQmlTestMessageHandler messageHandler;
116
QObject *o = component.create();
119
QEXPECT_FAIL("jsvalueHandling", "QTBUG-26951 - QJSValue has a different representation of NULL to QV8Engine", Continue);
120
const int v4ErrorCount = messageHandler.messages().filter(QLatin1String("QV4")).size();
121
QVERIFY2(v4ErrorCount == 0, qPrintable(messageHandler.messageString()));
123
QV4Compiler::enableBindingsTest(false);
126
void tst_v4::qtscript_data()
128
QTest::addColumn<QString>("file");
130
QTest::newRow("equals") << "equals.qml";
131
QTest::newRow("strict equals") << "strictEquals.qml";
132
QTest::newRow("qreal -> int rounding") << "qrealToIntRounding.qml";
133
QTest::newRow("exception on fetch") << "fetchException.qml";
134
QTest::newRow("logical or") << "logicalOr.qml";
135
QTest::newRow("conditional expressions") << "conditionalExpr.qml";
136
QTest::newRow("double bool jump") << "doubleBoolJump.qml";
137
QTest::newRow("unary minus") << "unaryMinus.qml";
138
QTest::newRow("null qobject") << "nullQObject.qml";
139
QTest::newRow("qobject -> bool") << "objectToBool.qml";
140
QTest::newRow("conversion from bool") << "conversions.1.qml";
141
QTest::newRow("conversion from int") << "conversions.2.qml";
142
QTest::newRow("conversion from float") << "conversions.3.qml";
143
QTest::newRow("conversion from double") << "conversions.4.qml";
144
QTest::newRow("conversion from real") << "conversions.5.qml";
145
QTest::newRow("conversion from string") << "conversions.6.qml";
146
QTest::newRow("conversion from url") << "conversions.7.qml";
147
QTest::newRow("conversion from vec3") << "conversions.8.qml";
148
QTest::newRow("variantHandling") << "variantHandling.qml";
149
QTest::newRow("varHandling") << "varHandling.qml";
150
QTest::newRow("jsvalueHandling") << "jsvalueHandling.qml";
151
QTest::newRow("integerOperations") << "integerOperations.qml";
154
void tst_v4::unnecessaryReeval()
156
QQmlComponent component(&engine, testFileUrl("unnecessaryReeval.qml"));
158
QObject *o = component.create();
161
ResultObject *ro = qobject_cast<ResultObject *>(o);
164
QCOMPARE(ro->resultCounter(), 1);
165
QCOMPARE(ro->result(), 19);
166
ro->resetResultCounter();
168
ro->setProperty("b", 6);
170
QCOMPARE(ro->resultCounter(), 1);
171
QCOMPARE(ro->result(), 6);
172
ro->resetResultCounter();
174
ro->setProperty("a", 14);
176
QCOMPARE(ro->resultCounter(), 1);
177
QCOMPARE(ro->result(), 7);
178
ro->resetResultCounter();
180
ro->setProperty("b", 14);
181
QCOMPARE(ro->resultCounter(), 0);
182
QCOMPARE(ro->result(), 7);
187
void tst_v4::logicalOr()
190
QQmlComponent component(&engine, testFileUrl("logicalOr.qml"));
192
QObject *o = component.create();
195
ResultObject *ro = qobject_cast<ResultObject *>(o);
198
QCOMPARE(ro->result(), 0);
203
QQmlComponent component(&engine, testFileUrl("logicalOr.2.qml"));
205
QObject *o = component.create();
208
ResultObject *ro = qobject_cast<ResultObject *>(o);
211
QCOMPARE(ro->result(), 1);
216
void tst_v4::nestedLogicalOr()
218
//we are primarily testing that v4 does not get caught in a loop (QTBUG-24038)
219
QQmlComponent component(&engine, testFileUrl("nestedLogicalOr.qml"));
221
QObject *o = component.create();
224
ResultObject *ro = qobject_cast<ResultObject *>(o);
227
QCOMPARE(ro->result(), 1);
231
void tst_v4::logicalAnd()
234
QQmlComponent component(&engine, testFileUrl("logicalAnd.qml"));
236
QObject *o = component.create();
239
ResultObject *ro = qobject_cast<ResultObject *>(o);
242
QCOMPARE(ro->result(), 0);
247
QQmlComponent component(&engine, testFileUrl("logicalAnd.2.qml"));
249
QObject *o = component.create();
252
ResultObject *ro = qobject_cast<ResultObject *>(o);
255
QCOMPARE(ro->result(), 1);
260
QQmlComponent component(&engine, testFileUrl("logicalAnd.3.qml"));
262
QObject *o = component.create();
265
ResultObject *ro = qobject_cast<ResultObject *>(o);
268
QCOMPARE(ro->result(), 1);
274
QQmlComponent component(&engine, testFileUrl("logicalAnd.4.qml"));
276
QObject *o = component.create();
279
ResultObject *ro = qobject_cast<ResultObject *>(o);
282
QCOMPARE(ro->result(), 1);
287
QQmlComponent component(&engine, testFileUrl("logicalAnd.5.qml"));
289
QObject *o = component.create();
292
ResultObject *ro = qobject_cast<ResultObject *>(o);
295
QCOMPARE(ro->result(), 1);
300
QQmlComponent component(&engine, testFileUrl("logicalAnd.6.qml"));
302
QObject *o = component.create();
305
ResultObject *ro = qobject_cast<ResultObject *>(o);
308
QCOMPARE(ro->result(), 1);
313
QQmlComponent component(&engine, testFileUrl("logicalAnd.7.qml"));
315
QObject *o = component.create();
318
ResultObject *ro = qobject_cast<ResultObject *>(o);
321
QCOMPARE(ro->result(), 1);
326
void tst_v4::nestedLogicalAnd()
328
QQmlComponent component(&engine, testFileUrl("nestedLogicalAnd.qml"));
330
QObject *o = component.create();
333
ResultObject *ro = qobject_cast<ResultObject *>(o);
336
QCOMPARE(ro->result(), 1);
340
void tst_v4::conditionalExpr()
343
QQmlComponent component(&engine, testFileUrl("conditionalExpr.qml"));
345
QObject *o = component.create();
348
ResultObject *ro = qobject_cast<ResultObject *>(o);
351
QCOMPARE(ro->result(), 0);
356
// This would previously use the metaObject of the root element to result the nested access.
357
// That is, the index for accessing "result" would have been RootObject::result, instead of
358
// NestedObject::result.
359
void tst_v4::nestedObjectAccess()
362
QQmlComponent component(&engine, testFileUrl("nestedObjectAccess.qml"));
364
QObject *o = component.create();
367
ResultObject *ro = qobject_cast<ResultObject *>(o);
370
QCOMPARE(ro->result(), 37);
376
QQmlComponent component(&engine, testFileUrl("nestedObjectAccess2.qml"));
378
QObject *o = component.create();
381
ResultObject *ro = qobject_cast<ResultObject *>(o);
384
QCOMPARE(ro->result(), 37);
390
void tst_v4::subscriptionsInConditionalExpressions()
392
QQmlComponent component(&engine, testFileUrl("subscriptionsInConditionalExpressions.qml"));
394
QObject *o = component.create();
397
QObject *ro = qobject_cast<QObject *>(o);
400
QCOMPARE(ro->property("result").toReal(), qreal(2));
406
void tst_v4::qtbug_21883()
408
QQmlComponent component(&engine, testFileUrl("qtbug_21883.qml"));
410
QString warning = component.url().toString() + ":4: Unable to assign null to ResultObject*";
411
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
413
QObject *o = component.create();
418
void tst_v4::qtbug_22816()
420
QQmlComponent component(&engine, testFileUrl("qtbug_22816.qml"));
422
QObject *o = component.create();
424
QCOMPARE(o->property("test1").toBool(), false);
425
QCOMPARE(o->property("test2").toBool(), false);
429
void tst_v4::stringComparison()
431
QQmlComponent component(&engine, testFileUrl("stringComparison.qml"));
433
QObject *o = component.create();
435
QCOMPARE(o->property("test1").toBool(), true);
436
QCOMPARE(o->property("test2").toBool(), true);
437
QCOMPARE(o->property("test3").toBool(), true);
438
QCOMPARE(o->property("test4").toBool(), true);
439
QCOMPARE(o->property("test5").toBool(), true);
440
QCOMPARE(o->property("test6").toBool(), true);
441
QCOMPARE(o->property("test7").toBool(), true);
442
QCOMPARE(o->property("test8").toBool(), true);
443
QCOMPARE(o->property("test9").toBool(), true);
444
QCOMPARE(o->property("test10").toBool(), true);
445
QCOMPARE(o->property("test11").toBool(), true);
446
QCOMPARE(o->property("test12").toBool(), true);
447
QCOMPARE(o->property("test13").toBool(), true);
448
QCOMPARE(o->property("test14").toBool(), true);
449
QCOMPARE(o->property("test15").toBool(), true);
450
QCOMPARE(o->property("test16").toBool(), true);
451
QCOMPARE(o->property("test17").toBool(), true);
452
QCOMPARE(o->property("test18").toBool(), true);
453
QCOMPARE(o->property("test19").toBool(), true);
454
QCOMPARE(o->property("test20").toBool(), true);
455
QCOMPARE(o->property("test21").toBool(), true);
456
QCOMPARE(o->property("test22").toBool(), true);
460
void tst_v4::unaryMinus()
462
QQmlComponent component(&engine, testFileUrl("unaryMinus.qml"));
464
QObject *o = component.create();
467
QCOMPARE(o->property("test1").toReal(), qreal(-18));
468
QCOMPARE(o->property("test2").toInt(), -18);
469
QCOMPARE(o->property("test3").toReal(), qreal(3.7));
470
QCOMPARE(o->property("test4").toInt(), 4);
471
QCOMPARE(o->property("test5").toReal(), qreal(3.3));
472
QCOMPARE(o->property("test6").toInt(), 3);
473
QCOMPARE(o->property("test7").toReal(), qreal(7));
474
QCOMPARE(o->property("test8").toInt(), 7);
475
QCOMPARE(o->property("test9").toReal(), qreal(-4.4));
476
QCOMPARE(o->property("test10").toInt(), -4);
481
void tst_v4::unaryPlus()
483
QQmlComponent component(&engine, testFileUrl("unaryPlus.qml"));
485
QObject *o = component.create();
488
QCOMPARE(o->property("test1").toReal(), qreal(18));
489
QCOMPARE(o->property("test2").toInt(), 18);
490
QCOMPARE(o->property("test3").toReal(), qreal(-3.7));
491
QCOMPARE(o->property("test4").toInt(), -4);
492
QCOMPARE(o->property("test5").toReal(), qreal(-3.3));
493
QCOMPARE(o->property("test6").toInt(), -3);
494
QCOMPARE(o->property("test7").toReal(), qreal(-7));
495
QCOMPARE(o->property("test8").toInt(), -7);
496
QCOMPARE(o->property("test9").toReal(), qreal(4.4));
497
QCOMPARE(o->property("test10").toInt(), 4);
502
void tst_v4::colorType()
504
QQmlComponent component(&engine, testFileUrl("colorType.qml"));
506
QObject *o = component.create();
508
QCOMPARE(o->property("test1").value<QColor>(), QColor("red"));
509
QCOMPARE(o->property("test2").value<QColor>(), QColor("red"));
510
QCOMPARE(o->property("test3").value<QColor>(), QColor("red"));
511
QCOMPARE(o->property("test4").toBool(), true);
512
QCOMPARE(o->property("test5").toBool(), true);
513
QCOMPARE(o->property("test6").toBool(), true);
514
QCOMPARE(o->property("test7").toBool(), true);
518
void tst_v4::mathAbs()
520
QQmlComponent component(&engine, testFileUrl("mathAbs.qml"));
522
QObject *o = component.create();
525
QCOMPARE(o->property("test1").toReal(), qreal(3.7));
526
QCOMPARE(o->property("test2").toReal(), qreal(4.5));
527
QCOMPARE(o->property("test3").toInt(), 18);
528
QCOMPARE(o->property("test4").toInt(), 72);
529
QCOMPARE(o->property("test5").toBool(), true);
530
QCOMPARE(o->property("test6").toBool(), true);
531
QCOMPARE(o->property("test7").toBool(), true);
532
QCOMPARE(o->property("test8").toInt(), 82);
533
QCOMPARE(o->property("test9").toBool(), true);
534
QCOMPARE(o->property("test10").toBool(), true);
535
QCOMPARE(o->property("test11").toInt(), 0);
536
QCOMPARE(o->property("test12").toBool(), true);
541
void tst_v4::mathCeil()
543
QQmlComponent component(&engine, testFileUrl("mathCeil.qml"));
545
QObject *o = component.create();
548
QCOMPARE(o->property("test1").toReal(), qreal(-3));
549
QCOMPARE(o->property("test2").toReal(), qreal(5));
550
QCOMPARE(o->property("test3").toBool(), true);
551
QCOMPARE(o->property("test4").toBool(), true);
552
QCOMPARE(o->property("test5").toBool(), true);
553
QCOMPARE(o->property("test6").toReal(), qreal(83));
554
QCOMPARE(o->property("test7").toBool(), true);
555
QCOMPARE(o->property("test8").toBool(), true);
556
QCOMPARE(o->property("test9").toInt(), 0);
557
QCOMPARE(o->property("test10").toBool(), true);
558
QCOMPARE(o->property("test11").toBool(), true);
563
void tst_v4::mathFloor()
565
QQmlComponent component(&engine, testFileUrl("mathFloor.qml"));
567
QObject *o = component.create();
570
QCOMPARE(o->property("test1").toReal(), qreal(-4));
571
QCOMPARE(o->property("test2").toReal(), qreal(4));
572
QCOMPARE(o->property("test3").toBool(), true);
573
QCOMPARE(o->property("test4").toBool(), true);
574
QCOMPARE(o->property("test5").toBool(), true);
575
QCOMPARE(o->property("test6").toReal(), qreal(82));
576
QCOMPARE(o->property("test7").toBool(), true);
577
QCOMPARE(o->property("test8").toBool(), true);
578
QCOMPARE(o->property("test9").toInt(), 0);
579
QCOMPARE(o->property("test10").toBool(), true);
584
void tst_v4::mathMax()
586
QQmlComponent component(&engine, testFileUrl("mathMax.qml"));
588
QObject *o = component.create();
591
QCOMPARE(o->property("test1").toReal(), qreal(4.4));
592
QCOMPARE(o->property("test2").toReal(), qreal(7));
593
QCOMPARE(o->property("test3").toBool(), true);
594
QCOMPARE(o->property("test4").toBool(), true);
595
QCOMPARE(o->property("test5").toBool(), true);
596
QCOMPARE(o->property("test6").toReal(), qreal(82.6));
597
QCOMPARE(o->property("test7").toReal(), qreal(4.4));
598
QCOMPARE(o->property("test8").toBool(), true);
599
QCOMPARE(o->property("test9").toBool(), true);
600
QCOMPARE(o->property("test10").toBool(), true);
601
QCOMPARE(o->property("test11").toReal(), qreal(0));
602
QCOMPARE(o->property("test12").toReal(), qreal(4.4));
603
QCOMPARE(o->property("test13").toReal(), qreal(7));
608
void tst_v4::mathMin()
610
QQmlComponent component(&engine, testFileUrl("mathMin.qml"));
612
QObject *o = component.create();
615
QCOMPARE(o->property("test1").toReal(), qreal(-3.7));
616
QCOMPARE(o->property("test2").toReal(), qreal(4.4));
617
QCOMPARE(o->property("test3").toBool(), true);
618
QCOMPARE(o->property("test4").toBool(), true);
619
QCOMPARE(o->property("test5").toBool(), true);
620
QCOMPARE(o->property("test6").toReal(), qreal(82.6));
621
QCOMPARE(o->property("test7").toBool(), true);
622
QCOMPARE(o->property("test8").toReal(), qreal(4.4));
623
QCOMPARE(o->property("test9").toBool(), true);
624
QCOMPARE(o->property("test10").toBool(), true);
625
QCOMPARE(o->property("test11").toReal(), qreal(-3.7));
626
QCOMPARE(o->property("test12").toReal(), qreal(0));
627
QCOMPARE(o->property("test13").toReal(), qreal(-3.7));
631
static bool fuzzyCompare(qreal a, qreal b)
633
const qreal EPSILON = 0.0001;
634
return (a + EPSILON > b) && (a - EPSILON < b);
637
void tst_v4::mathCos()
639
QQmlComponent component(&engine, testFileUrl("mathCos.qml"));
641
QObject *o = component.create();
644
QVERIFY(fuzzyCompare(o->property("test1").toReal(), qreal(-0.848100)));
645
QVERIFY(fuzzyCompare(o->property("test2").toReal(), qreal(-0.307333)));
646
QCOMPARE(o->property("test3").toBool(), true);
647
QCOMPARE(o->property("test4").toBool(), true);
648
QCOMPARE(o->property("test5").toBool(), true);
649
QVERIFY(fuzzyCompare(o->property("test6").toReal(), qreal(0.606941)));
650
QCOMPARE(o->property("test7").toBool(), true);
651
QCOMPARE(o->property("test8").toBool(), true);
652
QCOMPARE(o->property("test9").toBool(), true);
653
QCOMPARE(o->property("test10").toBool(), true);
654
QVERIFY(fuzzyCompare(o->property("test11").toReal(), qreal(0.890792)));
659
void tst_v4::mathSin()
661
QQmlComponent component(&engine, testFileUrl("mathSin.qml"));
663
QObject *o = component.create();
666
QVERIFY(fuzzyCompare(o->property("test1").toReal(), qreal(0.529836)));
667
QVERIFY(fuzzyCompare(o->property("test2").toReal(), qreal(-0.951602)));
668
QCOMPARE(o->property("test3").toBool(), true);
669
QCOMPARE(o->property("test4").toBool(), true);
670
QCOMPARE(o->property("test5").toBool(), true);
671
QVERIFY(fuzzyCompare(o->property("test6").toReal(), qreal(0.794747)));
672
QCOMPARE(o->property("test7").toBool(), true);
673
QCOMPARE(o->property("test8").toBool(), true);
674
QCOMPARE(o->property("test9").toBool(), true);
675
QCOMPARE(o->property("test10").toBool(), true);
676
QVERIFY(fuzzyCompare(o->property("test11").toReal(), qreal(0.454411)));
681
void tst_v4::integerOperations()
683
QQmlComponent component(&engine, testFileUrl("integerOperations.qml"));
685
QObject *o = component.create();
688
QCOMPARE(o->property("testa1").toInt(), 333);
689
QCOMPARE(o->property("testa2").toInt(), -666);
691
QCOMPARE(o->property("testb1").toInt(), 0);
692
QCOMPARE(o->property("testb2").toInt(), 2);
693
QCOMPARE(o->property("testb3").toInt(), 0);
694
QCOMPARE(o->property("testb4").toInt(), 2);
695
QCOMPARE(o->property("testb5").toInt(), 0);
696
QCOMPARE(o->property("testb6").toInt(), 2);
697
QCOMPARE(o->property("testb7").toInt(), 0);
698
QCOMPARE(o->property("testb8").toInt(), 2);
700
QCOMPARE(o->property("testc1").toInt(), 335);
701
QCOMPARE(o->property("testc2").toInt(), -666);
702
QCOMPARE(o->property("testc3").toInt(), 335);
703
QCOMPARE(o->property("testc4").toInt(), -666);
704
QCOMPARE(o->property("testc5").toInt(), 335);
705
QCOMPARE(o->property("testc6").toInt(), -666);
706
QCOMPARE(o->property("testc7").toInt(), 335);
707
QCOMPARE(o->property("testc8").toInt(), -666);
709
QCOMPARE(o->property("testd1").toInt(), 330);
710
QCOMPARE(o->property("testd2").toInt(), 330);
711
QCOMPARE(o->property("testd3").toInt(), 330);
712
QCOMPARE(o->property("testd4").toInt(), 330);
714
QCOMPARE(o->property("teste1").toInt(), 28);
715
QCOMPARE(o->property("teste2").toInt(), -28);
716
QCOMPARE(o->property("teste3").toInt(), 256);
717
QCOMPARE(o->property("teste4").toInt(), 28);
718
QCOMPARE(o->property("teste5").toInt(), -28);
719
QCOMPARE(o->property("teste6").toInt(), 256);
721
QCOMPARE(o->property("testf1").toInt(), 1);
722
QCOMPARE(o->property("testf2").toInt(), -2);
723
QCOMPARE(o->property("testf3").toInt(), 0);
724
QCOMPARE(o->property("testf4").toInt(), 1);
725
QCOMPARE(o->property("testf5").toInt(), -2);
726
QCOMPARE(o->property("testf6").toInt(), 0);
728
QCOMPARE(o->property("testg1").toInt(), 1);
729
QCOMPARE(o->property("testg2").toInt(), 0x3FFFFFFE);
730
QCOMPARE(o->property("testg3").toInt(), 0);
731
QCOMPARE(o->property("testg4").toInt(), 1);
732
QCOMPARE(o->property("testg5").toInt(), 0x3FFFFFFE);
733
QCOMPARE(o->property("testg6").toInt(), 0);
738
class V4SingletonType : public QObject
741
Q_PROPERTY(int ip READ ip WRITE setIp NOTIFY ipChanged FINAL)
743
V4SingletonType() : m_ip(12) {}
744
~V4SingletonType() {}
746
Q_INVOKABLE int random() { static int prng = 3; prng++; m_ip++; emit ipChanged(); return prng; }
748
int ip() const { return m_ip; }
749
void setIp(int v) { m_ip = v; emit ipChanged(); }
758
static QObject *v4_module_api_factory(QQmlEngine*, QJSEngine*)
760
return new V4SingletonType;
763
void tst_v4::singletonType()
765
// register singleton type, providing typeinfo via template
766
qmlRegisterSingletonType<V4SingletonType>("Qt.test", 1, 0, "V4", v4_module_api_factory);
767
QQmlComponent component(&engine, testFileUrl("singletonType.qml"));
768
QObject *o = component.create();
770
QCOMPARE(o->property("testProp").toInt(), 12);
771
QCOMPARE(o->property("testProp2").toInt(), 2);
772
QMetaObject::invokeMethod(o, "getRandom");
773
QCOMPARE(o->property("testProp").toInt(), 13);
774
QCOMPARE(o->property("testProp2").toInt(), 4);
778
void tst_v4::conversions_data()
780
QTest::addColumn<QUrl>("file");
781
QTest::addColumn<QStringList>("warnings");
782
QTest::addColumn<bool>("boolProp");
783
QTest::addColumn<int>("intProp");
784
QTest::addColumn<float>("floatProp");
785
QTest::addColumn<double>("doubleProp");
786
QTest::addColumn<qreal>("qrealProp");
787
QTest::addColumn<QString>("qstringProp");
788
QTest::addColumn<QUrl>("qurlProp");
789
QTest::addColumn<QVector3D>("vec3Prop");
791
QTest::newRow("from bool") << testFileUrl("conversions.1.qml")
792
<< (QStringList() << (testFileUrl("conversions.1.qml").toString() + QLatin1String(":11:15: Unable to assign bool to QUrl")))
798
<< QString(QLatin1String("true"))
799
<< QUrl() // cannot assign bool to url.
800
<< QVector3D(1, 1, 1);
802
QTest::newRow("from integer") << testFileUrl("conversions.2.qml")
803
<< (QStringList() << (testFileUrl("conversions.2.qml").toString() + QLatin1String(":11:15: Unable to assign int to QUrl")))
809
<< QString(QLatin1String("4"))
810
<< QUrl() // cannot assign int to url.
811
<< QVector3D(4, 4, 4);
813
QTest::newRow("from float") << testFileUrl("conversions.3.qml")
814
<< (QStringList() << (testFileUrl("conversions.3.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
818
<< (double)((float)4.4)
819
<< (qreal)((float)4.4)
820
<< QString::number((double)((float)4.4), 'g', 16)
821
<< QUrl() // cannot assign number to url.
822
<< QVector3D(4.4, 4.4, 4.4);
824
QTest::newRow("from double") << testFileUrl("conversions.4.qml")
825
<< (QStringList() << (testFileUrl("conversions.4.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
828
<< (float)4.444444444
829
<< (double)4.444444444
830
<< (qreal)4.444444444
831
<< QString::number((double)4.444444444, 'g', 16)
832
<< QUrl() // cannot assign number to url.
833
<< QVector3D(4.444444444, 4.444444444, 4.444444444);
835
QTest::newRow("from qreal") << testFileUrl("conversions.5.qml")
836
<< (QStringList() << (testFileUrl("conversions.5.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
842
<< QString(QLatin1String("4.44"))
843
<< QUrl() // cannot assign number to url.
844
<< QVector3D(4.44, 4.44, 4.44);
846
QTest::newRow("from string") << testFileUrl("conversions.6.qml")
853
<< QString(QLatin1String("4"))
854
<< QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
855
<< QVector3D(4, 4, 4);
857
QTest::newRow("from url") << testFileUrl("conversions.7.qml")
858
<< (QStringList() << (testFileUrl("conversions.7.qml").toString() + QLatin1String(":6:14: Unable to assign QUrl to int"))
859
<< (testFileUrl("conversions.7.qml").toString() + QLatin1String(":7:16: Unable to assign QUrl to number"))
860
<< (testFileUrl("conversions.7.qml").toString() + QLatin1String(":8:17: Unable to assign QUrl to number"))
861
<< (testFileUrl("conversions.7.qml").toString() + QLatin1String(":9:16: Unable to assign QUrl to number")))
867
<< QString(testFileUrl("").toString() + QString(QLatin1String("4")))
868
<< QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
869
<< QVector3D(qQNaN(), qQNaN(), qQNaN());
871
QTest::newRow("from vector") << testFileUrl("conversions.8.qml")
872
<< (QStringList() << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":11: Unable to assign QVector3D to QUrl"))
873
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":10: Unable to assign QVector3D to QString"))
874
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":9: Unable to assign QVector3D to double"))
875
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":8: Unable to assign QVector3D to double"))
876
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":7: Unable to assign QVector3D to float"))
877
<< (testFileUrl("conversions.8.qml").toString() + QLatin1String(":6: Unable to assign QVector3D to int")))
878
<< true // non-null therefore true
879
<< (int)0 // the other values should be the default-ctor values.
885
<< QVector3D(4, 4, 4); // except this one.
888
#define COMPARE_NUMBER(type, prop, expected) \
889
if (qIsNaN(expected)) \
890
QVERIFY(qIsNaN(qvariant_cast<type>(prop))); \
892
QCOMPARE((prop), QVariant::fromValue<type>(expected));
894
void tst_v4::conversions()
897
QFETCH(QStringList, warnings);
898
QFETCH(bool, boolProp);
899
QFETCH(int, intProp);
900
QFETCH(float, floatProp);
901
QFETCH(double, doubleProp);
902
QFETCH(qreal, qrealProp);
903
QFETCH(QString, qstringProp);
904
QFETCH(QUrl, qurlProp);
905
QFETCH(QVector3D, vec3Prop);
907
foreach (const QString &w, warnings)
908
QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
910
QQmlComponent component(&engine, file);
911
QObject *o = component.create();
913
QCOMPARE(o->property("boolProp"), QVariant::fromValue<bool>(boolProp));
914
QCOMPARE(o->property("intProp"), QVariant::fromValue<int>(intProp));
915
COMPARE_NUMBER(float, o->property("floatProp"), floatProp);
916
COMPARE_NUMBER(double, o->property("doubleProp"), doubleProp);
917
COMPARE_NUMBER(qreal, o->property("qrealProp"), qrealProp);
918
QCOMPARE(o->property("qstringProp"), QVariant::fromValue<QString>(qstringProp));
919
QCOMPARE(o->property("qurlProp"), QVariant::fromValue<QUrl>(qurlProp));
921
QVector3D vec3 = qvariant_cast<QVector3D>(o->property("vec3Prop"));
922
COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.x()), vec3Prop.x());
923
COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.y()), vec3Prop.y());
924
COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.z()), vec3Prop.z());
928
void tst_v4::subscriptions()
931
QQmlComponent component(&engine, testFileUrl("subscriptions.1.qml"));
933
QObject *o = component.create();
936
QObject *ro = qobject_cast<QObject *>(o);
939
QCOMPARE(ro->property("targetHeight"), QVariant::fromValue<qreal>(201));
945
static QByteArray getAddress(int address)
947
return QByteArray::number(address);
950
static QByteArray getLeading(int address)
954
leading = getAddress(address);
955
leading.prepend(QByteArray(8 - leading.count(), ' '));
960
#include <private/qv4instruction_p.h>
961
void tst_v4::debuggingDumpInstructions()
963
QStringList expectedPreAddress;
964
expectedPreAddress << "\t\tNoop";
965
expectedPreAddress << "\t0:0:";
966
expectedPreAddress << "\t\tSubscribeId\t\tId_Offset(0) -> Subscribe_Slot(0)";
967
expectedPreAddress << "\t\tFetchAndSubscribe\tObject_Reg(0) Fast_Accessor(0x0) -> Output_Reg(0) Subscription_Slot(0)";
968
expectedPreAddress << "\t\tLoadId\t\t\tId_Offset(0) -> Output_Reg(0)";
969
expectedPreAddress << "\t\tLoadScope\t\t-> Output_Reg(0)";
970
expectedPreAddress << "\t\tLoadRoot\t\t-> Output_Reg(0)";
971
expectedPreAddress << "\t\tLoadSingletonObject\t\t) -> Output_Reg(0)";
972
expectedPreAddress << "\t\tLoadAttached\t\tObject_Reg(0) Attached_Index(0) -> Output_Reg(0)";
973
expectedPreAddress << "\t\tUnaryNot\t\tInput_Reg(0) -> Output_Reg(0)";
974
expectedPreAddress << "\t\tUnaryMinusNumber\t\tInput_Reg(0) -> Output_Reg(0)";
975
expectedPreAddress << "\t\tUnaryMinusInt\t\tInput_Reg(0) -> Output_Reg(0)";
976
expectedPreAddress << "\t\tUnaryPlusNumber\t\tInput_Reg(0) -> Output_Reg(0)";
977
expectedPreAddress << "\t\tUnaryPlusInt\t\tInput_Reg(0) -> Output_Reg(0)";
978
expectedPreAddress << "\t\tConvertBoolToInt\tInput_Reg(0) -> Output_Reg(0)";
979
expectedPreAddress << "\t\tConvertBoolToJSValue\tInput_Reg(0) -> Output_Reg(0)";
980
expectedPreAddress << "\t\tConvertBoolToNumber\tInput_Reg(0) -> Output_Reg(0)";
981
expectedPreAddress << "\t\tConvertBoolToString\tInput_Reg(0) -> Output_Reg(0)";
982
expectedPreAddress << "\t\tConvertBoolToVariant\tInput_Reg(0) -> Output_Reg(0)";
983
expectedPreAddress << "\t\tConvertBoolToVar\tInput_Reg(0) -> Output_Reg(0)";
984
expectedPreAddress << "\t\tConvertIntToBool\tInput_Reg(0) -> Output_Reg(0)";
985
expectedPreAddress << "\t\tConvertIntToJSValue\tInput_Reg(0) -> Output_Reg(0)";
986
expectedPreAddress << "\t\tConvertIntToNumber\tInput_Reg(0) -> Output_Reg(0)";
987
expectedPreAddress << "\t\tConvertIntToString\tInput_Reg(0) -> Output_Reg(0)";
988
expectedPreAddress << "\t\tConvertIntToVariant\tInput_Reg(0) -> Output_Reg(0)";
989
expectedPreAddress << "\t\tConvertIntToVar\tInput_Reg(0) -> Output_Reg(0)";
990
expectedPreAddress << "\t\tConvertJSValueToVar\tInput_Reg(0) -> Output_Reg(0)";
991
expectedPreAddress << "\t\tConvertNumberToBool\tInput_Reg(0) -> Output_Reg(0)";
992
expectedPreAddress << "\t\tConvertNumberToInt\tInput_Reg(0) -> Output_Reg(0)";
993
expectedPreAddress << "\t\tConvertNumberToJSValue\tInput_Reg(0) -> Output_Reg(0)";
994
expectedPreAddress << "\t\tConvertNumberToString\tInput_Reg(0) -> Output_Reg(0)";
995
expectedPreAddress << "\t\tConvertNumberToVariant\tInput_Reg(0) -> Output_Reg(0)";
996
expectedPreAddress << "\t\tConvertNumberToVar\tInput_Reg(0) -> Output_Reg(0)";
997
expectedPreAddress << "\t\tConvertStringToBool\tInput_Reg(0) -> Output_Reg(0)";
998
expectedPreAddress << "\t\tConvertStringToInt\tInput_Reg(0) -> Output_Reg(0)";
999
expectedPreAddress << "\t\tConvertStringToJSValue\tInput_Reg(0) -> Output_Reg(0)";
1000
expectedPreAddress << "\t\tConvertStringToNumber\tInput_Reg(0) -> Output_Reg(0)";
1001
expectedPreAddress << "\t\tConvertStringToUrl\tInput_Reg(0) -> Output_Reg(0)";
1002
expectedPreAddress << "\t\tConvertStringToColor\tInput_Reg(0) -> Output_Reg(0)";
1003
expectedPreAddress << "\t\tConvertStringToVariant\tInput_Reg(0) -> Output_Reg(0)";
1004
expectedPreAddress << "\t\tConvertStringToVar\tInput_Reg(0) -> Output_Reg(0)";
1005
expectedPreAddress << "\t\tConvertUrlToBool\tInput_Reg(0) -> Output_Reg(0)";
1006
expectedPreAddress << "\t\tConvertUrlToJSValue\tInput_Reg(0) -> Output_Reg(0)";
1007
expectedPreAddress << "\t\tConvertUrlToString\tInput_Reg(0) -> Output_Reg(0)";
1008
expectedPreAddress << "\t\tConvertUrlToVariant\tInput_Reg(0) -> Output_Reg(0)";
1009
expectedPreAddress << "\t\tConvertUrlToVar\tInput_Reg(0) -> Output_Reg(0)";
1010
expectedPreAddress << "\t\tConvertColorToBool\tInput_Reg(0) -> Output_Reg(0)";
1011
expectedPreAddress << "\t\tConvertColorToJSValue\tInput_Reg(0) -> Output_Reg(0)";
1012
expectedPreAddress << "\t\tConvertColorToString\tInput_Reg(0) -> Output_Reg(0)";
1013
expectedPreAddress << "\t\tConvertColorToVariant\tInput_Reg(0) -> Output_Reg(0)";
1014
expectedPreAddress << "\t\tConvertColorToVar\tInput_Reg(0) -> Output_Reg(0)";
1015
expectedPreAddress << "\t\tConvertObjectToBool\tInput_Reg(0) -> Output_Reg(0)";
1016
expectedPreAddress << "\t\tConvertObjectToJSValue\tInput_Reg(0) -> Output_Reg(0)";
1017
expectedPreAddress << "\t\tConvertObjectToVariant\tInput_Reg(0) -> Output_Reg(0)";
1018
expectedPreAddress << "\t\tConvertObjectToVar\tInput_Reg(0) -> Output_Reg(0)";
1019
expectedPreAddress << "\t\tConvertVarToJSValue\tInput_Reg(0) -> Output_Reg(0)";
1020
expectedPreAddress << "\t\tConvertNullToJSValue\tInput_Reg(0) -> Output_Reg(0)";
1021
expectedPreAddress << "\t\tConvertNullToObject\tInput_Reg(0) -> Output_Reg(0)";
1022
expectedPreAddress << "\t\tConvertNullToVariant\tInput_Reg(0) -> Output_Reg(0)";
1023
expectedPreAddress << "\t\tConvertNullToVar\tInput_Reg(0) -> Output_Reg(0)";
1024
expectedPreAddress << "\t\tResolveUrl\t\tInput_Reg(0) -> Output_Reg(0)";
1025
expectedPreAddress << "\t\tMathSinNumber\t\tInput_Reg(0) -> Output_Reg(0)";
1026
expectedPreAddress << "\t\tMathCosNumber\t\tInput_Reg(0) -> Output_Reg(0)";
1027
expectedPreAddress << "\t\tMathAbsNumber\t\tInput_Reg(0) -> Output_Reg(0)";
1028
expectedPreAddress << "\t\tMathRoundNumber\t\tInput_Reg(0) -> Output_Reg(0)";
1029
expectedPreAddress << "\t\tMathFloorNumber\t\tInput_Reg(0) -> Output_Reg(0)";
1030
expectedPreAddress << "\t\tMathCeilNumber\t\tInput_Reg(0) -> Output_Reg(0)";
1031
expectedPreAddress << "\t\tMathPINumber\t\tInput_Reg(0) -> Output_Reg(0)";
1032
expectedPreAddress << "\t\tLoadNull\t\tConstant(null) -> Output_Reg(0)";
1033
expectedPreAddress << "\t\tLoadNumber\t\tConstant(0) -> Output_Reg(0)";
1034
expectedPreAddress << "\t\tLoadInt\t\t\tConstant(0) -> Output_Reg(0)";
1035
expectedPreAddress << "\t\tLoadBool\t\tConstant(false) -> Output_Reg(0)";
1036
expectedPreAddress << "\t\tLoadString\t\tString_DataIndex(0) String_Length(0) -> Output_Register(0)";
1037
expectedPreAddress << "\t\tEnableV4Test\t\tString_DataIndex(0) String_Length(0)";
1038
expectedPreAddress << "\t\tTestV4Store\t\tInput_Reg(0) Reg_Type(0)";
1039
expectedPreAddress << "\t\tBitAndInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1040
expectedPreAddress << "\t\tBitOrInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1041
expectedPreAddress << "\t\tBitXorInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1042
expectedPreAddress << "\t\tAddNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1043
expectedPreAddress << "\t\tAddString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1044
expectedPreAddress << "\t\tSubNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1045
expectedPreAddress << "\t\tMulNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1046
expectedPreAddress << "\t\tDivNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1047
expectedPreAddress << "\t\tModNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1048
expectedPreAddress << "\t\tLShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1049
expectedPreAddress << "\t\tRShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1050
expectedPreAddress << "\t\tURShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1051
expectedPreAddress << "\t\tGtNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1052
expectedPreAddress << "\t\tLtNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1053
expectedPreAddress << "\t\tGeNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1054
expectedPreAddress << "\t\tLeNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1055
expectedPreAddress << "\t\tEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1056
expectedPreAddress << "\t\tNotEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1057
expectedPreAddress << "\t\tStrictEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1058
expectedPreAddress << "\t\tStrictNotEqualNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1059
expectedPreAddress << "\t\tGtString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1060
expectedPreAddress << "\t\tLtString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1061
expectedPreAddress << "\t\tGeString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1062
expectedPreAddress << "\t\tLeString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1063
expectedPreAddress << "\t\tEqualString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1064
expectedPreAddress << "\t\tNotEqualString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1065
expectedPreAddress << "\t\tStrictEqualString\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1066
expectedPreAddress << "\t\tStrictNotEqualString\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1067
expectedPreAddress << "\t\tEqualObject\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1068
expectedPreAddress << "\t\tNotEqualObject\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1069
expectedPreAddress << "\t\tStrictEqualObject\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1070
expectedPreAddress << "\t\tStrictNotEqualObject\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1071
expectedPreAddress << "\t\tMathMaxNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1072
expectedPreAddress << "\t\tMathMinNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
1073
expectedPreAddress << "\t\tNewString\t\tRegister(0)";
1074
expectedPreAddress << "\t\tNewUrl\t\t\tRegister(0)";
1075
expectedPreAddress << "\t\tCleanupRegister\t\tRegister(0)";
1076
expectedPreAddress << "\t\tCopy\t\t\tInput_Reg(0) -> Output_Reg(0)";
1077
expectedPreAddress << "\t\tFetch\t\t\tObject_Reg(0) Property_Index(0) -> Output_Reg(0)";
1078
expectedPreAddress << "\t\tStore\t\t\tInput_Reg(0) -> Object_Reg(0) Property_Index(0)";
1079
expectedPreAddress << "\t\tJump\t\t\tAddress(UNIT_TEST_JUMP_ADDRESS) [if false == Input_Reg(0)]"; //(address + size() + i->jump.count)
1080
expectedPreAddress << "\t\tBranchTrue\t\tAddress(UNIT_TEST_BRANCH_ADDRESS) [if true == Input_Reg(0)]"; //(address + size() + i->branchop.offset)
1081
expectedPreAddress << "\t\tBranchFalse\t\tAddress(UNIT_TEST_BRANCH_ADDRESS) [if false == Input_Reg(0)]"; //(address + size() + i->branchop.offset)
1082
expectedPreAddress << "\t\tBranch\t\t\tAddress(UNIT_TEST_BRANCH_ADDRESS)"; //(address + size() + i->branchop.offset)
1083
expectedPreAddress << "\t\tBlock\t\t\tMask(0)";
1084
expectedPreAddress << "\t\tThrow\t\t\tInputReg(0)";
1085
expectedPreAddress << "\t\tInitString\t\tString_DataIndex(0) -> String_Slot(0)";
1086
QStringList expected;
1088
QQmlTestMessageHandler messageHandler;
1090
QQmlJS::Bytecode bc;
1091
#define DUMP_INSTR_IN_UNIT_TEST(I, FMT) { QQmlJS::V4InstrData<QQmlJS::V4Instr::I> i; memset(&i, 0, sizeof(i)); bc.append(i); }
1092
FOR_EACH_V4_INSTR(DUMP_INSTR_IN_UNIT_TEST);
1093
#undef DUMP_INSTR_IN_UNIT_TEST // NOTE: we memset in order to ensure stable output.
1094
const char *start = bc.constData();
1095
const char *end = start + bc.size();
1096
const char *codeAddr = start;
1097
int whichExpected = 0;
1098
#define DUMP_INSTR_SIZE_IN_UNIT_TEST(I, FMT) { \
1099
QString currExpected = whichExpected < expectedPreAddress.size() ? expectedPreAddress.at(whichExpected++) : QString(); \
1100
currExpected.prepend(getLeading(codeAddr - start)); \
1101
expected.append(currExpected); \
1102
codeAddr += QQmlJS::V4Instr::size(static_cast<QQmlJS::V4Instr::Type>(QQmlJS::V4Instr::I)); \
1104
FOR_EACH_V4_INSTR(DUMP_INSTR_SIZE_IN_UNIT_TEST);
1105
#undef DUMP_INSTR_SIZE_IN_UNIT_TEST // so that we generate the correct address for each instruction comparison
1106
bc.dump(start, end);
1108
// ensure that the output was expected.
1109
const int messageCount = messageHandler.messages().count();
1110
QCOMPARE(messageCount, expected.count());
1111
for (int ii = 0; ii < messageCount; ++ii) {
1112
// Calculating the destination address of a null jump/branch instruction is tricky
1113
// so instead we simply don't compare that part of those instructions.
1114
QRegExp ignoreAddress("\\bAddress\\((\\w*)\\)");
1115
ignoreAddress.setMinimal(true);
1116
QString expectOut = expected.at(ii); expectOut.replace(ignoreAddress, "");
1117
QString actualOut = messageHandler.messages().at(ii); actualOut.replace(ignoreAddress, "");
1118
QCOMPARE(actualOut, expectOut);
1125
#include "tst_v4.moc"