From 12a5ddf456ba8549645a8cb28a8b4ed6197a14da Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Mon, 30 Jan 2012 14:16:15 +1000 Subject: Import relevant source from Qt 4.8 Change-Id: I5078db4081d95290c54f39d3c0efc2fc2f62e6a6 --- .../tst_qdeclarativelanguage.cpp | 2028 ++++++++++++++++++++ 1 file changed, 2028 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp (limited to 'tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp') diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp new file mode 100644 index 00000000..bfc0a5f1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -0,0 +1,2028 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "testtypes.h" + +#include "../../../shared/util.h" +#include "testhttpserver.h" + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES) + + +/* +This test case covers QML language issues. This covers everything that does not +involve evaluating ECMAScript expressions and bindings. + +Evaluation of expressions and bindings is covered in qmlecmascript +*/ +class tst_qdeclarativelanguage : public QObject +{ + Q_OBJECT +public: + tst_qdeclarativelanguage() { + QDeclarativeMetaType::registerCustomStringConverter(qMetaTypeId(), myCustomVariantTypeConverter); + QFileInfo fileInfo(__FILE__); + engine.addImportPath(fileInfo.absoluteDir().filePath(QLatin1String("data/lib"))); + } + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void errors_data(); + void errors(); + + void insertedSemicolon_data(); + void insertedSemicolon(); + + void simpleObject(); + void simpleContainer(); + void interfaceProperty(); + void interfaceQList(); + void assignObjectToSignal(); + void assignObjectToVariant(); + void assignLiteralSignalProperty(); + void assignQmlComponent(); + void assignBasicTypes(); + void assignTypeExtremes(); + void assignCompositeToType(); + void assignLiteralToVariant(); + void customParserTypes(); + void rootAsQmlComponent(); + void inlineQmlComponents(); + void idProperty(); + void autoNotifyConnection(); + void assignSignal(); + void dynamicProperties(); + void dynamicPropertiesNested(); + void listProperties(); + void dynamicObjectProperties(); + void dynamicSignalsAndSlots(); + void simpleBindings(); + void autoComponentCreation(); + void propertyValueSource(); + void attachedProperties(); + void dynamicObjects(); + void customVariantTypes(); + void valueTypes(); + void cppnamespace(); + void aliasProperties(); + void aliasPropertiesAndSignals(); + void aliasPropertyChangeSignals(); + void componentCompositeType(); + void i18n(); + void i18n_data(); + void onCompleted(); + void onDestruction(); + void scriptString(); + void defaultPropertyListOrder(); + void declaredPropertyValues(); + void dontDoubleCallClassBegin(); + void reservedWords_data(); + void reservedWords(); + void inlineAssignmentsOverrideBindings(); + void nestedComponentRoots(); + + void basicRemote_data(); + void basicRemote(); + void importsBuiltin_data(); + void importsBuiltin(); + void importsLocal_data(); + void importsLocal(); + void importsRemote_data(); + void importsRemote(); + void importsInstalled_data(); + void importsInstalled(); + void importsOrder_data(); + void importsOrder(); + void importIncorrectCase(); + + void qmlAttachedPropertiesObjectMethod(); + void customOnProperty(); + void variantNotify(); + + void revisions(); + void revisionOverloads(); + + // regression tests for crashes + void crash1(); + void crash2(); + +private: + QDeclarativeEngine engine; + void testType(const QString& qml, const QString& type, const QString& error); +}; + +#define VERIFY_ERRORS(errorfile) \ + if (!errorfile) { \ + if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \ + qWarning() << "Unexpected Errors:" << component.errors(); \ + QVERIFY(!component.isError()); \ + QVERIFY(component.errors().isEmpty()); \ + } else { \ + QFile file(QLatin1String(SRCDIR) + QLatin1String("/data/") + QLatin1String(errorfile)); \ + QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \ + QByteArray data = file.readAll(); \ + file.close(); \ + QList expected = data.split('\n'); \ + expected.removeAll(QByteArray("")); \ + QList errors = component.errors(); \ + QList actual; \ + for (int ii = 0; ii < errors.count(); ++ii) { \ + const QDeclarativeError &error = errors.at(ii); \ + QByteArray errorStr = QByteArray::number(error.line()) + ":" + \ + QByteArray::number(error.column()) + ":" + \ + error.description().toUtf8(); \ + actual << errorStr; \ + } \ + if (qgetenv("DEBUG") != "" && expected != actual) \ + qWarning() << "Expected:" << expected << "Actual:" << actual; \ + if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\ + QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \ + QVERIFY(file.open(QIODevice::WriteOnly)); \ + for (int ii = 0; ii < actual.count(); ++ii) { \ + file.write(actual.at(ii)); file.write("\n"); \ + } \ + file.close(); \ + } else { \ + QCOMPARE(expected, actual); \ + } \ + } + +inline QUrl TEST_FILE(const QString &filename) +{ + QFileInfo fileInfo(__FILE__); + return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(QLatin1String("data/") + filename)); +} + +inline QUrl TEST_FILE(const char *filename) +{ + return TEST_FILE(QLatin1String(filename)); +} + +void tst_qdeclarativelanguage::cleanupTestCase() +{ + QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile())); +} + +void tst_qdeclarativelanguage::insertedSemicolon_data() +{ + QTest::addColumn("file"); + QTest::addColumn("errorFile"); + QTest::addColumn("create"); + + QTest::newRow("insertedSemicolon.1") << "insertedSemicolon.1.qml" << "insertedSemicolon.1.errors.txt" << false; +} + +void tst_qdeclarativelanguage::insertedSemicolon() +{ + QFETCH(QString, file); + QFETCH(QString, errorFile); + QFETCH(bool, create); + + QDeclarativeComponent component(&engine, TEST_FILE(file)); + + if(create) { + QObject *object = component.create(); + QVERIFY(object == 0); + } + + VERIFY_ERRORS(errorFile.toLatin1().constData()); +} + +void tst_qdeclarativelanguage::errors_data() +{ + QTest::addColumn("file"); + QTest::addColumn("errorFile"); + QTest::addColumn("create"); + + QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false; + QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false; + QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false; + QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false; + QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false; + QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false; + + QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false; + QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false; + QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false; + + QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false; + QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false; + QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false; + QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false; + QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false; + QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false; + QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false; + QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false; + QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false; + QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false; + QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false; + QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false; + QTest::newRow("wrongType (invalid object)") << "wrongType.16.qml" << "wrongType.16.errors.txt" << false; + + QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false; + QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false; + QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false; + QTest::newRow("readOnly.4") << "readOnly.4.qml" << "readOnly.4.errors.txt" << false; + QTest::newRow("readOnly.5") << "readOnly.5.qml" << "readOnly.5.errors.txt" << false; + + QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false; + QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false; + QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false; + + QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false; + QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false; + QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false; + QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false; + QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false; + QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false; + QTest::newRow("invalidID.7") << "invalidID.7.qml" << "invalidID.7.errors.txt" << false; + QTest::newRow("invalidID.8") << "invalidID.8.qml" << "invalidID.8.errors.txt" << false; + QTest::newRow("invalidID.9") << "invalidID.9.qml" << "invalidID.9.errors.txt" << false; + + QTest::newRow("scriptString.1") << "scriptString.1.qml" << "scriptString.1.errors.txt" << false; + QTest::newRow("scriptString.2") << "scriptString.2.qml" << "scriptString.2.errors.txt" << false; + + QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false; + QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true; + QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false; + QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false; + QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false; + QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false; + QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false; + QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false; + QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false; + QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false; + QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false; + + QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true; + QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false; + + QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false; + QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false; + QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false; + QTest::newRow("importNonExist (installed)") << "importNonExist.qml" << "importNonExist.errors.txt" << false; + QTest::newRow("importNonExistOlder (installed)") << "importNonExistOlder.qml" << "importNonExistOlder.errors.txt" << false; + QTest::newRow("importNewerVersion (installed)") << "importNewerVersion.qml" << "importNewerVersion.errors.txt" << false; + QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false; + QTest::newRow("importFile") << "importFile.qml" << "importFile.errors.txt" << false; + + QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false; + QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false; + QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false; + QTest::newRow("signal.4") << "signal.4.qml" << "signal.4.errors.txt" << false; + + QTest::newRow("method.1") << "method.1.qml" << "method.1.errors.txt" << false; + + QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false; + QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false; + QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false; + QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false; + QTest::newRow("property.5") << "property.5.qml" << "property.5.errors.txt" << false; + QTest::newRow("property.6") << "property.6.qml" << "property.6.errors.txt" << false; + QTest::newRow("property.7") << "property.7.qml" << "property.7.errors.txt" << false; + + QTest::newRow("importScript.1") << "importscript.1.qml" << "importscript.1.errors.txt" << false; + + QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false; + QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false; + QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false; + QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false; + QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false; + QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false; + QTest::newRow("Component.7") << "component.7.qml" << "component.7.errors.txt" << false; + QTest::newRow("Component.8") << "component.8.qml" << "component.8.errors.txt" << false; + QTest::newRow("Component.9") << "component.9.qml" << "component.9.errors.txt" << false; + + QTest::newRow("MultiSet.1") << "multiSet.1.qml" << "multiSet.1.errors.txt" << false; + QTest::newRow("MultiSet.2") << "multiSet.2.qml" << "multiSet.2.errors.txt" << false; + QTest::newRow("MultiSet.3") << "multiSet.3.qml" << "multiSet.3.errors.txt" << false; + QTest::newRow("MultiSet.4") << "multiSet.4.qml" << "multiSet.4.errors.txt" << false; + QTest::newRow("MultiSet.5") << "multiSet.5.qml" << "multiSet.5.errors.txt" << false; + QTest::newRow("MultiSet.6") << "multiSet.6.qml" << "multiSet.6.errors.txt" << false; + QTest::newRow("MultiSet.7") << "multiSet.7.qml" << "multiSet.7.errors.txt" << false; + QTest::newRow("MultiSet.8") << "multiSet.8.qml" << "multiSet.8.errors.txt" << false; + QTest::newRow("MultiSet.9") << "multiSet.9.qml" << "multiSet.9.errors.txt" << false; + QTest::newRow("MultiSet.10") << "multiSet.10.qml" << "multiSet.10.errors.txt" << false; + QTest::newRow("MultiSet.11") << "multiSet.11.qml" << "multiSet.11.errors.txt" << false; + + QTest::newRow("dynamicMeta.1") << "dynamicMeta.1.qml" << "dynamicMeta.1.errors.txt" << false; + QTest::newRow("dynamicMeta.2") << "dynamicMeta.2.qml" << "dynamicMeta.2.errors.txt" << false; + QTest::newRow("dynamicMeta.3") << "dynamicMeta.3.qml" << "dynamicMeta.3.errors.txt" << false; + QTest::newRow("dynamicMeta.4") << "dynamicMeta.4.qml" << "dynamicMeta.4.errors.txt" << false; + QTest::newRow("dynamicMeta.5") << "dynamicMeta.5.qml" << "dynamicMeta.5.errors.txt" << false; + + QTest::newRow("invalidAlias.1") << "invalidAlias.1.qml" << "invalidAlias.1.errors.txt" << false; + QTest::newRow("invalidAlias.2") << "invalidAlias.2.qml" << "invalidAlias.2.errors.txt" << false; + QTest::newRow("invalidAlias.3") << "invalidAlias.3.qml" << "invalidAlias.3.errors.txt" << false; + QTest::newRow("invalidAlias.4") << "invalidAlias.4.qml" << "invalidAlias.4.errors.txt" << false; + QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false; + QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false; + QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false; + QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false; + QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false; + QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false; + + QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.12") << "invalidAttachedProperty.12.qml" << "invalidAttachedProperty.12.errors.txt" << false; + QTest::newRow("invalidAttachedProperty.13") << "invalidAttachedProperty.13.qml" << "invalidAttachedProperty.13.errors.txt" << false; + + QTest::newRow("assignValueToSignal") << "assignValueToSignal.qml" << "assignValueToSignal.errors.txt" << false; + QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false; + + QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false; + QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false; + QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false; + QTest::newRow("invalidRoot") << "invalidRoot.qml" << "invalidRoot.errors.txt" << false; + QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false; + QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false; + QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false; + QTest::newRow("noCreation") << "noCreation.qml" << "noCreation.errors.txt" << false; + QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false; + QTest::newRow("assignToNamespace") << "assignToNamespace.qml" << "assignToNamespace.errors.txt" << false; + QTest::newRow("invalidOn") << "invalidOn.qml" << "invalidOn.errors.txt" << false; + QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false; + QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false; + QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false; + QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false; + QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false; + QTest::newRow("incorrectCase") << "incorrectCase.qml" +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) + << "incorrectCase.errors.insensitive.txt" +#else + << "incorrectCase.errors.sensitive.txt" +#endif + << false; + + QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false; + QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false; + QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false; +} + + +void tst_qdeclarativelanguage::errors() +{ + QFETCH(QString, file); + QFETCH(QString, errorFile); + QFETCH(bool, create); + + QDeclarativeComponent component(&engine, TEST_FILE(file)); + + if(create) { + QObject *object = component.create(); + QVERIFY(object == 0); + } + + VERIFY_ERRORS(errorFile.toLatin1().constData()); +} + +void tst_qdeclarativelanguage::simpleObject() +{ + QDeclarativeComponent component(&engine, TEST_FILE("simpleObject.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +void tst_qdeclarativelanguage::simpleContainer() +{ + QDeclarativeComponent component(&engine, TEST_FILE("simpleContainer.qml")); + VERIFY_ERRORS(0); + MyContainer *container= qobject_cast(component.create()); + QVERIFY(container != 0); + QCOMPARE(container->getChildren()->count(),2); +} + +void tst_qdeclarativelanguage::interfaceProperty() +{ + QDeclarativeComponent component(&engine, TEST_FILE("interfaceProperty.qml")); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QVERIFY(object->interface()); + QVERIFY(object->interface()->id == 913); +} + +void tst_qdeclarativelanguage::interfaceQList() +{ + QDeclarativeComponent component(&engine, TEST_FILE("interfaceQList.qml")); + VERIFY_ERRORS(0); + MyContainer *container= qobject_cast(component.create()); + QVERIFY(container != 0); + QVERIFY(container->getQListInterfaces()->count() == 2); + for(int ii = 0; ii < 2; ++ii) + QVERIFY(container->getQListInterfaces()->at(ii)->id == 913); +} + +void tst_qdeclarativelanguage::assignObjectToSignal() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignObjectToSignal.qml")); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot"); + emit object->basicSignal(); +} + +void tst_qdeclarativelanguage::assignObjectToVariant() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignObjectToVariant.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QVariant v = object->property("a"); + QVERIFY(v.userType() == qMetaTypeId()); +} + +void tst_qdeclarativelanguage::assignLiteralSignalProperty() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml")); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->onLiteralSignal(), 10); +} + +// Test is an external component can be loaded and assigned (to a qlist) +void tst_qdeclarativelanguage::assignQmlComponent() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignQmlComponent.qml")); + VERIFY_ERRORS(0); + MyContainer *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QVERIFY(object->getChildren()->count() == 1); + QObject *child = object->getChildren()->at(0); + QCOMPARE(child->property("x"), QVariant(10)); + QCOMPARE(child->property("y"), QVariant(11)); +} + +// Test literal assignment to all the basic types +void tst_qdeclarativelanguage::assignBasicTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml")); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3); + QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2); + QCOMPARE(object->stringProperty(), QString("Hello World!")); + QCOMPARE(object->uintProperty(), uint(10)); + QCOMPARE(object->intProperty(), -19); + QCOMPARE((float)object->realProperty(), float(23.2)); + QCOMPARE((float)object->doubleProperty(), float(-19.7)); + QCOMPARE((float)object->floatProperty(), float(8.5)); + QCOMPARE(object->colorProperty(), QColor("red")); + QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); + QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->pointProperty(), QPoint(99,13)); + QCOMPARE(object->pointFProperty(), QPointF((float)-10.1, (float)12.3)); + QCOMPARE(object->sizeProperty(), QSize(99, 13)); + QCOMPARE(object->sizeFProperty(), QSizeF((float)0.1, (float)0.2)); + QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200)); + QCOMPARE(object->rectFProperty(), QRectF((float)1000.1, (float)-10.9, (float)400, (float)90.99)); + QCOMPARE(object->boolProperty(), true); + QCOMPARE(object->variantProperty(), QVariant("Hello World!")); + QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2)); + QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml"))); + QVERIFY(object->objectProperty() != 0); + MyTypeObject *child = qobject_cast(object->objectProperty()); + QVERIFY(child != 0); + QCOMPARE(child->intProperty(), 8); +} + +// Test edge case type assignments +void tst_qdeclarativelanguage::assignTypeExtremes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignTypeExtremes.qml")); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->uintProperty(), 0xEE6B2800); + QCOMPARE(object->intProperty(), -0x77359400); +} + +// Test that a composite type can assign to a property of its base type +void tst_qdeclarativelanguage::assignCompositeToType() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignCompositeToType.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +// Test that literals are stored correctly in variant properties +void tst_qdeclarativelanguage::assignLiteralToVariant() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignLiteralToVariant.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").userType(), (int)QVariant::Int); + QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double); + QCOMPARE(object->property("test3").userType(), (int)QVariant::String); + QCOMPARE(object->property("test4").userType(), (int)QVariant::Color); + QCOMPARE(object->property("test5").userType(), (int)QVariant::RectF); + QCOMPARE(object->property("test6").userType(), (int)QVariant::PointF); + QCOMPARE(object->property("test7").userType(), (int)QVariant::SizeF); + QCOMPARE(object->property("test8").userType(), (int)QVariant::Vector3D); + QCOMPARE(object->property("test9").userType(), (int)QVariant::String); + QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool); + QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool); + + QVERIFY(object->property("test1") == QVariant(1)); + QVERIFY(object->property("test2") == QVariant((double)1.7)); + QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!")))); + QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800))); + QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10))); + QVERIFY(object->property("test6") == QVariant(QPointF(10, 10))); + QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10))); + QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100))); + QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800")))); + QVERIFY(object->property("test10") == QVariant(bool(true))); + QVERIFY(object->property("test11") == QVariant(bool(false))); + + delete object; +} + +// Tests that custom parser types can be instantiated +void tst_qdeclarativelanguage::customParserTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("customParserTypes.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QVERIFY(object->property("count") == QVariant(2)); +} + +// Tests that the root item can be a custom component +void tst_qdeclarativelanguage::rootAsQmlComponent() +{ + QDeclarativeComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml")); + VERIFY_ERRORS(0); + MyContainer *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->property("x"), QVariant(11)); + QCOMPARE(object->getChildren()->count(), 2); +} + +// Tests that components can be specified inline +void tst_qdeclarativelanguage::inlineQmlComponents() +{ + QDeclarativeComponent component(&engine, TEST_FILE("inlineQmlComponents.qml")); + VERIFY_ERRORS(0); + MyContainer *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->getChildren()->count(), 1); + QDeclarativeComponent *comp = qobject_cast(object->getChildren()->at(0)); + QVERIFY(comp != 0); + MyQmlObject *compObject = qobject_cast(comp->create()); + QVERIFY(compObject != 0); + QCOMPARE(compObject->value(), 11); +} + +// Tests that types that have an id property have it set +void tst_qdeclarativelanguage::idProperty() +{ + QDeclarativeComponent component(&engine, TEST_FILE("idProperty.qml")); + VERIFY_ERRORS(0); + MyContainer *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->getChildren()->count(), 1); + MyTypeObject *child = + qobject_cast(object->getChildren()->at(0)); + QVERIFY(child != 0); + QCOMPARE(child->id(), QString("myObjectId")); + QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child)); +} + +// Tests automatic connection to notify signals if "onBlahChanged" syntax is used +// even if the notify signal for "blah" is not called "blahChanged" +void tst_qdeclarativelanguage::autoNotifyConnection() +{ + QDeclarativeComponent component(&engine, TEST_FILE("autoNotifyConnection.qml")); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QMetaProperty prop = object->metaObject()->property(object->metaObject()->indexOfProperty("receivedNotify")); + QVERIFY(prop.isValid()); + + QCOMPARE(prop.read(object), QVariant::fromValue(false)); + object->setPropertyWithNotify(1); + QCOMPARE(prop.read(object), QVariant::fromValue(true)); +} + +// Tests that signals can be assigned to +void tst_qdeclarativelanguage::assignSignal() +{ + QDeclarativeComponent component(&engine, TEST_FILE("assignSignal.qml")); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot"); + emit object->basicSignal(); + QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)"); + emit object->basicParameterizedSignal(9); +} + +// Tests the creation and assignment of dynamic properties +void tst_qdeclarativelanguage::dynamicProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dynamicProperties.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("intProperty"), QVariant(10)); + QCOMPARE(object->property("boolProperty"), QVariant(false)); + QCOMPARE(object->property("doubleProperty"), QVariant(-10.1)); + QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9)); + QCOMPARE(object->property("stringProperty"), QVariant("Hello World!")); + QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml"))); + QCOMPARE(object->property("colorProperty"), QVariant(QColor("red"))); + QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2))); + QCOMPARE(object->property("varProperty"), QVariant("Hello World!")); +} + +// Test that nested types can use dynamic properties +void tst_qdeclarativelanguage::dynamicPropertiesNested() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("super_a").toInt(), 11); // Overridden + QCOMPARE(object->property("super_c").toInt(), 14); // Inherited + QCOMPARE(object->property("a").toInt(), 13); // New + QCOMPARE(object->property("b").toInt(), 12); // New + + delete object; +} + +// Tests the creation and assignment to dynamic list properties +void tst_qdeclarativelanguage::listProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 2); +} + +// Tests the creation and assignment of dynamic object properties +// ### Not complete +void tst_qdeclarativelanguage::dynamicObjectProperties() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0)); + QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0)); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("dynamicObjectProperties.2.qml")); + QEXPECT_FAIL("", "QTBUG-10822", Abort); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVERIFY(object->property("objectProperty") != qVariantFromValue((QObject*)0)); + } +} + +// Tests the declaration of dynamic signals and slots +void tst_qdeclarativelanguage::dynamicSignalsAndSlots() +{ + QTest::ignoreMessage(QtDebugMsg, "1921"); + + QDeclarativeComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1); + QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1); + QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1); + QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1); + + QCOMPARE(object->property("test").toInt(), 0); + QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10))); + QCOMPARE(object->property("test").toInt(), 10); +} + +void tst_qdeclarativelanguage::simpleBindings() +{ + QDeclarativeComponent component(&engine, TEST_FILE("simpleBindings.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value1"), QVariant(10)); + QCOMPARE(object->property("value2"), QVariant(10)); + QCOMPARE(object->property("value3"), QVariant(21)); + QCOMPARE(object->property("value4"), QVariant(10)); + QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object)); +} + +void tst_qdeclarativelanguage::autoComponentCreation() +{ + QDeclarativeComponent component(&engine, TEST_FILE("autoComponentCreation.qml")); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QVERIFY(object->componentProperty() != 0); + MyTypeObject *child = qobject_cast(object->componentProperty()->create()); + QVERIFY(child != 0); + QCOMPARE(child->realProperty(), qreal(9)); +} + +void tst_qdeclarativelanguage::propertyValueSource() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("propertyValueSource.qml")); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QList valueSources; + QObjectList allChildren = object->findChildren(); + foreach (QObject *child, allChildren) { + if (qobject_cast(child)) + valueSources.append(child); + } + + QCOMPARE(valueSources.count(), 1); + MyPropertyValueSource *valueSource = + qobject_cast(valueSources.at(0)); + QVERIFY(valueSource != 0); + QCOMPARE(valueSource->prop.object(), qobject_cast(object)); + QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty"))); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("propertyValueSource.2.qml")); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QList valueSources; + QObjectList allChildren = object->findChildren(); + foreach (QObject *child, allChildren) { + if (qobject_cast(child)) + valueSources.append(child); + } + + QCOMPARE(valueSources.count(), 1); + MyPropertyValueSource *valueSource = + qobject_cast(valueSources.at(0)); + QVERIFY(valueSource != 0); + QCOMPARE(valueSource->prop.object(), qobject_cast(object)); + QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty"))); + } +} + +void tst_qdeclarativelanguage::attachedProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("attachedProperties.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QObject *attached = qmlAttachedPropertiesObject(object); + QVERIFY(attached != 0); + QCOMPARE(attached->property("value"), QVariant(10)); + QCOMPARE(attached->property("value2"), QVariant(13)); +} + +// Tests non-static object properties +void tst_qdeclarativelanguage::dynamicObjects() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dynamicObject.1.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +// Tests the registration of custom variant string converters +void tst_qdeclarativelanguage::customVariantTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("customVariantTypes.qml")); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->customType().a, 10); +} + +void tst_qdeclarativelanguage::valueTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("valueTypes.qml")); + VERIFY_ERRORS(0); + + QString message = component.url().toString() + ":2:1: QML MyTypeObject: Binding loop detected for property \"rectProperty.width\""; + QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + + QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13)); + QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13)); + QCOMPARE(object->intProperty(), 10); + object->doAction(); + QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13)); + QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13)); + QCOMPARE(object->intProperty(), 12); + + // ### +#if 0 + QDeclarativeProperty p(object, "rectProperty.x"); + QCOMPARE(p.read(), QVariant(12)); + p.write(13); + QCOMPARE(p.read(), QVariant(13)); + + quint32 r = QDeclarativePropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex()); + QDeclarativeProperty p2; + QDeclarativePropertyPrivate::restore(p2, r, object); + QCOMPARE(p2.read(), QVariant(13)); +#endif +} + +void tst_qdeclarativelanguage::cppnamespace() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("cppnamespace.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("cppnamespace.2.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; + } +} + +void tst_qdeclarativelanguage::aliasProperties() +{ + // Simple "int" alias + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.1.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + // Read through alias + QCOMPARE(object->property("valueAlias").toInt(), 10); + object->setProperty("value", QVariant(13)); + QCOMPARE(object->property("valueAlias").toInt(), 13); + + // Write through alias + object->setProperty("valueAlias", QVariant(19)); + QCOMPARE(object->property("valueAlias").toInt(), 19); + QCOMPARE(object->property("value").toInt(), 19); + + delete object; + } + + // Complex object alias + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.2.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + // Read through alias + MyQmlObject *v = + qvariant_cast(object->property("aliasObject")); + QVERIFY(v != 0); + QCOMPARE(v->value(), 10); + + // Write through alias + MyQmlObject *v2 = new MyQmlObject(); + v2->setParent(object); + object->setProperty("aliasObject", qVariantFromValue(v2)); + MyQmlObject *v3 = + qvariant_cast(object->property("aliasObject")); + QVERIFY(v3 != 0); + QCOMPARE(v3, v2); + + delete object; + } + + // Nested aliases + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.3.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("value").toInt(), 1892); + QCOMPARE(object->property("value2").toInt(), 1892); + + object->setProperty("value", QVariant(1313)); + QCOMPARE(object->property("value").toInt(), 1313); + QCOMPARE(object->property("value2").toInt(), 1313); + + object->setProperty("value2", QVariant(8080)); + QCOMPARE(object->property("value").toInt(), 8080); + QCOMPARE(object->property("value2").toInt(), 8080); + + delete object; + } + + // Enum aliases + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.4.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("enumAlias").toInt(), 1); + + delete object; + } + + // Id aliases + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.5.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVariant v = object->property("otherAlias"); + QCOMPARE(v.userType(), qMetaTypeId()); + MyQmlObject *o = qvariant_cast(v); + QCOMPARE(o->value(), 10); + + delete o; + + v = object->property("otherAlias"); + QCOMPARE(v.userType(), qMetaTypeId()); + o = qvariant_cast(v); + QVERIFY(o == 0); + + delete object; + } + + // Nested aliases - this used to cause a crash + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.6.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("a").toInt(), 1923); + } + + // Ptr Alias Cleanup - check that aliases to ptr types return 0 + // if the object aliased to is removed + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.7.qml")); + VERIFY_ERRORS(0); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QObject *object1 = qvariant_cast(object->property("object")); + QVERIFY(object1 != 0); + QObject *object2 = qvariant_cast(object1->property("object")); + QVERIFY(object2 != 0); + + QObject *alias = qvariant_cast(object->property("aliasedObject")); + QVERIFY(alias == object2); + + delete object1; + + QObject *alias2 = object; // "Random" start value + int status = -1; + void *a[] = { &alias2, 0, &status }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, + object->metaObject()->indexOfProperty("aliasedObject"), a); + QVERIFY(alias2 == 0); + } + + // Simple composite type + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.8.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("value").toInt(), 10); + + delete object; + } + + // Complex composite type + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.9.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("value").toInt(), 10); + + delete object; + } + + // Valuetype alias + // Simple "int" alias + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.10.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + // Read through alias + QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8)); + object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100))); + QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100)); + + // Write through alias + object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9))); + QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9)); + QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9)); + + delete object; + } + + // Valuetype sub-alias + { + QDeclarativeComponent component(&engine, TEST_FILE("alias.11.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + // Read through alias + QCOMPARE(object->property("aliasProperty").toInt(), 19); + object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111))); + QCOMPARE(object->property("aliasProperty").toInt(), 33); + + // Write through alias + object->setProperty("aliasProperty", QVariant(4)); + QCOMPARE(object->property("aliasProperty").toInt(), 4); + QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111)); + + delete object; + } +} + +// QTBUG-13374 Test that alias properties and signals can coexist +void tst_qdeclarativelanguage::aliasPropertiesAndSignals() +{ + QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o); + QCOMPARE(o->property("test").toBool(), true); + delete o; +} + +// Test that the root element in a composite type can be a Component +void tst_qdeclarativelanguage::componentCompositeType() +{ + QDeclarativeComponent component(&engine, TEST_FILE("componentCompositeType.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +class TestType : public QObject { + Q_OBJECT +public: + TestType(QObject *p=0) : QObject(p) {} +}; + +class TestType2 : public QObject { + Q_OBJECT +public: + TestType2(QObject *p=0) : QObject(p) {} +}; + +void tst_qdeclarativelanguage::i18n_data() +{ + QTest::addColumn("file"); + QTest::addColumn("stringProperty"); + QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)"); + QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10"); + QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15"); + QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20"); + QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30"); + QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40"); +} + +void tst_qdeclarativelanguage::i18n() +{ + QFETCH(QString, file); + QFETCH(QString, stringProperty); + QDeclarativeComponent component(&engine, TEST_FILE(file)); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->stringProperty(), stringProperty); + + delete object; +} + +// Check that the Component::onCompleted attached property works +void tst_qdeclarativelanguage::onCompleted() +{ + QDeclarativeComponent component(&engine, TEST_FILE("onCompleted.qml")); + VERIFY_ERRORS(0); + QTest::ignoreMessage(QtDebugMsg, "Completed 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Completed 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Completed 10 11"); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +// Check that the Component::onDestruction attached property works +void tst_qdeclarativelanguage::onDestruction() +{ + QDeclarativeComponent component(&engine, TEST_FILE("onDestruction.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11"); + delete object; +} + +// Check that assignments to QDeclarativeScriptString properties work +void tst_qdeclarativelanguage::scriptString() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptString.qml")); + VERIFY_ERRORS(0); + + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->scriptProperty().script(), QString("foo + bar")); + QCOMPARE(object->scriptProperty().scopeObject(), qobject_cast(object)); + QCOMPARE(object->scriptProperty().context(), qmlContext(object)); + + QVERIFY(object->grouped() != 0); + QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)")); + QCOMPARE(object->grouped()->script().scopeObject(), qobject_cast(object)); + QCOMPARE(object->grouped()->script().context(), qmlContext(object)); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptString2.qml")); + VERIFY_ERRORS(0); + + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->scriptProperty().script(), QString("\"hello\\n\\\"world\\\"\"")); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptString3.qml")); + VERIFY_ERRORS(0); + + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->scriptProperty().script(), QString("12.345")); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptString4.qml")); + VERIFY_ERRORS(0); + + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->scriptProperty().script(), QString("true")); + } +} + +// Check that default property assignments are correctly spliced into explicit +// property assignments +void tst_qdeclarativelanguage::defaultPropertyListOrder() +{ + QDeclarativeComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml")); + VERIFY_ERRORS(0); + + MyContainer *container = qobject_cast(component.create()); + QVERIFY(container != 0); + + QCOMPARE(container->getChildren()->count(), 6); + QCOMPARE(container->getChildren()->at(0)->property("index"), QVariant(0)); + QCOMPARE(container->getChildren()->at(1)->property("index"), QVariant(1)); + QCOMPARE(container->getChildren()->at(2)->property("index"), QVariant(2)); + QCOMPARE(container->getChildren()->at(3)->property("index"), QVariant(3)); + QCOMPARE(container->getChildren()->at(4)->property("index"), QVariant(4)); + QCOMPARE(container->getChildren()->at(5)->property("index"), QVariant(5)); +} + +void tst_qdeclarativelanguage::declaredPropertyValues() +{ + QDeclarativeComponent component(&engine, TEST_FILE("declaredPropertyValues.qml")); + VERIFY_ERRORS(0); +} + +void tst_qdeclarativelanguage::dontDoubleCallClassBegin() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml")); + QObject *o = component.create(); + QVERIFY(o); + + MyParserStatus *o2 = qobject_cast(qvariant_cast(o->property("object"))); + QVERIFY(o2); + QCOMPARE(o2->classBeginCount(), 1); + QCOMPARE(o2->componentCompleteCount(), 1); + + delete o; +} + +void tst_qdeclarativelanguage::reservedWords_data() +{ + QTest::addColumn("word"); + + QTest::newRow("abstract") << QByteArray("abstract"); + QTest::newRow("as") << QByteArray("as"); + QTest::newRow("boolean") << QByteArray("boolean"); + QTest::newRow("break") << QByteArray("break"); + QTest::newRow("byte") << QByteArray("byte"); + QTest::newRow("case") << QByteArray("case"); + QTest::newRow("catch") << QByteArray("catch"); + QTest::newRow("char") << QByteArray("char"); + QTest::newRow("class") << QByteArray("class"); + QTest::newRow("continue") << QByteArray("continue"); + QTest::newRow("const") << QByteArray("const"); + QTest::newRow("debugger") << QByteArray("debugger"); + QTest::newRow("default") << QByteArray("default"); + QTest::newRow("delete") << QByteArray("delete"); + QTest::newRow("do") << QByteArray("do"); + QTest::newRow("double") << QByteArray("double"); + QTest::newRow("else") << QByteArray("else"); + QTest::newRow("enum") << QByteArray("enum"); + QTest::newRow("export") << QByteArray("export"); + QTest::newRow("extends") << QByteArray("extends"); + QTest::newRow("false") << QByteArray("false"); + QTest::newRow("final") << QByteArray("final"); + QTest::newRow("finally") << QByteArray("finally"); + QTest::newRow("float") << QByteArray("float"); + QTest::newRow("for") << QByteArray("for"); + QTest::newRow("function") << QByteArray("function"); + QTest::newRow("goto") << QByteArray("goto"); + QTest::newRow("if") << QByteArray("if"); + QTest::newRow("implements") << QByteArray("implements"); + QTest::newRow("import") << QByteArray("import"); + QTest::newRow("in") << QByteArray("in"); + QTest::newRow("instanceof") << QByteArray("instanceof"); + QTest::newRow("int") << QByteArray("int"); + QTest::newRow("interface") << QByteArray("interface"); + QTest::newRow("long") << QByteArray("long"); + QTest::newRow("native") << QByteArray("native"); + QTest::newRow("new") << QByteArray("new"); + QTest::newRow("null") << QByteArray("null"); + QTest::newRow("package") << QByteArray("package"); + QTest::newRow("private") << QByteArray("private"); + QTest::newRow("protected") << QByteArray("protected"); + QTest::newRow("public") << QByteArray("public"); + QTest::newRow("return") << QByteArray("return"); + QTest::newRow("short") << QByteArray("short"); + QTest::newRow("static") << QByteArray("static"); + QTest::newRow("super") << QByteArray("super"); + QTest::newRow("switch") << QByteArray("switch"); + QTest::newRow("synchronized") << QByteArray("synchronized"); + QTest::newRow("this") << QByteArray("this"); + QTest::newRow("throw") << QByteArray("throw"); + QTest::newRow("throws") << QByteArray("throws"); + QTest::newRow("transient") << QByteArray("transient"); + QTest::newRow("true") << QByteArray("true"); + QTest::newRow("try") << QByteArray("try"); + QTest::newRow("typeof") << QByteArray("typeof"); + QTest::newRow("var") << QByteArray("var"); + QTest::newRow("void") << QByteArray("void"); + QTest::newRow("volatile") << QByteArray("volatile"); + QTest::newRow("while") << QByteArray("while"); + QTest::newRow("with") << QByteArray("with"); +} + +void tst_qdeclarativelanguage::reservedWords() +{ + QFETCH(QByteArray, word); + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.0\nQtObject { property string " + word + " }", QUrl()); + QCOMPARE(component.errorString(), QLatin1String(":2 Expected token `identifier'\n")); +} + +// Check that first child of qml is of given type. Empty type insists on error. +void tst_qdeclarativelanguage::testType(const QString& qml, const QString& type, const QString& expectederror) +{ + QDeclarativeComponent component(&engine); + component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports + + QTRY_VERIFY(!component.isLoading()); + + if (type.isEmpty()) { + QVERIFY(component.isError()); + QString actualerror; + foreach (const QDeclarativeError e, component.errors()) { + if (!actualerror.isEmpty()) + actualerror.append("; "); + actualerror.append(e.description()); + } + QCOMPARE(actualerror,expectederror); + } else { + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(QString(object->metaObject()->className()), type); + } +} + +// QTBUG-17276 +void tst_qdeclarativelanguage::inlineAssignmentsOverrideBindings() +{ + QDeclarativeComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test").toInt(), 11); + delete o; +} + +// QTBUG-19354 +void tst_qdeclarativelanguage::nestedComponentRoots() +{ + QDeclarativeComponent component(&engine, TEST_FILE("nestedComponentRoots.qml")); +} + +// Import tests (QT-558) +void tst_qdeclarativelanguage::importsBuiltin_data() +{ + // QT-610 + + QTest::addColumn("qml"); + QTest::addColumn("type"); + QTest::addColumn("error"); + + // import built-ins + QTest::newRow("missing import") + << "Test {}" + << "" + << "Test is not a type"; + QTest::newRow("not in version 0.0") + << "import com.nokia.Test 0.0\n" + "Test {}" + << "" + << "Test is not a type"; + QTest::newRow("version not installed") + << "import com.nokia.Test 99.0\n" + "Test {}" + << "" + << "module \"com.nokia.Test\" version 99.0 is not installed"; + QTest::newRow("in version 0.0") + << "import com.nokia.Test 0.0\n" + "TestTP {}" + << "TestType" + << ""; + QTest::newRow("qualified in version 0.0") + << "import com.nokia.Test 0.0 as T\n" + "T.TestTP {}" + << "TestType" + << ""; + QTest::newRow("in version 1.0") + << "import com.nokia.Test 1.0\n" + "Test {}" + << "TestType" + << ""; + QTest::newRow("qualified wrong") + << "import com.nokia.Test 1.0 as T\n" // QT-610 + "Test {}" + << "" + << "Test is not a type"; + QTest::newRow("qualified right") + << "import com.nokia.Test 1.0 as T\n" + "T.Test {}" + << "TestType" + << ""; + QTest::newRow("qualified right but not in version 0.0") + << "import com.nokia.Test 0.0 as T\n" + "T.Test {}" + << "" + << "T.Test is not a type"; + QTest::newRow("in version 1.1") + << "import com.nokia.Test 1.1\n" + "Test {}" + << "TestType" + << ""; + QTest::newRow("in version 1.3") + << "import com.nokia.Test 1.3\n" + "Test {}" + << "TestType" + << ""; + QTest::newRow("in version 1.5") + << "import com.nokia.Test 1.5\n" + "Test {}" + << "TestType" + << ""; + QTest::newRow("changed in version 1.8") + << "import com.nokia.Test 1.8\n" + "Test {}" + << "TestType2" + << ""; + QTest::newRow("in version 1.12") + << "import com.nokia.Test 1.12\n" + "Test {}" + << "TestType2" + << ""; + QTest::newRow("old in version 1.9") + << "import com.nokia.Test 1.9\n" + "OldTest {}" + << "TestType" + << ""; + QTest::newRow("old in version 1.11") + << "import com.nokia.Test 1.11\n" + "OldTest {}" + << "TestType" + << ""; + QTest::newRow("multiversion 1") + << "import com.nokia.Test 1.11\n" + "import com.nokia.Test 1.12\n" + "Test {}" + << (!qmlCheckTypes()?"TestType2":"") + << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11"); + QTest::newRow("multiversion 2") + << "import com.nokia.Test 1.11\n" + "import com.nokia.Test 1.12\n" + "OldTest {}" + << (!qmlCheckTypes()?"TestType":"") + << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11"); + QTest::newRow("qualified multiversion 3") + << "import com.nokia.Test 1.0 as T0\n" + "import com.nokia.Test 1.8 as T8\n" + "T0.Test {}" + << "TestType" + << ""; + QTest::newRow("qualified multiversion 4") + << "import com.nokia.Test 1.0 as T0\n" + "import com.nokia.Test 1.8 as T8\n" + "T8.Test {}" + << "TestType2" + << ""; +} + +void tst_qdeclarativelanguage::importsBuiltin() +{ + QFETCH(QString, qml); + QFETCH(QString, type); + QFETCH(QString, error); + testType(qml,type,error); +} + +void tst_qdeclarativelanguage::importsLocal_data() +{ + QTest::addColumn("qml"); + QTest::addColumn("type"); + QTest::addColumn("error"); + + // import locals + QTest::newRow("local import") + << "import \"subdir\"\n" // QT-613 + "Test {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("local import second") + << "import QtQuick 1.0\nimport \"subdir\"\n" + "Test {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("local import subsubdir") + << "import QtQuick 1.0\nimport \"subdir/subsubdir\"\n" + "SubTest {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("local import QTBUG-7721 A") + << "subdir.Test {}" // no longer allowed (QTBUG-7721) + << "" + << "subdir.Test - subdir is not a namespace"; + QTest::newRow("local import QTBUG-7721 B") + << "import \"subdir\" as X\n" + "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721) + << "" + << "X.subsubdir.SubTest - nested namespaces not allowed"; + QTest::newRow("local import as") + << "import \"subdir\" as T\n" + "T.Test {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("wrong local import as") + << "import \"subdir\" as T\n" + "Test {}" + << "" + << "Test is not a type"; + QTest::newRow("library precedence over local import") + << "import \"subdir\"\n" + "import com.nokia.Test 1.0\n" + "Test {}" + << (!qmlCheckTypes()?"TestType":"") + << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test and in subdir"); +} + +void tst_qdeclarativelanguage::importsLocal() +{ + QFETCH(QString, qml); + QFETCH(QString, type); + QFETCH(QString, error); + testType(qml,type,error); +} + +void tst_qdeclarativelanguage::basicRemote_data() +{ + QTest::addColumn("url"); + QTest::addColumn("type"); + QTest::addColumn("error"); + + QString serverdir = "http://127.0.0.1:14447/qtest/declarative/qmllanguage/"; + + QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << ""; + QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << ""; + QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << ""; +} + +void tst_qdeclarativelanguage::basicRemote() +{ + QFETCH(QUrl, url); + QFETCH(QString, type); + QFETCH(QString, error); + + TestHTTPServer server(14447); + server.serveDirectory(SRCDIR); + + QDeclarativeComponent component(&engine, url); + + QTRY_VERIFY(!component.isLoading()); + + if (error.isEmpty()) { + if (component.isError()) + qDebug() << component.errors(); + QVERIFY(!component.isError()); + } else { + QVERIFY(component.isError()); + } +} + +void tst_qdeclarativelanguage::importsRemote_data() +{ + QTest::addColumn("qml"); + QTest::addColumn("type"); + QTest::addColumn("error"); + + QString serverdir = "http://127.0.0.1:14447/qtest/declarative/qmllanguage"; + + QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QDeclarativeRectangle" + << ""; + QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QDeclarativeText" + << ""; + QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QDeclarativeImage" + << ""; + QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << "" + << "WrongTestLocal is not a type"; + QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << "" + << "LocalInternal is not a type"; + QTest::newRow("wrong remote import of undeclared local") << "import \""+serverdir+"\"\nUndeclaredLocal {}" << "" + << "UndeclaredLocal is not a type"; +} + +void tst_qdeclarativelanguage::importsRemote() +{ + QFETCH(QString, qml); + QFETCH(QString, type); + QFETCH(QString, error); + + TestHTTPServer server(14447); + server.serveDirectory(SRCDIR); + + testType(qml,type,error); +} + +void tst_qdeclarativelanguage::importsInstalled_data() +{ + // QT-610 + + QTest::addColumn("qml"); + QTest::addColumn("type"); + QTest::addColumn("error"); + + // import installed + QTest::newRow("installed import 0") + << "import com.nokia.installedtest0 0.0\n" + "InstalledTestTP {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("installed import 0 as TP") + << "import com.nokia.installedtest0 0.0 as TP\n" + "TP.InstalledTestTP {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("installed import 1") + << "import com.nokia.installedtest 1.0\n" + "InstalledTest {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("installed import 2") + << "import com.nokia.installedtest 1.3\n" + "InstalledTest {}" + << "QDeclarativeRectangle" + << ""; + QTest::newRow("installed import 3") + << "import com.nokia.installedtest 1.4\n" + "InstalledTest {}" + << "QDeclarativeText" + << ""; + QTest::newRow("installed import minor version not available") // QTBUG-11936 + << "import com.nokia.installedtest 0.1\n" + "InstalledTest {}" + << "" + << "module \"com.nokia.installedtest\" version 0.1 is not installed"; + QTest::newRow("installed import minor version not available") // QTBUG-9627 + << "import com.nokia.installedtest 1.10\n" + "InstalledTest {}" + << "" + << "module \"com.nokia.installedtest\" version 1.10 is not installed"; + QTest::newRow("installed import major version not available") // QTBUG-9627 + << "import com.nokia.installedtest 9.0\n" + "InstalledTest {}" + << "" + << "module \"com.nokia.installedtest\" version 9.0 is not installed"; + QTest::newRow("installed import visibility") // QT-614 + << "import com.nokia.installedtest 1.4\n" + "PrivateType {}" + << "" + << "PrivateType is not a type"; +} + +void tst_qdeclarativelanguage::importsInstalled() +{ + QFETCH(QString, qml); + QFETCH(QString, type); + QFETCH(QString, error); + testType(qml,type,error); +} + + +void tst_qdeclarativelanguage::importsOrder_data() +{ + QTest::addColumn("qml"); + QTest::addColumn("type"); + QTest::addColumn("error"); + + QTest::newRow("double import") << + "import com.nokia.installedtest 1.4\n" + "import com.nokia.installedtest 1.4\n" + "InstalledTest {}" + << (!qmlCheckTypes()?"QDeclarativeText":"") + << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.4"); + QTest::newRow("installed import overrides 1") << + "import com.nokia.installedtest 1.0\n" + "import com.nokia.installedtest 1.4\n" + "InstalledTest {}" + << (!qmlCheckTypes()?"QDeclarativeText":"") + << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0"); + QTest::newRow("installed import overrides 2") << + "import com.nokia.installedtest 1.4\n" + "import com.nokia.installedtest 1.0\n" + "InstalledTest {}" + << (!qmlCheckTypes()?"QDeclarativeRectangle":"") + << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4"); + QTest::newRow("installed import re-overrides 1") << + "import com.nokia.installedtest 1.4\n" + "import com.nokia.installedtest 1.0\n" + "import com.nokia.installedtest 1.4\n" + "InstalledTest {}" + << (!qmlCheckTypes()?"QDeclarativeText":"") + << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0"); + QTest::newRow("installed import re-overrides 2") << + "import com.nokia.installedtest 1.4\n" + "import com.nokia.installedtest 1.0\n" + "import com.nokia.installedtest 1.4\n" + "import com.nokia.installedtest 1.0\n" + "InstalledTest {}" + << (!qmlCheckTypes()?"QDeclarativeRectangle":"") + << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4"); + + QTest::newRow("installed import versus builtin 1") << + "import com.nokia.installedtest 1.5\n" + "import QtQuick 1.0\n" + "Rectangle {}" + << (!qmlCheckTypes()?"QDeclarativeRectangle":"") + << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in Qt and in lib/com/nokia/installedtest"); + QTest::newRow("installed import versus builtin 2") << + "import QtQuick 1.0\n" + "import com.nokia.installedtest 1.5\n" + "Rectangle {}" + << (!qmlCheckTypes()?"QDeclarativeText":"") + << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest and in Qt"); + QTest::newRow("namespaces cannot be overridden by types 1") << + "import QtQuick 1.0 as Rectangle\n" + "import com.nokia.installedtest 1.5\n" + "Rectangle {}" + << "" + << "Namespace Rectangle cannot be used as a type"; + QTest::newRow("namespaces cannot be overridden by types 2") << + "import QtQuick 1.0 as Rectangle\n" + "import com.nokia.installedtest 1.5\n" + "Rectangle.Image {}" + << "QDeclarativeImage" + << ""; + QTest::newRow("local last 1") << + "LocalLast {}" + << "QDeclarativeText" + << ""; + QTest::newRow("local last 2") << + "import com.nokia.installedtest 1.0\n" + "LocalLast {}" + << (!qmlCheckTypes()?"QDeclarativeRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml + << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory"); +} + +void tst_qdeclarativelanguage::importsOrder() +{ + QFETCH(QString, qml); + QFETCH(QString, type); + QFETCH(QString, error); + testType(qml,type,error); +} + +void tst_qdeclarativelanguage::importIncorrectCase() +{ + QDeclarativeComponent component(&engine, TEST_FILE("importIncorrectCase.qml")); + + QList errors = component.errors(); + QCOMPARE(errors.count(), 1); + +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) + QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + QFileInfo(__FILE__).absoluteDir().filePath("data/lib/com/Nokia/installedtest/qmldir") + QLatin1String("\""); +#else + QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed"); +#endif + + QCOMPARE(errors.at(0).description(), expectedError); +} + +void tst_qdeclarativelanguage::qmlAttachedPropertiesObjectMethod() +{ + QObject object; + + QCOMPARE(qmlAttachedPropertiesObject(&object, false), (QObject *)0); + QCOMPARE(qmlAttachedPropertiesObject(&object, true), (QObject *)0); + + { + QDeclarativeComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(qmlAttachedPropertiesObject(object, false), (QObject *)0); + QVERIFY(qmlAttachedPropertiesObject(object, true) != 0); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVERIFY(qmlAttachedPropertiesObject(object, false) != 0); + QVERIFY(qmlAttachedPropertiesObject(object, true) != 0); + } +} + +void tst_qdeclarativelanguage::crash1() +{ + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.0\nComponent {}", QUrl()); +} + +void tst_qdeclarativelanguage::crash2() +{ + QDeclarativeComponent component(&engine, TEST_FILE("crash2.qml")); +} + +// QTBUG-8676 +void tst_qdeclarativelanguage::customOnProperty() +{ + QDeclarativeComponent component(&engine, TEST_FILE("customOnProperty.qml")); + + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("on").toInt(), 10); + + delete object; +} + +// QTBUG-12601 +void tst_qdeclarativelanguage::variantNotify() +{ + QDeclarativeComponent component(&engine, TEST_FILE("variantNotify.qml")); + + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("notifyCount").toInt(), 1); + + delete object; +} + +void tst_qdeclarativelanguage::revisions() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("revisions11.qml")); + + VERIFY_ERRORS(0); + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop2(), 10.0); + + delete object; + } + { + QDeclarativeEngine myEngine; + QDeclarativeComponent component(&myEngine, TEST_FILE("revisionssub11.qml")); + + VERIFY_ERRORS(0); + MyRevisionedSubclass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop1(), 10.0); + QCOMPARE(object->prop2(), 10.0); + QCOMPARE(object->prop3(), 10.0); + QCOMPARE(object->prop4(), 10.0); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("versionedbase.qml")); + VERIFY_ERRORS(0); + MySubclass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop1(), 10.0); + QCOMPARE(object->prop2(), 10.0); + + delete object; + } +} + +void tst_qdeclarativelanguage::revisionOverloads() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml")); + VERIFY_ERRORS(0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml")); + QEXPECT_FAIL("", "QTBUG-13849", Abort); + QVERIFY(0); + VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt"); + } +} + +void tst_qdeclarativelanguage::initTestCase() +{ + registerTypes(); + + // Registering the TestType class in other modules should have no adverse effects + qmlRegisterType("com.nokia.TestPre", 1, 0, "Test"); + + qmlRegisterType("com.nokia.Test", 0, 0, "TestTP"); + qmlRegisterType("com.nokia.Test", 1, 0, "Test"); + qmlRegisterType("com.nokia.Test", 1, 5, "Test"); + qmlRegisterType("com.nokia.Test", 1, 8, "Test"); + qmlRegisterType("com.nokia.Test", 1, 9, "OldTest"); + qmlRegisterType("com.nokia.Test", 1, 12, "Test"); + + // Registering the TestType class in other modules should have no adverse effects + qmlRegisterType("com.nokia.TestPost", 1, 0, "Test"); + + // Create locale-specific file + // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit + // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters + // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded + QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile()); + QVERIFY(in.open(QIODevice::ReadOnly)); + QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()); + QVERIFY(out.open(QIODevice::WriteOnly)); + out.write(in.readAll()); +} + +void tst_qdeclarativelanguage::aliasPropertyChangeSignals() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.qml")); + + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } + + // QTCREATORBUG-2769 + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.2.qml")); + + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } +} + +QTEST_MAIN(tst_qdeclarativelanguage) + +#include "tst_qdeclarativelanguage.moc" -- cgit v1.2.3