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