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