1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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>
51 #include <private/qqmlproperty_p.h>
52 #include <private/qqmlmetatype_p.h>
53 #include <private/qqmlglobal_p.h>
55 #include "testtypes.h"
56 #include "testhttpserver.h"
58 DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
61 Returns the path to some testdata file or directory.
63 QString testdata(QString const& name = QString())
65 static const QString dataDirectory = QDir::currentPath() + QLatin1String("/data");
66 QString result = dataDirectory;
67 if (!name.isEmpty()) {
68 result += QLatin1Char('/');
75 This test case covers QML language issues. This covers everything that does not
76 involve evaluating ECMAScript expressions and bindings.
78 Evaluation of expressions and bindings is covered in qmlecmascript
80 class tst_qqmllanguage : public QObject
85 QQmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
86 engine.addImportPath(testdata("lib"));
91 void cleanupTestCase();
96 void insertedSemicolon_data();
97 void insertedSemicolon();
100 void simpleContainer();
101 void interfaceProperty();
102 void interfaceQList();
103 void assignObjectToSignal();
104 void assignObjectToVariant();
105 void assignLiteralSignalProperty();
106 void assignQmlComponent();
107 void assignBasicTypes();
108 void assignTypeExtremes();
109 void assignCompositeToType();
110 void assignLiteralToVariant();
111 void assignLiteralToVar();
112 void customParserTypes();
113 void rootAsQmlComponent();
114 void inlineQmlComponents();
116 void autoNotifyConnection();
118 void dynamicProperties();
119 void dynamicPropertiesNested();
120 void listProperties();
121 void dynamicObjectProperties();
122 void dynamicSignalsAndSlots();
123 void simpleBindings();
124 void autoComponentCreation();
125 void propertyValueSource();
126 void attachedProperties();
127 void dynamicObjects();
128 void customVariantTypes();
131 void aliasProperties();
132 void aliasPropertiesAndSignals();
133 void aliasPropertyChangeSignals();
134 void componentCompositeType();
138 void onDestruction();
140 void defaultPropertyListOrder();
141 void declaredPropertyValues();
142 void dontDoubleCallClassBegin();
143 void reservedWords_data();
144 void reservedWords();
145 void inlineAssignmentsOverrideBindings();
146 void nestedComponentRoots();
147 void registrationOrder();
150 void basicRemote_data();
152 void importsBuiltin_data();
153 void importsBuiltin();
154 void importsLocal_data();
156 void importsRemote_data();
157 void importsRemote();
158 void importsInstalled_data();
159 void importsInstalled();
160 void importsOrder_data();
162 void importIncorrectCase();
163 void importJs_data();
166 void qmlAttachedPropertiesObjectMethod();
167 void customOnProperty();
168 void variantNotify();
171 void revisionOverloads();
174 void remoteLoadCrash();
176 // regression tests for crashes
184 void testType(const QString& qml, const QString& type, const QString& error);
187 #define DETERMINE_ERRORS(errorfile,expected,actual)\
188 QList<QByteArray> expected; \
189 QList<QByteArray> actual; \
191 QFile file(testdata(QLatin1String(errorfile))); \
192 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
193 QByteArray data = file.readAll(); \
195 expected = data.split('\n'); \
196 expected.removeAll(QByteArray("")); \
197 QList<QQmlError> errors = component.errors(); \
198 for (int ii = 0; ii < errors.count(); ++ii) { \
199 const QQmlError &error = errors.at(ii); \
200 QByteArray errorStr = QByteArray::number(error.line()) + ":" + \
201 QByteArray::number(error.column()) + ":" + \
202 error.description().toUtf8(); \
203 actual << errorStr; \
207 #define VERIFY_ERRORS(errorfile) \
209 if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
210 qWarning() << "Unexpected Errors:" << component.errors(); \
211 QVERIFY(!component.isError()); \
212 QVERIFY(component.errors().isEmpty()); \
214 DETERMINE_ERRORS(errorfile,actual,expected);\
215 if (qgetenv("DEBUG") != "" && expected != actual) \
216 qWarning() << "Expected:" << expected << "Actual:" << actual; \
217 if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
218 QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
219 QVERIFY(file.open(QIODevice::WriteOnly)); \
220 for (int ii = 0; ii < actual.count(); ++ii) { \
221 file.write(actual.at(ii)); file.write("\n"); \
225 QCOMPARE(expected, actual); \
229 inline QUrl TEST_FILE(const QString &filename)
231 return QUrl::fromLocalFile(testdata(filename));
234 inline QUrl TEST_FILE(const char *filename)
236 return TEST_FILE(QLatin1String(filename));
239 void tst_qqmllanguage::cleanupTestCase()
241 QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()));
244 void tst_qqmllanguage::insertedSemicolon_data()
246 QTest::addColumn<QString>("file");
247 QTest::addColumn<QString>("errorFile");
248 QTest::addColumn<bool>("create");
250 QTest::newRow("insertedSemicolon.1") << "insertedSemicolon.1.qml" << "insertedSemicolon.1.errors.txt" << false;
253 void tst_qqmllanguage::insertedSemicolon()
255 QFETCH(QString, file);
256 QFETCH(QString, errorFile);
257 QFETCH(bool, create);
259 QQmlComponent component(&engine, TEST_FILE(file));
262 QObject *object = component.create();
263 QVERIFY(object == 0);
266 VERIFY_ERRORS(errorFile.toLatin1().constData());
269 void tst_qqmllanguage::errors_data()
271 QTest::addColumn<QString>("file");
272 QTest::addColumn<QString>("errorFile");
273 QTest::addColumn<bool>("create");
275 QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false;
276 QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false;
277 QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false;
278 QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false;
279 QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false;
280 QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false;
282 QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false;
283 QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false;
284 QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false;
286 QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false;
287 QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false;
288 QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false;
289 QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false;
290 QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false;
291 QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false;
292 QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false;
293 QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false;
294 QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false;
295 QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false;
296 QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false;
297 QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false;
298 QTest::newRow("wrongType (invalid object)") << "wrongType.16.qml" << "wrongType.16.errors.txt" << false;
299 QTest::newRow("wrongType (int for enum)") << "wrongType.17.qml" << "wrongType.17.errors.txt" << false;
301 QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false;
302 QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false;
303 QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false;
304 QTest::newRow("readOnly.4") << "readOnly.4.qml" << "readOnly.4.errors.txt" << false;
305 QTest::newRow("readOnly.5") << "readOnly.5.qml" << "readOnly.5.errors.txt" << false;
307 QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false;
308 QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false;
309 QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false;
311 QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false;
312 QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false;
313 QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false;
314 QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false;
315 QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false;
316 QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false;
317 QTest::newRow("invalidID.7") << "invalidID.7.qml" << "invalidID.7.errors.txt" << false;
318 QTest::newRow("invalidID.8") << "invalidID.8.qml" << "invalidID.8.errors.txt" << false;
319 QTest::newRow("invalidID.9") << "invalidID.9.qml" << "invalidID.9.errors.txt" << false;
321 QTest::newRow("scriptString.1") << "scriptString.1.qml" << "scriptString.1.errors.txt" << false;
322 QTest::newRow("scriptString.2") << "scriptString.2.qml" << "scriptString.2.errors.txt" << false;
324 QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false;
325 QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true;
326 QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false;
327 QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false;
328 QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false;
329 QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false;
330 QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false;
331 QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false;
332 QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false;
333 QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
334 QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
336 QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
337 QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
338 QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
339 QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false;
340 QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false;
341 QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false;
342 QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true;
343 QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false;
344 QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false;
345 QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false;
347 QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false;
348 QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false;
349 QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false;
350 QTest::newRow("importNonExist (installed)") << "importNonExist.qml" << "importNonExist.errors.txt" << false;
351 QTest::newRow("importNonExistOlder (installed)") << "importNonExistOlder.qml" << "importNonExistOlder.errors.txt" << false;
352 QTest::newRow("importNewerVersion (installed)") << "importNewerVersion.qml" << "importNewerVersion.errors.txt" << false;
353 QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false;
354 QTest::newRow("importFile") << "importFile.qml" << "importFile.errors.txt" << false;
356 QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false;
357 QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false;
358 QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false;
359 QTest::newRow("signal.4") << "signal.4.qml" << "signal.4.errors.txt" << false;
360 QTest::newRow("signal.5") << "signal.5.qml" << "signal.5.errors.txt" << false;
362 QTest::newRow("method.1") << "method.1.qml" << "method.1.errors.txt" << false;
364 QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false;
365 QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false;
366 QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false;
367 QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false;
368 QTest::newRow("property.6") << "property.6.qml" << "property.6.errors.txt" << false;
369 QTest::newRow("property.7") << "property.7.qml" << "property.7.errors.txt" << false;
371 QTest::newRow("importScript.1") << "importscript.1.qml" << "importscript.1.errors.txt" << false;
373 QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false;
374 QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false;
375 QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false;
376 QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false;
377 QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false;
378 QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false;
379 QTest::newRow("Component.7") << "component.7.qml" << "component.7.errors.txt" << false;
380 QTest::newRow("Component.8") << "component.8.qml" << "component.8.errors.txt" << false;
381 QTest::newRow("Component.9") << "component.9.qml" << "component.9.errors.txt" << false;
383 QTest::newRow("MultiSet.1") << "multiSet.1.qml" << "multiSet.1.errors.txt" << false;
384 QTest::newRow("MultiSet.2") << "multiSet.2.qml" << "multiSet.2.errors.txt" << false;
385 QTest::newRow("MultiSet.3") << "multiSet.3.qml" << "multiSet.3.errors.txt" << false;
386 QTest::newRow("MultiSet.4") << "multiSet.4.qml" << "multiSet.4.errors.txt" << false;
387 QTest::newRow("MultiSet.5") << "multiSet.5.qml" << "multiSet.5.errors.txt" << false;
388 QTest::newRow("MultiSet.6") << "multiSet.6.qml" << "multiSet.6.errors.txt" << false;
389 QTest::newRow("MultiSet.7") << "multiSet.7.qml" << "multiSet.7.errors.txt" << false;
390 QTest::newRow("MultiSet.8") << "multiSet.8.qml" << "multiSet.8.errors.txt" << false;
391 QTest::newRow("MultiSet.9") << "multiSet.9.qml" << "multiSet.9.errors.txt" << false;
392 QTest::newRow("MultiSet.10") << "multiSet.10.qml" << "multiSet.10.errors.txt" << false;
393 QTest::newRow("MultiSet.11") << "multiSet.11.qml" << "multiSet.11.errors.txt" << false;
395 QTest::newRow("dynamicMeta.1") << "dynamicMeta.1.qml" << "dynamicMeta.1.errors.txt" << false;
396 QTest::newRow("dynamicMeta.2") << "dynamicMeta.2.qml" << "dynamicMeta.2.errors.txt" << false;
397 QTest::newRow("dynamicMeta.3") << "dynamicMeta.3.qml" << "dynamicMeta.3.errors.txt" << false;
398 QTest::newRow("dynamicMeta.4") << "dynamicMeta.4.qml" << "dynamicMeta.4.errors.txt" << false;
399 QTest::newRow("dynamicMeta.5") << "dynamicMeta.5.qml" << "dynamicMeta.5.errors.txt" << false;
401 QTest::newRow("invalidAlias.1") << "invalidAlias.1.qml" << "invalidAlias.1.errors.txt" << false;
402 QTest::newRow("invalidAlias.2") << "invalidAlias.2.qml" << "invalidAlias.2.errors.txt" << false;
403 QTest::newRow("invalidAlias.3") << "invalidAlias.3.qml" << "invalidAlias.3.errors.txt" << false;
404 QTest::newRow("invalidAlias.4") << "invalidAlias.4.qml" << "invalidAlias.4.errors.txt" << false;
405 QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false;
406 QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false;
407 QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false;
408 QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false;
409 QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false;
410 QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false;
412 QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
413 QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
414 QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false;
415 QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false;
416 QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false;
417 QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false;
418 QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false;
419 QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false;
420 QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false;
421 QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false;
422 QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false;
423 QTest::newRow("invalidAttachedProperty.12") << "invalidAttachedProperty.12.qml" << "invalidAttachedProperty.12.errors.txt" << false;
424 QTest::newRow("invalidAttachedProperty.13") << "invalidAttachedProperty.13.qml" << "invalidAttachedProperty.13.errors.txt" << false;
426 QTest::newRow("assignValueToSignal") << "assignValueToSignal.qml" << "assignValueToSignal.errors.txt" << false;
427 QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false;
429 QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false;
430 QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false;
431 QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false;
432 QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false;
433 QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false;
434 QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false;
435 QTest::newRow("noCreation") << "noCreation.qml" << "noCreation.errors.txt" << false;
436 QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false;
437 QTest::newRow("assignToNamespace") << "assignToNamespace.qml" << "assignToNamespace.errors.txt" << false;
438 QTest::newRow("invalidOn") << "invalidOn.qml" << "invalidOn.errors.txt" << false;
439 QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false;
440 QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false;
441 QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false;
442 QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
443 QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
444 QTest::newRow("incorrectCase") << "incorrectCase.qml"
445 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
446 << "incorrectCase.errors.insensitive.txt"
448 << "incorrectCase.errors.sensitive.txt"
452 QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false;
453 QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false;
454 QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false;
456 QTest::newRow("invalidRoot.1") << "invalidRoot.1.qml" << "invalidRoot.1.errors.txt" << false;
457 QTest::newRow("invalidRoot.2") << "invalidRoot.2.qml" << "invalidRoot.2.errors.txt" << false;
458 QTest::newRow("invalidRoot.3") << "invalidRoot.3.qml" << "invalidRoot.3.errors.txt" << false;
459 QTest::newRow("invalidRoot.4") << "invalidRoot.4.qml" << "invalidRoot.4.errors.txt" << false;
461 QTest::newRow("invalidTypeName.1") << "invalidTypeName.1.qml" << "invalidTypeName.1.errors.txt" << false;
462 QTest::newRow("invalidTypeName.2") << "invalidTypeName.2.qml" << "invalidTypeName.2.errors.txt" << false;
463 QTest::newRow("invalidTypeName.3") << "invalidTypeName.3.qml" << "invalidTypeName.3.errors.txt" << false;
464 QTest::newRow("invalidTypeName.4") << "invalidTypeName.4.qml" << "invalidTypeName.4.errors.txt" << false;
466 QTest::newRow("Major version isolation") << "majorVersionIsolation.qml" << "majorVersionIsolation.errors.txt" << false;
470 void tst_qqmllanguage::errors()
472 QFETCH(QString, file);
473 QFETCH(QString, errorFile);
474 QFETCH(bool, create);
476 QQmlComponent component(&engine, TEST_FILE(file));
479 QObject *object = component.create();
480 QVERIFY(object == 0);
483 VERIFY_ERRORS(errorFile.toLatin1().constData());
486 void tst_qqmllanguage::simpleObject()
488 QQmlComponent component(&engine, TEST_FILE("simpleObject.qml"));
490 QObject *object = component.create();
491 QVERIFY(object != 0);
494 void tst_qqmllanguage::simpleContainer()
496 QQmlComponent component(&engine, TEST_FILE("simpleContainer.qml"));
498 MyContainer *container= qobject_cast<MyContainer*>(component.create());
499 QVERIFY(container != 0);
500 QCOMPARE(container->getChildren()->count(),2);
503 void tst_qqmllanguage::interfaceProperty()
505 QQmlComponent component(&engine, TEST_FILE("interfaceProperty.qml"));
507 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
508 QVERIFY(object != 0);
509 QVERIFY(object->interface());
510 QVERIFY(object->interface()->id == 913);
513 void tst_qqmllanguage::interfaceQList()
515 QQmlComponent component(&engine, TEST_FILE("interfaceQList.qml"));
517 MyContainer *container= qobject_cast<MyContainer*>(component.create());
518 QVERIFY(container != 0);
519 QVERIFY(container->getQListInterfaces()->count() == 2);
520 for(int ii = 0; ii < 2; ++ii)
521 QVERIFY(container->getQListInterfaces()->at(ii)->id == 913);
524 void tst_qqmllanguage::assignObjectToSignal()
526 QQmlComponent component(&engine, TEST_FILE("assignObjectToSignal.qml"));
528 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
529 QVERIFY(object != 0);
530 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
531 emit object->basicSignal();
534 void tst_qqmllanguage::assignObjectToVariant()
536 QQmlComponent component(&engine, TEST_FILE("assignObjectToVariant.qml"));
538 QObject *object = component.create();
539 QVERIFY(object != 0);
540 QVariant v = object->property("a");
541 QVERIFY(v.userType() == qMetaTypeId<QObject *>());
544 void tst_qqmllanguage::assignLiteralSignalProperty()
546 QQmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml"));
548 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
549 QVERIFY(object != 0);
550 QCOMPARE(object->onLiteralSignal(), 10);
553 // Test is an external component can be loaded and assigned (to a qlist)
554 void tst_qqmllanguage::assignQmlComponent()
556 QQmlComponent component(&engine, TEST_FILE("assignQmlComponent.qml"));
558 MyContainer *object = qobject_cast<MyContainer *>(component.create());
559 QVERIFY(object != 0);
560 QVERIFY(object->getChildren()->count() == 1);
561 QObject *child = object->getChildren()->at(0);
562 QCOMPARE(child->property("x"), QVariant(10));
563 QCOMPARE(child->property("y"), QVariant(11));
566 // Test literal assignment to all the basic types
567 void tst_qqmllanguage::assignBasicTypes()
569 QQmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
571 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
572 QVERIFY(object != 0);
573 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
574 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
575 QCOMPARE(object->stringProperty(), QString("Hello World!"));
576 QCOMPARE(object->uintProperty(), uint(10));
577 QCOMPARE(object->intProperty(), -19);
578 QCOMPARE((float)object->realProperty(), float(23.2));
579 QCOMPARE((float)object->doubleProperty(), float(-19.7));
580 QCOMPARE((float)object->floatProperty(), float(8.5));
581 QCOMPARE(object->colorProperty(), QColor("red"));
582 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
583 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
584 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
585 QCOMPARE(object->pointProperty(), QPoint(99,13));
586 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
587 QCOMPARE(object->sizeProperty(), QSize(99, 13));
588 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
589 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
590 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
591 QCOMPARE(object->boolProperty(), true);
592 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
593 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
594 QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2, 2.3));
596 encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
597 QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
598 QVERIFY(object->objectProperty() != 0);
599 MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
601 QCOMPARE(child->intProperty(), 8);
604 // Test edge case type assignments
605 void tst_qqmllanguage::assignTypeExtremes()
607 QQmlComponent component(&engine, TEST_FILE("assignTypeExtremes.qml"));
609 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
610 QVERIFY(object != 0);
611 QCOMPARE(object->uintProperty(), 0xEE6B2800);
612 QCOMPARE(object->intProperty(), -0x77359400);
615 // Test that a composite type can assign to a property of its base type
616 void tst_qqmllanguage::assignCompositeToType()
618 QQmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml"));
620 QObject *object = component.create();
621 QVERIFY(object != 0);
624 // Test that literals are stored correctly in variant properties
625 void tst_qqmllanguage::assignLiteralToVariant()
627 QQmlComponent component(&engine, TEST_FILE("assignLiteralToVariant.qml"));
629 QObject *object = component.create();
630 QVERIFY(object != 0);
632 QCOMPARE(object->property("test1").userType(), (int)QVariant::Int);
633 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
634 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
635 QCOMPARE(object->property("test4").userType(), (int)QVariant::Color);
636 QCOMPARE(object->property("test5").userType(), (int)QVariant::RectF);
637 QCOMPARE(object->property("test6").userType(), (int)QVariant::PointF);
638 QCOMPARE(object->property("test7").userType(), (int)QVariant::SizeF);
639 QCOMPARE(object->property("test8").userType(), (int)QVariant::Vector3D);
640 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
641 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
642 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
643 QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D);
645 QVERIFY(object->property("test1") == QVariant(1));
646 QVERIFY(object->property("test2") == QVariant((double)1.7));
647 QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!"))));
648 QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800)));
649 QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10)));
650 QVERIFY(object->property("test6") == QVariant(QPointF(10, 10)));
651 QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10)));
652 QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100)));
653 QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800"))));
654 QVERIFY(object->property("test10") == QVariant(bool(true)));
655 QVERIFY(object->property("test11") == QVariant(bool(false)));
656 QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100)));
661 // Test that literals are stored correctly in "var" properties
662 // Note that behaviour differs from "variant" properties in that
663 // no conversion from "special strings" to QVariants is performed.
664 void tst_qqmllanguage::assignLiteralToVar()
666 QQmlComponent component(&engine, TEST_FILE("assignLiteralToVar.qml"));
668 QObject *object = component.create();
669 QVERIFY(object != 0);
671 QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
672 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
673 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
674 QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
675 QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
676 QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
677 QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
678 QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
679 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
680 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
681 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
682 QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
683 QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
684 QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
685 QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
686 QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
687 QCOMPARE(object->property("variantTest1Bound").userType(), (int)QMetaType::Int);
688 QCOMPARE(object->property("test1Bound").userType(), (int)QMetaType::Int);
690 QCOMPARE(object->property("test1"), QVariant(5));
691 QCOMPARE(object->property("test2"), QVariant((double)1.7));
692 QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
693 QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
694 QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
695 QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
696 QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
697 QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
698 QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
699 QCOMPARE(object->property("test10"), QVariant(bool(true)));
700 QCOMPARE(object->property("test11"), QVariant(bool(false)));
701 QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
702 QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
703 QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
704 QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
705 QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
706 QCOMPARE(object->property("variantTest1Bound"), QVariant(9));
707 QCOMPARE(object->property("test1Bound"), QVariant(11));
712 // Tests that custom parser types can be instantiated
713 void tst_qqmllanguage::customParserTypes()
715 QQmlComponent component(&engine, TEST_FILE("customParserTypes.qml"));
717 QObject *object = component.create();
718 QVERIFY(object != 0);
719 QVERIFY(object->property("count") == QVariant(2));
722 // Tests that the root item can be a custom component
723 void tst_qqmllanguage::rootAsQmlComponent()
725 QQmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml"));
727 MyContainer *object = qobject_cast<MyContainer *>(component.create());
728 QVERIFY(object != 0);
729 QCOMPARE(object->property("x"), QVariant(11));
730 QCOMPARE(object->getChildren()->count(), 2);
733 // Tests that components can be specified inline
734 void tst_qqmllanguage::inlineQmlComponents()
736 QQmlComponent component(&engine, TEST_FILE("inlineQmlComponents.qml"));
738 MyContainer *object = qobject_cast<MyContainer *>(component.create());
739 QVERIFY(object != 0);
740 QCOMPARE(object->getChildren()->count(), 1);
741 QQmlComponent *comp = qobject_cast<QQmlComponent *>(object->getChildren()->at(0));
743 MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
744 QVERIFY(compObject != 0);
745 QCOMPARE(compObject->value(), 11);
748 // Tests that types that have an id property have it set
749 void tst_qqmllanguage::idProperty()
751 QQmlComponent component(&engine, TEST_FILE("idProperty.qml"));
753 MyContainer *object = qobject_cast<MyContainer *>(component.create());
754 QVERIFY(object != 0);
755 QCOMPARE(object->getChildren()->count(), 1);
756 MyTypeObject *child =
757 qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
759 QCOMPARE(child->id(), QString("myObjectId"));
760 QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
763 // Tests automatic connection to notify signals if "onBlahChanged" syntax is used
764 // even if the notify signal for "blah" is not called "blahChanged"
765 void tst_qqmllanguage::autoNotifyConnection()
767 QQmlComponent component(&engine, TEST_FILE("autoNotifyConnection.qml"));
769 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
770 QVERIFY(object != 0);
771 QMetaProperty prop = object->metaObject()->property(object->metaObject()->indexOfProperty("receivedNotify"));
772 QVERIFY(prop.isValid());
774 QCOMPARE(prop.read(object), QVariant::fromValue(false));
775 object->setPropertyWithNotify(1);
776 QCOMPARE(prop.read(object), QVariant::fromValue(true));
779 // Tests that signals can be assigned to
780 void tst_qqmllanguage::assignSignal()
782 QQmlComponent component(&engine, TEST_FILE("assignSignal.qml"));
784 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
785 QVERIFY(object != 0);
786 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
787 emit object->basicSignal();
788 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
789 emit object->basicParameterizedSignal(9);
792 // Tests the creation and assignment of dynamic properties
793 void tst_qqmllanguage::dynamicProperties()
795 QQmlComponent component(&engine, TEST_FILE("dynamicProperties.qml"));
797 QObject *object = component.create();
798 QVERIFY(object != 0);
799 QCOMPARE(object->property("intProperty"), QVariant(10));
800 QCOMPARE(object->property("boolProperty"), QVariant(false));
801 QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
802 QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
803 QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
804 QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml")));
805 QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
806 QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
807 QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
810 // Test that nested types can use dynamic properties
811 void tst_qqmllanguage::dynamicPropertiesNested()
813 QQmlComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml"));
815 QObject *object = component.create();
816 QVERIFY(object != 0);
818 QCOMPARE(object->property("super_a").toInt(), 11); // Overridden
819 QCOMPARE(object->property("super_c").toInt(), 14); // Inherited
820 QCOMPARE(object->property("a").toInt(), 13); // New
821 QCOMPARE(object->property("b").toInt(), 12); // New
826 // Tests the creation and assignment to dynamic list properties
827 void tst_qqmllanguage::listProperties()
829 QQmlComponent component(&engine, TEST_FILE("listProperties.qml"));
831 QObject *object = component.create();
832 QVERIFY(object != 0);
834 QCOMPARE(object->property("test").toInt(), 2);
837 // Tests the creation and assignment of dynamic object properties
839 void tst_qqmllanguage::dynamicObjectProperties()
842 QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
844 QObject *object = component.create();
845 QVERIFY(object != 0);
847 QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
848 QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
851 QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.2.qml"));
852 QEXPECT_FAIL("", "QTBUG-10822", Abort);
854 QObject *object = component.create();
855 QVERIFY(object != 0);
857 QVERIFY(object->property("objectProperty") != qVariantFromValue((QObject*)0));
861 // Tests the declaration of dynamic signals and slots
862 void tst_qqmllanguage::dynamicSignalsAndSlots()
864 QTest::ignoreMessage(QtDebugMsg, "1921");
866 QQmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml"));
868 QObject *object = component.create();
869 QVERIFY(object != 0);
870 QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
871 QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
872 QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
873 QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
875 QCOMPARE(object->property("test").toInt(), 0);
876 QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10)));
877 QCOMPARE(object->property("test").toInt(), 10);
880 void tst_qqmllanguage::simpleBindings()
882 QQmlComponent component(&engine, TEST_FILE("simpleBindings.qml"));
884 QObject *object = component.create();
885 QVERIFY(object != 0);
886 QCOMPARE(object->property("value1"), QVariant(10));
887 QCOMPARE(object->property("value2"), QVariant(10));
888 QCOMPARE(object->property("value3"), QVariant(21));
889 QCOMPARE(object->property("value4"), QVariant(10));
890 QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
893 void tst_qqmllanguage::autoComponentCreation()
895 QQmlComponent component(&engine, TEST_FILE("autoComponentCreation.qml"));
897 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
898 QVERIFY(object != 0);
899 QVERIFY(object->componentProperty() != 0);
900 MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
902 QCOMPARE(child->realProperty(), qreal(9));
905 void tst_qqmllanguage::propertyValueSource()
908 QQmlComponent component(&engine, TEST_FILE("propertyValueSource.qml"));
910 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
911 QVERIFY(object != 0);
913 QList<QObject *> valueSources;
914 QObjectList allChildren = object->findChildren<QObject*>();
915 foreach (QObject *child, allChildren) {
916 if (qobject_cast<QQmlPropertyValueSource *>(child))
917 valueSources.append(child);
920 QCOMPARE(valueSources.count(), 1);
921 MyPropertyValueSource *valueSource =
922 qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
923 QVERIFY(valueSource != 0);
924 QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
925 QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
929 QQmlComponent component(&engine, TEST_FILE("propertyValueSource.2.qml"));
931 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
932 QVERIFY(object != 0);
934 QList<QObject *> valueSources;
935 QObjectList allChildren = object->findChildren<QObject*>();
936 foreach (QObject *child, allChildren) {
937 if (qobject_cast<QQmlPropertyValueSource *>(child))
938 valueSources.append(child);
941 QCOMPARE(valueSources.count(), 1);
942 MyPropertyValueSource *valueSource =
943 qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
944 QVERIFY(valueSource != 0);
945 QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
946 QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
950 void tst_qqmllanguage::attachedProperties()
952 QQmlComponent component(&engine, TEST_FILE("attachedProperties.qml"));
954 QObject *object = component.create();
955 QVERIFY(object != 0);
956 QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
957 QVERIFY(attached != 0);
958 QCOMPARE(attached->property("value"), QVariant(10));
959 QCOMPARE(attached->property("value2"), QVariant(13));
962 // Tests non-static object properties
963 void tst_qqmllanguage::dynamicObjects()
965 QQmlComponent component(&engine, TEST_FILE("dynamicObject.1.qml"));
967 QObject *object = component.create();
968 QVERIFY(object != 0);
971 // Tests the registration of custom variant string converters
972 void tst_qqmllanguage::customVariantTypes()
974 QQmlComponent component(&engine, TEST_FILE("customVariantTypes.qml"));
976 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
977 QVERIFY(object != 0);
978 QCOMPARE(object->customType().a, 10);
981 void tst_qqmllanguage::valueTypes()
983 QQmlComponent component(&engine, TEST_FILE("valueTypes.qml"));
986 QString message = component.url().toString() + ":2:1: QML MyTypeObject: Binding loop detected for property \"rectProperty.width\"";
987 QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
988 QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
990 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
991 QVERIFY(object != 0);
994 QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13));
995 QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13));
996 QCOMPARE(object->intProperty(), 10);
998 QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13));
999 QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13));
1000 QCOMPARE(object->intProperty(), 12);
1004 QQmlProperty p(object, "rectProperty.x");
1005 QCOMPARE(p.read(), QVariant(12));
1007 QCOMPARE(p.read(), QVariant(13));
1009 quint32 r = QQmlPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex());
1011 QQmlPropertyPrivate::restore(p2, r, object);
1012 QCOMPARE(p2.read(), QVariant(13));
1016 void tst_qqmllanguage::cppnamespace()
1019 QQmlComponent component(&engine, TEST_FILE("cppnamespace.qml"));
1021 QObject *object = component.create();
1022 QVERIFY(object != 0);
1027 QQmlComponent component(&engine, TEST_FILE("cppnamespace.2.qml"));
1029 QObject *object = component.create();
1030 QVERIFY(object != 0);
1035 void tst_qqmllanguage::aliasProperties()
1037 // Simple "int" alias
1039 QQmlComponent component(&engine, TEST_FILE("alias.1.qml"));
1041 QObject *object = component.create();
1042 QVERIFY(object != 0);
1044 // Read through alias
1045 QCOMPARE(object->property("valueAlias").toInt(), 10);
1046 object->setProperty("value", QVariant(13));
1047 QCOMPARE(object->property("valueAlias").toInt(), 13);
1049 // Write through alias
1050 object->setProperty("valueAlias", QVariant(19));
1051 QCOMPARE(object->property("valueAlias").toInt(), 19);
1052 QCOMPARE(object->property("value").toInt(), 19);
1057 // Complex object alias
1059 QQmlComponent component(&engine, TEST_FILE("alias.2.qml"));
1061 QObject *object = component.create();
1062 QVERIFY(object != 0);
1064 // Read through alias
1066 qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1068 QCOMPARE(v->value(), 10);
1070 // Write through alias
1071 MyQmlObject *v2 = new MyQmlObject();
1072 v2->setParent(object);
1073 object->setProperty("aliasObject", qVariantFromValue(v2));
1075 qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1084 QQmlComponent component(&engine, TEST_FILE("alias.3.qml"));
1086 QObject *object = component.create();
1087 QVERIFY(object != 0);
1089 QCOMPARE(object->property("value").toInt(), 1892);
1090 QCOMPARE(object->property("value2").toInt(), 1892);
1092 object->setProperty("value", QVariant(1313));
1093 QCOMPARE(object->property("value").toInt(), 1313);
1094 QCOMPARE(object->property("value2").toInt(), 1313);
1096 object->setProperty("value2", QVariant(8080));
1097 QCOMPARE(object->property("value").toInt(), 8080);
1098 QCOMPARE(object->property("value2").toInt(), 8080);
1105 QQmlComponent component(&engine, TEST_FILE("alias.4.qml"));
1107 QObject *object = component.create();
1108 QVERIFY(object != 0);
1110 QCOMPARE(object->property("enumAlias").toInt(), 1);
1117 QQmlComponent component(&engine, TEST_FILE("alias.5.qml"));
1119 QObject *object = component.create();
1120 QVERIFY(object != 0);
1122 QVariant v = object->property("otherAlias");
1123 QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1124 MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
1125 QCOMPARE(o->value(), 10);
1129 v = object->property("otherAlias");
1130 QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1131 o = qvariant_cast<MyQmlObject*>(v);
1137 // Nested aliases - this used to cause a crash
1139 QQmlComponent component(&engine, TEST_FILE("alias.6.qml"));
1141 QObject *object = component.create();
1142 QVERIFY(object != 0);
1144 QCOMPARE(object->property("a").toInt(), 1923);
1147 // Ptr Alias Cleanup - check that aliases to ptr types return 0
1148 // if the object aliased to is removed
1150 QQmlComponent component(&engine, TEST_FILE("alias.7.qml"));
1153 QObject *object = component.create();
1154 QVERIFY(object != 0);
1156 QObject *object1 = qvariant_cast<QObject *>(object->property("object"));
1157 QVERIFY(object1 != 0);
1158 QObject *object2 = qvariant_cast<QObject *>(object1->property("object"));
1159 QVERIFY(object2 != 0);
1161 QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
1162 QVERIFY(alias == object2);
1166 QObject *alias2 = object; // "Random" start value
1168 void *a[] = { &alias2, 0, &status };
1169 QMetaObject::metacall(object, QMetaObject::ReadProperty,
1170 object->metaObject()->indexOfProperty("aliasedObject"), a);
1171 QVERIFY(alias2 == 0);
1174 // Simple composite type
1176 QQmlComponent component(&engine, TEST_FILE("alias.8.qml"));
1178 QObject *object = component.create();
1179 QVERIFY(object != 0);
1181 QCOMPARE(object->property("value").toInt(), 10);
1186 // Complex composite type
1188 QQmlComponent component(&engine, TEST_FILE("alias.9.qml"));
1190 QObject *object = component.create();
1191 QVERIFY(object != 0);
1193 QCOMPARE(object->property("value").toInt(), 10);
1199 // Simple "int" alias
1201 QQmlComponent component(&engine, TEST_FILE("alias.10.qml"));
1203 QObject *object = component.create();
1204 QVERIFY(object != 0);
1206 // Read through alias
1207 QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8));
1208 object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100)));
1209 QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100));
1211 // Write through alias
1212 object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9)));
1213 QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9));
1214 QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9));
1219 // Valuetype sub-alias
1221 QQmlComponent component(&engine, TEST_FILE("alias.11.qml"));
1223 QObject *object = component.create();
1224 QVERIFY(object != 0);
1226 // Read through alias
1227 QCOMPARE(object->property("aliasProperty").toInt(), 19);
1228 object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111)));
1229 QCOMPARE(object->property("aliasProperty").toInt(), 33);
1231 // Write through alias
1232 object->setProperty("aliasProperty", QVariant(4));
1233 QCOMPARE(object->property("aliasProperty").toInt(), 4);
1234 QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111));
1240 // QTBUG-13374 Test that alias properties and signals can coexist
1241 void tst_qqmllanguage::aliasPropertiesAndSignals()
1243 QQmlComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml"));
1245 QObject *o = component.create();
1247 QCOMPARE(o->property("test").toBool(), true);
1251 // Test that the root element in a composite type can be a Component
1252 void tst_qqmllanguage::componentCompositeType()
1254 QQmlComponent component(&engine, TEST_FILE("componentCompositeType.qml"));
1256 QObject *object = component.create();
1257 QVERIFY(object != 0);
1260 class TestType : public QObject {
1263 TestType(QObject *p=0) : QObject(p) {}
1266 class TestType2 : public QObject {
1269 TestType2(QObject *p=0) : QObject(p) {}
1272 void tst_qqmllanguage::i18n_data()
1274 QTest::addColumn<QString>("file");
1275 QTest::addColumn<QString>("stringProperty");
1276 QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)");
1277 QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10");
1278 QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15");
1279 QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20");
1280 QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30");
1281 QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40");
1284 void tst_qqmllanguage::i18n()
1286 QFETCH(QString, file);
1287 QFETCH(QString, stringProperty);
1288 QQmlComponent component(&engine, TEST_FILE(file));
1290 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1291 QVERIFY(object != 0);
1292 QCOMPARE(object->stringProperty(), stringProperty);
1297 // Check that the Component::onCompleted attached property works
1298 void tst_qqmllanguage::onCompleted()
1300 QQmlComponent component(&engine, TEST_FILE("onCompleted.qml"));
1302 QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1303 QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1304 QTest::ignoreMessage(QtDebugMsg, "Completed 10 11");
1305 QObject *object = component.create();
1306 QVERIFY(object != 0);
1309 // Check that the Component::onDestruction attached property works
1310 void tst_qqmllanguage::onDestruction()
1312 QQmlComponent component(&engine, TEST_FILE("onDestruction.qml"));
1314 QObject *object = component.create();
1315 QVERIFY(object != 0);
1316 QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1317 QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1318 QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11");
1322 // Check that assignments to QQmlScriptString properties work
1323 void tst_qqmllanguage::scriptString()
1326 QQmlComponent component(&engine, TEST_FILE("scriptString.qml"));
1329 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1330 QVERIFY(object != 0);
1331 QCOMPARE(object->scriptProperty().script(), QString("foo + bar"));
1332 QCOMPARE(object->scriptProperty().scopeObject(), qobject_cast<QObject*>(object));
1333 QCOMPARE(object->scriptProperty().context(), qmlContext(object));
1335 QVERIFY(object->grouped() != 0);
1336 QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)"));
1337 QCOMPARE(object->grouped()->script().scopeObject(), qobject_cast<QObject*>(object));
1338 QCOMPARE(object->grouped()->script().context(), qmlContext(object));
1342 QQmlComponent component(&engine, TEST_FILE("scriptString2.qml"));
1345 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1346 QVERIFY(object != 0);
1347 QCOMPARE(object->scriptProperty().script(), QString("\"hello\\n\\\"world\\\"\""));
1351 QQmlComponent component(&engine, TEST_FILE("scriptString3.qml"));
1354 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1355 QVERIFY(object != 0);
1356 QCOMPARE(object->scriptProperty().script(), QString("12.345"));
1360 QQmlComponent component(&engine, TEST_FILE("scriptString4.qml"));
1363 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1364 QVERIFY(object != 0);
1365 QCOMPARE(object->scriptProperty().script(), QString("true"));
1369 // Check that default property assignments are correctly spliced into explicit
1370 // property assignments
1371 void tst_qqmllanguage::defaultPropertyListOrder()
1373 QQmlComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml"));
1376 MyContainer *container = qobject_cast<MyContainer *>(component.create());
1377 QVERIFY(container != 0);
1379 QCOMPARE(container->getChildren()->count(), 6);
1380 QCOMPARE(container->getChildren()->at(0)->property("index"), QVariant(0));
1381 QCOMPARE(container->getChildren()->at(1)->property("index"), QVariant(1));
1382 QCOMPARE(container->getChildren()->at(2)->property("index"), QVariant(2));
1383 QCOMPARE(container->getChildren()->at(3)->property("index"), QVariant(3));
1384 QCOMPARE(container->getChildren()->at(4)->property("index"), QVariant(4));
1385 QCOMPARE(container->getChildren()->at(5)->property("index"), QVariant(5));
1388 void tst_qqmllanguage::declaredPropertyValues()
1390 QQmlComponent component(&engine, TEST_FILE("declaredPropertyValues.qml"));
1394 void tst_qqmllanguage::dontDoubleCallClassBegin()
1396 QQmlComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml"));
1397 QObject *o = component.create();
1400 MyParserStatus *o2 = qobject_cast<MyParserStatus *>(qvariant_cast<QObject *>(o->property("object")));
1402 QCOMPARE(o2->classBeginCount(), 1);
1403 QCOMPARE(o2->componentCompleteCount(), 1);
1408 void tst_qqmllanguage::reservedWords_data()
1410 QTest::addColumn<QByteArray>("word");
1412 QTest::newRow("abstract") << QByteArray("abstract");
1413 QTest::newRow("as") << QByteArray("as");
1414 QTest::newRow("boolean") << QByteArray("boolean");
1415 QTest::newRow("break") << QByteArray("break");
1416 QTest::newRow("byte") << QByteArray("byte");
1417 QTest::newRow("case") << QByteArray("case");
1418 QTest::newRow("catch") << QByteArray("catch");
1419 QTest::newRow("char") << QByteArray("char");
1420 QTest::newRow("class") << QByteArray("class");
1421 QTest::newRow("continue") << QByteArray("continue");
1422 QTest::newRow("const") << QByteArray("const");
1423 QTest::newRow("debugger") << QByteArray("debugger");
1424 QTest::newRow("default") << QByteArray("default");
1425 QTest::newRow("delete") << QByteArray("delete");
1426 QTest::newRow("do") << QByteArray("do");
1427 QTest::newRow("double") << QByteArray("double");
1428 QTest::newRow("else") << QByteArray("else");
1429 QTest::newRow("enum") << QByteArray("enum");
1430 QTest::newRow("export") << QByteArray("export");
1431 QTest::newRow("extends") << QByteArray("extends");
1432 QTest::newRow("false") << QByteArray("false");
1433 QTest::newRow("final") << QByteArray("final");
1434 QTest::newRow("finally") << QByteArray("finally");
1435 QTest::newRow("float") << QByteArray("float");
1436 QTest::newRow("for") << QByteArray("for");
1437 QTest::newRow("function") << QByteArray("function");
1438 QTest::newRow("goto") << QByteArray("goto");
1439 QTest::newRow("if") << QByteArray("if");
1440 QTest::newRow("implements") << QByteArray("implements");
1441 QTest::newRow("import") << QByteArray("import");
1442 QTest::newRow("in") << QByteArray("in");
1443 QTest::newRow("instanceof") << QByteArray("instanceof");
1444 QTest::newRow("int") << QByteArray("int");
1445 QTest::newRow("interface") << QByteArray("interface");
1446 QTest::newRow("long") << QByteArray("long");
1447 QTest::newRow("native") << QByteArray("native");
1448 QTest::newRow("new") << QByteArray("new");
1449 QTest::newRow("null") << QByteArray("null");
1450 QTest::newRow("package") << QByteArray("package");
1451 QTest::newRow("private") << QByteArray("private");
1452 QTest::newRow("protected") << QByteArray("protected");
1453 QTest::newRow("public") << QByteArray("public");
1454 QTest::newRow("return") << QByteArray("return");
1455 QTest::newRow("short") << QByteArray("short");
1456 QTest::newRow("static") << QByteArray("static");
1457 QTest::newRow("super") << QByteArray("super");
1458 QTest::newRow("switch") << QByteArray("switch");
1459 QTest::newRow("synchronized") << QByteArray("synchronized");
1460 QTest::newRow("this") << QByteArray("this");
1461 QTest::newRow("throw") << QByteArray("throw");
1462 QTest::newRow("throws") << QByteArray("throws");
1463 QTest::newRow("transient") << QByteArray("transient");
1464 QTest::newRow("true") << QByteArray("true");
1465 QTest::newRow("try") << QByteArray("try");
1466 QTest::newRow("typeof") << QByteArray("typeof");
1467 QTest::newRow("var") << QByteArray("var");
1468 QTest::newRow("void") << QByteArray("void");
1469 QTest::newRow("volatile") << QByteArray("volatile");
1470 QTest::newRow("while") << QByteArray("while");
1471 QTest::newRow("with") << QByteArray("with");
1474 void tst_qqmllanguage::reservedWords()
1476 QFETCH(QByteArray, word);
1477 QQmlComponent component(&engine);
1478 component.setData("import QtQuick 2.0\nQtObject { property string " + word + " }", QUrl());
1479 QCOMPARE(component.errorString(), QLatin1String(":2 Expected token `identifier'\n"));
1482 // Check that first child of qml is of given type. Empty type insists on error.
1483 void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror)
1485 QQmlComponent component(&engine);
1486 component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
1488 QTRY_VERIFY(!component.isLoading());
1490 if (type.isEmpty()) {
1491 QVERIFY(component.isError());
1492 QString actualerror;
1493 foreach (const QQmlError e, component.errors()) {
1494 if (!actualerror.isEmpty())
1495 actualerror.append("; ");
1496 actualerror.append(e.description());
1498 QCOMPARE(actualerror,expectederror);
1501 QObject *object = component.create();
1502 QVERIFY(object != 0);
1503 QCOMPARE(QString(object->metaObject()->className()), type);
1509 void tst_qqmllanguage::inlineAssignmentsOverrideBindings()
1511 QQmlComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml"));
1513 QObject *o = component.create();
1515 QCOMPARE(o->property("test").toInt(), 11);
1520 void tst_qqmllanguage::nestedComponentRoots()
1522 QQmlComponent component(&engine, TEST_FILE("nestedComponentRoots.qml"));
1525 // Import tests (QT-558)
1526 void tst_qqmllanguage::importsBuiltin_data()
1530 QTest::addColumn<QString>("qml");
1531 QTest::addColumn<QString>("type");
1532 QTest::addColumn<QString>("error");
1535 QTest::newRow("missing import")
1538 << "Test is not a type";
1539 QTest::newRow("not in version 0.0")
1540 << "import com.nokia.Test 0.0\n"
1543 << "Test is not a type";
1544 QTest::newRow("version not installed")
1545 << "import com.nokia.Test 99.0\n"
1548 << "module \"com.nokia.Test\" version 99.0 is not installed";
1549 QTest::newRow("in version 0.0")
1550 << "import com.nokia.Test 0.0\n"
1554 QTest::newRow("qualified in version 0.0")
1555 << "import com.nokia.Test 0.0 as T\n"
1559 QTest::newRow("in version 1.0")
1560 << "import com.nokia.Test 1.0\n"
1564 QTest::newRow("qualified wrong")
1565 << "import com.nokia.Test 1.0 as T\n" // QT-610
1568 << "Test is not a type";
1569 QTest::newRow("qualified right")
1570 << "import com.nokia.Test 1.0 as T\n"
1574 QTest::newRow("qualified right but not in version 0.0")
1575 << "import com.nokia.Test 0.0 as T\n"
1578 << "T.Test is not a type";
1579 QTest::newRow("in version 1.1")
1580 << "import com.nokia.Test 1.1\n"
1584 QTest::newRow("in version 1.3")
1585 << "import com.nokia.Test 1.3\n"
1589 QTest::newRow("in version 1.5")
1590 << "import com.nokia.Test 1.5\n"
1594 QTest::newRow("changed in version 1.8")
1595 << "import com.nokia.Test 1.8\n"
1599 QTest::newRow("in version 1.12")
1600 << "import com.nokia.Test 1.12\n"
1604 QTest::newRow("old in version 1.9")
1605 << "import com.nokia.Test 1.9\n"
1609 QTest::newRow("old in version 1.11")
1610 << "import com.nokia.Test 1.11\n"
1614 QTest::newRow("multiversion 1")
1615 << "import com.nokia.Test 1.11\n"
1616 "import com.nokia.Test 1.12\n"
1618 << (!qmlCheckTypes()?"TestType2":"")
1619 << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
1620 QTest::newRow("multiversion 2")
1621 << "import com.nokia.Test 1.11\n"
1622 "import com.nokia.Test 1.12\n"
1624 << (!qmlCheckTypes()?"TestType":"")
1625 << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
1626 QTest::newRow("qualified multiversion 3")
1627 << "import com.nokia.Test 1.0 as T0\n"
1628 "import com.nokia.Test 1.8 as T8\n"
1632 QTest::newRow("qualified multiversion 4")
1633 << "import com.nokia.Test 1.0 as T0\n"
1634 "import com.nokia.Test 1.8 as T8\n"
1640 void tst_qqmllanguage::importsBuiltin()
1642 QFETCH(QString, qml);
1643 QFETCH(QString, type);
1644 QFETCH(QString, error);
1645 testType(qml,type,error);
1648 void tst_qqmllanguage::importsLocal_data()
1650 QTest::addColumn<QString>("qml");
1651 QTest::addColumn<QString>("type");
1652 QTest::addColumn<QString>("error");
1655 QTest::newRow("local import")
1656 << "import \"subdir\"\n" // QT-613
1658 << "QQuickRectangle"
1660 QTest::newRow("local import second")
1661 << "import QtQuick 2.0\nimport \"subdir\"\n"
1663 << "QQuickRectangle"
1665 QTest::newRow("local import subsubdir")
1666 << "import QtQuick 2.0\nimport \"subdir/subsubdir\"\n"
1668 << "QQuickRectangle"
1670 QTest::newRow("local import QTBUG-7721 A")
1671 << "subdir.Test {}" // no longer allowed (QTBUG-7721)
1673 << "subdir.Test - subdir is not a namespace";
1674 QTest::newRow("local import QTBUG-7721 B")
1675 << "import \"subdir\" as X\n"
1676 "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
1678 << "X.subsubdir.SubTest - nested namespaces not allowed";
1679 QTest::newRow("local import as")
1680 << "import \"subdir\" as T\n"
1682 << "QQuickRectangle"
1684 QTest::newRow("wrong local import as")
1685 << "import \"subdir\" as T\n"
1688 << "Test is not a type";
1689 QTest::newRow("library precedence over local import")
1690 << "import \"subdir\"\n"
1691 "import com.nokia.Test 1.0\n"
1693 << (!qmlCheckTypes()?"TestType":"")
1694 << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test and in subdir");
1697 void tst_qqmllanguage::importsLocal()
1699 QFETCH(QString, qml);
1700 QFETCH(QString, type);
1701 QFETCH(QString, error);
1702 testType(qml,type,error);
1705 void tst_qqmllanguage::basicRemote_data()
1707 QTest::addColumn<QUrl>("url");
1708 QTest::addColumn<QString>("type");
1709 QTest::addColumn<QString>("error");
1711 QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage/";
1713 QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << "";
1714 QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << "";
1715 QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << "";
1718 void tst_qqmllanguage::basicRemote()
1721 QFETCH(QString, type);
1722 QFETCH(QString, error);
1724 TestHTTPServer server(14447);
1725 server.serveDirectory(testdata());
1727 QQmlComponent component(&engine, url);
1729 QTRY_VERIFY(!component.isLoading());
1731 if (error.isEmpty()) {
1732 if (component.isError())
1733 qDebug() << component.errors();
1734 QVERIFY(!component.isError());
1736 QVERIFY(component.isError());
1740 void tst_qqmllanguage::importsRemote_data()
1742 QTest::addColumn<QString>("qml");
1743 QTest::addColumn<QString>("type");
1744 QTest::addColumn<QString>("error");
1746 QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage";
1748 QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QQuickRectangle"
1750 QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QQuickText"
1752 QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QQuickImage"
1754 QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << ""
1755 << "WrongTestLocal is not a type";
1756 QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << ""
1757 << "LocalInternal is not a type";
1758 QTest::newRow("wrong remote import of undeclared local") << "import \""+serverdir+"\"\nUndeclaredLocal {}" << ""
1759 << "UndeclaredLocal is not a type";
1762 void tst_qqmllanguage::importsRemote()
1764 QFETCH(QString, qml);
1765 QFETCH(QString, type);
1766 QFETCH(QString, error);
1768 TestHTTPServer server(14447);
1769 server.serveDirectory(testdata());
1771 testType(qml,type,error);
1774 void tst_qqmllanguage::importsInstalled_data()
1778 QTest::addColumn<QString>("qml");
1779 QTest::addColumn<QString>("type");
1780 QTest::addColumn<QString>("error");
1783 QTest::newRow("installed import 0")
1784 << "import com.nokia.installedtest0 0.0\n"
1785 "InstalledTestTP {}"
1786 << "QQuickRectangle"
1788 QTest::newRow("installed import 0 as TP")
1789 << "import com.nokia.installedtest0 0.0 as TP\n"
1790 "TP.InstalledTestTP {}"
1791 << "QQuickRectangle"
1793 QTest::newRow("installed import 1")
1794 << "import com.nokia.installedtest 1.0\n"
1796 << "QQuickRectangle"
1798 QTest::newRow("installed import 2")
1799 << "import com.nokia.installedtest 1.3\n"
1801 << "QQuickRectangle"
1803 QTest::newRow("installed import 3")
1804 << "import com.nokia.installedtest 1.4\n"
1808 QTest::newRow("installed import minor version not available") // QTBUG-11936
1809 << "import com.nokia.installedtest 0.1\n"
1812 << "module \"com.nokia.installedtest\" version 0.1 is not installed";
1813 QTest::newRow("installed import minor version not available") // QTBUG-9627
1814 << "import com.nokia.installedtest 1.10\n"
1817 << "module \"com.nokia.installedtest\" version 1.10 is not installed";
1818 QTest::newRow("installed import major version not available") // QTBUG-9627
1819 << "import com.nokia.installedtest 9.0\n"
1822 << "module \"com.nokia.installedtest\" version 9.0 is not installed";
1823 QTest::newRow("installed import visibility") // QT-614
1824 << "import com.nokia.installedtest 1.4\n"
1827 << "PrivateType is not a type";
1830 void tst_qqmllanguage::importsInstalled()
1832 QFETCH(QString, qml);
1833 QFETCH(QString, type);
1834 QFETCH(QString, error);
1835 testType(qml,type,error);
1839 void tst_qqmllanguage::importsOrder_data()
1841 QTest::addColumn<QString>("qml");
1842 QTest::addColumn<QString>("type");
1843 QTest::addColumn<QString>("error");
1845 QTest::newRow("double import") <<
1846 "import com.nokia.installedtest 1.4\n"
1847 "import com.nokia.installedtest 1.4\n"
1849 << (!qmlCheckTypes()?"QQuickText":"")
1850 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.4");
1851 QTest::newRow("installed import overrides 1") <<
1852 "import com.nokia.installedtest 1.0\n"
1853 "import com.nokia.installedtest 1.4\n"
1855 << (!qmlCheckTypes()?"QQuickText":"")
1856 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
1857 QTest::newRow("installed import overrides 2") <<
1858 "import com.nokia.installedtest 1.4\n"
1859 "import com.nokia.installedtest 1.0\n"
1861 << (!qmlCheckTypes()?"QQuickRectangle":"")
1862 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
1863 QTest::newRow("installed import re-overrides 1") <<
1864 "import com.nokia.installedtest 1.4\n"
1865 "import com.nokia.installedtest 1.0\n"
1866 "import com.nokia.installedtest 1.4\n"
1868 << (!qmlCheckTypes()?"QQuickText":"")
1869 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
1870 QTest::newRow("installed import re-overrides 2") <<
1871 "import com.nokia.installedtest 1.4\n"
1872 "import com.nokia.installedtest 1.0\n"
1873 "import com.nokia.installedtest 1.4\n"
1874 "import com.nokia.installedtest 1.0\n"
1876 << (!qmlCheckTypes()?"QQuickRectangle":"")
1877 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
1879 QTest::newRow("installed import versus builtin 1") <<
1880 "import com.nokia.installedtest 1.5\n"
1881 "import QtQuick 2.0\n"
1883 << (!qmlCheckTypes()?"QQuickRectangle":"")
1884 << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in Qt and in lib/com/nokia/installedtest");
1885 QTest::newRow("installed import versus builtin 2") <<
1886 "import QtQuick 2.0\n"
1887 "import com.nokia.installedtest 1.5\n"
1889 << (!qmlCheckTypes()?"QQuickText":"")
1890 << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest and in Qt");
1891 QTest::newRow("namespaces cannot be overridden by types 1") <<
1892 "import QtQuick 2.0 as Rectangle\n"
1893 "import com.nokia.installedtest 1.5\n"
1896 << "Namespace Rectangle cannot be used as a type";
1897 QTest::newRow("namespaces cannot be overridden by types 2") <<
1898 "import QtQuick 2.0 as Rectangle\n"
1899 "import com.nokia.installedtest 1.5\n"
1900 "Rectangle.Image {}"
1903 QTest::newRow("local last 1") <<
1907 QTest::newRow("local last 2") <<
1908 "import com.nokia.installedtest 1.0\n"
1910 << (!qmlCheckTypes()?"QQuickRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
1911 << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory");
1914 void tst_qqmllanguage::importsOrder()
1916 QFETCH(QString, qml);
1917 QFETCH(QString, type);
1918 QFETCH(QString, error);
1919 testType(qml,type,error);
1922 void tst_qqmllanguage::importIncorrectCase()
1924 QQmlComponent component(&engine, TEST_FILE("importIncorrectCase.qml"));
1926 QList<QQmlError> errors = component.errors();
1927 QCOMPARE(errors.count(), 1);
1929 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1930 QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + testdata("lib/com/Nokia/installedtest/qmldir") + QLatin1String("\"");
1932 QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed");
1935 QCOMPARE(errors.at(0).description(), expectedError);
1938 void tst_qqmllanguage::importJs_data()
1940 QTest::addColumn<QString>("file");
1941 QTest::addColumn<QString>("errorFile");
1942 QTest::addColumn<bool>("performTest");
1944 QTest::newRow("defaultVersion")
1946 << "importJs.1.errors.txt"
1949 QTest::newRow("specifiedVersion")
1951 << "importJs.2.errors.txt"
1954 QTest::newRow("excludeExcessiveVersion")
1956 << "importJs.3.errors.txt"
1959 QTest::newRow("includeAppropriateVersion")
1961 << "importJs.4.errors.txt"
1964 QTest::newRow("noDefaultVersion")
1966 << "importJs.5.errors.txt"
1969 QTest::newRow("repeatImportFails")
1971 << "importJs.6.errors.txt"
1974 QTest::newRow("multipleVersionImportFails")
1976 << "importJs.7.errors.txt"
1979 QTest::newRow("namespacedImport")
1981 << "importJs.8.errors.txt"
1984 QTest::newRow("namespacedVersionedImport")
1986 << "importJs.9.errors.txt"
1989 QTest::newRow("namespacedRepeatImport")
1990 << "importJs.10.qml"
1991 << "importJs.10.errors.txt"
1995 void tst_qqmllanguage::importJs()
1997 QFETCH(QString, file);
1998 QFETCH(QString, errorFile);
1999 QFETCH(bool, performTest);
2001 QQmlComponent component(&engine, TEST_FILE(file));
2004 DETERMINE_ERRORS(errorFile.toLatin1().constData(),expected,actual);
2005 QCOMPARE(expected.size(), actual.size());
2006 for (int i = 0; i < expected.size(); ++i)
2008 size_t compareLen = std::min(expected.at(i).length(), actual.at(i).length());
2009 QCOMPARE(expected.at(i).left(compareLen), actual.at(i).left(compareLen));
2014 QObject *object = component.create();
2015 QVERIFY(object != 0);
2016 QCOMPARE(object->property("test").toBool(),true);
2021 void tst_qqmllanguage::qmlAttachedPropertiesObjectMethod()
2025 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
2026 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
2029 QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml"));
2031 QObject *object = component.create();
2032 QVERIFY(object != 0);
2034 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(object, false), (QObject *)0);
2035 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2039 QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml"));
2041 QObject *object = component.create();
2042 QVERIFY(object != 0);
2044 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, false) != 0);
2045 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2049 void tst_qqmllanguage::crash1()
2051 QQmlComponent component(&engine);
2052 component.setData("import QtQuick 2.0\nComponent {}", QUrl());
2055 void tst_qqmllanguage::crash2()
2057 QQmlComponent component(&engine, TEST_FILE("crash2.qml"));
2061 void tst_qqmllanguage::customOnProperty()
2063 QQmlComponent component(&engine, TEST_FILE("customOnProperty.qml"));
2066 QObject *object = component.create();
2067 QVERIFY(object != 0);
2069 QCOMPARE(object->property("on").toInt(), 10);
2075 void tst_qqmllanguage::variantNotify()
2077 QQmlComponent component(&engine, TEST_FILE("variantNotify.qml"));
2080 QObject *object = component.create();
2081 QVERIFY(object != 0);
2083 QCOMPARE(object->property("notifyCount").toInt(), 1);
2088 void tst_qqmllanguage::revisions()
2091 QQmlComponent component(&engine, TEST_FILE("revisions11.qml"));
2094 MyRevisionedClass *object = qobject_cast<MyRevisionedClass*>(component.create());
2095 QVERIFY(object != 0);
2097 QCOMPARE(object->prop2(), 10.0);
2102 QQmlEngine myEngine;
2103 QQmlComponent component(&myEngine, TEST_FILE("revisionssub11.qml"));
2106 MyRevisionedSubclass *object = qobject_cast<MyRevisionedSubclass*>(component.create());
2107 QVERIFY(object != 0);
2109 QCOMPARE(object->prop1(), 10.0);
2110 QCOMPARE(object->prop2(), 10.0);
2111 QCOMPARE(object->prop3(), 10.0);
2112 QCOMPARE(object->prop4(), 10.0);
2117 QQmlComponent component(&engine, TEST_FILE("versionedbase.qml"));
2119 MySubclass *object = qobject_cast<MySubclass*>(component.create());
2120 QVERIFY(object != 0);
2122 QCOMPARE(object->prop1(), 10.0);
2123 QCOMPARE(object->prop2(), 10.0);
2129 void tst_qqmllanguage::revisionOverloads()
2132 QQmlComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml"));
2136 QQmlComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml"));
2137 QEXPECT_FAIL("", "QTBUG-13849", Abort);
2139 VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt");
2143 void tst_qqmllanguage::initTestCase()
2145 QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath();
2146 QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
2150 // Registering the TestType class in other modules should have no adverse effects
2151 qmlRegisterType<TestType>("com.nokia.TestPre", 1, 0, "Test");
2153 qmlRegisterType<TestType>("com.nokia.Test", 0, 0, "TestTP");
2154 qmlRegisterType<TestType>("com.nokia.Test", 1, 0, "Test");
2155 qmlRegisterType<TestType>("com.nokia.Test", 1, 5, "Test");
2156 qmlRegisterType<TestType2>("com.nokia.Test", 1, 8, "Test");
2157 qmlRegisterType<TestType>("com.nokia.Test", 1, 9, "OldTest");
2158 qmlRegisterType<TestType2>("com.nokia.Test", 1, 12, "Test");
2160 // Registering the TestType class in other modules should have no adverse effects
2161 qmlRegisterType<TestType>("com.nokia.TestPost", 1, 0, "Test");
2163 // Create locale-specific file
2164 // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit
2165 // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters
2166 // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded
2167 QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile());
2168 QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString())));
2169 QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile());
2170 QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString())));
2171 out.write(in.readAll());
2174 void tst_qqmllanguage::aliasPropertyChangeSignals()
2177 QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.qml"));
2180 QObject *o = component.create();
2183 QCOMPARE(o->property("test").toBool(), true);
2188 // QTCREATORBUG-2769
2190 QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.2.qml"));
2193 QObject *o = component.create();
2196 QCOMPARE(o->property("test").toBool(), true);
2202 // Tests property initializers
2203 void tst_qqmllanguage::propertyInit()
2206 QQmlComponent component(&engine, TEST_FILE("propertyInit.1.qml"));
2209 QObject *o = component.create();
2212 QCOMPARE(o->property("test").toInt(), 1);
2218 QQmlComponent component(&engine, TEST_FILE("propertyInit.2.qml"));
2221 QObject *o = component.create();
2224 QCOMPARE(o->property("test").toInt(), 123);
2230 // Test that registration order doesn't break type availability
2232 void tst_qqmllanguage::registrationOrder()
2234 QQmlComponent component(&engine, TEST_FILE("registrationOrder.qml"));
2236 QObject *o = component.create();
2238 QVERIFY(o->metaObject() == &MyVersion2Class::staticMetaObject);
2242 void tst_qqmllanguage::readonly()
2244 QQmlComponent component(&engine, TEST_FILE("readonly.qml"));
2246 QObject *o = component.create();
2249 QCOMPARE(o->property("test1").toInt(), 10);
2250 QCOMPARE(o->property("test2").toInt(), 18);
2251 QCOMPARE(o->property("test3").toInt(), 13);
2253 o->setProperty("testData", 13);
2255 QCOMPARE(o->property("test1").toInt(), 10);
2256 QCOMPARE(o->property("test2").toInt(), 22);
2257 QCOMPARE(o->property("test3").toInt(), 13);
2259 o->setProperty("testData2", 2);
2261 QCOMPARE(o->property("test1").toInt(), 10);
2262 QCOMPARE(o->property("test2").toInt(), 22);
2263 QCOMPARE(o->property("test3").toInt(), 2);
2265 o->setProperty("test1", 11);
2266 o->setProperty("test2", 11);
2267 o->setProperty("test3", 11);
2269 QCOMPARE(o->property("test1").toInt(), 10);
2270 QCOMPARE(o->property("test2").toInt(), 22);
2271 QCOMPARE(o->property("test3").toInt(), 2);
2277 void tst_qqmllanguage::remoteLoadCrash()
2279 TestHTTPServer server(14448);
2280 server.serveDirectory(testdata());
2282 QQmlComponent component(&engine);
2283 component.setData("import QtQuick 2.0; Text {}", QUrl("http://127.0.0.1:14448/remoteLoadCrash.qml"));
2284 while (component.isLoading())
2285 QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50);
2287 QObject *o = component.create();
2292 void tst_qqmllanguage::globalEnums()
2294 qRegisterMetaType<MyEnum1Class::EnumA>();
2295 qRegisterMetaType<MyEnum2Class::EnumB>();
2297 QQmlComponent component(&engine, TEST_FILE("globalEnums.qml"));
2299 QObject *o = component.create();
2302 MyEnum1Class *enum1Class = o->findChild<MyEnum1Class *>(QString::fromLatin1("enum1Class"));
2303 QVERIFY(enum1Class != 0);
2304 QVERIFY(enum1Class->getValue() == -1);
2306 MyEnumDerivedClass *enum2Class = o->findChild<MyEnumDerivedClass *>(QString::fromLatin1("enumDerivedClass"));
2307 QVERIFY(enum2Class != 0);
2308 QVERIFY(enum2Class->getValueA() == -1);
2309 QVERIFY(enum2Class->getValueB() == -1);
2311 QVERIFY(enum2Class->property("aValue") == 0);
2312 QVERIFY(enum2Class->property("bValue") == 0);
2314 QSignalSpy signalA(enum2Class, SIGNAL(valueAChanged(MyEnum1Class::EnumA)));
2315 QSignalSpy signalB(enum2Class, SIGNAL(valueBChanged(MyEnum2Class::EnumB)));
2317 QMetaObject::invokeMethod(o, "setEnumValues");
2319 QVERIFY(enum1Class->getValue() == MyEnum1Class::A_13);
2320 QVERIFY(enum2Class->getValueA() == MyEnum1Class::A_11);
2321 QVERIFY(enum2Class->getValueB() == MyEnum2Class::B_37);
2323 QVERIFY(signalA.count() == 1);
2324 QVERIFY(signalB.count() == 1);
2326 QVERIFY(enum2Class->property("aValue") == MyEnum1Class::A_11);
2327 QVERIFY(enum2Class->property("bValue") == 37);
2332 QTEST_MAIN(tst_qqmllanguage)
2334 #include "tst_qqmllanguage.moc"