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>
50 #include <private/qqmlproperty_p.h>
51 #include <private/qqmlmetatype_p.h>
52 #include <private/qqmlglobal_p.h>
54 #include "testtypes.h"
55 #include "testhttpserver.h"
57 DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
60 Returns the path to some testdata file or directory.
62 QString testdata(QString const& name = QString())
64 static const QString dataDirectory = QDir::currentPath() + QLatin1String("/data");
65 QString result = dataDirectory;
66 if (!name.isEmpty()) {
67 result += QLatin1Char('/');
74 This test case covers QML language issues. This covers everything that does not
75 involve evaluating ECMAScript expressions and bindings.
77 Evaluation of expressions and bindings is covered in qmlecmascript
79 class tst_qqmllanguage : public QObject
84 QQmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
85 engine.addImportPath(testdata("lib"));
90 void cleanupTestCase();
95 void insertedSemicolon_data();
96 void insertedSemicolon();
99 void simpleContainer();
100 void interfaceProperty();
101 void interfaceQList();
102 void assignObjectToSignal();
103 void assignObjectToVariant();
104 void assignLiteralSignalProperty();
105 void assignQmlComponent();
106 void assignBasicTypes();
107 void assignTypeExtremes();
108 void assignCompositeToType();
109 void assignLiteralToVariant();
110 void assignLiteralToVar();
111 void customParserTypes();
112 void rootAsQmlComponent();
113 void inlineQmlComponents();
115 void autoNotifyConnection();
117 void dynamicProperties();
118 void dynamicPropertiesNested();
119 void listProperties();
120 void dynamicObjectProperties();
121 void dynamicSignalsAndSlots();
122 void simpleBindings();
123 void autoComponentCreation();
124 void propertyValueSource();
125 void attachedProperties();
126 void dynamicObjects();
127 void customVariantTypes();
130 void aliasProperties();
131 void aliasPropertiesAndSignals();
132 void aliasPropertyChangeSignals();
133 void componentCompositeType();
137 void onDestruction();
139 void defaultPropertyListOrder();
140 void declaredPropertyValues();
141 void dontDoubleCallClassBegin();
142 void reservedWords_data();
143 void reservedWords();
144 void inlineAssignmentsOverrideBindings();
145 void nestedComponentRoots();
146 void registrationOrder();
149 void basicRemote_data();
151 void importsBuiltin_data();
152 void importsBuiltin();
153 void importsLocal_data();
155 void importsRemote_data();
156 void importsRemote();
157 void importsInstalled_data();
158 void importsInstalled();
159 void importsOrder_data();
161 void importIncorrectCase();
162 void importJs_data();
165 void qmlAttachedPropertiesObjectMethod();
166 void customOnProperty();
167 void variantNotify();
170 void revisionOverloads();
173 void remoteLoadCrash();
175 // regression tests for crashes
181 void testType(const QString& qml, const QString& type, const QString& error);
184 #define DETERMINE_ERRORS(errorfile,expected,actual)\
185 QList<QByteArray> expected; \
186 QList<QByteArray> actual; \
188 QFile file(testdata(QLatin1String(errorfile))); \
189 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
190 QByteArray data = file.readAll(); \
192 expected = data.split('\n'); \
193 expected.removeAll(QByteArray("")); \
194 QList<QQmlError> errors = component.errors(); \
195 for (int ii = 0; ii < errors.count(); ++ii) { \
196 const QQmlError &error = errors.at(ii); \
197 QByteArray errorStr = QByteArray::number(error.line()) + ":" + \
198 QByteArray::number(error.column()) + ":" + \
199 error.description().toUtf8(); \
200 actual << errorStr; \
204 #define VERIFY_ERRORS(errorfile) \
206 if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
207 qWarning() << "Unexpected Errors:" << component.errors(); \
208 QVERIFY(!component.isError()); \
209 QVERIFY(component.errors().isEmpty()); \
211 DETERMINE_ERRORS(errorfile,actual,expected);\
212 if (qgetenv("DEBUG") != "" && expected != actual) \
213 qWarning() << "Expected:" << expected << "Actual:" << actual; \
214 if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
215 QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
216 QVERIFY(file.open(QIODevice::WriteOnly)); \
217 for (int ii = 0; ii < actual.count(); ++ii) { \
218 file.write(actual.at(ii)); file.write("\n"); \
222 QCOMPARE(expected, actual); \
226 inline QUrl TEST_FILE(const QString &filename)
228 return QUrl::fromLocalFile(testdata(filename));
231 inline QUrl TEST_FILE(const char *filename)
233 return TEST_FILE(QLatin1String(filename));
236 void tst_qqmllanguage::cleanupTestCase()
238 QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()));
241 void tst_qqmllanguage::insertedSemicolon_data()
243 QTest::addColumn<QString>("file");
244 QTest::addColumn<QString>("errorFile");
245 QTest::addColumn<bool>("create");
247 QTest::newRow("insertedSemicolon.1") << "insertedSemicolon.1.qml" << "insertedSemicolon.1.errors.txt" << false;
250 void tst_qqmllanguage::insertedSemicolon()
252 QFETCH(QString, file);
253 QFETCH(QString, errorFile);
254 QFETCH(bool, create);
256 QQmlComponent component(&engine, TEST_FILE(file));
259 QObject *object = component.create();
260 QVERIFY(object == 0);
263 VERIFY_ERRORS(errorFile.toLatin1().constData());
266 void tst_qqmllanguage::errors_data()
268 QTest::addColumn<QString>("file");
269 QTest::addColumn<QString>("errorFile");
270 QTest::addColumn<bool>("create");
272 QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false;
273 QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false;
274 QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false;
275 QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false;
276 QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false;
277 QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false;
279 QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false;
280 QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false;
281 QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false;
283 QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false;
284 QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false;
285 QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false;
286 QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false;
287 QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false;
288 QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false;
289 QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false;
290 QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false;
291 QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false;
292 QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false;
293 QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false;
294 QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false;
295 QTest::newRow("wrongType (invalid object)") << "wrongType.16.qml" << "wrongType.16.errors.txt" << false;
296 QTest::newRow("wrongType (int for enum)") << "wrongType.17.qml" << "wrongType.17.errors.txt" << false;
298 QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false;
299 QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false;
300 QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false;
301 QTest::newRow("readOnly.4") << "readOnly.4.qml" << "readOnly.4.errors.txt" << false;
302 QTest::newRow("readOnly.5") << "readOnly.5.qml" << "readOnly.5.errors.txt" << false;
304 QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false;
305 QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false;
306 QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false;
308 QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false;
309 QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false;
310 QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false;
311 QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false;
312 QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false;
313 QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false;
314 QTest::newRow("invalidID.7") << "invalidID.7.qml" << "invalidID.7.errors.txt" << false;
315 QTest::newRow("invalidID.8") << "invalidID.8.qml" << "invalidID.8.errors.txt" << false;
316 QTest::newRow("invalidID.9") << "invalidID.9.qml" << "invalidID.9.errors.txt" << false;
318 QTest::newRow("scriptString.1") << "scriptString.1.qml" << "scriptString.1.errors.txt" << false;
319 QTest::newRow("scriptString.2") << "scriptString.2.qml" << "scriptString.2.errors.txt" << false;
321 QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false;
322 QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true;
323 QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false;
324 QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false;
325 QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false;
326 QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false;
327 QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false;
328 QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false;
329 QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false;
330 QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
331 QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
333 QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
334 QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
335 QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
336 QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false;
337 QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false;
338 QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false;
339 QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true;
340 QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false;
341 QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false;
342 QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false;
344 QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false;
345 QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false;
346 QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false;
347 QTest::newRow("importNonExist (installed)") << "importNonExist.qml" << "importNonExist.errors.txt" << false;
348 QTest::newRow("importNonExistOlder (installed)") << "importNonExistOlder.qml" << "importNonExistOlder.errors.txt" << false;
349 QTest::newRow("importNewerVersion (installed)") << "importNewerVersion.qml" << "importNewerVersion.errors.txt" << false;
350 QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false;
351 QTest::newRow("importFile") << "importFile.qml" << "importFile.errors.txt" << false;
353 QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false;
354 QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false;
355 QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false;
356 QTest::newRow("signal.4") << "signal.4.qml" << "signal.4.errors.txt" << false;
357 QTest::newRow("signal.5") << "signal.5.qml" << "signal.5.errors.txt" << false;
359 QTest::newRow("method.1") << "method.1.qml" << "method.1.errors.txt" << false;
361 QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false;
362 QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false;
363 QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false;
364 QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false;
365 QTest::newRow("property.6") << "property.6.qml" << "property.6.errors.txt" << false;
366 QTest::newRow("property.7") << "property.7.qml" << "property.7.errors.txt" << false;
368 QTest::newRow("importScript.1") << "importscript.1.qml" << "importscript.1.errors.txt" << false;
370 QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false;
371 QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false;
372 QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false;
373 QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false;
374 QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false;
375 QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false;
376 QTest::newRow("Component.7") << "component.7.qml" << "component.7.errors.txt" << false;
377 QTest::newRow("Component.8") << "component.8.qml" << "component.8.errors.txt" << false;
378 QTest::newRow("Component.9") << "component.9.qml" << "component.9.errors.txt" << false;
380 QTest::newRow("MultiSet.1") << "multiSet.1.qml" << "multiSet.1.errors.txt" << false;
381 QTest::newRow("MultiSet.2") << "multiSet.2.qml" << "multiSet.2.errors.txt" << false;
382 QTest::newRow("MultiSet.3") << "multiSet.3.qml" << "multiSet.3.errors.txt" << false;
383 QTest::newRow("MultiSet.4") << "multiSet.4.qml" << "multiSet.4.errors.txt" << false;
384 QTest::newRow("MultiSet.5") << "multiSet.5.qml" << "multiSet.5.errors.txt" << false;
385 QTest::newRow("MultiSet.6") << "multiSet.6.qml" << "multiSet.6.errors.txt" << false;
386 QTest::newRow("MultiSet.7") << "multiSet.7.qml" << "multiSet.7.errors.txt" << false;
387 QTest::newRow("MultiSet.8") << "multiSet.8.qml" << "multiSet.8.errors.txt" << false;
388 QTest::newRow("MultiSet.9") << "multiSet.9.qml" << "multiSet.9.errors.txt" << false;
389 QTest::newRow("MultiSet.10") << "multiSet.10.qml" << "multiSet.10.errors.txt" << false;
390 QTest::newRow("MultiSet.11") << "multiSet.11.qml" << "multiSet.11.errors.txt" << false;
392 QTest::newRow("dynamicMeta.1") << "dynamicMeta.1.qml" << "dynamicMeta.1.errors.txt" << false;
393 QTest::newRow("dynamicMeta.2") << "dynamicMeta.2.qml" << "dynamicMeta.2.errors.txt" << false;
394 QTest::newRow("dynamicMeta.3") << "dynamicMeta.3.qml" << "dynamicMeta.3.errors.txt" << false;
395 QTest::newRow("dynamicMeta.4") << "dynamicMeta.4.qml" << "dynamicMeta.4.errors.txt" << false;
396 QTest::newRow("dynamicMeta.5") << "dynamicMeta.5.qml" << "dynamicMeta.5.errors.txt" << false;
398 QTest::newRow("invalidAlias.1") << "invalidAlias.1.qml" << "invalidAlias.1.errors.txt" << false;
399 QTest::newRow("invalidAlias.2") << "invalidAlias.2.qml" << "invalidAlias.2.errors.txt" << false;
400 QTest::newRow("invalidAlias.3") << "invalidAlias.3.qml" << "invalidAlias.3.errors.txt" << false;
401 QTest::newRow("invalidAlias.4") << "invalidAlias.4.qml" << "invalidAlias.4.errors.txt" << false;
402 QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false;
403 QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false;
404 QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false;
405 QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false;
406 QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false;
407 QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false;
409 QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
410 QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
411 QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false;
412 QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false;
413 QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false;
414 QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false;
415 QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false;
416 QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false;
417 QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false;
418 QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false;
419 QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false;
420 QTest::newRow("invalidAttachedProperty.12") << "invalidAttachedProperty.12.qml" << "invalidAttachedProperty.12.errors.txt" << false;
421 QTest::newRow("invalidAttachedProperty.13") << "invalidAttachedProperty.13.qml" << "invalidAttachedProperty.13.errors.txt" << false;
423 QTest::newRow("assignValueToSignal") << "assignValueToSignal.qml" << "assignValueToSignal.errors.txt" << false;
424 QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false;
426 QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false;
427 QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false;
428 QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false;
429 QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false;
430 QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false;
431 QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false;
432 QTest::newRow("noCreation") << "noCreation.qml" << "noCreation.errors.txt" << false;
433 QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false;
434 QTest::newRow("assignToNamespace") << "assignToNamespace.qml" << "assignToNamespace.errors.txt" << false;
435 QTest::newRow("invalidOn") << "invalidOn.qml" << "invalidOn.errors.txt" << false;
436 QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false;
437 QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false;
438 QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false;
439 QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
440 QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
441 QTest::newRow("incorrectCase") << "incorrectCase.qml"
442 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
443 << "incorrectCase.errors.insensitive.txt"
445 << "incorrectCase.errors.sensitive.txt"
449 QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false;
450 QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false;
451 QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false;
453 QTest::newRow("invalidRoot.1") << "invalidRoot.1.qml" << "invalidRoot.1.errors.txt" << false;
454 QTest::newRow("invalidRoot.2") << "invalidRoot.2.qml" << "invalidRoot.2.errors.txt" << false;
455 QTest::newRow("invalidRoot.3") << "invalidRoot.3.qml" << "invalidRoot.3.errors.txt" << false;
456 QTest::newRow("invalidRoot.4") << "invalidRoot.4.qml" << "invalidRoot.4.errors.txt" << false;
458 QTest::newRow("invalidTypeName.1") << "invalidTypeName.1.qml" << "invalidTypeName.1.errors.txt" << false;
459 QTest::newRow("invalidTypeName.2") << "invalidTypeName.2.qml" << "invalidTypeName.2.errors.txt" << false;
460 QTest::newRow("invalidTypeName.3") << "invalidTypeName.3.qml" << "invalidTypeName.3.errors.txt" << false;
461 QTest::newRow("invalidTypeName.4") << "invalidTypeName.4.qml" << "invalidTypeName.4.errors.txt" << false;
463 QTest::newRow("Major version isolation") << "majorVersionIsolation.qml" << "majorVersionIsolation.errors.txt" << false;
467 void tst_qqmllanguage::errors()
469 QFETCH(QString, file);
470 QFETCH(QString, errorFile);
471 QFETCH(bool, create);
473 QQmlComponent component(&engine, TEST_FILE(file));
476 QObject *object = component.create();
477 QVERIFY(object == 0);
480 VERIFY_ERRORS(errorFile.toLatin1().constData());
483 void tst_qqmllanguage::simpleObject()
485 QQmlComponent component(&engine, TEST_FILE("simpleObject.qml"));
487 QObject *object = component.create();
488 QVERIFY(object != 0);
491 void tst_qqmllanguage::simpleContainer()
493 QQmlComponent component(&engine, TEST_FILE("simpleContainer.qml"));
495 MyContainer *container= qobject_cast<MyContainer*>(component.create());
496 QVERIFY(container != 0);
497 QCOMPARE(container->getChildren()->count(),2);
500 void tst_qqmllanguage::interfaceProperty()
502 QQmlComponent component(&engine, TEST_FILE("interfaceProperty.qml"));
504 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
505 QVERIFY(object != 0);
506 QVERIFY(object->interface());
507 QVERIFY(object->interface()->id == 913);
510 void tst_qqmllanguage::interfaceQList()
512 QQmlComponent component(&engine, TEST_FILE("interfaceQList.qml"));
514 MyContainer *container= qobject_cast<MyContainer*>(component.create());
515 QVERIFY(container != 0);
516 QVERIFY(container->getQListInterfaces()->count() == 2);
517 for(int ii = 0; ii < 2; ++ii)
518 QVERIFY(container->getQListInterfaces()->at(ii)->id == 913);
521 void tst_qqmllanguage::assignObjectToSignal()
523 QQmlComponent component(&engine, TEST_FILE("assignObjectToSignal.qml"));
525 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
526 QVERIFY(object != 0);
527 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
528 emit object->basicSignal();
531 void tst_qqmllanguage::assignObjectToVariant()
533 QQmlComponent component(&engine, TEST_FILE("assignObjectToVariant.qml"));
535 QObject *object = component.create();
536 QVERIFY(object != 0);
537 QVariant v = object->property("a");
538 QVERIFY(v.userType() == qMetaTypeId<QObject *>());
541 void tst_qqmllanguage::assignLiteralSignalProperty()
543 QQmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml"));
545 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
546 QVERIFY(object != 0);
547 QCOMPARE(object->onLiteralSignal(), 10);
550 // Test is an external component can be loaded and assigned (to a qlist)
551 void tst_qqmllanguage::assignQmlComponent()
553 QQmlComponent component(&engine, TEST_FILE("assignQmlComponent.qml"));
555 MyContainer *object = qobject_cast<MyContainer *>(component.create());
556 QVERIFY(object != 0);
557 QVERIFY(object->getChildren()->count() == 1);
558 QObject *child = object->getChildren()->at(0);
559 QCOMPARE(child->property("x"), QVariant(10));
560 QCOMPARE(child->property("y"), QVariant(11));
563 // Test literal assignment to all the basic types
564 void tst_qqmllanguage::assignBasicTypes()
566 QQmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
568 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
569 QVERIFY(object != 0);
570 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
571 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
572 QCOMPARE(object->stringProperty(), QString("Hello World!"));
573 QCOMPARE(object->uintProperty(), uint(10));
574 QCOMPARE(object->intProperty(), -19);
575 QCOMPARE((float)object->realProperty(), float(23.2));
576 QCOMPARE((float)object->doubleProperty(), float(-19.7));
577 QCOMPARE((float)object->floatProperty(), float(8.5));
578 QCOMPARE(object->colorProperty(), QColor("red"));
579 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
580 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
581 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
582 QCOMPARE(object->pointProperty(), QPoint(99,13));
583 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
584 QCOMPARE(object->sizeProperty(), QSize(99, 13));
585 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
586 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
587 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
588 QCOMPARE(object->boolProperty(), true);
589 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
590 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
591 QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2, 2.3));
593 encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
594 QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
595 QVERIFY(object->objectProperty() != 0);
596 MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
598 QCOMPARE(child->intProperty(), 8);
601 // Test edge case type assignments
602 void tst_qqmllanguage::assignTypeExtremes()
604 QQmlComponent component(&engine, TEST_FILE("assignTypeExtremes.qml"));
606 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
607 QVERIFY(object != 0);
608 QCOMPARE(object->uintProperty(), 0xEE6B2800);
609 QCOMPARE(object->intProperty(), -0x77359400);
612 // Test that a composite type can assign to a property of its base type
613 void tst_qqmllanguage::assignCompositeToType()
615 QQmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml"));
617 QObject *object = component.create();
618 QVERIFY(object != 0);
621 // Test that literals are stored correctly in variant properties
622 void tst_qqmllanguage::assignLiteralToVariant()
624 QQmlComponent component(&engine, TEST_FILE("assignLiteralToVariant.qml"));
626 QObject *object = component.create();
627 QVERIFY(object != 0);
629 QCOMPARE(object->property("test1").userType(), (int)QVariant::Int);
630 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
631 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
632 QCOMPARE(object->property("test4").userType(), (int)QVariant::Color);
633 QCOMPARE(object->property("test5").userType(), (int)QVariant::RectF);
634 QCOMPARE(object->property("test6").userType(), (int)QVariant::PointF);
635 QCOMPARE(object->property("test7").userType(), (int)QVariant::SizeF);
636 QCOMPARE(object->property("test8").userType(), (int)QVariant::Vector3D);
637 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
638 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
639 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
640 QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D);
642 QVERIFY(object->property("test1") == QVariant(1));
643 QVERIFY(object->property("test2") == QVariant((double)1.7));
644 QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!"))));
645 QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800)));
646 QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10)));
647 QVERIFY(object->property("test6") == QVariant(QPointF(10, 10)));
648 QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10)));
649 QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100)));
650 QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800"))));
651 QVERIFY(object->property("test10") == QVariant(bool(true)));
652 QVERIFY(object->property("test11") == QVariant(bool(false)));
653 QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100)));
658 // Test that literals are stored correctly in "var" properties
659 // Note that behaviour differs from "variant" properties in that
660 // no conversion from "special strings" to QVariants is performed.
661 void tst_qqmllanguage::assignLiteralToVar()
663 QQmlComponent component(&engine, TEST_FILE("assignLiteralToVar.qml"));
665 QObject *object = component.create();
666 QVERIFY(object != 0);
668 QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
669 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
670 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
671 QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
672 QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
673 QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
674 QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
675 QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
676 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
677 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
678 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
679 QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
680 QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
681 QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
682 QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
683 QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
684 QCOMPARE(object->property("variantTest1Bound").userType(), (int)QMetaType::Int);
685 QCOMPARE(object->property("test1Bound").userType(), (int)QMetaType::Int);
687 QCOMPARE(object->property("test1"), QVariant(5));
688 QCOMPARE(object->property("test2"), QVariant((double)1.7));
689 QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
690 QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
691 QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
692 QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
693 QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
694 QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
695 QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
696 QCOMPARE(object->property("test10"), QVariant(bool(true)));
697 QCOMPARE(object->property("test11"), QVariant(bool(false)));
698 QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
699 QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
700 QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
701 QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
702 QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
703 QCOMPARE(object->property("variantTest1Bound"), QVariant(9));
704 QCOMPARE(object->property("test1Bound"), QVariant(11));
709 // Tests that custom parser types can be instantiated
710 void tst_qqmllanguage::customParserTypes()
712 QQmlComponent component(&engine, TEST_FILE("customParserTypes.qml"));
714 QObject *object = component.create();
715 QVERIFY(object != 0);
716 QVERIFY(object->property("count") == QVariant(2));
719 // Tests that the root item can be a custom component
720 void tst_qqmllanguage::rootAsQmlComponent()
722 QQmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml"));
724 MyContainer *object = qobject_cast<MyContainer *>(component.create());
725 QVERIFY(object != 0);
726 QCOMPARE(object->property("x"), QVariant(11));
727 QCOMPARE(object->getChildren()->count(), 2);
730 // Tests that components can be specified inline
731 void tst_qqmllanguage::inlineQmlComponents()
733 QQmlComponent component(&engine, TEST_FILE("inlineQmlComponents.qml"));
735 MyContainer *object = qobject_cast<MyContainer *>(component.create());
736 QVERIFY(object != 0);
737 QCOMPARE(object->getChildren()->count(), 1);
738 QQmlComponent *comp = qobject_cast<QQmlComponent *>(object->getChildren()->at(0));
740 MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
741 QVERIFY(compObject != 0);
742 QCOMPARE(compObject->value(), 11);
745 // Tests that types that have an id property have it set
746 void tst_qqmllanguage::idProperty()
748 QQmlComponent component(&engine, TEST_FILE("idProperty.qml"));
750 MyContainer *object = qobject_cast<MyContainer *>(component.create());
751 QVERIFY(object != 0);
752 QCOMPARE(object->getChildren()->count(), 1);
753 MyTypeObject *child =
754 qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
756 QCOMPARE(child->id(), QString("myObjectId"));
757 QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
760 // Tests automatic connection to notify signals if "onBlahChanged" syntax is used
761 // even if the notify signal for "blah" is not called "blahChanged"
762 void tst_qqmllanguage::autoNotifyConnection()
764 QQmlComponent component(&engine, TEST_FILE("autoNotifyConnection.qml"));
766 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
767 QVERIFY(object != 0);
768 QMetaProperty prop = object->metaObject()->property(object->metaObject()->indexOfProperty("receivedNotify"));
769 QVERIFY(prop.isValid());
771 QCOMPARE(prop.read(object), QVariant::fromValue(false));
772 object->setPropertyWithNotify(1);
773 QCOMPARE(prop.read(object), QVariant::fromValue(true));
776 // Tests that signals can be assigned to
777 void tst_qqmllanguage::assignSignal()
779 QQmlComponent component(&engine, TEST_FILE("assignSignal.qml"));
781 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
782 QVERIFY(object != 0);
783 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
784 emit object->basicSignal();
785 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
786 emit object->basicParameterizedSignal(9);
789 // Tests the creation and assignment of dynamic properties
790 void tst_qqmllanguage::dynamicProperties()
792 QQmlComponent component(&engine, TEST_FILE("dynamicProperties.qml"));
794 QObject *object = component.create();
795 QVERIFY(object != 0);
796 QCOMPARE(object->property("intProperty"), QVariant(10));
797 QCOMPARE(object->property("boolProperty"), QVariant(false));
798 QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
799 QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
800 QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
801 QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml")));
802 QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
803 QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
804 QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
807 // Test that nested types can use dynamic properties
808 void tst_qqmllanguage::dynamicPropertiesNested()
810 QQmlComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml"));
812 QObject *object = component.create();
813 QVERIFY(object != 0);
815 QCOMPARE(object->property("super_a").toInt(), 11); // Overridden
816 QCOMPARE(object->property("super_c").toInt(), 14); // Inherited
817 QCOMPARE(object->property("a").toInt(), 13); // New
818 QCOMPARE(object->property("b").toInt(), 12); // New
823 // Tests the creation and assignment to dynamic list properties
824 void tst_qqmllanguage::listProperties()
826 QQmlComponent component(&engine, TEST_FILE("listProperties.qml"));
828 QObject *object = component.create();
829 QVERIFY(object != 0);
831 QCOMPARE(object->property("test").toInt(), 2);
834 // Tests the creation and assignment of dynamic object properties
836 void tst_qqmllanguage::dynamicObjectProperties()
839 QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
841 QObject *object = component.create();
842 QVERIFY(object != 0);
844 QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
845 QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
848 QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.2.qml"));
849 QEXPECT_FAIL("", "QTBUG-10822", Abort);
851 QObject *object = component.create();
852 QVERIFY(object != 0);
854 QVERIFY(object->property("objectProperty") != qVariantFromValue((QObject*)0));
858 // Tests the declaration of dynamic signals and slots
859 void tst_qqmllanguage::dynamicSignalsAndSlots()
861 QTest::ignoreMessage(QtDebugMsg, "1921");
863 QQmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml"));
865 QObject *object = component.create();
866 QVERIFY(object != 0);
867 QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
868 QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
869 QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
870 QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
872 QCOMPARE(object->property("test").toInt(), 0);
873 QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10)));
874 QCOMPARE(object->property("test").toInt(), 10);
877 void tst_qqmllanguage::simpleBindings()
879 QQmlComponent component(&engine, TEST_FILE("simpleBindings.qml"));
881 QObject *object = component.create();
882 QVERIFY(object != 0);
883 QCOMPARE(object->property("value1"), QVariant(10));
884 QCOMPARE(object->property("value2"), QVariant(10));
885 QCOMPARE(object->property("value3"), QVariant(21));
886 QCOMPARE(object->property("value4"), QVariant(10));
887 QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
890 void tst_qqmllanguage::autoComponentCreation()
892 QQmlComponent component(&engine, TEST_FILE("autoComponentCreation.qml"));
894 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
895 QVERIFY(object != 0);
896 QVERIFY(object->componentProperty() != 0);
897 MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
899 QCOMPARE(child->realProperty(), qreal(9));
902 void tst_qqmllanguage::propertyValueSource()
905 QQmlComponent component(&engine, TEST_FILE("propertyValueSource.qml"));
907 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
908 QVERIFY(object != 0);
910 QList<QObject *> valueSources;
911 QObjectList allChildren = object->findChildren<QObject*>();
912 foreach (QObject *child, allChildren) {
913 if (qobject_cast<QQmlPropertyValueSource *>(child))
914 valueSources.append(child);
917 QCOMPARE(valueSources.count(), 1);
918 MyPropertyValueSource *valueSource =
919 qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
920 QVERIFY(valueSource != 0);
921 QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
922 QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
926 QQmlComponent component(&engine, TEST_FILE("propertyValueSource.2.qml"));
928 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
929 QVERIFY(object != 0);
931 QList<QObject *> valueSources;
932 QObjectList allChildren = object->findChildren<QObject*>();
933 foreach (QObject *child, allChildren) {
934 if (qobject_cast<QQmlPropertyValueSource *>(child))
935 valueSources.append(child);
938 QCOMPARE(valueSources.count(), 1);
939 MyPropertyValueSource *valueSource =
940 qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
941 QVERIFY(valueSource != 0);
942 QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
943 QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
947 void tst_qqmllanguage::attachedProperties()
949 QQmlComponent component(&engine, TEST_FILE("attachedProperties.qml"));
951 QObject *object = component.create();
952 QVERIFY(object != 0);
953 QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
954 QVERIFY(attached != 0);
955 QCOMPARE(attached->property("value"), QVariant(10));
956 QCOMPARE(attached->property("value2"), QVariant(13));
959 // Tests non-static object properties
960 void tst_qqmllanguage::dynamicObjects()
962 QQmlComponent component(&engine, TEST_FILE("dynamicObject.1.qml"));
964 QObject *object = component.create();
965 QVERIFY(object != 0);
968 // Tests the registration of custom variant string converters
969 void tst_qqmllanguage::customVariantTypes()
971 QQmlComponent component(&engine, TEST_FILE("customVariantTypes.qml"));
973 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
974 QVERIFY(object != 0);
975 QCOMPARE(object->customType().a, 10);
978 void tst_qqmllanguage::valueTypes()
980 QQmlComponent component(&engine, TEST_FILE("valueTypes.qml"));
983 QString message = component.url().toString() + ":2:1: QML MyTypeObject: Binding loop detected for property \"rectProperty.width\"";
984 QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
985 QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
987 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
988 QVERIFY(object != 0);
991 QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13));
992 QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13));
993 QCOMPARE(object->intProperty(), 10);
995 QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13));
996 QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13));
997 QCOMPARE(object->intProperty(), 12);
1001 QQmlProperty p(object, "rectProperty.x");
1002 QCOMPARE(p.read(), QVariant(12));
1004 QCOMPARE(p.read(), QVariant(13));
1006 quint32 r = QQmlPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex());
1008 QQmlPropertyPrivate::restore(p2, r, object);
1009 QCOMPARE(p2.read(), QVariant(13));
1013 void tst_qqmllanguage::cppnamespace()
1016 QQmlComponent component(&engine, TEST_FILE("cppnamespace.qml"));
1018 QObject *object = component.create();
1019 QVERIFY(object != 0);
1024 QQmlComponent component(&engine, TEST_FILE("cppnamespace.2.qml"));
1026 QObject *object = component.create();
1027 QVERIFY(object != 0);
1032 void tst_qqmllanguage::aliasProperties()
1034 // Simple "int" alias
1036 QQmlComponent component(&engine, TEST_FILE("alias.1.qml"));
1038 QObject *object = component.create();
1039 QVERIFY(object != 0);
1041 // Read through alias
1042 QCOMPARE(object->property("valueAlias").toInt(), 10);
1043 object->setProperty("value", QVariant(13));
1044 QCOMPARE(object->property("valueAlias").toInt(), 13);
1046 // Write through alias
1047 object->setProperty("valueAlias", QVariant(19));
1048 QCOMPARE(object->property("valueAlias").toInt(), 19);
1049 QCOMPARE(object->property("value").toInt(), 19);
1054 // Complex object alias
1056 QQmlComponent component(&engine, TEST_FILE("alias.2.qml"));
1058 QObject *object = component.create();
1059 QVERIFY(object != 0);
1061 // Read through alias
1063 qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1065 QCOMPARE(v->value(), 10);
1067 // Write through alias
1068 MyQmlObject *v2 = new MyQmlObject();
1069 v2->setParent(object);
1070 object->setProperty("aliasObject", qVariantFromValue(v2));
1072 qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1081 QQmlComponent component(&engine, TEST_FILE("alias.3.qml"));
1083 QObject *object = component.create();
1084 QVERIFY(object != 0);
1086 QCOMPARE(object->property("value").toInt(), 1892);
1087 QCOMPARE(object->property("value2").toInt(), 1892);
1089 object->setProperty("value", QVariant(1313));
1090 QCOMPARE(object->property("value").toInt(), 1313);
1091 QCOMPARE(object->property("value2").toInt(), 1313);
1093 object->setProperty("value2", QVariant(8080));
1094 QCOMPARE(object->property("value").toInt(), 8080);
1095 QCOMPARE(object->property("value2").toInt(), 8080);
1102 QQmlComponent component(&engine, TEST_FILE("alias.4.qml"));
1104 QObject *object = component.create();
1105 QVERIFY(object != 0);
1107 QCOMPARE(object->property("enumAlias").toInt(), 1);
1114 QQmlComponent component(&engine, TEST_FILE("alias.5.qml"));
1116 QObject *object = component.create();
1117 QVERIFY(object != 0);
1119 QVariant v = object->property("otherAlias");
1120 QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1121 MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
1122 QCOMPARE(o->value(), 10);
1126 v = object->property("otherAlias");
1127 QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1128 o = qvariant_cast<MyQmlObject*>(v);
1134 // Nested aliases - this used to cause a crash
1136 QQmlComponent component(&engine, TEST_FILE("alias.6.qml"));
1138 QObject *object = component.create();
1139 QVERIFY(object != 0);
1141 QCOMPARE(object->property("a").toInt(), 1923);
1144 // Ptr Alias Cleanup - check that aliases to ptr types return 0
1145 // if the object aliased to is removed
1147 QQmlComponent component(&engine, TEST_FILE("alias.7.qml"));
1150 QObject *object = component.create();
1151 QVERIFY(object != 0);
1153 QObject *object1 = qvariant_cast<QObject *>(object->property("object"));
1154 QVERIFY(object1 != 0);
1155 QObject *object2 = qvariant_cast<QObject *>(object1->property("object"));
1156 QVERIFY(object2 != 0);
1158 QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
1159 QVERIFY(alias == object2);
1163 QObject *alias2 = object; // "Random" start value
1165 void *a[] = { &alias2, 0, &status };
1166 QMetaObject::metacall(object, QMetaObject::ReadProperty,
1167 object->metaObject()->indexOfProperty("aliasedObject"), a);
1168 QVERIFY(alias2 == 0);
1171 // Simple composite type
1173 QQmlComponent component(&engine, TEST_FILE("alias.8.qml"));
1175 QObject *object = component.create();
1176 QVERIFY(object != 0);
1178 QCOMPARE(object->property("value").toInt(), 10);
1183 // Complex composite type
1185 QQmlComponent component(&engine, TEST_FILE("alias.9.qml"));
1187 QObject *object = component.create();
1188 QVERIFY(object != 0);
1190 QCOMPARE(object->property("value").toInt(), 10);
1196 // Simple "int" alias
1198 QQmlComponent component(&engine, TEST_FILE("alias.10.qml"));
1200 QObject *object = component.create();
1201 QVERIFY(object != 0);
1203 // Read through alias
1204 QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8));
1205 object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100)));
1206 QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100));
1208 // Write through alias
1209 object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9)));
1210 QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9));
1211 QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9));
1216 // Valuetype sub-alias
1218 QQmlComponent component(&engine, TEST_FILE("alias.11.qml"));
1220 QObject *object = component.create();
1221 QVERIFY(object != 0);
1223 // Read through alias
1224 QCOMPARE(object->property("aliasProperty").toInt(), 19);
1225 object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111)));
1226 QCOMPARE(object->property("aliasProperty").toInt(), 33);
1228 // Write through alias
1229 object->setProperty("aliasProperty", QVariant(4));
1230 QCOMPARE(object->property("aliasProperty").toInt(), 4);
1231 QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111));
1237 // QTBUG-13374 Test that alias properties and signals can coexist
1238 void tst_qqmllanguage::aliasPropertiesAndSignals()
1240 QQmlComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml"));
1242 QObject *o = component.create();
1244 QCOMPARE(o->property("test").toBool(), true);
1248 // Test that the root element in a composite type can be a Component
1249 void tst_qqmllanguage::componentCompositeType()
1251 QQmlComponent component(&engine, TEST_FILE("componentCompositeType.qml"));
1253 QObject *object = component.create();
1254 QVERIFY(object != 0);
1257 class TestType : public QObject {
1260 TestType(QObject *p=0) : QObject(p) {}
1263 class TestType2 : public QObject {
1266 TestType2(QObject *p=0) : QObject(p) {}
1269 void tst_qqmllanguage::i18n_data()
1271 QTest::addColumn<QString>("file");
1272 QTest::addColumn<QString>("stringProperty");
1273 QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)");
1274 QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10");
1275 QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15");
1276 QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20");
1277 QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30");
1278 QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40");
1281 void tst_qqmllanguage::i18n()
1283 QFETCH(QString, file);
1284 QFETCH(QString, stringProperty);
1285 QQmlComponent component(&engine, TEST_FILE(file));
1287 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1288 QVERIFY(object != 0);
1289 QCOMPARE(object->stringProperty(), stringProperty);
1294 // Check that the Component::onCompleted attached property works
1295 void tst_qqmllanguage::onCompleted()
1297 QQmlComponent component(&engine, TEST_FILE("onCompleted.qml"));
1299 QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1300 QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1301 QTest::ignoreMessage(QtDebugMsg, "Completed 10 11");
1302 QObject *object = component.create();
1303 QVERIFY(object != 0);
1306 // Check that the Component::onDestruction attached property works
1307 void tst_qqmllanguage::onDestruction()
1309 QQmlComponent component(&engine, TEST_FILE("onDestruction.qml"));
1311 QObject *object = component.create();
1312 QVERIFY(object != 0);
1313 QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1314 QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1315 QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11");
1319 // Check that assignments to QQmlScriptString properties work
1320 void tst_qqmllanguage::scriptString()
1323 QQmlComponent component(&engine, TEST_FILE("scriptString.qml"));
1326 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1327 QVERIFY(object != 0);
1328 QCOMPARE(object->scriptProperty().script(), QString("foo + bar"));
1329 QCOMPARE(object->scriptProperty().scopeObject(), qobject_cast<QObject*>(object));
1330 QCOMPARE(object->scriptProperty().context(), qmlContext(object));
1332 QVERIFY(object->grouped() != 0);
1333 QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)"));
1334 QCOMPARE(object->grouped()->script().scopeObject(), qobject_cast<QObject*>(object));
1335 QCOMPARE(object->grouped()->script().context(), qmlContext(object));
1339 QQmlComponent component(&engine, TEST_FILE("scriptString2.qml"));
1342 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1343 QVERIFY(object != 0);
1344 QCOMPARE(object->scriptProperty().script(), QString("\"hello\\n\\\"world\\\"\""));
1348 QQmlComponent component(&engine, TEST_FILE("scriptString3.qml"));
1351 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1352 QVERIFY(object != 0);
1353 QCOMPARE(object->scriptProperty().script(), QString("12.345"));
1357 QQmlComponent component(&engine, TEST_FILE("scriptString4.qml"));
1360 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1361 QVERIFY(object != 0);
1362 QCOMPARE(object->scriptProperty().script(), QString("true"));
1366 // Check that default property assignments are correctly spliced into explicit
1367 // property assignments
1368 void tst_qqmllanguage::defaultPropertyListOrder()
1370 QQmlComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml"));
1373 MyContainer *container = qobject_cast<MyContainer *>(component.create());
1374 QVERIFY(container != 0);
1376 QCOMPARE(container->getChildren()->count(), 6);
1377 QCOMPARE(container->getChildren()->at(0)->property("index"), QVariant(0));
1378 QCOMPARE(container->getChildren()->at(1)->property("index"), QVariant(1));
1379 QCOMPARE(container->getChildren()->at(2)->property("index"), QVariant(2));
1380 QCOMPARE(container->getChildren()->at(3)->property("index"), QVariant(3));
1381 QCOMPARE(container->getChildren()->at(4)->property("index"), QVariant(4));
1382 QCOMPARE(container->getChildren()->at(5)->property("index"), QVariant(5));
1385 void tst_qqmllanguage::declaredPropertyValues()
1387 QQmlComponent component(&engine, TEST_FILE("declaredPropertyValues.qml"));
1391 void tst_qqmllanguage::dontDoubleCallClassBegin()
1393 QQmlComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml"));
1394 QObject *o = component.create();
1397 MyParserStatus *o2 = qobject_cast<MyParserStatus *>(qvariant_cast<QObject *>(o->property("object")));
1399 QCOMPARE(o2->classBeginCount(), 1);
1400 QCOMPARE(o2->componentCompleteCount(), 1);
1405 void tst_qqmllanguage::reservedWords_data()
1407 QTest::addColumn<QByteArray>("word");
1409 QTest::newRow("abstract") << QByteArray("abstract");
1410 QTest::newRow("as") << QByteArray("as");
1411 QTest::newRow("boolean") << QByteArray("boolean");
1412 QTest::newRow("break") << QByteArray("break");
1413 QTest::newRow("byte") << QByteArray("byte");
1414 QTest::newRow("case") << QByteArray("case");
1415 QTest::newRow("catch") << QByteArray("catch");
1416 QTest::newRow("char") << QByteArray("char");
1417 QTest::newRow("class") << QByteArray("class");
1418 QTest::newRow("continue") << QByteArray("continue");
1419 QTest::newRow("const") << QByteArray("const");
1420 QTest::newRow("debugger") << QByteArray("debugger");
1421 QTest::newRow("default") << QByteArray("default");
1422 QTest::newRow("delete") << QByteArray("delete");
1423 QTest::newRow("do") << QByteArray("do");
1424 QTest::newRow("double") << QByteArray("double");
1425 QTest::newRow("else") << QByteArray("else");
1426 QTest::newRow("enum") << QByteArray("enum");
1427 QTest::newRow("export") << QByteArray("export");
1428 QTest::newRow("extends") << QByteArray("extends");
1429 QTest::newRow("false") << QByteArray("false");
1430 QTest::newRow("final") << QByteArray("final");
1431 QTest::newRow("finally") << QByteArray("finally");
1432 QTest::newRow("float") << QByteArray("float");
1433 QTest::newRow("for") << QByteArray("for");
1434 QTest::newRow("function") << QByteArray("function");
1435 QTest::newRow("goto") << QByteArray("goto");
1436 QTest::newRow("if") << QByteArray("if");
1437 QTest::newRow("implements") << QByteArray("implements");
1438 QTest::newRow("import") << QByteArray("import");
1439 QTest::newRow("in") << QByteArray("in");
1440 QTest::newRow("instanceof") << QByteArray("instanceof");
1441 QTest::newRow("int") << QByteArray("int");
1442 QTest::newRow("interface") << QByteArray("interface");
1443 QTest::newRow("long") << QByteArray("long");
1444 QTest::newRow("native") << QByteArray("native");
1445 QTest::newRow("new") << QByteArray("new");
1446 QTest::newRow("null") << QByteArray("null");
1447 QTest::newRow("package") << QByteArray("package");
1448 QTest::newRow("private") << QByteArray("private");
1449 QTest::newRow("protected") << QByteArray("protected");
1450 QTest::newRow("public") << QByteArray("public");
1451 QTest::newRow("return") << QByteArray("return");
1452 QTest::newRow("short") << QByteArray("short");
1453 QTest::newRow("static") << QByteArray("static");
1454 QTest::newRow("super") << QByteArray("super");
1455 QTest::newRow("switch") << QByteArray("switch");
1456 QTest::newRow("synchronized") << QByteArray("synchronized");
1457 QTest::newRow("this") << QByteArray("this");
1458 QTest::newRow("throw") << QByteArray("throw");
1459 QTest::newRow("throws") << QByteArray("throws");
1460 QTest::newRow("transient") << QByteArray("transient");
1461 QTest::newRow("true") << QByteArray("true");
1462 QTest::newRow("try") << QByteArray("try");
1463 QTest::newRow("typeof") << QByteArray("typeof");
1464 QTest::newRow("var") << QByteArray("var");
1465 QTest::newRow("void") << QByteArray("void");
1466 QTest::newRow("volatile") << QByteArray("volatile");
1467 QTest::newRow("while") << QByteArray("while");
1468 QTest::newRow("with") << QByteArray("with");
1471 void tst_qqmllanguage::reservedWords()
1473 QFETCH(QByteArray, word);
1474 QQmlComponent component(&engine);
1475 component.setData("import QtQuick 2.0\nQtObject { property string " + word + " }", QUrl());
1476 QCOMPARE(component.errorString(), QLatin1String(":2 Expected token `identifier'\n"));
1479 // Check that first child of qml is of given type. Empty type insists on error.
1480 void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror)
1482 QQmlComponent component(&engine);
1483 component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
1485 QTRY_VERIFY(!component.isLoading());
1487 if (type.isEmpty()) {
1488 QVERIFY(component.isError());
1489 QString actualerror;
1490 foreach (const QQmlError e, component.errors()) {
1491 if (!actualerror.isEmpty())
1492 actualerror.append("; ");
1493 actualerror.append(e.description());
1495 QCOMPARE(actualerror,expectederror);
1498 QObject *object = component.create();
1499 QVERIFY(object != 0);
1500 QCOMPARE(QString(object->metaObject()->className()), type);
1506 void tst_qqmllanguage::inlineAssignmentsOverrideBindings()
1508 QQmlComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml"));
1510 QObject *o = component.create();
1512 QCOMPARE(o->property("test").toInt(), 11);
1517 void tst_qqmllanguage::nestedComponentRoots()
1519 QQmlComponent component(&engine, TEST_FILE("nestedComponentRoots.qml"));
1522 // Import tests (QT-558)
1523 void tst_qqmllanguage::importsBuiltin_data()
1527 QTest::addColumn<QString>("qml");
1528 QTest::addColumn<QString>("type");
1529 QTest::addColumn<QString>("error");
1532 QTest::newRow("missing import")
1535 << "Test is not a type";
1536 QTest::newRow("not in version 0.0")
1537 << "import com.nokia.Test 0.0\n"
1540 << "Test is not a type";
1541 QTest::newRow("version not installed")
1542 << "import com.nokia.Test 99.0\n"
1545 << "module \"com.nokia.Test\" version 99.0 is not installed";
1546 QTest::newRow("in version 0.0")
1547 << "import com.nokia.Test 0.0\n"
1551 QTest::newRow("qualified in version 0.0")
1552 << "import com.nokia.Test 0.0 as T\n"
1556 QTest::newRow("in version 1.0")
1557 << "import com.nokia.Test 1.0\n"
1561 QTest::newRow("qualified wrong")
1562 << "import com.nokia.Test 1.0 as T\n" // QT-610
1565 << "Test is not a type";
1566 QTest::newRow("qualified right")
1567 << "import com.nokia.Test 1.0 as T\n"
1571 QTest::newRow("qualified right but not in version 0.0")
1572 << "import com.nokia.Test 0.0 as T\n"
1575 << "T.Test is not a type";
1576 QTest::newRow("in version 1.1")
1577 << "import com.nokia.Test 1.1\n"
1581 QTest::newRow("in version 1.3")
1582 << "import com.nokia.Test 1.3\n"
1586 QTest::newRow("in version 1.5")
1587 << "import com.nokia.Test 1.5\n"
1591 QTest::newRow("changed in version 1.8")
1592 << "import com.nokia.Test 1.8\n"
1596 QTest::newRow("in version 1.12")
1597 << "import com.nokia.Test 1.12\n"
1601 QTest::newRow("old in version 1.9")
1602 << "import com.nokia.Test 1.9\n"
1606 QTest::newRow("old in version 1.11")
1607 << "import com.nokia.Test 1.11\n"
1611 QTest::newRow("multiversion 1")
1612 << "import com.nokia.Test 1.11\n"
1613 "import com.nokia.Test 1.12\n"
1615 << (!qmlCheckTypes()?"TestType2":"")
1616 << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
1617 QTest::newRow("multiversion 2")
1618 << "import com.nokia.Test 1.11\n"
1619 "import com.nokia.Test 1.12\n"
1621 << (!qmlCheckTypes()?"TestType":"")
1622 << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
1623 QTest::newRow("qualified multiversion 3")
1624 << "import com.nokia.Test 1.0 as T0\n"
1625 "import com.nokia.Test 1.8 as T8\n"
1629 QTest::newRow("qualified multiversion 4")
1630 << "import com.nokia.Test 1.0 as T0\n"
1631 "import com.nokia.Test 1.8 as T8\n"
1637 void tst_qqmllanguage::importsBuiltin()
1639 QFETCH(QString, qml);
1640 QFETCH(QString, type);
1641 QFETCH(QString, error);
1642 testType(qml,type,error);
1645 void tst_qqmllanguage::importsLocal_data()
1647 QTest::addColumn<QString>("qml");
1648 QTest::addColumn<QString>("type");
1649 QTest::addColumn<QString>("error");
1652 QTest::newRow("local import")
1653 << "import \"subdir\"\n" // QT-613
1655 << "QQuickRectangle"
1657 QTest::newRow("local import second")
1658 << "import QtQuick 2.0\nimport \"subdir\"\n"
1660 << "QQuickRectangle"
1662 QTest::newRow("local import subsubdir")
1663 << "import QtQuick 2.0\nimport \"subdir/subsubdir\"\n"
1665 << "QQuickRectangle"
1667 QTest::newRow("local import QTBUG-7721 A")
1668 << "subdir.Test {}" // no longer allowed (QTBUG-7721)
1670 << "subdir.Test - subdir is not a namespace";
1671 QTest::newRow("local import QTBUG-7721 B")
1672 << "import \"subdir\" as X\n"
1673 "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
1675 << "X.subsubdir.SubTest - nested namespaces not allowed";
1676 QTest::newRow("local import as")
1677 << "import \"subdir\" as T\n"
1679 << "QQuickRectangle"
1681 QTest::newRow("wrong local import as")
1682 << "import \"subdir\" as T\n"
1685 << "Test is not a type";
1686 QTest::newRow("library precedence over local import")
1687 << "import \"subdir\"\n"
1688 "import com.nokia.Test 1.0\n"
1690 << (!qmlCheckTypes()?"TestType":"")
1691 << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test and in subdir");
1694 void tst_qqmllanguage::importsLocal()
1696 QFETCH(QString, qml);
1697 QFETCH(QString, type);
1698 QFETCH(QString, error);
1699 testType(qml,type,error);
1702 void tst_qqmllanguage::basicRemote_data()
1704 QTest::addColumn<QUrl>("url");
1705 QTest::addColumn<QString>("type");
1706 QTest::addColumn<QString>("error");
1708 QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage/";
1710 QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << "";
1711 QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << "";
1712 QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << "";
1715 void tst_qqmllanguage::basicRemote()
1718 QFETCH(QString, type);
1719 QFETCH(QString, error);
1721 TestHTTPServer server(14447);
1722 server.serveDirectory(testdata());
1724 QQmlComponent component(&engine, url);
1726 QTRY_VERIFY(!component.isLoading());
1728 if (error.isEmpty()) {
1729 if (component.isError())
1730 qDebug() << component.errors();
1731 QVERIFY(!component.isError());
1733 QVERIFY(component.isError());
1737 void tst_qqmllanguage::importsRemote_data()
1739 QTest::addColumn<QString>("qml");
1740 QTest::addColumn<QString>("type");
1741 QTest::addColumn<QString>("error");
1743 QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage";
1745 QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QQuickRectangle"
1747 QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QQuickText"
1749 QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QQuickImage"
1751 QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << ""
1752 << "WrongTestLocal is not a type";
1753 QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << ""
1754 << "LocalInternal is not a type";
1755 QTest::newRow("wrong remote import of undeclared local") << "import \""+serverdir+"\"\nUndeclaredLocal {}" << ""
1756 << "UndeclaredLocal is not a type";
1759 void tst_qqmllanguage::importsRemote()
1761 QFETCH(QString, qml);
1762 QFETCH(QString, type);
1763 QFETCH(QString, error);
1765 TestHTTPServer server(14447);
1766 server.serveDirectory(testdata());
1768 testType(qml,type,error);
1771 void tst_qqmllanguage::importsInstalled_data()
1775 QTest::addColumn<QString>("qml");
1776 QTest::addColumn<QString>("type");
1777 QTest::addColumn<QString>("error");
1780 QTest::newRow("installed import 0")
1781 << "import com.nokia.installedtest0 0.0\n"
1782 "InstalledTestTP {}"
1783 << "QQuickRectangle"
1785 QTest::newRow("installed import 0 as TP")
1786 << "import com.nokia.installedtest0 0.0 as TP\n"
1787 "TP.InstalledTestTP {}"
1788 << "QQuickRectangle"
1790 QTest::newRow("installed import 1")
1791 << "import com.nokia.installedtest 1.0\n"
1793 << "QQuickRectangle"
1795 QTest::newRow("installed import 2")
1796 << "import com.nokia.installedtest 1.3\n"
1798 << "QQuickRectangle"
1800 QTest::newRow("installed import 3")
1801 << "import com.nokia.installedtest 1.4\n"
1805 QTest::newRow("installed import minor version not available") // QTBUG-11936
1806 << "import com.nokia.installedtest 0.1\n"
1809 << "module \"com.nokia.installedtest\" version 0.1 is not installed";
1810 QTest::newRow("installed import minor version not available") // QTBUG-9627
1811 << "import com.nokia.installedtest 1.10\n"
1814 << "module \"com.nokia.installedtest\" version 1.10 is not installed";
1815 QTest::newRow("installed import major version not available") // QTBUG-9627
1816 << "import com.nokia.installedtest 9.0\n"
1819 << "module \"com.nokia.installedtest\" version 9.0 is not installed";
1820 QTest::newRow("installed import visibility") // QT-614
1821 << "import com.nokia.installedtest 1.4\n"
1824 << "PrivateType is not a type";
1827 void tst_qqmllanguage::importsInstalled()
1829 QFETCH(QString, qml);
1830 QFETCH(QString, type);
1831 QFETCH(QString, error);
1832 testType(qml,type,error);
1836 void tst_qqmllanguage::importsOrder_data()
1838 QTest::addColumn<QString>("qml");
1839 QTest::addColumn<QString>("type");
1840 QTest::addColumn<QString>("error");
1842 QTest::newRow("double import") <<
1843 "import com.nokia.installedtest 1.4\n"
1844 "import com.nokia.installedtest 1.4\n"
1846 << (!qmlCheckTypes()?"QQuickText":"")
1847 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.4");
1848 QTest::newRow("installed import overrides 1") <<
1849 "import com.nokia.installedtest 1.0\n"
1850 "import com.nokia.installedtest 1.4\n"
1852 << (!qmlCheckTypes()?"QQuickText":"")
1853 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
1854 QTest::newRow("installed import overrides 2") <<
1855 "import com.nokia.installedtest 1.4\n"
1856 "import com.nokia.installedtest 1.0\n"
1858 << (!qmlCheckTypes()?"QQuickRectangle":"")
1859 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
1860 QTest::newRow("installed import re-overrides 1") <<
1861 "import com.nokia.installedtest 1.4\n"
1862 "import com.nokia.installedtest 1.0\n"
1863 "import com.nokia.installedtest 1.4\n"
1865 << (!qmlCheckTypes()?"QQuickText":"")
1866 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
1867 QTest::newRow("installed import re-overrides 2") <<
1868 "import com.nokia.installedtest 1.4\n"
1869 "import com.nokia.installedtest 1.0\n"
1870 "import com.nokia.installedtest 1.4\n"
1871 "import com.nokia.installedtest 1.0\n"
1873 << (!qmlCheckTypes()?"QQuickRectangle":"")
1874 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
1876 QTest::newRow("installed import versus builtin 1") <<
1877 "import com.nokia.installedtest 1.5\n"
1878 "import QtQuick 2.0\n"
1880 << (!qmlCheckTypes()?"QQuickRectangle":"")
1881 << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in Qt and in lib/com/nokia/installedtest");
1882 QTest::newRow("installed import versus builtin 2") <<
1883 "import QtQuick 2.0\n"
1884 "import com.nokia.installedtest 1.5\n"
1886 << (!qmlCheckTypes()?"QQuickText":"")
1887 << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest and in Qt");
1888 QTest::newRow("namespaces cannot be overridden by types 1") <<
1889 "import QtQuick 2.0 as Rectangle\n"
1890 "import com.nokia.installedtest 1.5\n"
1893 << "Namespace Rectangle cannot be used as a type";
1894 QTest::newRow("namespaces cannot be overridden by types 2") <<
1895 "import QtQuick 2.0 as Rectangle\n"
1896 "import com.nokia.installedtest 1.5\n"
1897 "Rectangle.Image {}"
1900 QTest::newRow("local last 1") <<
1904 QTest::newRow("local last 2") <<
1905 "import com.nokia.installedtest 1.0\n"
1907 << (!qmlCheckTypes()?"QQuickRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
1908 << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory");
1911 void tst_qqmllanguage::importsOrder()
1913 QFETCH(QString, qml);
1914 QFETCH(QString, type);
1915 QFETCH(QString, error);
1916 testType(qml,type,error);
1919 void tst_qqmllanguage::importIncorrectCase()
1921 QQmlComponent component(&engine, TEST_FILE("importIncorrectCase.qml"));
1923 QList<QQmlError> errors = component.errors();
1924 QCOMPARE(errors.count(), 1);
1926 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1927 QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + testdata("lib/com/Nokia/installedtest/qmldir") + QLatin1String("\"");
1929 QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed");
1932 QCOMPARE(errors.at(0).description(), expectedError);
1935 void tst_qqmllanguage::importJs_data()
1937 QTest::addColumn<QString>("file");
1938 QTest::addColumn<QString>("errorFile");
1939 QTest::addColumn<bool>("performTest");
1941 QTest::newRow("defaultVersion")
1943 << "importJs.1.errors.txt"
1946 QTest::newRow("specifiedVersion")
1948 << "importJs.2.errors.txt"
1951 QTest::newRow("excludeExcessiveVersion")
1953 << "importJs.3.errors.txt"
1956 QTest::newRow("includeAppropriateVersion")
1958 << "importJs.4.errors.txt"
1961 QTest::newRow("noDefaultVersion")
1963 << "importJs.5.errors.txt"
1966 QTest::newRow("repeatImportFails")
1968 << "importJs.6.errors.txt"
1971 QTest::newRow("multipleVersionImportFails")
1973 << "importJs.7.errors.txt"
1976 QTest::newRow("namespacedImport")
1978 << "importJs.8.errors.txt"
1981 QTest::newRow("namespacedVersionedImport")
1983 << "importJs.9.errors.txt"
1986 QTest::newRow("namespacedRepeatImport")
1987 << "importJs.10.qml"
1988 << "importJs.10.errors.txt"
1992 void tst_qqmllanguage::importJs()
1994 QFETCH(QString, file);
1995 QFETCH(QString, errorFile);
1996 QFETCH(bool, performTest);
1998 QQmlComponent component(&engine, TEST_FILE(file));
2001 DETERMINE_ERRORS(errorFile.toLatin1().constData(),expected,actual);
2002 QCOMPARE(expected.size(), actual.size());
2003 for (int i = 0; i < expected.size(); ++i)
2005 size_t compareLen = std::min(expected.at(i).length(), actual.at(i).length());
2006 QCOMPARE(expected.at(i).left(compareLen), actual.at(i).left(compareLen));
2011 QObject *object = component.create();
2012 QVERIFY(object != 0);
2013 QCOMPARE(object->property("test").toBool(),true);
2018 void tst_qqmllanguage::qmlAttachedPropertiesObjectMethod()
2022 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
2023 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
2026 QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml"));
2028 QObject *object = component.create();
2029 QVERIFY(object != 0);
2031 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(object, false), (QObject *)0);
2032 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2036 QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml"));
2038 QObject *object = component.create();
2039 QVERIFY(object != 0);
2041 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, false) != 0);
2042 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2046 void tst_qqmllanguage::crash1()
2048 QQmlComponent component(&engine);
2049 component.setData("import QtQuick 2.0\nComponent {}", QUrl());
2052 void tst_qqmllanguage::crash2()
2054 QQmlComponent component(&engine, TEST_FILE("crash2.qml"));
2058 void tst_qqmllanguage::customOnProperty()
2060 QQmlComponent component(&engine, TEST_FILE("customOnProperty.qml"));
2063 QObject *object = component.create();
2064 QVERIFY(object != 0);
2066 QCOMPARE(object->property("on").toInt(), 10);
2072 void tst_qqmllanguage::variantNotify()
2074 QQmlComponent component(&engine, TEST_FILE("variantNotify.qml"));
2077 QObject *object = component.create();
2078 QVERIFY(object != 0);
2080 QCOMPARE(object->property("notifyCount").toInt(), 1);
2085 void tst_qqmllanguage::revisions()
2088 QQmlComponent component(&engine, TEST_FILE("revisions11.qml"));
2091 MyRevisionedClass *object = qobject_cast<MyRevisionedClass*>(component.create());
2092 QVERIFY(object != 0);
2094 QCOMPARE(object->prop2(), 10.0);
2099 QQmlEngine myEngine;
2100 QQmlComponent component(&myEngine, TEST_FILE("revisionssub11.qml"));
2103 MyRevisionedSubclass *object = qobject_cast<MyRevisionedSubclass*>(component.create());
2104 QVERIFY(object != 0);
2106 QCOMPARE(object->prop1(), 10.0);
2107 QCOMPARE(object->prop2(), 10.0);
2108 QCOMPARE(object->prop3(), 10.0);
2109 QCOMPARE(object->prop4(), 10.0);
2114 QQmlComponent component(&engine, TEST_FILE("versionedbase.qml"));
2116 MySubclass *object = qobject_cast<MySubclass*>(component.create());
2117 QVERIFY(object != 0);
2119 QCOMPARE(object->prop1(), 10.0);
2120 QCOMPARE(object->prop2(), 10.0);
2126 void tst_qqmllanguage::revisionOverloads()
2129 QQmlComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml"));
2133 QQmlComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml"));
2134 QEXPECT_FAIL("", "QTBUG-13849", Abort);
2136 VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt");
2140 void tst_qqmllanguage::initTestCase()
2142 QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath();
2143 QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
2147 // Registering the TestType class in other modules should have no adverse effects
2148 qmlRegisterType<TestType>("com.nokia.TestPre", 1, 0, "Test");
2150 qmlRegisterType<TestType>("com.nokia.Test", 0, 0, "TestTP");
2151 qmlRegisterType<TestType>("com.nokia.Test", 1, 0, "Test");
2152 qmlRegisterType<TestType>("com.nokia.Test", 1, 5, "Test");
2153 qmlRegisterType<TestType2>("com.nokia.Test", 1, 8, "Test");
2154 qmlRegisterType<TestType>("com.nokia.Test", 1, 9, "OldTest");
2155 qmlRegisterType<TestType2>("com.nokia.Test", 1, 12, "Test");
2157 // Registering the TestType class in other modules should have no adverse effects
2158 qmlRegisterType<TestType>("com.nokia.TestPost", 1, 0, "Test");
2160 // Create locale-specific file
2161 // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit
2162 // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters
2163 // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded
2164 QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile());
2165 QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString())));
2166 QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile());
2167 QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString())));
2168 out.write(in.readAll());
2171 void tst_qqmllanguage::aliasPropertyChangeSignals()
2174 QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.qml"));
2177 QObject *o = component.create();
2180 QCOMPARE(o->property("test").toBool(), true);
2185 // QTCREATORBUG-2769
2187 QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.2.qml"));
2190 QObject *o = component.create();
2193 QCOMPARE(o->property("test").toBool(), true);
2199 // Tests property initializers
2200 void tst_qqmllanguage::propertyInit()
2203 QQmlComponent component(&engine, TEST_FILE("propertyInit.1.qml"));
2206 QObject *o = component.create();
2209 QCOMPARE(o->property("test").toInt(), 1);
2215 QQmlComponent component(&engine, TEST_FILE("propertyInit.2.qml"));
2218 QObject *o = component.create();
2221 QCOMPARE(o->property("test").toInt(), 123);
2227 // Test that registration order doesn't break type availability
2229 void tst_qqmllanguage::registrationOrder()
2231 QQmlComponent component(&engine, TEST_FILE("registrationOrder.qml"));
2233 QObject *o = component.create();
2235 QVERIFY(o->metaObject() == &MyVersion2Class::staticMetaObject);
2239 void tst_qqmllanguage::readonly()
2241 QQmlComponent component(&engine, TEST_FILE("readonly.qml"));
2243 QObject *o = component.create();
2246 QCOMPARE(o->property("test1").toInt(), 10);
2247 QCOMPARE(o->property("test2").toInt(), 18);
2248 QCOMPARE(o->property("test3").toInt(), 13);
2250 o->setProperty("testData", 13);
2252 QCOMPARE(o->property("test1").toInt(), 10);
2253 QCOMPARE(o->property("test2").toInt(), 22);
2254 QCOMPARE(o->property("test3").toInt(), 13);
2256 o->setProperty("testData2", 2);
2258 QCOMPARE(o->property("test1").toInt(), 10);
2259 QCOMPARE(o->property("test2").toInt(), 22);
2260 QCOMPARE(o->property("test3").toInt(), 2);
2262 o->setProperty("test1", 11);
2263 o->setProperty("test2", 11);
2264 o->setProperty("test3", 11);
2266 QCOMPARE(o->property("test1").toInt(), 10);
2267 QCOMPARE(o->property("test2").toInt(), 22);
2268 QCOMPARE(o->property("test3").toInt(), 2);
2274 void tst_qqmllanguage::remoteLoadCrash()
2276 TestHTTPServer server(14448);
2277 server.serveDirectory(testdata());
2279 QQmlComponent component(&engine);
2280 component.setData("import QtQuick 2.0; Text {}", QUrl("http://127.0.0.1:14448/remoteLoadCrash.qml"));
2281 while (component.isLoading())
2282 QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50);
2284 QObject *o = component.create();
2288 QTEST_MAIN(tst_qqmllanguage)
2290 #include "tst_qqmllanguage.moc"