~loic.molinari/+junk/qtdeclarative-shadereffectsource-changes

« back to all changes in this revision

Viewing changes to tests/auto/qml/v4/tst_v4.cpp

  • Committer: Loïc Molinari
  • Date: 2012-04-21 17:59:51 UTC
  • Revision ID: loic.molinari@canonical.com-20120421175951-bqx68caaf5zrp76l
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include <QtCore/qnumeric.h>
 
50
 
 
51
#include <private/qv4compiler_p.h>
 
52
 
 
53
#include "../../shared/util.h"
 
54
#include "testtypes.h"
 
55
 
 
56
class tst_v4 : public QQmlDataTest
 
57
{
 
58
    Q_OBJECT
 
59
public:
 
60
    tst_v4() {}
 
61
 
 
62
private slots:
 
63
    void initTestCase();
 
64
 
 
65
    void unnecessaryReeval();
 
66
    void logicalOr();
 
67
    void nestedLogicalOr();
 
68
    void logicalAnd();
 
69
    void nestedLogicalAnd();
 
70
    void conditionalExpr();
 
71
    void qtscript();
 
72
    void qtscript_data();
 
73
    void nestedObjectAccess();
 
74
    void subscriptionsInConditionalExpressions();
 
75
    void qtbug_21883();
 
76
    void qtbug_22816();
 
77
    void stringComparison();
 
78
    void unaryMinus();
 
79
    void unaryPlus();
 
80
    void colorType();
 
81
    void mathAbs();
 
82
    void mathCeil();
 
83
    void mathMax();
 
84
    void mathMin();
 
85
    void moduleApi();
 
86
 
 
87
    void conversions_data();
 
88
    void conversions();
 
89
    void subscriptions();
 
90
 
 
91
    void debuggingDumpInstructions(); // this test should be last.
 
92
 
 
93
private:
 
94
    QQmlEngine engine;
 
95
};
 
96
 
 
97
void tst_v4::initTestCase()
 
98
{
 
99
    QQmlDataTest::initTestCase();
 
100
    registerTypes();
 
101
}
 
102
 
 
103
static int v4ErrorsMsgCount = 0;
 
104
static void v4ErrorsMsgHandler(QtMsgType, const char *message)
 
105
{
 
106
    QByteArray m(message);
 
107
    if (m.contains("QV4"))
 
108
        v4ErrorsMsgCount++;
 
109
}
 
110
 
 
111
void tst_v4::qtscript()
 
112
{
 
113
    QFETCH(QString, file);
 
114
    QV4Compiler::enableBindingsTest(true);
 
115
 
 
116
    QQmlComponent component(&engine, testFileUrl(file));
 
117
 
 
118
    v4ErrorsMsgCount = 0;
 
119
    QtMsgHandler old = qInstallMsgHandler(v4ErrorsMsgHandler);
 
120
 
 
121
    QObject *o = component.create();
 
122
    delete o;
 
123
 
 
124
    qInstallMsgHandler(old);
 
125
 
 
126
    QCOMPARE(v4ErrorsMsgCount, 0);
 
127
 
 
128
    QV4Compiler::enableBindingsTest(false);
 
129
}
 
130
 
 
131
void tst_v4::qtscript_data()
 
132
{
 
133
    QTest::addColumn<QString>("file");
 
134
 
 
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";
 
154
}
 
155
 
 
156
void tst_v4::unnecessaryReeval()
 
157
{
 
158
    QQmlComponent component(&engine, testFileUrl("unnecessaryReeval.qml"));
 
159
 
 
160
    QObject *o = component.create();
 
161
    QVERIFY(o != 0);
 
162
 
 
163
    ResultObject *ro = qobject_cast<ResultObject *>(o);
 
164
    QVERIFY(ro != 0);
 
165
 
 
166
    QCOMPARE(ro->resultCounter(),  1);
 
167
    QCOMPARE(ro->result(), 19);
 
168
    ro->resetResultCounter();
 
169
 
 
170
    ro->setProperty("b", 6);
 
171
 
 
172
    QCOMPARE(ro->resultCounter(),  1);
 
173
    QCOMPARE(ro->result(), 6);
 
174
    ro->resetResultCounter();
 
175
 
 
176
    ro->setProperty("a", 14);
 
177
 
 
178
    QCOMPARE(ro->resultCounter(),  1);
 
179
    QCOMPARE(ro->result(), 7);
 
180
    ro->resetResultCounter();
 
181
 
 
182
    ro->setProperty("b", 14);
 
183
    QCOMPARE(ro->resultCounter(),  0);
 
184
    QCOMPARE(ro->result(), 7);
 
185
 
 
186
    delete o;
 
187
}
 
