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