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