188
 
 
189
void tst_v4::logicalOr()
 
190
{
 
191
    {
 
192
        QQmlComponent component(&engine, testFileUrl("logicalOr.qml"));
 
193
 
 
194
        QObject *o = component.create();
 
195
        QVERIFY(o != 0);
 
196
 
 
197
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
198
        QVERIFY(ro != 0);
 
199
 
 
200
        QCOMPARE(ro->result(), 0);
 
201
        delete o;
 
202
    }
 
203
 
 
204
    {
 
205
        QQmlComponent component(&engine, testFileUrl("logicalOr.2.qml"));
 
206
 
 
207
        QObject *o = component.create();
 
208
        QVERIFY(o != 0);
 
209
 
 
210
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
211
        QVERIFY(ro != 0);
 
212
 
 
213
        QCOMPARE(ro->result(), 1);
 
214
        delete o;
 
215
    }
 
216
}
 
217
 
 
218
void tst_v4::nestedLogicalOr()
 
219
{
 
220
    //we are primarily testing that v4 does not get caught in a loop (QTBUG-24038)
 
221
    QQmlComponent component(&engine, testFileUrl("nestedLogicalOr.qml"));
 
222
 
 
223
    QObject *o = component.create();
 
224
    QVERIFY(o != 0);
 
225
 
 
226
    ResultObject *ro = qobject_cast<ResultObject *>(o);
 
227
    QVERIFY(ro != 0);
 
228
 
 
229
    QCOMPARE(ro->result(), 1);
 
230
    delete o;
 
231
}
 
232
 
 
233
void tst_v4::logicalAnd()
 
234
{
 
235
    {
 
236
        QQmlComponent component(&engine, testFileUrl("logicalAnd.qml"));
 
237
 
 
238
        QObject *o = component.create();
 
239
        QVERIFY(o != 0);
 
240
 
 
241
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
242
        QVERIFY(ro != 0);
 
243
 
 
244
        QCOMPARE(ro->result(), 0);
 
245
        delete o;
 
246
    }
 
247
 
 
248
    {
 
249
        QQmlComponent component(&engine, testFileUrl("logicalAnd.2.qml"));
 
250
 
 
251
        QObject *o = component.create();
 
252
        QVERIFY(o != 0);
 
253
 
 
254
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
255
        QVERIFY(ro != 0);
 
256
 
 
257
        QCOMPARE(ro->result(), 1);
 
258
        delete o;
 
259
    }
 
260
 
 
261
    {
 
262
        QQmlComponent component(&engine, testFileUrl("logicalAnd.3.qml"));
 
263
 
 
264
        QObject *o = component.create();
 
265
        QVERIFY(o != 0);
 
266
 
 
267
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
268
        QVERIFY(ro != 0);
 
269
 
 
270
        QCOMPARE(ro->result(), 1);
 
271
        delete o;
 
272
    }
 
273
 
 
274
    {
 
275
        // QTBUG-24660
 
276
        QQmlComponent component(&engine, testFileUrl("logicalAnd.4.qml"));
 
277
 
 
278
        QObject *o = component.create();
 
279
        QVERIFY(o != 0);
 
280
 
 
281
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
282
        QVERIFY(ro != 0);
 
283
 
 
284
        QCOMPARE(ro->result(), 1);
 
285
        delete o;
 
286
    }
 
287
 
 
288
    {
 
289
        QQmlComponent component(&engine, testFileUrl("logicalAnd.5.qml"));
 
290
 
 
291
        QObject *o = component.create();
 
292
        QVERIFY(o != 0);
 
293
 
 
294
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
295
        QVERIFY(ro != 0);
 
296
 
 
297
        QCOMPARE(ro->result(), 1);
 
298
        delete o;
 
299
    }
 
300
 
 
301
    {
 
302
        QQmlComponent component(&engine, testFileUrl("logicalAnd.6.qml"));
 
303
 
 
304
        QObject *o = component.create();
 
305
        QVERIFY(o != 0);
 
306
 
 
307
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
308
        QVERIFY(ro != 0);
 
309
 
 
310
        QCOMPARE(ro->result(), 1);
 
311
        delete o;
 
312
    }
 
313
 
 
314
    {
 
315
        QQmlComponent component(&engine, testFileUrl("logicalAnd.7.qml"));
 
316
 
 
317
        QObject *o = component.create();
 
318
        QVERIFY(o != 0);
 
319
 
 
320
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
321
        QVERIFY(ro != 0);
 
322
 
 
323
        QCOMPARE(ro->result(), 1);
 
324
        delete o;
 
325
    }
 
326
}
 
