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