9205f2d7309db01d00065245dcb0543440862b95
[profile/ivi/qtdeclarative.git] / tests / auto / qml / qqmllanguage / tst_qqmllanguage.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QtQml/qqmlengine.h>
43 #include <QtQml/qqmlcomponent.h>
44 #include <QtCore/qcoreapplication.h>
45 #include <QtCore/qfile.h>
46 #include <QtCore/qdebug.h>
47 #include <QtCore/qfileinfo.h>
48 #include <QtCore/qdir.h>
49 #include <QSignalSpy>
50
51 #include <private/qqmlproperty_p.h>
52 #include <private/qqmlmetatype_p.h>
53 #include <private/qqmlglobal_p.h>
54
55 #include "testtypes.h"
56 #include "testhttpserver.h"
57
58 DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
59
60 /*
61     Returns the path to some testdata file or directory.
62 */
63 QString testdata(QString const& name = QString())
64 {
65     static const QString dataDirectory = QDir::currentPath() + QLatin1String("/data");
66     QString result = dataDirectory;
67     if (!name.isEmpty()) {
68         result += QLatin1Char('/');
69         result += name;
70     }
71     return result;
72 }
73
74 /*
75 This test case covers QML language issues.  This covers everything that does not
76 involve evaluating ECMAScript expressions and bindings.
77
78 Evaluation of expressions and bindings is covered in qmlecmascript
79 */
80 class tst_qqmllanguage : public QObject
81 {
82     Q_OBJECT
83 public:
84     tst_qqmllanguage() {
85         QQmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
86         engine.addImportPath(testdata("lib"));
87     }
88
89 private slots:
90     void initTestCase();
91     void cleanupTestCase();
92
93     void errors_data();
94     void errors();
95
96     void insertedSemicolon_data();
97     void insertedSemicolon();
98
99     void simpleObject();
100     void simpleContainer();
101     void interfaceProperty();
102     void interfaceQList();
103     void assignObjectToSignal();
104     void assignObjectToVariant();
105     void assignLiteralSignalProperty();
106     void assignQmlComponent();
107     void assignBasicTypes();
108     void assignTypeExtremes();
109     void assignCompositeToType();
110     void assignLiteralToVariant();
111     void assignLiteralToVar();
112     void assignLiteralToJSValue();
113     void bindJSValueToVar();
114     void bindJSValueToVariant();
115     void bindJSValueToType();
116     void bindTypeToJSValue();
117     void customParserTypes();
118     void rootAsQmlComponent();
119     void inlineQmlComponents();
120     void idProperty();
121     void autoNotifyConnection();
122     void assignSignal();
123     void dynamicProperties();
124     void dynamicPropertiesNested();
125     void listProperties();
126     void dynamicObjectProperties();
127     void dynamicSignalsAndSlots();
128     void simpleBindings();
129     void autoComponentCreation();
130     void propertyValueSource();
131     void attachedProperties();
132     void dynamicObjects();
133     void customVariantTypes();
134     void valueTypes();
135     void cppnamespace();
136     void aliasProperties();
137     void aliasPropertiesAndSignals();
138     void aliasPropertyChangeSignals();
139     void componentCompositeType();
140     void i18n();
141     void i18n_data();
142     void onCompleted();
143     void onDestruction();
144     void scriptString();
145     void defaultPropertyListOrder();
146     void declaredPropertyValues();
147     void dontDoubleCallClassBegin();
148     void reservedWords_data();
149     void reservedWords();
150     void inlineAssignmentsOverrideBindings();
151     void nestedComponentRoots();
152     void registrationOrder();
153     void readonly();
154     void receivers();
155
156     void basicRemote_data();
157     void basicRemote();
158     void importsBuiltin_data();
159     void importsBuiltin();
160     void importsLocal_data();
161     void importsLocal();
162     void importsRemote_data();
163     void importsRemote();
164     void importsInstalled_data();
165     void importsInstalled();
166     void importsOrder_data();
167     void importsOrder();
168     void importIncorrectCase();
169     void importJs_data();
170     void importJs();
171
172     void qmlAttachedPropertiesObjectMethod();
173     void customOnProperty();
174     void variantNotify();
175
176     void revisions();
177     void revisionOverloads();
178
179     void propertyInit();
180     void remoteLoadCrash();
181     void signalWithDefaultArg();
182
183     // regression tests for crashes
184     void crash1();
185     void crash2();
186
187     void globalEnums();
188
189 private:
190     QQmlEngine engine;
191     void testType(const QString& qml, const QString& type, const QString& error, bool partialMatch = false);
192 };
193
194 #define DETERMINE_ERRORS(errorfile,expected,actual)\
195     QList<QByteArray> expected; \
196     QList<QByteArray> actual; \
197     do { \
198         QFile file(testdata(QLatin1String(errorfile))); \
199         QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
200         QByteArray data = file.readAll(); \
201         file.close(); \
202         expected = data.split('\n'); \
203         expected.removeAll(QByteArray("")); \
204         QList<QQmlError> errors = component.errors(); \
205         for (int ii = 0; ii < errors.count(); ++ii) { \
206             const QQmlError &error = errors.at(ii); \
207             QByteArray errorStr = QByteArray::number(error.line()) + ":" +  \
208                                   QByteArray::number(error.column()) + ":" + \
209                                   error.description().toUtf8(); \
210             actual << errorStr; \
211         } \
212     } while (false);
213
214 #define VERIFY_ERRORS(errorfile) \
215     if (!errorfile) { \
216         if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
217             qWarning() << "Unexpected Errors:" << component.errors(); \
218         QVERIFY(!component.isError()); \
219         QVERIFY(component.errors().isEmpty()); \
220     } else { \
221         DETERMINE_ERRORS(errorfile,actual,expected);\
222         if (qgetenv("DEBUG") != "" && expected != actual) \
223             qWarning() << "Expected:" << expected << "Actual:" << actual;  \
224         if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
225             QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
226             QVERIFY(file.open(QIODevice::WriteOnly)); \
227             for (int ii = 0; ii < actual.count(); ++ii) { \
228                 file.write(actual.at(ii)); file.write("\n"); \
229             } \
230             file.close(); \
231         } else { \
232             QCOMPARE(expected, actual); \
233         } \
234     }
235
236 inline QUrl TEST_FILE(const QString &filename)
237 {
238     return QUrl::fromLocalFile(testdata(filename));
239 }
240
241 inline QUrl TEST_FILE(const char *filename)
242 {
243     return TEST_FILE(QLatin1String(filename));
244 }
245
246 void tst_qqmllanguage::cleanupTestCase()
247 {
248     QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()));
249 }
250
251 void tst_qqmllanguage::insertedSemicolon_data()
252 {
253     QTest::addColumn<QString>("file");
254     QTest::addColumn<QString>("errorFile");
255     QTest::addColumn<bool>("create");
256
257     QTest::newRow("insertedSemicolon.1") << "insertedSemicolon.1.qml" << "insertedSemicolon.1.errors.txt" << false;
258 }
259
260 void tst_qqmllanguage::insertedSemicolon()
261 {
262     QFETCH(QString, file);
263     QFETCH(QString, errorFile);
264     QFETCH(bool, create);
265
266     QQmlComponent component(&engine, TEST_FILE(file));
267
268     if(create) {
269         QObject *object = component.create();
270         QVERIFY(object == 0);
271     }
272
273     VERIFY_ERRORS(errorFile.toLatin1().constData());
274 }
275
276 void tst_qqmllanguage::errors_data()
277 {
278     QTest::addColumn<QString>("file");
279     QTest::addColumn<QString>("errorFile");
280     QTest::addColumn<bool>("create");
281
282     QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false;
283     QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false;
284     QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false;
285     QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false;
286     QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false;
287     QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false;
288
289     QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false;
290     QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false;
291     QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false;
292
293     QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false;
294     QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false;
295     QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false;
296     QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false;
297     QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false;
298     QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false;
299     QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false;
300     QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false;
301     QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false;
302     QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false;
303     QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false;
304     QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false;
305     QTest::newRow("wrongType (invalid object)") << "wrongType.16.qml" << "wrongType.16.errors.txt" << false;
306     QTest::newRow("wrongType (int for enum)") << "wrongType.17.qml" << "wrongType.17.errors.txt" << false;
307
308     QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false;
309     QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false;
310     QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false;
311     QTest::newRow("readOnly.4") << "readOnly.4.qml" << "readOnly.4.errors.txt" << false;
312     QTest::newRow("readOnly.5") << "readOnly.5.qml" << "readOnly.5.errors.txt" << false;
313
314     QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false;
315     QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false;
316     QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false;
317
318     QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false;
319     QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false;
320     QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false;
321     QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false;
322     QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false;
323     QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false;
324     QTest::newRow("invalidID.7") << "invalidID.7.qml" << "invalidID.7.errors.txt" << false;
325     QTest::newRow("invalidID.8") << "invalidID.8.qml" << "invalidID.8.errors.txt" << false;
326     QTest::newRow("invalidID.9") << "invalidID.9.qml" << "invalidID.9.errors.txt" << false;
327
328     QTest::newRow("scriptString.1") << "scriptString.1.qml" << "scriptString.1.errors.txt" << false;
329     QTest::newRow("scriptString.2") << "scriptString.2.qml" << "scriptString.2.errors.txt" << false;
330
331     QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false;
332     QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true;
333     QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false;
334     QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false;
335     QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false;
336     QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false;
337     QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false;
338     QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false;
339     QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false;
340     QTest::newRow("missingSignal2") << "missingSignal.2.qml" << "missingSignal.2.errors.txt" << false;
341     QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
342     QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
343
344     QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
345     QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
346     QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
347     QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false;
348     QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false;
349     QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false;
350     QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true;
351     QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false;
352     QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false;
353     QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false;
354
355     QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false;
356     QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false;
357     QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false;
358     QTest::newRow("importNonExist (installed)") << "importNonExist.qml" << "importNonExist.errors.txt" << false;
359     QTest::newRow("importNonExistOlder (installed)") << "importNonExistOlder.qml" << "importNonExistOlder.errors.txt" << false;
360     QTest::newRow("importNewerVersion (installed)") << "importNewerVersion.qml" << "importNewerVersion.errors.txt" << false;
361     QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false;
362     QTest::newRow("importFile") << "importFile.qml" << "importFile.errors.txt" << false;
363
364     QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false;
365     QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false;
366     QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false;
367     QTest::newRow("signal.4") << "signal.4.qml" << "signal.4.errors.txt" << false;
368     QTest::newRow("signal.5") << "signal.5.qml" << "signal.5.errors.txt" << false;
369
370     QTest::newRow("method.1") << "method.1.qml" << "method.1.errors.txt" << false;
371
372     QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false;
373     QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false;
374     QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false;
375     QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false;
376     QTest::newRow("property.6") << "property.6.qml" << "property.6.errors.txt" << false;
377     QTest::newRow("property.7") << "property.7.qml" << "property.7.errors.txt" << false;
378
379     QTest::newRow("importScript.1") << "importscript.1.qml" << "importscript.1.errors.txt" << false;
380
381     QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false;
382     QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false;
383     QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false;
384     QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false;
385     QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false;
386     QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false;
387     QTest::newRow("Component.7") << "component.7.qml" << "component.7.errors.txt" << false;
388     QTest::newRow("Component.8") << "component.8.qml" << "component.8.errors.txt" << false;
389     QTest::newRow("Component.9") << "component.9.qml" << "component.9.errors.txt" << false;
390
391     QTest::newRow("MultiSet.1") << "multiSet.1.qml" << "multiSet.1.errors.txt" << false;
392     QTest::newRow("MultiSet.2") << "multiSet.2.qml" << "multiSet.2.errors.txt" << false;
393     QTest::newRow("MultiSet.3") << "multiSet.3.qml" << "multiSet.3.errors.txt" << false;
394     QTest::newRow("MultiSet.4") << "multiSet.4.qml" << "multiSet.4.errors.txt" << false;
395     QTest::newRow("MultiSet.5") << "multiSet.5.qml" << "multiSet.5.errors.txt" << false;
396     QTest::newRow("MultiSet.6") << "multiSet.6.qml" << "multiSet.6.errors.txt" << false;
397     QTest::newRow("MultiSet.7") << "multiSet.7.qml" << "multiSet.7.errors.txt" << false;
398     QTest::newRow("MultiSet.8") << "multiSet.8.qml" << "multiSet.8.errors.txt" << false;
399     QTest::newRow("MultiSet.9") << "multiSet.9.qml" << "multiSet.9.errors.txt" << false;
400     QTest::newRow("MultiSet.10") << "multiSet.10.qml" << "multiSet.10.errors.txt" << false;
401     QTest::newRow("MultiSet.11") << "multiSet.11.qml" << "multiSet.11.errors.txt" << false;
402
403     QTest::newRow("dynamicMeta.1") << "dynamicMeta.1.qml" << "dynamicMeta.1.errors.txt" << false;
404     QTest::newRow("dynamicMeta.2") << "dynamicMeta.2.qml" << "dynamicMeta.2.errors.txt" << false;
405     QTest::newRow("dynamicMeta.3") << "dynamicMeta.3.qml" << "dynamicMeta.3.errors.txt" << false;
406     QTest::newRow("dynamicMeta.4") << "dynamicMeta.4.qml" << "dynamicMeta.4.errors.txt" << false;
407     QTest::newRow("dynamicMeta.5") << "dynamicMeta.5.qml" << "dynamicMeta.5.errors.txt" << false;
408
409     QTest::newRow("invalidAlias.1") << "invalidAlias.1.qml" << "invalidAlias.1.errors.txt" << false;
410     QTest::newRow("invalidAlias.2") << "invalidAlias.2.qml" << "invalidAlias.2.errors.txt" << false;
411     QTest::newRow("invalidAlias.3") << "invalidAlias.3.qml" << "invalidAlias.3.errors.txt" << false;
412     QTest::newRow("invalidAlias.4") << "invalidAlias.4.qml" << "invalidAlias.4.errors.txt" << false;
413     QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false;
414     QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false;
415     QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false;
416     QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false;
417     QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false;
418     QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false;
419
420     QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
421     QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
422     QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false;
423     QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false;
424     QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false;
425     QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false;
426     QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false;
427     QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false;
428     QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false;
429     QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false;
430     QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false;
431     QTest::newRow("invalidAttachedProperty.12") << "invalidAttachedProperty.12.qml" << "invalidAttachedProperty.12.errors.txt" << false;
432     QTest::newRow("invalidAttachedProperty.13") << "invalidAttachedProperty.13.qml" << "invalidAttachedProperty.13.errors.txt" << false;
433
434     QTest::newRow("assignValueToSignal") << "assignValueToSignal.qml" << "assignValueToSignal.errors.txt" << false;
435     QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false;
436
437     QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false;
438     QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false;
439     QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false;
440     QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false;
441     QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false;
442     QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false;
443     QTest::newRow("noCreation") << "noCreation.qml" << "noCreation.errors.txt" << false;
444     QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false;
445     QTest::newRow("assignToNamespace") << "assignToNamespace.qml" << "assignToNamespace.errors.txt" << false;
446     QTest::newRow("invalidOn") << "invalidOn.qml" << "invalidOn.errors.txt" << false;
447     QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false;
448     QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false;
449     QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false;
450     QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
451     QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
452     QTest::newRow("incorrectCase") << "incorrectCase.qml" 
453 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
454         << "incorrectCase.errors.insensitive.txt" 
455 #else
456         << "incorrectCase.errors.sensitive.txt" 
457 #endif
458         << false;
459
460     QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false;
461     QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false;
462     QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false;
463
464     QTest::newRow("invalidRoot.1") << "invalidRoot.1.qml" << "invalidRoot.1.errors.txt" << false;
465     QTest::newRow("invalidRoot.2") << "invalidRoot.2.qml" << "invalidRoot.2.errors.txt" << false;
466     QTest::newRow("invalidRoot.3") << "invalidRoot.3.qml" << "invalidRoot.3.errors.txt" << false;
467     QTest::newRow("invalidRoot.4") << "invalidRoot.4.qml" << "invalidRoot.4.errors.txt" << false;
468
469     QTest::newRow("invalidTypeName.1") << "invalidTypeName.1.qml" << "invalidTypeName.1.errors.txt" << false;
470     QTest::newRow("invalidTypeName.2") << "invalidTypeName.2.qml" << "invalidTypeName.2.errors.txt" << false;
471     QTest::newRow("invalidTypeName.3") << "invalidTypeName.3.qml" << "invalidTypeName.3.errors.txt" << false;
472     QTest::newRow("invalidTypeName.4") << "invalidTypeName.4.qml" << "invalidTypeName.4.errors.txt" << false;
473
474     QTest::newRow("Major version isolation") << "majorVersionIsolation.qml" << "majorVersionIsolation.errors.txt" << false;
475 }
476
477
478 void tst_qqmllanguage::errors()
479 {
480     QFETCH(QString, file);
481     QFETCH(QString, errorFile);
482     QFETCH(bool, create);
483
484     QQmlComponent component(&engine, TEST_FILE(file));
485
486     if(create) {
487         QObject *object = component.create();
488         QVERIFY(object == 0);
489     }
490
491     VERIFY_ERRORS(errorFile.toLatin1().constData());
492 }
493
494 void tst_qqmllanguage::simpleObject()
495 {
496     QQmlComponent component(&engine, TEST_FILE("simpleObject.qml"));
497     VERIFY_ERRORS(0);
498     QObject *object = component.create();
499     QVERIFY(object != 0);
500 }
501
502 void tst_qqmllanguage::simpleContainer()
503 {
504     QQmlComponent component(&engine, TEST_FILE("simpleContainer.qml"));
505     VERIFY_ERRORS(0);
506     MyContainer *container= qobject_cast<MyContainer*>(component.create());
507     QVERIFY(container != 0);
508     QCOMPARE(container->getChildren()->count(),2);
509 }
510
511 void tst_qqmllanguage::interfaceProperty()
512 {
513     QQmlComponent component(&engine, TEST_FILE("interfaceProperty.qml"));
514     VERIFY_ERRORS(0);
515     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
516     QVERIFY(object != 0);
517     QVERIFY(object->interface());
518     QVERIFY(object->interface()->id == 913);
519 }
520
521 void tst_qqmllanguage::interfaceQList()
522 {
523     QQmlComponent component(&engine, TEST_FILE("interfaceQList.qml"));
524     VERIFY_ERRORS(0);
525     MyContainer *container= qobject_cast<MyContainer*>(component.create());
526     QVERIFY(container != 0);
527     QVERIFY(container->getQListInterfaces()->count() == 2);
528     for(int ii = 0; ii < 2; ++ii)
529         QVERIFY(container->getQListInterfaces()->at(ii)->id == 913);
530 }
531
532 void tst_qqmllanguage::assignObjectToSignal()
533 {
534     QQmlComponent component(&engine, TEST_FILE("assignObjectToSignal.qml"));
535     VERIFY_ERRORS(0);
536     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
537     QVERIFY(object != 0);
538     QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
539     emit object->basicSignal();
540 }
541
542 void tst_qqmllanguage::assignObjectToVariant()
543 {
544     QQmlComponent component(&engine, TEST_FILE("assignObjectToVariant.qml"));
545     VERIFY_ERRORS(0);
546     QObject *object = component.create();
547     QVERIFY(object != 0);
548     QVariant v = object->property("a");
549     QVERIFY(v.userType() == qMetaTypeId<QObject *>());
550 }
551
552 void tst_qqmllanguage::assignLiteralSignalProperty()
553 {
554     QQmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml"));
555     VERIFY_ERRORS(0);
556     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
557     QVERIFY(object != 0);
558     QCOMPARE(object->onLiteralSignal(), 10);
559 }
560
561 // Test is an external component can be loaded and assigned (to a qlist)
562 void tst_qqmllanguage::assignQmlComponent()
563 {
564     QQmlComponent component(&engine, TEST_FILE("assignQmlComponent.qml"));
565     VERIFY_ERRORS(0);
566     MyContainer *object = qobject_cast<MyContainer *>(component.create());
567     QVERIFY(object != 0);
568     QVERIFY(object->getChildren()->count() == 1);
569     QObject *child = object->getChildren()->at(0);
570     QCOMPARE(child->property("x"), QVariant(10));
571     QCOMPARE(child->property("y"), QVariant(11));
572 }
573
574 // Test literal assignment to all the basic types 
575 void tst_qqmllanguage::assignBasicTypes()
576 {
577     QQmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
578     VERIFY_ERRORS(0);
579     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
580     QVERIFY(object != 0);
581     QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
582     QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
583     QCOMPARE(object->qtEnumProperty(), Qt::RichText);
584     QCOMPARE(object->mirroredEnumProperty(), MyTypeObject::MirroredEnumVal3);
585     QCOMPARE(object->stringProperty(), QString("Hello World!"));
586     QCOMPARE(object->uintProperty(), uint(10));
587     QCOMPARE(object->intProperty(), -19);
588     QCOMPARE((float)object->realProperty(), float(23.2));
589     QCOMPARE((float)object->doubleProperty(), float(-19.7));
590     QCOMPARE((float)object->floatProperty(), float(8.5));
591     QCOMPARE(object->colorProperty(), QColor("red"));
592     QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
593     QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
594     QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
595     QCOMPARE(object->pointProperty(), QPoint(99,13));
596     QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
597     QCOMPARE(object->sizeProperty(), QSize(99, 13));
598     QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
599     QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
600     QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
601     QCOMPARE(object->boolProperty(), true);
602     QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
603     QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
604     QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2, 2.3));
605     QUrl encoded;
606     encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
607     QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
608     QVERIFY(object->objectProperty() != 0);
609     MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
610     QVERIFY(child != 0);
611     QCOMPARE(child->intProperty(), 8);
612
613     //these used to go via script. Ensure they no longer do
614     QCOMPARE(object->property("qtEnumTriggeredChange").toBool(), false);
615     QCOMPARE(object->property("mirroredEnumTriggeredChange").toBool(), false);
616 }
617
618 // Test edge case type assignments
619 void tst_qqmllanguage::assignTypeExtremes()
620 {
621     QQmlComponent component(&engine, TEST_FILE("assignTypeExtremes.qml"));
622     VERIFY_ERRORS(0);
623     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
624     QVERIFY(object != 0);
625     QCOMPARE(object->uintProperty(), 0xEE6B2800);
626     QCOMPARE(object->intProperty(), -0x77359400);
627 }
628
629 // Test that a composite type can assign to a property of its base type
630 void tst_qqmllanguage::assignCompositeToType()
631 {
632     QQmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml"));
633     VERIFY_ERRORS(0);
634     QObject *object = component.create();
635     QVERIFY(object != 0);
636 }
637
638 // Test that literals are stored correctly in variant properties
639 void tst_qqmllanguage::assignLiteralToVariant()
640 {
641     QQmlComponent component(&engine, TEST_FILE("assignLiteralToVariant.qml"));
642     VERIFY_ERRORS(0);
643     QObject *object = component.create();
644     QVERIFY(object != 0);
645
646     QCOMPARE(object->property("test1").userType(), (int)QVariant::Int);
647     QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
648     QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
649     QCOMPARE(object->property("test4").userType(), (int)QVariant::Color);
650     QCOMPARE(object->property("test5").userType(), (int)QVariant::RectF);
651     QCOMPARE(object->property("test6").userType(), (int)QVariant::PointF);
652     QCOMPARE(object->property("test7").userType(), (int)QVariant::SizeF);
653     QCOMPARE(object->property("test8").userType(), (int)QVariant::Vector3D);
654     QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
655     QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
656     QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
657     QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D);
658
659     QVERIFY(object->property("test1") == QVariant(1));
660     QVERIFY(object->property("test2") == QVariant((double)1.7));
661     QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!"))));
662     QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800)));
663     QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10)));
664     QVERIFY(object->property("test6") == QVariant(QPointF(10, 10)));
665     QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10)));
666     QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100)));
667     QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800"))));
668     QVERIFY(object->property("test10") == QVariant(bool(true)));
669     QVERIFY(object->property("test11") == QVariant(bool(false)));
670     QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100)));
671
672     delete object;
673 }
674
675 // Test that literals are stored correctly in "var" properties
676 // Note that behaviour differs from "variant" properties in that
677 // no conversion from "special strings" to QVariants is performed.
678 void tst_qqmllanguage::assignLiteralToVar()
679 {
680     QQmlComponent component(&engine, TEST_FILE("assignLiteralToVar.qml"));
681     VERIFY_ERRORS(0);
682     QObject *object = component.create();
683     QVERIFY(object != 0);
684
685     QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
686     QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
687     QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
688     QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
689     QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
690     QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
691     QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
692     QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
693     QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
694     QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
695     QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
696     QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
697     QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
698     QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
699     QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
700     QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
701     QCOMPARE(object->property("variantTest1Bound").userType(), (int)QMetaType::Int);
702     QCOMPARE(object->property("test1Bound").userType(), (int)QMetaType::Int);
703
704     QCOMPARE(object->property("test1"), QVariant(5));
705     QCOMPARE(object->property("test2"), QVariant((double)1.7));
706     QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
707     QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
708     QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
709     QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
710     QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
711     QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
712     QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
713     QCOMPARE(object->property("test10"), QVariant(bool(true)));
714     QCOMPARE(object->property("test11"), QVariant(bool(false)));
715     QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
716     QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
717     QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
718     QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
719     QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
720     QCOMPARE(object->property("variantTest1Bound"), QVariant(9));
721     QCOMPARE(object->property("test1Bound"), QVariant(11));
722
723     delete object;
724 }
725
726 void tst_qqmllanguage::assignLiteralToJSValue()
727 {
728     QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
729     VERIFY_ERRORS(0);
730     QObject *root = component.create();
731     QVERIFY(root != 0);
732
733     {
734         MyQmlObject *object = root->findChild<MyQmlObject *>("test1");
735         QJSValue value = object->qjsvalue();
736         QVERIFY(value.isNumber());
737         QCOMPARE(value.toNumber(), qreal(5));
738     } {
739         MyQmlObject *object = root->findChild<MyQmlObject *>("test2");
740         QJSValue value = object->qjsvalue();
741         QVERIFY(value.isNumber());
742         QCOMPARE(value.toNumber(), qreal(1.7));
743     } {
744         MyQmlObject *object = root->findChild<MyQmlObject *>("test3");
745         QJSValue value = object->qjsvalue();
746         QVERIFY(value.isString());
747         QCOMPARE(value.toString(), QString(QLatin1String("Hello world!")));
748     }{
749         MyQmlObject *object = root->findChild<MyQmlObject *>("test4");
750         QJSValue value = object->qjsvalue();
751         QVERIFY(value.isString());
752         QCOMPARE(value.toString(), QString(QLatin1String("#FF008800")));
753     } {
754         MyQmlObject *object = root->findChild<MyQmlObject *>("test5");
755         QJSValue value = object->qjsvalue();
756         QVERIFY(value.isString());
757         QCOMPARE(value.toString(), QString(QLatin1String("10,10,10x10")));
758     } {
759         MyQmlObject *object = root->findChild<MyQmlObject *>("test6");
760         QJSValue value = object->qjsvalue();
761         QVERIFY(value.isString());
762         QCOMPARE(value.toString(), QString(QLatin1String("10,10")));
763     } {
764         MyQmlObject *object = root->findChild<MyQmlObject *>("test7");
765         QJSValue value = object->qjsvalue();
766         QVERIFY(value.isString());
767         QCOMPARE(value.toString(), QString(QLatin1String("10x10")));
768     } {
769         MyQmlObject *object = root->findChild<MyQmlObject *>("test8");
770         QJSValue value = object->qjsvalue();
771         QVERIFY(value.isString());
772         QCOMPARE(value.toString(), QString(QLatin1String("100,100,100")));
773     } {
774         MyQmlObject *object = root->findChild<MyQmlObject *>("test9");
775         QJSValue value = object->qjsvalue();
776         QVERIFY(value.isString());
777         QCOMPARE(value.toString(), QString(QLatin1String("#FF008800")));
778     } {
779         MyQmlObject *object = root->findChild<MyQmlObject *>("test10");
780         QJSValue value = object->qjsvalue();
781         QVERIFY(value.isBool());
782         QCOMPARE(value.toBool(), true);
783     } {
784         MyQmlObject *object = root->findChild<MyQmlObject *>("test11");
785         QJSValue value = object->qjsvalue();
786         QVERIFY(value.isBool());
787         QCOMPARE(value.toBool(), false);
788     } {
789         MyQmlObject *object = root->findChild<MyQmlObject *>("test20");
790         QJSValue value = object->qjsvalue();
791         QVERIFY(value.isCallable());
792         QCOMPARE(value.call(QList<QJSValue> () << QJSValue(4)).toInt(), 12);
793     } {
794         MyQmlObject *object = root->findChild<MyQmlObject *>("test21");
795         QJSValue value = object->qjsvalue();
796         QVERIFY(value.isUndefined());
797     } {
798         MyQmlObject *object = root->findChild<MyQmlObject *>("test22");
799         QJSValue value = object->qjsvalue();
800         QVERIFY(value.isNull());
801     } {
802         MyQmlObject *object = root->findChild<MyQmlObject *>("test1Bound");
803         QJSValue value = object->qjsvalue();
804         QVERIFY(value.isNumber());
805         QCOMPARE(value.toNumber(), qreal(9));
806     } {
807         MyQmlObject *object = root->findChild<MyQmlObject *>("test20Bound");
808         QJSValue value = object->qjsvalue();
809         QVERIFY(value.isNumber());
810         QCOMPARE(value.toNumber(), qreal(27));
811     }
812 }
813
814 void tst_qqmllanguage::bindJSValueToVar()
815 {
816     QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
817
818     VERIFY_ERRORS(0);
819     QObject *root = component.create();
820     QVERIFY(root != 0);
821
822     QObject *object = root->findChild<QObject *>("varProperties");
823
824     QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
825     QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
826     QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
827     QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
828     QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
829     QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
830     QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
831     QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
832     QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
833     QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
834     QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
835     QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
836     QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
837     QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
838     QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
839     QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
840     QCOMPARE(object->property("test1Bound").userType(), (int)QVariant::Int);
841     QCOMPARE(object->property("test20Bound").userType(), (int)QVariant::Int);
842
843     QCOMPARE(object->property("test1"), QVariant(5));
844     QCOMPARE(object->property("test2"), QVariant((double)1.7));
845     QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
846     QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
847     QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
848     QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
849     QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
850     QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
851     QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
852     QCOMPARE(object->property("test10"), QVariant(bool(true)));
853     QCOMPARE(object->property("test11"), QVariant(bool(false)));
854     QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
855     QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
856     QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
857     QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
858     QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
859     QCOMPARE(object->property("test1Bound"), QVariant(9));
860     QCOMPARE(object->property("test20Bound"), QVariant(27));
861 }
862
863 void tst_qqmllanguage::bindJSValueToVariant()
864 {
865     QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
866
867     VERIFY_ERRORS(0);
868     QObject *root = component.create();
869     QVERIFY(root != 0);
870
871     QObject *object = root->findChild<QObject *>("variantProperties");
872
873     QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
874     QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
875     QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
876     QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
877     QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
878     QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
879     QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
880     QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
881     QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
882     QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
883     QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
884     QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
885     QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
886     QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
887     QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
888     QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
889     QCOMPARE(object->property("test1Bound").userType(), (int)QVariant::Int);
890     QCOMPARE(object->property("test20Bound").userType(), (int)QVariant::Int);
891
892     QCOMPARE(object->property("test1"), QVariant(5));
893     QCOMPARE(object->property("test2"), QVariant((double)1.7));
894     QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
895     QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
896     QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
897     QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
898     QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
899     QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
900     QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
901     QCOMPARE(object->property("test10"), QVariant(bool(true)));
902     QCOMPARE(object->property("test11"), QVariant(bool(false)));
903     QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
904     QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
905     QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
906     QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
907     QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
908     QCOMPARE(object->property("test1Bound"), QVariant(9));
909     QCOMPARE(object->property("test20Bound"), QVariant(27));
910 }
911
912 void tst_qqmllanguage::bindJSValueToType()
913 {
914     QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
915
916     VERIFY_ERRORS(0);
917     QObject *root = component.create();
918     QVERIFY(root != 0);
919
920     {
921         MyTypeObject *object = root->findChild<MyTypeObject *>("typedProperties");
922
923         QCOMPARE(object->intProperty(), 5);
924         QCOMPARE(object->doubleProperty(), double(1.7));
925         QCOMPARE(object->stringProperty(), QString(QLatin1String("Hello world!")));
926         QCOMPARE(object->boolProperty(), true);
927         QCOMPARE(object->colorProperty(), QColor::fromRgbF(0.2, 0.3, 0.4, 0.5));
928         QCOMPARE(object->rectFProperty(), QRectF(10, 10, 10, 10));
929         QCOMPARE(object->pointFProperty(), QPointF(10, 10));
930         QCOMPARE(object->sizeFProperty(), QSizeF(10, 10));
931         QCOMPARE(object->vectorProperty(), QVector3D(100, 100, 100));
932     } {
933         MyTypeObject *object = root->findChild<MyTypeObject *>("stringProperties");
934
935         QCOMPARE(object->intProperty(), 1);
936         QCOMPARE(object->doubleProperty(), double(1.7));
937         QCOMPARE(object->stringProperty(), QString(QLatin1String("Hello world!")));
938         QCOMPARE(object->boolProperty(), true);
939         QCOMPARE(object->colorProperty(), QColor::fromRgb(0x00, 0x88, 0x00, 0xFF));
940         QCOMPARE(object->rectFProperty(), QRectF(10, 10, 10, 10));
941         QCOMPARE(object->pointFProperty(), QPointF(10, 10));
942         QCOMPARE(object->sizeFProperty(), QSizeF(10, 10));
943         QCOMPARE(object->vectorProperty(), QVector3D(100, 100, 100));
944     }
945 }
946
947 void tst_qqmllanguage::bindTypeToJSValue()
948 {
949     QQmlComponent component(&engine, TEST_FILE("bindTypeToJSValue.qml"));
950
951     VERIFY_ERRORS(0);
952     QObject *root = component.create();
953     QVERIFY(root != 0);
954
955     {
956         MyQmlObject *object = root->findChild<MyQmlObject *>("flagProperty");
957         QVERIFY(object);
958         QJSValue value = object->qjsvalue();
959         QVERIFY(value.isNumber());
960         QCOMPARE(value.toNumber(), qreal(MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3));
961     } {
962         MyQmlObject *object = root->findChild<MyQmlObject *>("enumProperty");
963         QJSValue value = object->qjsvalue();
964         QVERIFY(value.isNumber());
965         QCOMPARE(value.toNumber(), qreal(MyTypeObject::EnumVal2));
966     } {
967         MyQmlObject *object = root->findChild<MyQmlObject *>("stringProperty");
968         QJSValue value = object->qjsvalue();
969         QVERIFY(value.isString());
970         QCOMPARE(value.toString(), QString(QLatin1String("Hello World!")));
971     } {
972         MyQmlObject *object = root->findChild<MyQmlObject *>("uintProperty");
973         QJSValue value = object->qjsvalue();
974         QVERIFY(value.isNumber());
975         QCOMPARE(value.toNumber(), qreal(10));
976     } {
977         MyQmlObject *object = root->findChild<MyQmlObject *>("intProperty");
978         QJSValue value = object->qjsvalue();
979         QVERIFY(value.isNumber());
980         QCOMPARE(value.toNumber(), qreal(-19));
981     } {
982         MyQmlObject *object = root->findChild<MyQmlObject *>("realProperty");
983         QJSValue value = object->qjsvalue();
984         QVERIFY(value.isNumber());
985         QCOMPARE(value.toNumber(), qreal(23.2));
986     } {
987         MyQmlObject *object = root->findChild<MyQmlObject *>("doubleProperty");
988         QJSValue value = object->qjsvalue();
989         QVERIFY(value.isNumber());
990         QCOMPARE(value.toNumber(), qreal(-19.7));
991     } {
992         MyQmlObject *object = root->findChild<MyQmlObject *>("floatProperty");
993         QJSValue value = object->qjsvalue();
994         QVERIFY(value.isNumber());
995         QCOMPARE(value.toNumber(), qreal(8.5));
996     } {
997         MyQmlObject *object = root->findChild<MyQmlObject *>("colorProperty");
998         QJSValue value = object->qjsvalue();
999         QVERIFY(value.isObject());
1000         QCOMPARE(value.property(QLatin1String("r")).toNumber(), qreal(1.0));
1001         QCOMPARE(value.property(QLatin1String("g")).toNumber(), qreal(0.0));
1002         QCOMPARE(value.property(QLatin1String("b")).toNumber(), qreal(0.0));
1003     } {
1004         MyQmlObject *object = root->findChild<MyQmlObject *>("dateProperty");
1005         QJSValue value = object->qjsvalue();
1006         QCOMPARE(value.toDateTime().isValid(), true);
1007     } {
1008         MyQmlObject *object = root->findChild<MyQmlObject *>("timeProperty");
1009         QJSValue value = object->qjsvalue();
1010         QCOMPARE(value.toDateTime().isValid(), true);
1011     } {
1012         MyQmlObject *object = root->findChild<MyQmlObject *>("dateTimeProperty");
1013         QJSValue value = object->qjsvalue();
1014         QCOMPARE(value.toDateTime().isValid(), true);
1015     } {
1016         MyQmlObject *object = root->findChild<MyQmlObject *>("pointProperty");
1017         QJSValue value = object->qjsvalue();
1018         QVERIFY(value.isObject());
1019         QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(99));
1020         QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(13));
1021     } {
1022         MyQmlObject *object = root->findChild<MyQmlObject *>("pointFProperty");
1023         QJSValue value = object->qjsvalue();
1024         QVERIFY(value.isObject());
1025         QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(-10.1));
1026         QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(12.3));
1027     } {
1028         MyQmlObject *object = root->findChild<MyQmlObject *>("rectProperty");
1029         QJSValue value = object->qjsvalue();
1030         QVERIFY(value.isObject());
1031         QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(9));
1032         QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(7));
1033         QCOMPARE(value.property(QLatin1String("width")).toNumber(), qreal(100));
1034         QCOMPARE(value.property(QLatin1String("height")).toNumber(), qreal(200));
1035     } {
1036         MyQmlObject *object = root->findChild<MyQmlObject *>("rectFProperty");
1037         QJSValue value = object->qjsvalue();
1038         QVERIFY(value.isObject());
1039         QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(1000.1));
1040         QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(-10.9));
1041         QCOMPARE(value.property(QLatin1String("width")).toNumber(), qreal(400));
1042         QCOMPARE(value.property(QLatin1String("height")).toNumber(), qreal(90.99));
1043     } {
1044         MyQmlObject *object = root->findChild<MyQmlObject *>("boolProperty");
1045         QJSValue value = object->qjsvalue();
1046         QVERIFY(value.isBool());
1047         QCOMPARE(value.toBool(), true);
1048     } {
1049         MyQmlObject *object = root->findChild<MyQmlObject *>("variantProperty");
1050         QJSValue value = object->qjsvalue();
1051         QVERIFY(value.isString());
1052         QCOMPARE(value.toString(), QString(QLatin1String("Hello World!")));
1053     } {
1054         MyQmlObject *object = root->findChild<MyQmlObject *>("vectorProperty");
1055         QJSValue value = object->qjsvalue();
1056         QVERIFY(value.isObject());
1057         QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(10.0f));
1058         QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(1.0f));
1059         QCOMPARE(value.property(QLatin1String("z")).toNumber(), qreal(2.2f));
1060     } {
1061         MyQmlObject *object = root->findChild<MyQmlObject *>("vector4Property");
1062         QJSValue value = object->qjsvalue();
1063         QVERIFY(value.isObject());
1064         QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(10.0f));
1065         QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(1.0f));
1066         QCOMPARE(value.property(QLatin1String("z")).toNumber(), qreal(2.2f));
1067         QCOMPARE(value.property(QLatin1String("w")).toNumber(), qreal(2.3f));
1068     } {
1069         MyQmlObject *object = root->findChild<MyQmlObject *>("urlProperty");
1070         QJSValue value = object->qjsvalue();
1071         QVERIFY(value.isString());
1072         QUrl encoded;
1073         encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
1074         QCOMPARE(value.toString(), component.url().resolved(encoded).toString());
1075     } {
1076         MyQmlObject *object = root->findChild<MyQmlObject *>("objectProperty");
1077         QJSValue value = object->qjsvalue();
1078         QVERIFY(value.isQObject());
1079         QVERIFY(qobject_cast<MyTypeObject *>(value.toQObject()));
1080     } {
1081         MyQmlObject *object = root->findChild<MyQmlObject *>("varProperty");
1082         QJSValue value = object->qjsvalue();
1083         QVERIFY(value.isString());
1084         QCOMPARE(value.toString(), QString(QLatin1String("Hello World!")));
1085     }
1086 }
1087
1088 // Tests that custom parser types can be instantiated
1089 void tst_qqmllanguage::customParserTypes()
1090 {
1091     QQmlComponent component(&engine, TEST_FILE("customParserTypes.qml"));
1092     VERIFY_ERRORS(0);
1093     QObject *object = component.create();
1094     QVERIFY(object != 0);
1095     QVERIFY(object->property("count") == QVariant(2));
1096 }
1097
1098 // Tests that the root item can be a custom component
1099 void tst_qqmllanguage::rootAsQmlComponent()
1100 {
1101     QQmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml"));
1102     VERIFY_ERRORS(0);
1103     MyContainer *object = qobject_cast<MyContainer *>(component.create());
1104     QVERIFY(object != 0);
1105     QCOMPARE(object->property("x"), QVariant(11));
1106     QCOMPARE(object->getChildren()->count(), 2);
1107 }
1108
1109 // Tests that components can be specified inline
1110 void tst_qqmllanguage::inlineQmlComponents()
1111 {
1112     QQmlComponent component(&engine, TEST_FILE("inlineQmlComponents.qml"));
1113     VERIFY_ERRORS(0);
1114     MyContainer *object = qobject_cast<MyContainer *>(component.create());
1115     QVERIFY(object != 0);
1116     QCOMPARE(object->getChildren()->count(), 1);
1117     QQmlComponent *comp = qobject_cast<QQmlComponent *>(object->getChildren()->at(0));
1118     QVERIFY(comp != 0);
1119     MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
1120     QVERIFY(compObject != 0);
1121     QCOMPARE(compObject->value(), 11);
1122 }
1123
1124 // Tests that types that have an id property have it set
1125 void tst_qqmllanguage::idProperty()
1126 {
1127     QQmlComponent component(&engine, TEST_FILE("idProperty.qml"));
1128     VERIFY_ERRORS(0);
1129     MyContainer *object = qobject_cast<MyContainer *>(component.create());
1130     QVERIFY(object != 0);
1131     QCOMPARE(object->getChildren()->count(), 1);
1132     MyTypeObject *child = 
1133         qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
1134     QVERIFY(child != 0);
1135     QCOMPARE(child->id(), QString("myObjectId"));
1136     QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
1137 }
1138
1139 // Tests automatic connection to notify signals if "onBlahChanged" syntax is used
1140 // even if the notify signal for "blah" is not called "blahChanged"
1141 void tst_qqmllanguage::autoNotifyConnection()
1142 {
1143     QQmlComponent component(&engine, TEST_FILE("autoNotifyConnection.qml"));
1144     VERIFY_ERRORS(0);
1145     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1146     QVERIFY(object != 0);
1147     QMetaProperty prop = object->metaObject()->property(object->metaObject()->indexOfProperty("receivedNotify"));
1148     QVERIFY(prop.isValid());
1149
1150     QCOMPARE(prop.read(object), QVariant::fromValue(false));
1151     object->setPropertyWithNotify(1);
1152     QCOMPARE(prop.read(object), QVariant::fromValue(true));
1153 }
1154
1155 // Tests that signals can be assigned to
1156 void tst_qqmllanguage::assignSignal()
1157 {
1158     QQmlComponent component(&engine, TEST_FILE("assignSignal.qml"));
1159     VERIFY_ERRORS(0);
1160     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1161     QVERIFY(object != 0);
1162     QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
1163     emit object->basicSignal();
1164     QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
1165     emit object->basicParameterizedSignal(9);
1166 }
1167
1168 // Tests the creation and assignment of dynamic properties
1169 void tst_qqmllanguage::dynamicProperties()
1170 {
1171     QQmlComponent component(&engine, TEST_FILE("dynamicProperties.qml"));
1172     VERIFY_ERRORS(0);
1173     QObject *object = component.create();
1174     QVERIFY(object != 0);
1175     QCOMPARE(object->property("intProperty"), QVariant(10));
1176     QCOMPARE(object->property("boolProperty"), QVariant(false));
1177     QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
1178     QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
1179     QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
1180     QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml")));
1181     QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
1182     QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
1183     QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
1184 }
1185
1186 // Test that nested types can use dynamic properties
1187 void tst_qqmllanguage::dynamicPropertiesNested()
1188 {
1189     QQmlComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml"));
1190     VERIFY_ERRORS(0);
1191     QObject *object = component.create();
1192     QVERIFY(object != 0);
1193
1194     QCOMPARE(object->property("super_a").toInt(), 11); // Overridden
1195     QCOMPARE(object->property("super_c").toInt(), 14); // Inherited
1196     QCOMPARE(object->property("a").toInt(), 13); // New
1197     QCOMPARE(object->property("b").toInt(), 12); // New
1198
1199     delete object;
1200 }
1201
1202 // Tests the creation and assignment to dynamic list properties
1203 void tst_qqmllanguage::listProperties()
1204 {
1205     QQmlComponent component(&engine, TEST_FILE("listProperties.qml"));
1206     VERIFY_ERRORS(0);
1207     QObject *object = component.create();
1208     QVERIFY(object != 0);
1209
1210     QCOMPARE(object->property("test").toInt(), 2);
1211 }
1212
1213 // Tests the creation and assignment of dynamic object properties
1214 // ### Not complete
1215 void tst_qqmllanguage::dynamicObjectProperties()
1216 {
1217     {
1218     QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
1219     VERIFY_ERRORS(0);
1220     QObject *object = component.create();
1221     QVERIFY(object != 0);
1222
1223     QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
1224     QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
1225     }
1226     {
1227     QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.2.qml"));
1228     QEXPECT_FAIL("", "QTBUG-10822", Abort);
1229     VERIFY_ERRORS(0);
1230     QObject *object = component.create();
1231     QVERIFY(object != 0);
1232
1233     QVERIFY(object->property("objectProperty") != qVariantFromValue((QObject*)0));
1234     }
1235 }
1236
1237 // Tests the declaration of dynamic signals and slots
1238 void tst_qqmllanguage::dynamicSignalsAndSlots()
1239 {
1240     QTest::ignoreMessage(QtDebugMsg, "1921");
1241
1242     QQmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml"));
1243     VERIFY_ERRORS(0);
1244     QObject *object = component.create();
1245     QVERIFY(object != 0);
1246     QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
1247     QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
1248     QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
1249     QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
1250
1251     QCOMPARE(object->property("test").toInt(), 0);
1252     QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10)));
1253     QCOMPARE(object->property("test").toInt(), 10);
1254 }
1255
1256 void tst_qqmllanguage::simpleBindings()
1257 {
1258     QQmlComponent component(&engine, TEST_FILE("simpleBindings.qml"));
1259     VERIFY_ERRORS(0);
1260     QObject *object = component.create();
1261     QVERIFY(object != 0);
1262     QCOMPARE(object->property("value1"), QVariant(10));
1263     QCOMPARE(object->property("value2"), QVariant(10));
1264     QCOMPARE(object->property("value3"), QVariant(21));
1265     QCOMPARE(object->property("value4"), QVariant(10));
1266     QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
1267 }
1268
1269 void tst_qqmllanguage::autoComponentCreation()
1270 {
1271     QQmlComponent component(&engine, TEST_FILE("autoComponentCreation.qml"));
1272     VERIFY_ERRORS(0);
1273     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1274     QVERIFY(object != 0);
1275     QVERIFY(object->componentProperty() != 0);
1276     MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
1277     QVERIFY(child != 0);
1278     QCOMPARE(child->realProperty(), qreal(9));
1279 }
1280
1281 void tst_qqmllanguage::propertyValueSource()
1282 {
1283     {
1284     QQmlComponent component(&engine, TEST_FILE("propertyValueSource.qml"));
1285     VERIFY_ERRORS(0);
1286     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1287     QVERIFY(object != 0);
1288
1289     QList<QObject *> valueSources;
1290     QObjectList allChildren = object->findChildren<QObject*>();
1291     foreach (QObject *child, allChildren) {
1292         if (qobject_cast<QQmlPropertyValueSource *>(child)) 
1293             valueSources.append(child);
1294     }
1295
1296     QCOMPARE(valueSources.count(), 1);
1297     MyPropertyValueSource *valueSource = 
1298         qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
1299     QVERIFY(valueSource != 0);
1300     QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
1301     QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
1302     }
1303
1304     {
1305     QQmlComponent component(&engine, TEST_FILE("propertyValueSource.2.qml"));
1306     VERIFY_ERRORS(0);
1307     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1308     QVERIFY(object != 0);
1309
1310     QList<QObject *> valueSources;
1311     QObjectList allChildren = object->findChildren<QObject*>();
1312     foreach (QObject *child, allChildren) {
1313         if (qobject_cast<QQmlPropertyValueSource *>(child)) 
1314             valueSources.append(child);
1315     }
1316
1317     QCOMPARE(valueSources.count(), 1);
1318     MyPropertyValueSource *valueSource = 
1319         qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
1320     QVERIFY(valueSource != 0);
1321     QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
1322     QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
1323     }
1324 }
1325
1326 void tst_qqmllanguage::attachedProperties()
1327 {
1328     QQmlComponent component(&engine, TEST_FILE("attachedProperties.qml"));
1329     VERIFY_ERRORS(0);
1330     QObject *object = component.create();
1331     QVERIFY(object != 0);
1332     QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
1333     QVERIFY(attached != 0);
1334     QCOMPARE(attached->property("value"), QVariant(10));
1335     QCOMPARE(attached->property("value2"), QVariant(13));
1336 }
1337
1338 // Tests non-static object properties
1339 void tst_qqmllanguage::dynamicObjects()
1340 {
1341     QQmlComponent component(&engine, TEST_FILE("dynamicObject.1.qml"));
1342     VERIFY_ERRORS(0);
1343     QObject *object = component.create();
1344     QVERIFY(object != 0);
1345 }
1346
1347 // Tests the registration of custom variant string converters
1348 void tst_qqmllanguage::customVariantTypes()
1349 {
1350     QQmlComponent component(&engine, TEST_FILE("customVariantTypes.qml"));
1351     VERIFY_ERRORS(0);
1352     MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1353     QVERIFY(object != 0);
1354     QCOMPARE(object->customType().a, 10);
1355 }
1356
1357 void tst_qqmllanguage::valueTypes()
1358 {
1359     QQmlComponent component(&engine, TEST_FILE("valueTypes.qml"));
1360     VERIFY_ERRORS(0);
1361
1362     QString message = component.url().toString() + ":2:1: QML MyTypeObject: Binding loop detected for property \"rectProperty.width\"";
1363     QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
1364     QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
1365
1366     MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1367     QVERIFY(object != 0);
1368
1369
1370     QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13));
1371     QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13));
1372     QCOMPARE(object->intProperty(), 10);
1373     object->doAction();
1374     QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13));
1375     QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13));
1376     QCOMPARE(object->intProperty(), 12);
1377
1378     // ###
1379 #if 0
1380     QQmlProperty p(object, "rectProperty.x");
1381     QCOMPARE(p.read(), QVariant(12));
1382     p.write(13);
1383     QCOMPARE(p.read(), QVariant(13));
1384
1385     quint32 r = QQmlPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex());
1386     QQmlProperty p2;
1387     QQmlPropertyPrivate::restore(p2, r, object);
1388     QCOMPARE(p2.read(), QVariant(13));
1389 #endif
1390 }
1391
1392 void tst_qqmllanguage::cppnamespace()
1393 {
1394     {
1395         QQmlComponent component(&engine, TEST_FILE("cppnamespace.qml"));
1396         VERIFY_ERRORS(0);
1397         QObject *object = component.create();
1398         QVERIFY(object != 0);
1399         delete object;
1400     }
1401
1402     {
1403         QQmlComponent component(&engine, TEST_FILE("cppnamespace.2.qml"));
1404         VERIFY_ERRORS(0);
1405         QObject *object = component.create();
1406         QVERIFY(object != 0);
1407         delete object;
1408     }
1409 }
1410
1411 void tst_qqmllanguage::aliasProperties()
1412 {
1413     // Simple "int" alias
1414     {
1415         QQmlComponent component(&engine, TEST_FILE("alias.1.qml"));
1416         VERIFY_ERRORS(0);
1417         QObject *object = component.create();
1418         QVERIFY(object != 0);
1419
1420         // Read through alias
1421         QCOMPARE(object->property("valueAlias").toInt(), 10);
1422         object->setProperty("value", QVariant(13));
1423         QCOMPARE(object->property("valueAlias").toInt(), 13);
1424
1425         // Write through alias
1426         object->setProperty("valueAlias", QVariant(19));
1427         QCOMPARE(object->property("valueAlias").toInt(), 19);
1428         QCOMPARE(object->property("value").toInt(), 19);
1429
1430         delete object;
1431     }
1432
1433     // Complex object alias
1434     {
1435         QQmlComponent component(&engine, TEST_FILE("alias.2.qml"));
1436         VERIFY_ERRORS(0);
1437         QObject *object = component.create();
1438         QVERIFY(object != 0);
1439
1440         // Read through alias
1441         MyQmlObject *v = 
1442             qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1443         QVERIFY(v != 0);
1444         QCOMPARE(v->value(), 10);
1445
1446         // Write through alias
1447         MyQmlObject *v2 = new MyQmlObject();
1448         v2->setParent(object);
1449         object->setProperty("aliasObject", qVariantFromValue(v2));
1450         MyQmlObject *v3 = 
1451             qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1452         QVERIFY(v3 != 0);
1453         QCOMPARE(v3, v2);
1454
1455         delete object;
1456     }
1457
1458     // Nested aliases
1459     {
1460         QQmlComponent component(&engine, TEST_FILE("alias.3.qml"));
1461         VERIFY_ERRORS(0);
1462         QObject *object = component.create();
1463         QVERIFY(object != 0);
1464
1465         QCOMPARE(object->property("value").toInt(), 1892);
1466         QCOMPARE(object->property("value2").toInt(), 1892);
1467
1468         object->setProperty("value", QVariant(1313));
1469         QCOMPARE(object->property("value").toInt(), 1313);
1470         QCOMPARE(object->property("value2").toInt(), 1313);
1471
1472         object->setProperty("value2", QVariant(8080));
1473         QCOMPARE(object->property("value").toInt(), 8080);
1474         QCOMPARE(object->property("value2").toInt(), 8080);
1475
1476         delete object;
1477     }
1478
1479     // Enum aliases
1480     {
1481         QQmlComponent component(&engine, TEST_FILE("alias.4.qml"));
1482         VERIFY_ERRORS(0);
1483         QObject *object = component.create();
1484         QVERIFY(object != 0);
1485
1486         QCOMPARE(object->property("enumAlias").toInt(), 1);
1487
1488         delete object;
1489     }
1490
1491     // Id aliases
1492     {
1493         QQmlComponent component(&engine, TEST_FILE("alias.5.qml"));
1494         VERIFY_ERRORS(0);
1495         QObject *object = component.create();
1496         QVERIFY(object != 0);
1497
1498         QVariant v = object->property("otherAlias");
1499         QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1500         MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
1501         QCOMPARE(o->value(), 10);
1502
1503         delete o;
1504
1505         v = object->property("otherAlias");
1506         QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1507         o = qvariant_cast<MyQmlObject*>(v);
1508         QVERIFY(o == 0);
1509
1510         delete object;
1511     }
1512
1513     // Nested aliases - this used to cause a crash
1514     {
1515         QQmlComponent component(&engine, TEST_FILE("alias.6.qml"));
1516         VERIFY_ERRORS(0);
1517         QObject *object = component.create();
1518         QVERIFY(object != 0);
1519
1520         QCOMPARE(object->property("a").toInt(), 1923);
1521     }
1522
1523     // Ptr Alias Cleanup - check that aliases to ptr types return 0 
1524     // if the object aliased to is removed
1525     {
1526         QQmlComponent component(&engine, TEST_FILE("alias.7.qml"));
1527         VERIFY_ERRORS(0);
1528
1529         QObject *object = component.create();
1530         QVERIFY(object != 0);
1531
1532         QObject *object1 = qvariant_cast<QObject *>(object->property("object"));
1533         QVERIFY(object1 != 0);
1534         QObject *object2 = qvariant_cast<QObject *>(object1->property("object"));
1535         QVERIFY(object2 != 0);
1536
1537         QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
1538         QVERIFY(alias == object2);
1539
1540         delete object1;
1541
1542         QObject *alias2 = object; // "Random" start value
1543         int status = -1;
1544         void *a[] = { &alias2, 0, &status };
1545         QMetaObject::metacall(object, QMetaObject::ReadProperty,
1546                               object->metaObject()->indexOfProperty("aliasedObject"), a);
1547         QVERIFY(alias2 == 0);
1548     }
1549
1550     // Simple composite type
1551     {
1552         QQmlComponent component(&engine, TEST_FILE("alias.8.qml"));
1553         VERIFY_ERRORS(0);
1554         QObject *object = component.create();
1555         QVERIFY(object != 0);
1556
1557         QCOMPARE(object->property("value").toInt(), 10);
1558
1559         delete object;
1560     }
1561
1562     // Complex composite type
1563     {
1564         QQmlComponent component(&engine, TEST_FILE("alias.9.qml"));
1565         VERIFY_ERRORS(0);
1566         QObject *object = component.create();
1567         QVERIFY(object != 0);
1568
1569         QCOMPARE(object->property("value").toInt(), 10);
1570
1571         delete object;
1572     }
1573
1574     // Valuetype alias
1575     // Simple "int" alias
1576     {
1577         QQmlComponent component(&engine, TEST_FILE("alias.10.qml"));
1578         VERIFY_ERRORS(0);
1579         QObject *object = component.create();
1580         QVERIFY(object != 0);
1581
1582         // Read through alias
1583         QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8));
1584         object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100)));
1585         QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100));
1586
1587         // Write through alias
1588         object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9)));
1589         QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9));
1590         QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9));
1591
1592         delete object;
1593     }
1594
1595     // Valuetype sub-alias
1596     {
1597         QQmlComponent component(&engine, TEST_FILE("alias.11.qml"));
1598         VERIFY_ERRORS(0);
1599         QObject *object = component.create();
1600         QVERIFY(object != 0);
1601
1602         // Read through alias
1603         QCOMPARE(object->property("aliasProperty").toInt(), 19);
1604         object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111)));
1605         QCOMPARE(object->property("aliasProperty").toInt(), 33);
1606
1607         // Write through alias
1608         object->setProperty("aliasProperty", QVariant(4));
1609         QCOMPARE(object->property("aliasProperty").toInt(), 4);
1610         QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111));
1611
1612         delete object;
1613     }
1614 }
1615
1616 // QTBUG-13374 Test that alias properties and signals can coexist
1617 void tst_qqmllanguage::aliasPropertiesAndSignals()
1618 {
1619     QQmlComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml"));
1620     VERIFY_ERRORS(0);
1621     QObject *o = component.create();
1622     QVERIFY(o);
1623     QCOMPARE(o->property("test").toBool(), true);
1624     delete o;
1625 }
1626
1627 // Test that the root element in a composite type can be a Component
1628 void tst_qqmllanguage::componentCompositeType()
1629 {
1630     QQmlComponent component(&engine, TEST_FILE("componentCompositeType.qml"));
1631     VERIFY_ERRORS(0);
1632     QObject *object = component.create();
1633     QVERIFY(object != 0);
1634 }
1635
1636 class TestType : public QObject {
1637     Q_OBJECT
1638 public:
1639     TestType(QObject *p=0) : QObject(p) {}
1640 };
1641
1642 class TestType2 : public QObject {
1643     Q_OBJECT
1644 public:
1645     TestType2(QObject *p=0) : QObject(p) {}
1646 };
1647
1648 void tst_qqmllanguage::i18n_data()
1649 {
1650     QTest::addColumn<QString>("file");
1651     QTest::addColumn<QString>("stringProperty");
1652     QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)");
1653     QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10");
1654     QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15");
1655     QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20");
1656     QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30");
1657     QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40");
1658 }
1659
1660 void tst_qqmllanguage::i18n()
1661 {
1662     QFETCH(QString, file);
1663     QFETCH(QString, stringProperty);
1664     QQmlComponent component(&engine, TEST_FILE(file));
1665     VERIFY_ERRORS(0);
1666     MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1667     QVERIFY(object != 0);
1668     QCOMPARE(object->stringProperty(), stringProperty);
1669
1670     delete object;
1671 }
1672
1673 // Check that the Component::onCompleted attached property works
1674 void tst_qqmllanguage::onCompleted()
1675 {
1676     QQmlComponent component(&engine, TEST_FILE("onCompleted.qml"));
1677     VERIFY_ERRORS(0);
1678     QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1679     QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1680     QTest::ignoreMessage(QtDebugMsg, "Completed 10 11");
1681     QObject *object = component.create();
1682     QVERIFY(object != 0);
1683 }
1684
1685 // Check that the Component::onDestruction attached property works
1686 void tst_qqmllanguage::onDestruction()
1687 {
1688     QQmlComponent component(&engine, TEST_FILE("onDestruction.qml"));
1689     VERIFY_ERRORS(0);
1690     QObject *object = component.create();
1691     QVERIFY(object != 0);
1692     QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1693     QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1694     QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11");
1695     delete object;
1696 }
1697
1698 // Check that assignments to QQmlScriptString properties work
1699 void tst_qqmllanguage::scriptString()
1700 {
1701     {
1702         QQmlComponent component(&engine, TEST_FILE("scriptString.qml"));
1703         VERIFY_ERRORS(0);
1704
1705         MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1706         QVERIFY(object != 0);
1707         QCOMPARE(object->scriptProperty().script(), QString("foo + bar"));
1708         QCOMPARE(object->scriptProperty().scopeObject(), qobject_cast<QObject*>(object));
1709         QCOMPARE(object->scriptProperty().context(), qmlContext(object));
1710
1711         QVERIFY(object->grouped() != 0);
1712         QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)"));
1713         QCOMPARE(object->grouped()->script().scopeObject(), qobject_cast<QObject*>(object));
1714         QCOMPARE(object->grouped()->script().context(), qmlContext(object));
1715     }
1716
1717     {
1718         QQmlComponent component(&engine, TEST_FILE("scriptString2.qml"));
1719         VERIFY_ERRORS(0);
1720
1721         MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1722         QVERIFY(object != 0);
1723         QCOMPARE(object->scriptProperty().script(), QString("\"hello\\n\\\"world\\\"\""));
1724     }
1725
1726     {
1727         QQmlComponent component(&engine, TEST_FILE("scriptString3.qml"));
1728         VERIFY_ERRORS(0);
1729
1730         MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1731         QVERIFY(object != 0);
1732         QCOMPARE(object->scriptProperty().script(), QString("12.345"));
1733     }
1734
1735     {
1736         QQmlComponent component(&engine, TEST_FILE("scriptString4.qml"));
1737         VERIFY_ERRORS(0);
1738
1739         MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1740         QVERIFY(object != 0);
1741         QCOMPARE(object->scriptProperty().script(), QString("true"));
1742     }
1743 }
1744
1745 // Check that default property assignments are correctly spliced into explicit 
1746 // property assignments
1747 void tst_qqmllanguage::defaultPropertyListOrder()
1748 {
1749     QQmlComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml"));
1750     VERIFY_ERRORS(0);
1751
1752     MyContainer *container = qobject_cast<MyContainer *>(component.create());
1753     QVERIFY(container  != 0);
1754
1755     QCOMPARE(container->getChildren()->count(), 6);
1756     QCOMPARE(container->getChildren()->at(0)->property("index"), QVariant(0));
1757     QCOMPARE(container->getChildren()->at(1)->property("index"), QVariant(1));
1758     QCOMPARE(container->getChildren()->at(2)->property("index"), QVariant(2));
1759     QCOMPARE(container->getChildren()->at(3)->property("index"), QVariant(3));
1760     QCOMPARE(container->getChildren()->at(4)->property("index"), QVariant(4));
1761     QCOMPARE(container->getChildren()->at(5)->property("index"), QVariant(5));
1762 }
1763
1764 void tst_qqmllanguage::declaredPropertyValues()
1765 {
1766     QQmlComponent component(&engine, TEST_FILE("declaredPropertyValues.qml"));
1767     VERIFY_ERRORS(0);
1768 }
1769
1770 void tst_qqmllanguage::dontDoubleCallClassBegin()
1771 {
1772     QQmlComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml"));
1773     QObject *o = component.create();
1774     QVERIFY(o);
1775
1776     MyParserStatus *o2 = qobject_cast<MyParserStatus *>(qvariant_cast<QObject *>(o->property("object")));
1777     QVERIFY(o2);
1778     QCOMPARE(o2->classBeginCount(), 1);
1779     QCOMPARE(o2->componentCompleteCount(), 1);
1780
1781     delete o;
1782 }
1783
1784 void tst_qqmllanguage::reservedWords_data()
1785 {
1786     QTest::addColumn<QByteArray>("word");
1787
1788     QTest::newRow("abstract") << QByteArray("abstract");
1789     QTest::newRow("as") << QByteArray("as");
1790     QTest::newRow("boolean") << QByteArray("boolean");
1791     QTest::newRow("break") << QByteArray("break");
1792     QTest::newRow("byte") << QByteArray("byte");
1793     QTest::newRow("case") << QByteArray("case");
1794     QTest::newRow("catch") << QByteArray("catch");
1795     QTest::newRow("char") << QByteArray("char");
1796     QTest::newRow("class") << QByteArray("class");
1797     QTest::newRow("continue") << QByteArray("continue");
1798     QTest::newRow("const") << QByteArray("const");
1799     QTest::newRow("debugger") << QByteArray("debugger");
1800     QTest::newRow("default") << QByteArray("default");
1801     QTest::newRow("delete") << QByteArray("delete");
1802     QTest::newRow("do") << QByteArray("do");
1803     QTest::newRow("double") << QByteArray("double");
1804     QTest::newRow("else") << QByteArray("else");
1805     QTest::newRow("enum") << QByteArray("enum");
1806     QTest::newRow("export") << QByteArray("export");
1807     QTest::newRow("extends") << QByteArray("extends");
1808     QTest::newRow("false") << QByteArray("false");
1809     QTest::newRow("final") << QByteArray("final");
1810     QTest::newRow("finally") << QByteArray("finally");
1811     QTest::newRow("float") << QByteArray("float");
1812     QTest::newRow("for") << QByteArray("for");
1813     QTest::newRow("function") << QByteArray("function");
1814     QTest::newRow("goto") << QByteArray("goto");
1815     QTest::newRow("if") << QByteArray("if");
1816     QTest::newRow("implements") << QByteArray("implements");
1817     QTest::newRow("import") << QByteArray("import");
1818     QTest::newRow("in") << QByteArray("in");
1819     QTest::newRow("instanceof") << QByteArray("instanceof");
1820     QTest::newRow("int") << QByteArray("int");
1821     QTest::newRow("interface") << QByteArray("interface");
1822     QTest::newRow("long") << QByteArray("long");
1823     QTest::newRow("native") << QByteArray("native");
1824     QTest::newRow("new") << QByteArray("new");
1825     QTest::newRow("null") << QByteArray("null");
1826     QTest::newRow("package") << QByteArray("package");
1827     QTest::newRow("private") << QByteArray("private");
1828     QTest::newRow("protected") << QByteArray("protected");
1829     QTest::newRow("public") << QByteArray("public");
1830     QTest::newRow("return") << QByteArray("return");
1831     QTest::newRow("short") << QByteArray("short");
1832     QTest::newRow("static") << QByteArray("static");
1833     QTest::newRow("super") << QByteArray("super");
1834     QTest::newRow("switch") << QByteArray("switch");
1835     QTest::newRow("synchronized") << QByteArray("synchronized");
1836     QTest::newRow("this") << QByteArray("this");
1837     QTest::newRow("throw") << QByteArray("throw");
1838     QTest::newRow("throws") << QByteArray("throws");
1839     QTest::newRow("transient") << QByteArray("transient");
1840     QTest::newRow("true") << QByteArray("true");
1841     QTest::newRow("try") << QByteArray("try");
1842     QTest::newRow("typeof") << QByteArray("typeof");
1843     QTest::newRow("var") << QByteArray("var");
1844     QTest::newRow("void") << QByteArray("void");
1845     QTest::newRow("volatile") << QByteArray("volatile");
1846     QTest::newRow("while") << QByteArray("while");
1847     QTest::newRow("with") << QByteArray("with");
1848 }
1849
1850 void tst_qqmllanguage::reservedWords()
1851 {
1852     QFETCH(QByteArray, word);
1853     QQmlComponent component(&engine);
1854     component.setData("import QtQuick 2.0\nQtObject { property string " + word + " }", QUrl());
1855     QCOMPARE(component.errorString(), QLatin1String(":2 Expected token `identifier'\n"));
1856 }
1857
1858 // Check that first child of qml is of given type. Empty type insists on error.
1859 void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror, bool partialMatch)
1860 {
1861     QQmlComponent component(&engine);
1862     component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
1863
1864     QTRY_VERIFY(!component.isLoading());
1865
1866     if (type.isEmpty()) {
1867         QVERIFY(component.isError());
1868         QString actualerror;
1869         foreach (const QQmlError e, component.errors()) {
1870             if (!actualerror.isEmpty())
1871                 actualerror.append("; ");
1872             actualerror.append(e.description());
1873         }
1874         QCOMPARE(actualerror.left(partialMatch ? expectederror.length(): -1),expectederror);
1875     } else {
1876         VERIFY_ERRORS(0);
1877         QObject *object = component.create();
1878         QVERIFY(object != 0);
1879         QCOMPARE(QString(object->metaObject()->className()), type);
1880         delete object;
1881     }
1882 }
1883
1884 // QTBUG-17276
1885 void tst_qqmllanguage::inlineAssignmentsOverrideBindings()
1886 {
1887     QQmlComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml"));
1888
1889     QObject *o = component.create();
1890     QVERIFY(o != 0);
1891     QCOMPARE(o->property("test").toInt(), 11);
1892     delete o;
1893 }
1894
1895 // QTBUG-19354
1896 void tst_qqmllanguage::nestedComponentRoots()
1897 {
1898     QQmlComponent component(&engine, TEST_FILE("nestedComponentRoots.qml"));
1899 }
1900
1901 // Import tests (QT-558)
1902 void tst_qqmllanguage::importsBuiltin_data()
1903 {
1904     // QT-610
1905
1906     QTest::addColumn<QString>("qml");
1907     QTest::addColumn<QString>("type");
1908     QTest::addColumn<QString>("error");
1909
1910     // import built-ins
1911     QTest::newRow("missing import")
1912         << "Test {}"
1913         << ""
1914         << "Test is not a type";
1915     QTest::newRow("not in version 0.0")
1916         << "import com.nokia.Test 0.0\n"
1917            "Test {}"
1918         << ""
1919         << "Test is not a type";
1920     QTest::newRow("version not installed")
1921         << "import com.nokia.Test 99.0\n"
1922            "Test {}"
1923         << ""
1924         << "module \"com.nokia.Test\" version 99.0 is not installed";
1925     QTest::newRow("in version 0.0")
1926         << "import com.nokia.Test 0.0\n"
1927            "TestTP {}"
1928         << "TestType"
1929         << "";
1930     QTest::newRow("qualified in version 0.0")
1931         << "import com.nokia.Test 0.0 as T\n"
1932            "T.TestTP {}"
1933         << "TestType"
1934         << "";
1935     QTest::newRow("in version 1.0")
1936         << "import com.nokia.Test 1.0\n"
1937            "Test {}"
1938         << "TestType"
1939         << "";
1940     QTest::newRow("qualified wrong")
1941         << "import com.nokia.Test 1.0 as T\n" // QT-610
1942            "Test {}"
1943         << ""
1944         << "Test is not a type";
1945     QTest::newRow("qualified right")
1946         << "import com.nokia.Test 1.0 as T\n"
1947            "T.Test {}"
1948         << "TestType"
1949         << "";
1950     QTest::newRow("qualified right but not in version 0.0")
1951         << "import com.nokia.Test 0.0 as T\n"
1952            "T.Test {}"
1953         << ""
1954         << "T.Test is not a type";
1955     QTest::newRow("in version 1.1")
1956         << "import com.nokia.Test 1.1\n"
1957            "Test {}"
1958         << "TestType"
1959         << "";
1960     QTest::newRow("in version 1.3")
1961         << "import com.nokia.Test 1.3\n"
1962            "Test {}"
1963         << "TestType"
1964         << "";
1965     QTest::newRow("in version 1.5")
1966         << "import com.nokia.Test 1.5\n"
1967            "Test {}"
1968         << "TestType"
1969         << "";
1970     QTest::newRow("changed in version 1.8")
1971         << "import com.nokia.Test 1.8\n"
1972            "Test {}"
1973         << "TestType2"
1974         << "";
1975     QTest::newRow("in version 1.12")
1976         << "import com.nokia.Test 1.12\n"
1977            "Test {}"
1978         << "TestType2"
1979         << "";
1980     QTest::newRow("old in version 1.9")
1981         << "import com.nokia.Test 1.9\n"
1982            "OldTest {}"
1983         << "TestType"
1984         << "";
1985     QTest::newRow("old in version 1.11")
1986         << "import com.nokia.Test 1.11\n"
1987            "OldTest {}"
1988         << "TestType"
1989         << "";
1990     QTest::newRow("multiversion 1")
1991         << "import com.nokia.Test 1.11\n"
1992            "import com.nokia.Test 1.12\n"
1993            "Test {}"
1994         << (!qmlCheckTypes()?"TestType2":"")
1995         << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test/ in version 1.12 and 1.11");
1996     QTest::newRow("multiversion 2")
1997         << "import com.nokia.Test 1.11\n"
1998            "import com.nokia.Test 1.12\n"
1999            "OldTest {}"
2000         << (!qmlCheckTypes()?"TestType":"")
2001         << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test/ in version 1.12 and 1.11");
2002     QTest::newRow("qualified multiversion 3")
2003         << "import com.nokia.Test 1.0 as T0\n"
2004            "import com.nokia.Test 1.8 as T8\n"
2005            "T0.Test {}"
2006         << "TestType"
2007         << "";
2008     QTest::newRow("qualified multiversion 4")
2009         << "import com.nokia.Test 1.0 as T0\n"
2010            "import com.nokia.Test 1.8 as T8\n"
2011            "T8.Test {}"
2012         << "TestType2"
2013         << "";
2014 }
2015
2016 void tst_qqmllanguage::importsBuiltin()
2017 {
2018     QFETCH(QString, qml);
2019     QFETCH(QString, type);
2020     QFETCH(QString, error);
2021     testType(qml,type,error);
2022 }
2023
2024 void tst_qqmllanguage::importsLocal_data()
2025 {
2026     QTest::addColumn<QString>("qml");
2027     QTest::addColumn<QString>("type");
2028     QTest::addColumn<QString>("error");
2029
2030     // import locals
2031     QTest::newRow("local import")
2032         << "import \"subdir\"\n" // QT-613
2033            "Test {}"
2034         << "QQuickRectangle"
2035         << "";
2036     QTest::newRow("local import second")
2037         << "import QtQuick 2.0\nimport \"subdir\"\n"
2038            "Test {}"
2039         << "QQuickRectangle"
2040         << "";
2041     QTest::newRow("local import subsubdir")
2042         << "import QtQuick 2.0\nimport \"subdir/subsubdir\"\n"
2043            "SubTest {}"
2044         << "QQuickRectangle"
2045         << "";
2046     QTest::newRow("local import QTBUG-7721 A")
2047         << "subdir.Test {}" // no longer allowed (QTBUG-7721)
2048         << ""
2049         << "subdir.Test - subdir is not a namespace";
2050     QTest::newRow("local import QTBUG-7721 B")
2051         << "import \"subdir\" as X\n"
2052            "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
2053         << ""
2054         << "X.subsubdir.SubTest - nested namespaces not allowed";
2055     QTest::newRow("local import as")
2056         << "import \"subdir\" as T\n"
2057            "T.Test {}"
2058         << "QQuickRectangle"
2059         << "";
2060     QTest::newRow("wrong local import as")
2061         << "import \"subdir\" as T\n"
2062            "Test {}"
2063         << ""
2064         << "Test is not a type";
2065     QTest::newRow("library precedence over local import")
2066         << "import \"subdir\"\n"
2067            "import com.nokia.Test 1.0\n"
2068            "Test {}"
2069         << (!qmlCheckTypes()?"TestType":"")
2070         << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test/ and in subdir/");
2071 }
2072
2073 void tst_qqmllanguage::importsLocal()
2074 {
2075     QFETCH(QString, qml);
2076     QFETCH(QString, type);
2077     QFETCH(QString, error);
2078     testType(qml,type,error);
2079 }
2080
2081 void tst_qqmllanguage::basicRemote_data()
2082 {
2083     QTest::addColumn<QUrl>("url");
2084     QTest::addColumn<QString>("type");
2085     QTest::addColumn<QString>("error");
2086
2087     QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage/";
2088
2089     QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << "";
2090     QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << "";
2091     QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << "";
2092 }
2093
2094 void tst_qqmllanguage::basicRemote()
2095 {
2096     QFETCH(QUrl, url);
2097     QFETCH(QString, type);
2098     QFETCH(QString, error);
2099
2100     TestHTTPServer server(14447);
2101     server.serveDirectory(testdata());
2102
2103     QQmlComponent component(&engine, url);
2104
2105     QTRY_VERIFY(!component.isLoading());
2106
2107     if (error.isEmpty()) {
2108         if (component.isError())
2109             qDebug() << component.errors();
2110         QVERIFY(!component.isError());
2111     } else {
2112         QVERIFY(component.isError());
2113     }
2114 }
2115
2116 void tst_qqmllanguage::importsRemote_data()
2117 {
2118     QTest::addColumn<QString>("qml");
2119     QTest::addColumn<QString>("type");
2120     QTest::addColumn<QString>("error");
2121
2122     QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage";
2123
2124     QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QQuickRectangle"
2125         << "";
2126     QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QQuickText"
2127         << "";
2128     QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QQuickImage"
2129         << "";
2130     QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << ""
2131         << "WrongTestLocal is not a type";
2132     QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << ""
2133         << "LocalInternal is not a type";
2134     QTest::newRow("wrong remote import of undeclared local") << "import \""+serverdir+"\"\nUndeclaredLocal {}" << ""
2135         << "UndeclaredLocal is not a type";
2136 }
2137
2138 void tst_qqmllanguage::importsRemote()
2139 {
2140     QFETCH(QString, qml);
2141     QFETCH(QString, type);
2142     QFETCH(QString, error);
2143
2144     TestHTTPServer server(14447);
2145     server.serveDirectory(testdata());
2146
2147     testType(qml,type,error);
2148 }
2149
2150 void tst_qqmllanguage::importsInstalled_data()
2151 {
2152     // QT-610
2153
2154     QTest::addColumn<QString>("qml");
2155     QTest::addColumn<QString>("type");
2156     QTest::addColumn<QString>("error");
2157
2158     // import installed
2159     QTest::newRow("installed import 0")
2160         << "import com.nokia.installedtest0 0.0\n"
2161            "InstalledTestTP {}"
2162         << "QQuickRectangle"
2163         << "";
2164     QTest::newRow("installed import 0 as TP")
2165         << "import com.nokia.installedtest0 0.0 as TP\n"
2166            "TP.InstalledTestTP {}"
2167         << "QQuickRectangle"
2168         << "";
2169     QTest::newRow("installed import 1")
2170         << "import com.nokia.installedtest 1.0\n"
2171            "InstalledTest {}"
2172         << "QQuickRectangle"
2173         << "";
2174     QTest::newRow("installed import 2")
2175         << "import com.nokia.installedtest 1.3\n"
2176            "InstalledTest {}"
2177         << "QQuickRectangle"
2178         << "";
2179     QTest::newRow("installed import 3")
2180         << "import com.nokia.installedtest 1.4\n"
2181            "InstalledTest {}"
2182         << "QQuickText"
2183         << "";
2184     QTest::newRow("installed import minor version not available") // QTBUG-11936
2185         << "import com.nokia.installedtest 0.1\n"
2186            "InstalledTest {}"
2187         << ""
2188         << "module \"com.nokia.installedtest\" version 0.1 is not installed";
2189     QTest::newRow("installed import minor version not available") // QTBUG-9627
2190         << "import com.nokia.installedtest 1.10\n"
2191            "InstalledTest {}"
2192         << ""
2193         << "module \"com.nokia.installedtest\" version 1.10 is not installed";
2194     QTest::newRow("installed import major version not available") // QTBUG-9627
2195         << "import com.nokia.installedtest 9.0\n"
2196            "InstalledTest {}"
2197         << ""
2198         << "module \"com.nokia.installedtest\" version 9.0 is not installed";
2199     QTest::newRow("installed import visibility") // QT-614
2200         << "import com.nokia.installedtest 1.4\n"
2201            "PrivateType {}"
2202         << ""
2203         << "PrivateType is not a type";
2204 }
2205
2206 void tst_qqmllanguage::importsInstalled()
2207 {
2208     QFETCH(QString, qml);
2209     QFETCH(QString, type);
2210     QFETCH(QString, error);
2211     testType(qml,type,error);
2212 }
2213
2214
2215 void tst_qqmllanguage::importsOrder_data()
2216 {
2217     QTest::addColumn<QString>("qml");
2218     QTest::addColumn<QString>("type");
2219     QTest::addColumn<QString>("error");
2220     QTest::addColumn<bool>("partialMatch");
2221
2222     QTest::newRow("double import") <<
2223            "import com.nokia.installedtest 1.4\n"
2224            "import com.nokia.installedtest 1.4\n"
2225            "InstalledTest {}"
2226            << (!qmlCheckTypes()?"QQuickText":"")
2227            << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.4")
2228            << false;
2229     QTest::newRow("installed import overrides 1") <<
2230            "import com.nokia.installedtest 1.0\n"
2231            "import com.nokia.installedtest 1.4\n"
2232            "InstalledTest {}"
2233            << (!qmlCheckTypes()?"QQuickText":"")
2234            << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.0")
2235            << false;
2236     QTest::newRow("installed import overrides 2") <<
2237            "import com.nokia.installedtest 1.4\n"
2238            "import com.nokia.installedtest 1.0\n"
2239            "InstalledTest {}"
2240            << (!qmlCheckTypes()?"QQuickRectangle":"")
2241            << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.0 and 1.4")
2242            << false;
2243     QTest::newRow("installed import re-overrides 1") <<
2244            "import com.nokia.installedtest 1.4\n"
2245            "import com.nokia.installedtest 1.0\n"
2246            "import com.nokia.installedtest 1.4\n"
2247            "InstalledTest {}"
2248            << (!qmlCheckTypes()?"QQuickText":"")
2249            << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.0")
2250            << false;
2251     QTest::newRow("installed import re-overrides 2") <<
2252            "import com.nokia.installedtest 1.4\n"
2253            "import com.nokia.installedtest 1.0\n"
2254            "import com.nokia.installedtest 1.4\n"
2255            "import com.nokia.installedtest 1.0\n"
2256            "InstalledTest {}"
2257            << (!qmlCheckTypes()?"QQuickRectangle":"")
2258            << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.0 and 1.4")
2259            << false;
2260     QTest::newRow("installed import versus builtin 1") <<
2261            "import com.nokia.installedtest 1.5\n"
2262            "import QtQuick 2.0\n"
2263            "Rectangle {}"
2264            << (!qmlCheckTypes()?"QQuickRectangle":"")
2265            << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in file://")
2266            << true;
2267     QTest::newRow("installed import versus builtin 2") <<
2268            "import QtQuick 2.0\n"
2269            "import com.nokia.installedtest 1.5\n"
2270            "Rectangle {}"
2271            << (!qmlCheckTypes()?"QQuickText":"")
2272            << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest/ and in file://")
2273            << true;
2274     QTest::newRow("namespaces cannot be overridden by types 1") <<
2275            "import QtQuick 2.0 as Rectangle\n"
2276            "import com.nokia.installedtest 1.5\n"
2277            "Rectangle {}"
2278            << ""
2279            << "Namespace Rectangle cannot be used as a type"
2280            << false;
2281     QTest::newRow("namespaces cannot be overridden by types 2") <<
2282            "import QtQuick 2.0 as Rectangle\n"
2283            "import com.nokia.installedtest 1.5\n"
2284            "Rectangle.Image {}"
2285            << "QQuickImage"
2286            << ""
2287            << false;
2288     QTest::newRow("local last 1") <<
2289            "LocalLast {}"
2290            << "QQuickText"
2291            << ""
2292            << false;
2293     QTest::newRow("local last 2") <<
2294            "import com.nokia.installedtest 1.0\n"
2295            "LocalLast {}"
2296            << (!qmlCheckTypes()?"QQuickRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
2297            << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest/ and in ")
2298            << false;
2299 }
2300
2301 void tst_qqmllanguage::importsOrder()
2302 {
2303     QFETCH(QString, qml);
2304     QFETCH(QString, type);
2305     QFETCH(QString, error);
2306     QFETCH(bool, partialMatch);
2307     testType(qml,type,error,partialMatch);
2308 }
2309
2310 void tst_qqmllanguage::importIncorrectCase()
2311 {
2312     QQmlComponent component(&engine, TEST_FILE("importIncorrectCase.qml"));
2313
2314     QList<QQmlError> errors = component.errors();
2315     QCOMPARE(errors.count(), 1);
2316
2317 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
2318     QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + testdata("lib/com/Nokia/installedtest/qmldir") + QLatin1String("\"");
2319 #else
2320     QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed");
2321 #endif
2322
2323     QCOMPARE(errors.at(0).description(), expectedError);
2324 }
2325
2326 void tst_qqmllanguage::importJs_data()
2327 {
2328     QTest::addColumn<QString>("file");
2329     QTest::addColumn<QString>("errorFile");
2330     QTest::addColumn<bool>("performTest");
2331
2332     QTest::newRow("defaultVersion")
2333         << "importJs.1.qml"
2334         << "importJs.1.errors.txt"
2335         << true;
2336
2337     QTest::newRow("specifiedVersion")
2338         << "importJs.2.qml"
2339         << "importJs.2.errors.txt"
2340         << true;
2341
2342     QTest::newRow("excludeExcessiveVersion")
2343         << "importJs.3.qml"
2344         << "importJs.3.errors.txt"
2345         << false;
2346
2347     QTest::newRow("includeAppropriateVersion")
2348         << "importJs.4.qml"
2349         << "importJs.4.errors.txt"
2350         << true;
2351
2352     QTest::newRow("noDefaultVersion")
2353         << "importJs.5.qml"
2354         << "importJs.5.errors.txt"
2355         << false;
2356
2357     QTest::newRow("repeatImportFails")
2358         << "importJs.6.qml"
2359         << "importJs.6.errors.txt"
2360         << false;
2361
2362     QTest::newRow("multipleVersionImportFails")
2363         << "importJs.7.qml"
2364         << "importJs.7.errors.txt"
2365         << false;
2366
2367     QTest::newRow("namespacedImport")
2368         << "importJs.8.qml"
2369         << "importJs.8.errors.txt"
2370         << true;
2371
2372     QTest::newRow("namespacedVersionedImport")
2373         << "importJs.9.qml"
2374         << "importJs.9.errors.txt"
2375         << true;
2376
2377     QTest::newRow("namespacedRepeatImport")
2378         << "importJs.10.qml"
2379         << "importJs.10.errors.txt"
2380         << true;
2381 }
2382
2383 void tst_qqmllanguage::importJs()
2384 {
2385     QFETCH(QString, file);
2386     QFETCH(QString, errorFile);
2387     QFETCH(bool, performTest);
2388
2389     QQmlComponent component(&engine, TEST_FILE(file));
2390
2391     {
2392         DETERMINE_ERRORS(errorFile.toLatin1().constData(),expected,actual);
2393         QCOMPARE(expected.size(), actual.size());
2394         for (int i = 0; i < expected.size(); ++i)
2395         {
2396             size_t compareLen = std::min(expected.at(i).length(), actual.at(i).length());
2397             QCOMPARE(expected.at(i).left(compareLen), actual.at(i).left(compareLen));
2398         }
2399     }
2400
2401     if (performTest) {
2402         QObject *object = component.create();
2403         QVERIFY(object != 0);
2404         QCOMPARE(object->property("test").toBool(),true);
2405         delete object;
2406     }
2407 }
2408
2409 void tst_qqmllanguage::qmlAttachedPropertiesObjectMethod()
2410 {
2411     QObject object;
2412
2413     QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
2414     QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
2415
2416     {
2417         QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml"));
2418         VERIFY_ERRORS(0);
2419         QObject *object = component.create();
2420         QVERIFY(object != 0);
2421
2422         QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(object, false), (QObject *)0);
2423         QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2424     }
2425
2426     {
2427         QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml"));
2428         VERIFY_ERRORS(0);
2429         QObject *object = component.create();
2430         QVERIFY(object != 0);
2431
2432         QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, false) != 0);
2433         QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2434     }
2435 }
2436
2437 void tst_qqmllanguage::crash1()
2438 {
2439     QQmlComponent component(&engine);
2440     component.setData("import QtQuick 2.0\nComponent {}", QUrl());
2441 }
2442
2443 void tst_qqmllanguage::crash2()
2444 {
2445     QQmlComponent component(&engine, TEST_FILE("crash2.qml"));
2446 }
2447
2448 // QTBUG-8676
2449 void tst_qqmllanguage::customOnProperty()
2450 {
2451     QQmlComponent component(&engine, TEST_FILE("customOnProperty.qml"));
2452
2453     VERIFY_ERRORS(0);
2454     QObject *object = component.create();
2455     QVERIFY(object != 0);
2456
2457     QCOMPARE(object->property("on").toInt(), 10);
2458
2459     delete object;
2460 }
2461
2462 // QTBUG-12601
2463 void tst_qqmllanguage::variantNotify()
2464 {
2465     QQmlComponent component(&engine, TEST_FILE("variantNotify.qml"));
2466
2467     VERIFY_ERRORS(0);
2468     QObject *object = component.create();
2469     QVERIFY(object != 0);
2470
2471     QCOMPARE(object->property("notifyCount").toInt(), 1);
2472
2473     delete object;
2474 }
2475
2476 void tst_qqmllanguage::revisions()
2477 {
2478     {
2479         QQmlComponent component(&engine, TEST_FILE("revisions11.qml"));
2480
2481         VERIFY_ERRORS(0);
2482         MyRevisionedClass *object = qobject_cast<MyRevisionedClass*>(component.create());
2483         QVERIFY(object != 0);
2484
2485         QCOMPARE(object->prop2(), 10.0);
2486
2487         delete object;
2488     }
2489     {
2490         QQmlEngine myEngine;
2491         QQmlComponent component(&myEngine, TEST_FILE("revisionssub11.qml"));
2492
2493         VERIFY_ERRORS(0);
2494         MyRevisionedSubclass *object = qobject_cast<MyRevisionedSubclass*>(component.create());
2495         QVERIFY(object != 0);
2496
2497         QCOMPARE(object->prop1(), 10.0);
2498         QCOMPARE(object->prop2(), 10.0);
2499         QCOMPARE(object->prop3(), 10.0);
2500         QCOMPARE(object->prop4(), 10.0);
2501
2502         delete object;
2503     }
2504     {
2505         QQmlComponent component(&engine, TEST_FILE("versionedbase.qml"));
2506         VERIFY_ERRORS(0);
2507         MySubclass *object = qobject_cast<MySubclass*>(component.create());
2508         QVERIFY(object != 0);
2509
2510         QCOMPARE(object->prop1(), 10.0);
2511         QCOMPARE(object->prop2(), 10.0);
2512
2513         delete object;
2514     }
2515 }
2516
2517 void tst_qqmllanguage::revisionOverloads()
2518 {
2519     {
2520     QQmlComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml"));
2521     VERIFY_ERRORS(0);
2522     }
2523     {
2524     QQmlComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml"));
2525     QEXPECT_FAIL("", "QTBUG-13849", Abort);
2526     QVERIFY(0);
2527     VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt");
2528     }
2529 }
2530
2531 void tst_qqmllanguage::initTestCase()
2532 {
2533     QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath();
2534     QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
2535
2536     registerTypes();
2537
2538     // Registering the TestType class in other modules should have no adverse effects
2539     qmlRegisterType<TestType>("com.nokia.TestPre", 1, 0, "Test");
2540
2541     qmlRegisterType<TestType>("com.nokia.Test", 0, 0, "TestTP");
2542     qmlRegisterType<TestType>("com.nokia.Test", 1, 0, "Test");
2543     qmlRegisterType<TestType>("com.nokia.Test", 1, 5, "Test");
2544     qmlRegisterType<TestType2>("com.nokia.Test", 1, 8, "Test");
2545     qmlRegisterType<TestType>("com.nokia.Test", 1, 9, "OldTest");
2546     qmlRegisterType<TestType2>("com.nokia.Test", 1, 12, "Test");
2547
2548     // Registering the TestType class in other modules should have no adverse effects
2549     qmlRegisterType<TestType>("com.nokia.TestPost", 1, 0, "Test");
2550
2551     // Create locale-specific file
2552     // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit
2553     // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters
2554     // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded
2555     QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile());
2556     QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString())));
2557     QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile());
2558     QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString())));
2559     out.write(in.readAll());
2560 }
2561
2562 void tst_qqmllanguage::aliasPropertyChangeSignals()
2563 {
2564     {
2565         QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.qml"));
2566
2567         VERIFY_ERRORS(0);
2568         QObject *o = component.create();
2569         QVERIFY(o != 0);
2570
2571         QCOMPARE(o->property("test").toBool(), true);
2572
2573         delete o;
2574     }
2575
2576     // QTCREATORBUG-2769
2577     {
2578         QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.2.qml"));
2579
2580         VERIFY_ERRORS(0);
2581         QObject *o = component.create();
2582         QVERIFY(o != 0);
2583
2584         QCOMPARE(o->property("test").toBool(), true);
2585
2586         delete o;
2587     }
2588 }
2589
2590 // Tests property initializers
2591 void tst_qqmllanguage::propertyInit()
2592 {
2593     {
2594         QQmlComponent component(&engine, TEST_FILE("propertyInit.1.qml"));
2595
2596         VERIFY_ERRORS(0);
2597         QObject *o = component.create();
2598         QVERIFY(o != 0);
2599
2600         QCOMPARE(o->property("test").toInt(), 1);
2601
2602         delete o;
2603     }
2604
2605     {
2606         QQmlComponent component(&engine, TEST_FILE("propertyInit.2.qml"));
2607
2608         VERIFY_ERRORS(0);
2609         QObject *o = component.create();
2610         QVERIFY(o != 0);
2611
2612         QCOMPARE(o->property("test").toInt(), 123);
2613
2614         delete o;
2615     }
2616 }
2617
2618 // Test that registration order doesn't break type availability
2619 // QTBUG-16878
2620 void tst_qqmllanguage::registrationOrder()
2621 {
2622     QQmlComponent component(&engine, TEST_FILE("registrationOrder.qml"));
2623
2624     QObject *o = component.create();
2625     QVERIFY(o != 0);
2626     QVERIFY(o->metaObject() == &MyVersion2Class::staticMetaObject);
2627     delete o;
2628 }
2629
2630 void tst_qqmllanguage::readonly()
2631 {
2632     QQmlComponent component(&engine, TEST_FILE("readonly.qml"));
2633
2634     QObject *o = component.create();
2635     QVERIFY(o != 0);
2636
2637     QCOMPARE(o->property("test1").toInt(), 10);
2638     QCOMPARE(o->property("test2").toInt(), 18);
2639     QCOMPARE(o->property("test3").toInt(), 13);
2640
2641     o->setProperty("testData", 13);
2642
2643     QCOMPARE(o->property("test1").toInt(), 10);
2644     QCOMPARE(o->property("test2").toInt(), 22);
2645     QCOMPARE(o->property("test3").toInt(), 13);
2646
2647     o->setProperty("testData2", 2);
2648
2649     QCOMPARE(o->property("test1").toInt(), 10);
2650     QCOMPARE(o->property("test2").toInt(), 22);
2651     QCOMPARE(o->property("test3").toInt(), 2);
2652
2653     o->setProperty("test1", 11);
2654     o->setProperty("test2", 11);
2655     o->setProperty("test3", 11);
2656
2657     QCOMPARE(o->property("test1").toInt(), 10);
2658     QCOMPARE(o->property("test2").toInt(), 22);
2659     QCOMPARE(o->property("test3").toInt(), 2);
2660
2661     delete o;
2662 }
2663
2664 void tst_qqmllanguage::receivers()
2665 {
2666     QQmlComponent component(&engine, TEST_FILE("receivers.qml"));
2667
2668     MyReceiversTestObject *o = qobject_cast<MyReceiversTestObject*>(component.create());
2669     QVERIFY(o != 0);
2670     QCOMPARE(o->mySignalCount(), 1);
2671     QCOMPARE(o->propChangedCount(), 2);
2672
2673     delete o;
2674 }
2675
2676 // QTBUG-18268
2677 void tst_qqmllanguage::remoteLoadCrash()
2678 {
2679     TestHTTPServer server(14448);
2680     server.serveDirectory(testdata());
2681
2682     QQmlComponent component(&engine);
2683     component.setData("import QtQuick 2.0; Text {}", QUrl("http://127.0.0.1:14448/remoteLoadCrash.qml"));
2684     while (component.isLoading()) 
2685         QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50);
2686
2687     QObject *o = component.create();
2688     delete o;
2689 }
2690
2691 void tst_qqmllanguage::signalWithDefaultArg()
2692 {
2693     QQmlComponent component(&engine, TEST_FILE("signalWithDefaultArg.qml"));
2694
2695     MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2696     QVERIFY(object != 0);
2697
2698     QCOMPARE(object->property("signalCount").toInt(), 0);
2699     QCOMPARE(object->property("signalArg").toInt(), 0);
2700
2701     emit object->signalWithDefaultArg();
2702     QCOMPARE(object-> property("signalCount").toInt(), 1);
2703     QCOMPARE(object->property("signalArg").toInt(), 5);
2704
2705     emit object->signalWithDefaultArg(15);
2706     QCOMPARE(object->property("signalCount").toInt(), 2);
2707     QCOMPARE(object->property("signalArg").toInt(), 15);
2708
2709     const QMetaObject *metaObject = object->metaObject();
2710
2711     metaObject->invokeMethod(object, "emitNoArgSignal");
2712     QCOMPARE(object->property("signalCount").toInt(), 3);
2713     QCOMPARE(object->property("signalArg").toInt(), 5);
2714
2715     metaObject->invokeMethod(object, "emitArgSignal");
2716     QCOMPARE(object->property("signalCount").toInt(), 4);
2717     QCOMPARE(object->property("signalArg").toInt(), 22);
2718
2719     delete object;
2720 }
2721
2722 // QTBUG-20639
2723 void tst_qqmllanguage::globalEnums()
2724 {
2725     qRegisterMetaType<MyEnum1Class::EnumA>();
2726     qRegisterMetaType<MyEnum2Class::EnumB>();
2727     qRegisterMetaType<Qt::TextFormat>();
2728
2729     QQmlComponent component(&engine, TEST_FILE("globalEnums.qml"));
2730
2731     QObject *o = component.create();
2732     QVERIFY(o != 0);
2733
2734     MyEnum1Class *enum1Class = o->findChild<MyEnum1Class *>(QString::fromLatin1("enum1Class"));
2735     QVERIFY(enum1Class != 0);
2736     QVERIFY(enum1Class->getValue() == -1);
2737
2738     MyEnumDerivedClass *enum2Class = o->findChild<MyEnumDerivedClass *>(QString::fromLatin1("enumDerivedClass"));
2739     QVERIFY(enum2Class != 0);
2740     QVERIFY(enum2Class->getValueA() == -1);
2741     QVERIFY(enum2Class->getValueB() == -1);
2742     QVERIFY(enum2Class->getValueC() == 0);
2743     QVERIFY(enum2Class->getValueD() == 0);
2744     QVERIFY(enum2Class->getValueE() == -1);
2745     QVERIFY(enum2Class->getValueE2() == -1);
2746
2747     QVERIFY(enum2Class->property("aValue") == 0);
2748     QVERIFY(enum2Class->property("bValue") == 0);
2749     QVERIFY(enum2Class->property("cValue") == 0);
2750     QVERIFY(enum2Class->property("dValue") == 0);
2751     QVERIFY(enum2Class->property("eValue") == 0);
2752     QVERIFY(enum2Class->property("e2Value") == 0);
2753
2754     QSignalSpy signalA(enum2Class, SIGNAL(valueAChanged(MyEnum1Class::EnumA)));
2755     QSignalSpy signalB(enum2Class, SIGNAL(valueBChanged(MyEnum2Class::EnumB)));
2756
2757     QMetaObject::invokeMethod(o, "setEnumValues");
2758
2759     QVERIFY(enum1Class->getValue() == MyEnum1Class::A_13);
2760     QVERIFY(enum2Class->getValueA() == MyEnum1Class::A_11);
2761     QVERIFY(enum2Class->getValueB() == MyEnum2Class::B_37);
2762     QVERIFY(enum2Class->getValueC() == Qt::RichText);
2763     QVERIFY(enum2Class->getValueD() == Qt::ElideMiddle);
2764     QVERIFY(enum2Class->getValueE() == MyEnum2Class::E_14);
2765     QVERIFY(enum2Class->getValueE2() == MyEnum2Class::E_76);
2766
2767     QVERIFY(signalA.count() == 1);
2768     QVERIFY(signalB.count() == 1);
2769
2770     QVERIFY(enum2Class->property("aValue") == MyEnum1Class::A_11);
2771     QVERIFY(enum2Class->property("bValue") == 37);
2772     QVERIFY(enum2Class->property("cValue") == 1);
2773     QVERIFY(enum2Class->property("dValue") == 2);
2774     QVERIFY(enum2Class->property("eValue") == 14);
2775     QVERIFY(enum2Class->property("e2Value") == 76);
2776
2777     delete o;
2778 }
2779
2780 QTEST_MAIN(tst_qqmllanguage)
2781
2782 #include "tst_qqmllanguage.moc"