327
 
 
328
void tst_v4::nestedLogicalAnd()
 
329
{
 
330
    QQmlComponent component(&engine, testFileUrl("nestedLogicalAnd.qml"));
 
331
 
 
332
    QObject *o = component.create();
 
333
    QVERIFY(o != 0);
 
334
 
 
335
    ResultObject *ro = qobject_cast<ResultObject *>(o);
 
336
    QVERIFY(ro != 0);
 
337
 
 
338
    QCOMPARE(ro->result(), 1);
 
339
    delete o;
 
340
}
 
341
 
 
342
void tst_v4::conditionalExpr()
 
343
{
 
344
    {
 
345
        QQmlComponent component(&engine, testFileUrl("conditionalExpr.qml"));
 
346
 
 
347
        QObject *o = component.create();
 
348
        QVERIFY(o != 0);
 
349
 
 
350
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
351
        QVERIFY(ro != 0);
 
352
 
 
353
        QCOMPARE(ro->result(), 0);
 
354
        delete o;
 
355
    }
 
356
}
 
357
 
 
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()
 
362
{
 
363
    {
 
364
        QQmlComponent component(&engine, testFileUrl("nestedObjectAccess.qml"));
 
365
 
 
366
        QObject *o = component.create();
 
367
        QVERIFY(o != 0);
 
368
 
 
369
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
370
        QVERIFY(ro != 0);
 
371
 
 
372
        QCOMPARE(ro->result(), 37);
 
373
 
 
374
        delete o;
 
375
    }
 
376
 
 
377
    {
 
378
        QQmlComponent component(&engine, testFileUrl("nestedObjectAccess2.qml"));
 
379
 
 
380
        QObject *o = component.create();
 
381
        QVERIFY(o != 0);
 
382
 
 
383
        ResultObject *ro = qobject_cast<ResultObject *>(o);
 
384
        QVERIFY(ro != 0);
 
385
 
 
386
        QCOMPARE(ro->result(), 37);
 
387
 
 
388
        delete o;
 
389
    }
 
390
}
 
391
 
 
392
void tst_v4::subscriptionsInConditionalExpressions()
 
393
{
 
394
    QQmlComponent component(&engine, testFileUrl("subscriptionsInConditionalExpressions.qml"));
 
395
 
 
396
    QObject *o = component.create();
 
397
    QVERIFY(o != 0);
 
398
 
 
399
    QObject *ro = qobject_cast<QObject *>(o);
 
400
    QVERIFY(ro != 0);
 
401
 
 
402
    QCOMPARE(ro->property("result").toReal(), qreal(2));
 
403
 
 
404
    delete o;
 
405
}
 
406
 
 
407
// Crash test
 
408
void tst_v4::qtbug_21883()
 
409
{
 
410
    QQmlComponent component(&engine, testFileUrl("qtbug_21883.qml"));
 
411
 
 
412
    QString warning = component.url().toString() + ":4: Unable to assign null to ResultObject*";
 
413
    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 
414
 
 
415
    QObject *o = component.create();
 
416
    QVERIFY(o != 0);
 
417
    delete o;
 
418
}
 
419
 
 
420
void tst_v4::qtbug_22816()
 
421
{
 
422
    QQmlComponent component(&engine, testFileUrl("qtbug_22816.qml"));
 
423
 
 
424
    QObject *o = component.create();
 
425
    QVERIFY(o != 0);
 
426
    QCOMPARE(o->property("test1").toBool(), false);
 
427
    QCOMPARE(o->property("test2").toBool(), false);
 
428
    delete o;
 
429
}
 
430
 
 
431
void tst_v4::stringComparison()
 
432
{
 
433
    QQmlComponent component(&engine, testFileUrl("stringComparison.qml"));
 
434
 
 
435
    QObject *o = component.create();
 
436
    QVERIFY(o != 0);
 
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);
 
