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