459
    delete o;
 
460
}
 
461
 
 
462
void tst_v4::unaryMinus()
 
463
{
 
464
    QQmlComponent component(&engine, testFileUrl("unaryMinus.qml"));
 
465
 
 
466
    QObject *o = component.create();
 
467
    QVERIFY(o != 0);
 
468
 
 
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);
 
479
 
 
480
    delete o;
 
481
}
 
482
 
 
483
void tst_v4::unaryPlus()
 
484
{
 
485
    QQmlComponent component(&engine, testFileUrl("unaryPlus.qml"));
 
486
 
 
487
    QObject *o = component.create();
 
488
    QVERIFY(o != 0);
 
489
 
 
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);
 
500
 
 
501
    delete o;
 
502
}
 
503
 
 
504
void tst_v4::colorType()
 
505
{
 
506
    QQmlComponent component(&engine, testFileUrl("colorType.qml"));
 
507
 
 
508
    QObject *o = component.create();
 
509
    QVERIFY(o != 0);
 
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);
 
517
    delete o;
 
518
}
 
519
 
 
520
void tst_v4::mathAbs()
 
521
{
 
522
    QQmlComponent component(&engine, testFileUrl("mathAbs.qml"));
 
523
 
 
524
    QObject *o = component.create();
 
525
    QVERIFY(o != 0);
 
526
 
 
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
 
539
 
 
540
    delete o;
 
541
}
 
542
 
 
543
void tst_v4::mathCeil()
 
544
{
 
545
    QQmlComponent component(&engine, testFileUrl("mathCeil.qml"));
 
546
 
 
547
    QObject *o = component.create();
 
548
    QVERIFY(o != 0);
 
549
 
 
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
 
560
 
 
561
    delete o;
 
562
}
 
563
 
 
564
void tst_v4::mathMax()
 
565
{
 
566
    QQmlComponent component(&engine, testFileUrl("mathMax.qml"));
 
567
 
 
568
    QObject *o = component.create();
 
569
    QVERIFY(o != 0);
 
570
 
 
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));
 
583
 
 
584
    delete o;
 
585
}
 
586
 
 
587
void tst_v4::mathMin()
 
588
{
 
589
    QQmlComponent component(&engine, testFileUrl("mathMin.qml"));
 
590
 
 
591
    QObject *o = component.create();
 
592
    QVERIFY(o != 0);
 
593
 
 
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));
 
606
    delete o;
 
607
}
 
608
 
 
609
class V4ModuleApi : public QObject
 
610
{
 
611
    Q_OBJECT
 
612
    Q_PROPERTY(int ip READ ip WRITE setIp NOTIFY ipChanged FINAL)
 
613
public:
 
614
    V4ModuleApi() : m_ip(12) {}
 
615
    ~V4ModuleApi() {}
 
616
 
 
617
    Q_INVOKABLE int random() { static int prng = 3; prng++; m_ip++; emit ipChanged(); return prng; }
 
618
 
 
619
    int ip() const { return m_ip; }
 
620
    void setIp(int v) { m_ip = v; emit ipChanged(); }
 
621
 
 
622
signals:
 
623
    void ipChanged();
 
624
 
 
625
private:
 
626
    int m_ip;
 
627
};
 
628
 
 
629
static QObject *v4_module_api_factory(QQmlEngine*, QJSEngine*)
 
630
{
 
631
    return new V4ModuleApi;
 
632
}
 
633
 
 
634
void tst_v4::moduleApi()
 
635
{
 
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();
 
640
    QVERIFY(o != 0);
 
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);
 
646
    delete o;
 
647
}
 
648
 
 
649
void tst_v4::conversions_data()
 
650
{
 
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");
 
661
 
 
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")))
 
664
            << true
 
665
            << (int)true
 
666
            << (float)1.0
 
667
            << (double)1.0
 
668
            << (qreal)1.0
 
669
            << QString(QLatin1String("true"))
 
670
            << QUrl() // cannot assign bool to url.
 
671
            << QVector3D(1, 1, 1);
 
672
 
 
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")))
 
675
            << (bool)4
 
676
            << 4
 
677
            << (float)4.0
 
678
            << (double)4.0
 
679
            << (qreal)4.0
 
680
            << QString(QLatin1String("4"))
 
681
            << QUrl() // cannot assign int to url.
 
682
            << QVector3D(4, 4, 4);
 
683
 
 
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")))
 
686
            << (bool)4.4
 
687
            << (int)4.4
 
688
            << (float)4.4
 
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);
 
694
 
 
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")))
 
697
            << (bool)4.444444444
 
698
            << (int)4.444444444
 
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);
 
705
 
 
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")))
 
708
            << (bool)4.44
 
709
            << (int)4.44
 
710
            << (float)4.44
 
711
            << (double)4.44
 
712
            << (qreal)4.44
 
713
            << QString(QLatin1String("4.44"))
 
714
            << QUrl() // cannot assign number to url.
 
715
            << QVector3D(4.44, 4.44, 4.44);
 
716
 
 
717
    QTest::newRow("from string") << testFileUrl("conversions.6.qml")
 
718
            << (QStringList())
 
719
            << true
 
720
            << 4
 
721
            << (float)4.0
 
722
            << (double)4.0
 
723
            << (qreal)4.0
 
724
            << QString(QLatin1String("4"))
 
725
            << QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
 
726
            << QVector3D(4, 4, 4);
 
727
 
 
728
    // QTBUG-24706
 
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")))
 
734
            << true
 
735
            << 0
 
736
            << (float) 0
 
737
            << (double) 0
 
738
            << (qreal) 0
 
739
            << QString(testFileUrl("").toString() + QString(QLatin1String("4")))
 
740
            << QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
 
741
            << QVector3D(qQNaN(), qQNaN(), qQNaN());
 
742
 
 
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.
 
752
            << (float)0
 
753
            << (double)0
 
754
            << (qreal)0
 
755
            << QString()
 
756
            << QUrl()
 
757
            << QVector3D(4, 4, 4); // except this one.
 
758
}
 
759
 
 
760
#define COMPARE_NUMBER(type, prop, expected) \
 
761
    if (qIsNaN(expected)) \
 
762
        QVERIFY(qIsNaN(qvariant_cast<type>(prop))); \
 
763
    else \
 
764
        QCOMPARE((prop), QVariant::fromValue<type>(expected));
 
765
 
 
766
void tst_v4::conversions()
 
767
{
 
768
    QFETCH(QUrl, file);
 
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);
 
778
 
 
779
    foreach (const QString &w, warnings)
 
780
        QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
 
781
 
 
782
    QQmlComponent component(&engine, file);
 
783
    QObject *o = component.create();
 
784
    QVERIFY(o != 0);
 
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));
 
792
 
 
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());
 
797
    delete o;
 
798
}
 
799
 
 
800
void tst_v4::subscriptions()
 
801
{
 
802
    {
 
803
        QQmlComponent component(&engine, testFileUrl("subscriptions.1.qml"));
 
804
 
 
805
        QObject *o = component.create();
 
806
        QVERIFY(o != 0);
 
807
 
 
808
        QObject *ro = qobject_cast<QObject *>(o);
 
809
        QVERIFY(ro != 0);
 
810
 
 
811
        QCOMPARE(ro->property("targetHeight"), QVariant::fromValue<qreal>(201));
 
812
 
 
813
        delete o;
 
814
    }
 
815
}
 
816
 
 
817
static QStringList messages;
 
818
static void msgHandler(QtMsgType, const char *msg)
 
819
{
 
820
    messages << QLatin1String(msg);
 
821
}
 
822
 
 
823
static QByteArray getAddress(int address)
 
824
{
 
825
    return QByteArray::number(address);
 
826
}
 
827
 
 
828
static QByteArray getLeading(int address)
 
829
{
 
830
    QByteArray leading;
 
831
    if (address != -1) {
 
832
        leading = getAddress(address);
 
833
        leading.prepend(QByteArray(8 - leading.count(), ' '));
 
834
    }
 
835
    return leading;
 
836
}
 
837
 
 
838
#include <private/qv4instruction_p.h>
 
839
void tst_v4::debuggingDumpInstructions()
 
840
{
 
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;
 
948
 
 
949
    messages = QStringList();
 
950
    QtMsgHandler old = qInstallMsgHandler(msgHandler);
 
951
 
 
952
    QQmlJS::Bytecode bc;
 
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)); \
 
965
        }
 
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
 
968
    bc.dump(start, end);
 
969
 
 
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);
 
981
    }
 
982
}
 
983
 
 
984
 
 
985
QTEST_MAIN(tst_v4)
 
986
 
 
987
#include "tst_v4.moc"