diff options
60 files changed, 1142 insertions, 17 deletions
diff --git a/src/imports/folderlistmodel/qmldir b/src/imports/folderlistmodel/qmldir index 6e115bbc7e..bbd91356cf 100644 --- a/src/imports/folderlistmodel/qmldir +++ b/src/imports/folderlistmodel/qmldir @@ -1 +1,2 @@ +module Qt.labs.folderlistmodel plugin qmlfolderlistmodelplugin diff --git a/src/imports/localstorage/qmldir b/src/imports/localstorage/qmldir index 33288a1afa..8bb2c3bc68 100644 --- a/src/imports/localstorage/qmldir +++ b/src/imports/localstorage/qmldir @@ -1 +1,2 @@ -plugin qmllocalstorageplugin
\ No newline at end of file +module QtQuick.LocalStorage +plugin qmllocalstorageplugin diff --git a/src/imports/particles/qmldir b/src/imports/particles/qmldir index 593915f83f..25d58dec0d 100644 --- a/src/imports/particles/qmldir +++ b/src/imports/particles/qmldir @@ -1 +1,2 @@ +module QtQuick.Particles plugin particlesplugin diff --git a/src/imports/qtquick2/qmldir b/src/imports/qtquick2/qmldir index bb4d33a5be..1fcbb13f3a 100644 --- a/src/imports/qtquick2/qmldir +++ b/src/imports/qtquick2/qmldir @@ -1 +1,2 @@ +module QtQuick plugin qtquick2plugin diff --git a/src/imports/testlib/qmldir b/src/imports/testlib/qmldir index 9e872f9683..d126464e9a 100644 --- a/src/imports/testlib/qmldir +++ b/src/imports/testlib/qmldir @@ -1,3 +1,4 @@ +module QtTest plugin qmltestplugin TestCase 1.0 TestCase.qml SignalSpy 1.0 SignalSpy.qml diff --git a/src/imports/window/qmldir b/src/imports/window/qmldir index 32844a6ed6..2dad388ba3 100644 --- a/src/imports/window/qmldir +++ b/src/imports/window/qmldir @@ -1 +1,2 @@ +module QtQuick.Window plugin windowplugin diff --git a/src/imports/xmllistmodel/qmldir b/src/imports/xmllistmodel/qmldir index dd39bcd7f8..945d15ac9f 100644 --- a/src/imports/xmllistmodel/qmldir +++ b/src/imports/xmllistmodel/qmldir @@ -1 +1,2 @@ -plugin qmlxmllistmodelplugin
\ No newline at end of file +module QtQuick.XmlListModel +plugin qmlxmllistmodelplugin diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp index 0805a24e6d..705f715a00 100644 --- a/src/qml/qml/qqmldirparser.cpp +++ b/src/qml/qml/qqmldirparser.cpp @@ -99,11 +99,13 @@ bool QQmlDirParser::parse(const QString &source) _scripts.clear(); int lineNumber = 0; + bool firstLine = true; const QChar *ch = source.constData(); while (!ch->isNull()) { ++lineNumber; + bool invalidLine = false; const QChar *lineStart = ch; scanSpace(ch); @@ -129,6 +131,7 @@ bool QQmlDirParser::parse(const QString &source) } else { reportError(lineNumber, start-lineStart, QLatin1String("unexpected token")); scanToEnd(ch); + invalidLine = true; break; } scanSpace(ch); @@ -137,9 +140,32 @@ bool QQmlDirParser::parse(const QString &source) if (!ch->isNull()) ++ch; - if (sectionCount == 0) { + if (invalidLine) { + reportError(lineNumber, -1, + QString::fromUtf8("invalid qmldir directive contains too many tokens")); + continue; + } else if (sectionCount == 0) { continue; // no sections, no party. + } else if (sections[0] == QLatin1String("module")) { + if (sectionCount != 2) { + reportError(lineNumber, -1, + QString::fromUtf8("module directive requires one argument, but %1 were provided").arg(sectionCount - 1)); + continue; + } + if (!_typeNamespace.isEmpty()) { + reportError(lineNumber, -1, + QString::fromUtf8("only one module directive may be defined in a qmldir file")); + continue; + } + if (!firstLine) { + reportError(lineNumber, -1, + QString::fromUtf8("module directive must be the first directive in a qmldir file")); + continue; + } + + _typeNamespace = sections[1]; + } else if (sections[0] == QLatin1String("plugin")) { if (sectionCount < 2) { reportError(lineNumber, -1, @@ -209,6 +235,8 @@ bool QQmlDirParser::parse(const QString &source) reportError(lineNumber, -1, QString::fromUtf8("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount)); } + + firstLine = false; } return hasError(); @@ -239,16 +267,28 @@ void QQmlDirParser::setError(const QQmlError &e) QList<QQmlError> QQmlDirParser::errors(const QString &uri) const { + QUrl url(uri); QList<QQmlError> errors = _errors; for (int i = 0; i < errors.size(); ++i) { QQmlError &e = errors[i]; QString description = e.description(); description.replace(QLatin1String("$$URI$$"), uri); e.setDescription(description); + e.setUrl(url); } return errors; } +QString QQmlDirParser::typeNamespace() const +{ + return _typeNamespace; +} + +void QQmlDirParser::setTypeNamespace(const QString &s) +{ + _typeNamespace = s; +} + QList<QQmlDirParser::Plugin> QQmlDirParser::plugins() const { return _plugins; diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h index c38a3e1791..7a9078180e 100644 --- a/src/qml/qml/qqmldirparser_p.h +++ b/src/qml/qml/qqmldirparser_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QQmlError; class QQmlEngine; -class QQmlDirParser +class Q_AUTOTEST_EXPORT QQmlDirParser { Q_DISABLE_COPY(QQmlDirParser) @@ -76,6 +76,9 @@ public: void setError(const QQmlError &); QList<QQmlError> errors(const QString &uri) const; + QString typeNamespace() const; + void setTypeNamespace(const QString &s); + struct Plugin { Plugin() {} @@ -139,6 +142,7 @@ private: private: QList<QQmlError> _errors; + QString _typeNamespace; QHash<QHashedStringRef,Component> _components; // multi hash QList<Script> _scripts; QList<Plugin> _plugins; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 72c1c35244..65eeb242bb 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1729,7 +1729,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths) bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors) { Q_D(QQmlEngine); - return d->importDatabase.importPlugin(filePath, uri, errors); + return d->importDatabase.importPlugin(filePath, uri, QString(), errors); } /*! diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 20da154673..e7133992d9 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -47,6 +47,7 @@ #include <QtCore/qfileinfo.h> #include <QtCore/qpluginloader.h> #include <QtCore/qlibraryinfo.h> +#include <QtCore/qreadwritelock.h> #include <QtQml/qqmlextensioninterface.h> #include <private/qqmlglobal_p.h> #include <private/qqmltypenamecache_p.h> @@ -734,7 +735,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name); if (!resolvedFilePath.isEmpty()) { - if (!database->importPlugin(resolvedFilePath, uri, errors)) { + if (!database->importPlugin(resolvedFilePath, uri, qmldir->typeNamespace(), errors)) { if (errors) { // XXX TODO: should we leave the import plugin error alone? // Here, we pop it off the top and coalesce it into this error's message. @@ -1590,7 +1591,7 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) /*! \internal */ -bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors) +bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors) { if (qmlImportTrace()) qDebug().nospace() << "QQmlImportDatabase::importPlugin: " << uri << " from " << filePath; @@ -1635,9 +1636,53 @@ bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &ur const char *moduleId = bytes.constData(); if (!typesRegistered) { - // XXX thread this code should probably be protected with a mutex. qmlEnginePluginsWithRegisteredTypes()->insert(absoluteFilePath, uri); - iface->registerTypes(moduleId); + + QStringList registrationFailures; + + { + QWriteLocker lock(QQmlMetaType::typeRegistrationLock()); + + if (!typeNamespace.isEmpty()) { + // This is a 'strict' module + if (typeNamespace != uri) { + // The namespace for type registrations must match the URI for locating the module + QQmlError error; + error.setDescription(tr("Module namespace '%1' does not match import URI '%2'").arg(typeNamespace).arg(uri)); + errors->prepend(error); + return false; + } + + if (QQmlMetaType::namespaceContainsRegistrations(typeNamespace)) { + // Other modules have already installed to this namespace + QQmlError error; + error.setDescription(tr("Namespace '%1' has already been used for type registration").arg(typeNamespace)); + errors->prepend(error); + return false; + } else { + QQmlMetaType::protectNamespace(typeNamespace); + } + } else { + // This is not a stict module - provide a warning + qWarning().nospace() << qPrintable(tr("Module '%1' does not contain a module directive - it cannot be protected from external registrations.").arg(uri)); + } + + QQmlMetaType::setTypeRegistrationNamespace(typeNamespace); + + iface->registerTypes(moduleId); + + registrationFailures = QQmlMetaType::typeRegistrationFailures(); + QQmlMetaType::setTypeRegistrationNamespace(QString()); + } + + if (!registrationFailures.isEmpty()) { + foreach (const QString &failure, registrationFailures) { + QQmlError error; + error.setDescription(failure); + errors->prepend(error); + } + return false; + } } if (!engineInitialized) { // things on the engine (eg. adding new global objects) have to be done for every diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index dbff6fd219..2a1fe48b6e 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -143,7 +143,7 @@ public: QQmlImportDatabase(QQmlEngine *); ~QQmlImportDatabase(); - bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors); + bool importPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, QList<QQmlError> *errors); QStringList importPathList(PathType type = LocalOrRemote) const; void setImportPathList(const QStringList &paths); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index c1147b025b..b3a16b034c 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -108,6 +108,11 @@ struct QQmlMetaTypeData QBitArray lists; QList<QQmlPrivate::AutoParentFunction> parentFunctions; + + QSet<QString> protectedNamespaces; + + QString typeRegistrationNamespace; + QStringList typeRegistrationFailures; }; class QQmlTypeModulePrivate @@ -128,7 +133,7 @@ public: }; Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData) -Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) +Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, metaTypeDataLock, (QReadWriteLock::Recursive)) static uint qHash(const QQmlMetaTypeData::VersionedUri &v) { @@ -193,7 +198,7 @@ public: // Avoid multiple fromUtf8(), copies and hashing of the module name. // This is only called when metaTypeDataLock is locked. -static QHashedString moduletoUtf8(const char *module) +static QHashedString moduleFromUtf8(const char *module) { if (!module) return QHashedString(); @@ -241,7 +246,7 @@ QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface) QQmlType::QQmlType(int index, const QQmlPrivate::RegisterType &type) : d(new QQmlTypePrivate) { - d->m_module = moduletoUtf8(type.uri); + d->m_module = moduleFromUtf8(type.uri); d->m_elementName = QString::fromUtf8(type.elementName); d->m_version_maj = type.versionMajor; @@ -902,6 +907,29 @@ int registerType(const QQmlPrivate::RegisterType &type) QWriteLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); + + if (type.uri && type.elementName) { + QString nameSpace = moduleFromUtf8(type.uri); + + if (!data->typeRegistrationNamespace.isEmpty()) { + // We can only install types into the registered namespace + if (nameSpace != data->typeRegistrationNamespace) { + QString failure(QCoreApplication::translate("qmlRegisterType", + "Cannot install element '%1' into unregistered namespace '%2'")); + data->typeRegistrationFailures.append(failure.arg(QString::fromUtf8(type.elementName)).arg(nameSpace)); + return -1; + } + } else if (data->typeRegistrationNamespace != nameSpace) { + // Is the target namespace protected against further registrations? + if (data->protectedNamespaces.contains(nameSpace)) { + QString failure(QCoreApplication::translate("qmlRegisterType", + "Cannot install element '%1' into protected namespace '%2'")); + data->typeRegistrationFailures.append(failure.arg(QString::fromUtf8(type.elementName)).arg(nameSpace)); + return -1; + } + } + } + int index = data->types.count(); QQmlType *dtype = new QQmlType(index, type); @@ -985,6 +1013,46 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) return -1; } +bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri) +{ + QQmlMetaTypeData *data = metaTypeData(); + + // Has any type previously been installed to this namespace? + QHashedString nameSpace(uri); + foreach (const QQmlType *type, data->types) + if (type->module() == nameSpace) + return true; + + return false; +} + +void QQmlMetaType::protectNamespace(const QString &uri) +{ + QQmlMetaTypeData *data = metaTypeData(); + + data->protectedNamespaces.insert(uri); +} + +void QQmlMetaType::setTypeRegistrationNamespace(const QString &uri) +{ + QQmlMetaTypeData *data = metaTypeData(); + + data->typeRegistrationNamespace = uri; + data->typeRegistrationFailures.clear(); +} + +QStringList QQmlMetaType::typeRegistrationFailures() +{ + QQmlMetaTypeData *data = metaTypeData(); + + return data->typeRegistrationFailures; +} + +QReadWriteLock *QQmlMetaType::typeRegistrationLock() +{ + return metaTypeDataLock(); +} + /* Returns true if a module \a uri of any version is installed. */ diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index fbba733018..6f76c95544 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -69,6 +69,7 @@ class QQmlTypePrivate; class QQmlTypeModule; class QHashedString; class QHashedStringRef; +class QReadWriteLock; class Q_QML_PRIVATE_EXPORT QQmlMetaType { @@ -139,6 +140,15 @@ public: static ModuleApi moduleApi(const QString &, int, int); static QHash<QString, QList<ModuleApi> > moduleApis(); + static bool namespaceContainsRegistrations(const QString &); + + static void protectNamespace(const QString &); + + static void setTypeRegistrationNamespace(const QString &); + static QStringList typeRegistrationFailures(); + + static QReadWriteLock *typeRegistrationLock(); + private: static CompareFunction anchorLineCompareFunction; }; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index c66cd283da..0790b7664e 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1381,6 +1381,11 @@ QList<QQmlError> QQmlTypeLoader::QmldirContent::errors(const QString &uri) const return m_parser.errors(uri); } +QString QQmlTypeLoader::QmldirContent::typeNamespace() const +{ + return m_parser.typeNamespace(); +} + void QQmlTypeLoader::QmldirContent::setContent(const QString &location, const QString &content) { m_location = location; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 6461c1c484..47f7742cf0 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -302,6 +302,8 @@ public: bool hasError() const; QList<QQmlError> errors(const QString &uri) const; + QString typeNamespace() const; + QQmlDirComponents components() const; QQmlDirScripts scripts() const; QQmlDirPlugins plugins() const; diff --git a/tests/auto/qml/qqmlbundle/data/imports/bundletest/bundledata/qmldir b/tests/auto/qml/qqmlbundle/data/imports/bundletest/bundledata/qmldir index db8aabfefd..febddf6a47 100644 --- a/tests/auto/qml/qqmlbundle/data/imports/bundletest/bundledata/qmldir +++ b/tests/auto/qml/qqmlbundle/data/imports/bundletest/bundledata/qmldir @@ -1 +1,2 @@ +module bundletest plugin plugin1 diff --git a/tests/auto/qml/qqmldirparser/data/empty/qmldir b/tests/auto/qml/qqmldirparser/data/empty/qmldir new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/empty/qmldir diff --git a/tests/auto/qml/qqmldirparser/data/excessive-module/qmldir b/tests/auto/qml/qqmldirparser/data/excessive-module/qmldir new file mode 100644 index 0000000000..c4fdbd4e35 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/excessive-module/qmldir @@ -0,0 +1 @@ +module foo bar diff --git a/tests/auto/qml/qqmldirparser/data/excessive-plugin/qmldir b/tests/auto/qml/qqmldirparser/data/excessive-plugin/qmldir new file mode 100644 index 0000000000..4acde714ac --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/excessive-plugin/qmldir @@ -0,0 +1 @@ +plugin foo bar baz diff --git a/tests/auto/qml/qqmldirparser/data/four-sections/qmldir b/tests/auto/qml/qqmldirparser/data/four-sections/qmldir new file mode 100644 index 0000000000..03b37a0d27 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/four-sections/qmldir @@ -0,0 +1 @@ +foo bar baz qux diff --git a/tests/auto/qml/qqmldirparser/data/incomplete-module/qmldir b/tests/auto/qml/qqmldirparser/data/incomplete-module/qmldir new file mode 100644 index 0000000000..0cca093d7a --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/incomplete-module/qmldir @@ -0,0 +1 @@ +module diff --git a/tests/auto/qml/qqmldirparser/data/incomplete-plugin/qmldir b/tests/auto/qml/qqmldirparser/data/incomplete-plugin/qmldir new file mode 100644 index 0000000000..8cb205e9b3 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/incomplete-plugin/qmldir @@ -0,0 +1 @@ +plugin diff --git a/tests/auto/qml/qqmldirparser/data/invalid-versioned-component/qmldir b/tests/auto/qml/qqmldirparser/data/invalid-versioned-component/qmldir new file mode 100644 index 0000000000..c322b0f278 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/invalid-versioned-component/qmldir @@ -0,0 +1 @@ +foo 100 bar diff --git a/tests/auto/qml/qqmldirparser/data/multiple/qmldir b/tests/auto/qml/qqmldirparser/data/multiple/qmldir new file mode 100644 index 0000000000..e74bad5617 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/multiple/qmldir @@ -0,0 +1,15 @@ + +# +# Comment + +module ModuleNamespace + +plugin PluginA plugina.so # More comment + +ComponentA 1.0 componenta-1_0.qml +ScriptA 1.0 scripta-1_0.js + +# +ComponentA 1.5 componenta-1_5.qml +ComponentB 1.5 componentb-1_5.qml + diff --git a/tests/auto/qml/qqmldirparser/data/name-path-plugin/qmldir b/tests/auto/qml/qqmldirparser/data/name-path-plugin/qmldir new file mode 100644 index 0000000000..5cf8bd345d --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/name-path-plugin/qmldir @@ -0,0 +1 @@ +plugin foo bar diff --git a/tests/auto/qml/qqmldirparser/data/name-plugin/qmldir b/tests/auto/qml/qqmldirparser/data/name-plugin/qmldir new file mode 100644 index 0000000000..fb12cab37d --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/name-plugin/qmldir @@ -0,0 +1 @@ +plugin foo diff --git a/tests/auto/qml/qqmldirparser/data/no-content/qmldir b/tests/auto/qml/qqmldirparser/data/no-content/qmldir new file mode 100644 index 0000000000..3ce87ada21 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/no-content/qmldir @@ -0,0 +1,4 @@ + +# only empty lines + # and comments + diff --git a/tests/auto/qml/qqmldirparser/data/non-first-module/qmldir b/tests/auto/qml/qqmldirparser/data/non-first-module/qmldir new file mode 100644 index 0000000000..932e43a94c --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/non-first-module/qmldir @@ -0,0 +1,2 @@ +plugin foo +module bar diff --git a/tests/auto/qml/qqmldirparser/data/one-section/qmldir b/tests/auto/qml/qqmldirparser/data/one-section/qmldir new file mode 100644 index 0000000000..257cc5642c --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/one-section/qmldir @@ -0,0 +1 @@ +foo diff --git a/tests/auto/qml/qqmldirparser/data/repeated-module/qmldir b/tests/auto/qml/qqmldirparser/data/repeated-module/qmldir new file mode 100644 index 0000000000..80c3e0c750 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/repeated-module/qmldir @@ -0,0 +1,2 @@ +module foo +module bar diff --git a/tests/auto/qml/qqmldirparser/data/unversioned-component/qmldir b/tests/auto/qml/qqmldirparser/data/unversioned-component/qmldir new file mode 100644 index 0000000000..d675fa44e5 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/unversioned-component/qmldir @@ -0,0 +1 @@ +foo bar diff --git a/tests/auto/qml/qqmldirparser/data/versioned-component/qmldir b/tests/auto/qml/qqmldirparser/data/versioned-component/qmldir new file mode 100644 index 0000000000..a2afd1835e --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/versioned-component/qmldir @@ -0,0 +1 @@ +foo 33.66 bar diff --git a/tests/auto/qml/qqmldirparser/data/versioned-script/qmldir b/tests/auto/qml/qqmldirparser/data/versioned-script/qmldir new file mode 100644 index 0000000000..1345a6855b --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/versioned-script/qmldir @@ -0,0 +1 @@ +foo 33.66 bar.js diff --git a/tests/auto/qml/qqmldirparser/qqmldirparser.pro b/tests/auto/qml/qqmldirparser/qqmldirparser.pro new file mode 100644 index 0000000000..8efb415d43 --- /dev/null +++ b/tests/auto/qml/qqmldirparser/qqmldirparser.pro @@ -0,0 +1,10 @@ +CONFIG += testcase +TARGET = tst_qqmldirparser +QT += qml testlib v8-private +macx:CONFIG -= app_bundle + +SOURCES += tst_qqmldirparser.cpp + +include (../../shared/util.pri) + +CONFIG += parallel_test diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp new file mode 100644 index 0000000000..82616ffa8a --- /dev/null +++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp @@ -0,0 +1,288 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 "../../shared/util.h" + +#include <qtest.h> +#include <QObject> +#include <QQmlEngine> +#include <QQmlComponent> +#include <private/v8.h> +#include <private/qqmldirparser_p.h> +#include <QDebug> + +// Test the parsing of qmldir files + +class tst_qqmldirparser : public QQmlDataTest +{ + Q_OBJECT +public: + tst_qqmldirparser(); + +private slots: + void parse_data(); + void parse(); +}; + +tst_qqmldirparser::tst_qqmldirparser() +{ +} + +namespace { + + QStringList toStringList(const QList<QQmlError> &errors) + { + QStringList rv; + + foreach (const QQmlError &e, errors) + rv.append(e.toString()); + + return rv; + } + + QString toString(const QQmlDirParser::Plugin &p) + { + return p.name + "|" + p.path; + } + + QStringList toStringList(const QList<QQmlDirParser::Plugin> &plugins) + { + QStringList rv; + + foreach (const QQmlDirParser::Plugin &p, plugins) + rv.append(toString(p)); + + return rv; + } + + QString toString(const QQmlDirParser::Component &c) + { + return c.typeName + "|" + c.fileName + "|" + QString::number(c.majorVersion) + "|" + QString::number(c.minorVersion) + "|" + (c.internal ? "true" : "false"); + } + + QStringList toStringList(const QQmlDirComponents &components) + { + QStringList rv; + + foreach (const QQmlDirParser::Component &c, components.values()) + rv.append(toString(c)); + + qSort(rv); + return rv; + } + + QString toString(const QQmlDirParser::Script &s) + { + return s.nameSpace + "|" + s.fileName + "|" + QString::number(s.majorVersion) + "|" + QString::number(s.minorVersion); + } + + QStringList toStringList(const QList<QQmlDirParser::Script> &scripts) + { + QStringList rv; + + foreach (const QQmlDirParser::Script &s, scripts) + rv.append(toString(s)); + + return rv; + } +} + +void tst_qqmldirparser::parse_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QStringList>("errors"); + QTest::addColumn<QStringList>("plugins"); + QTest::addColumn<QStringList>("components"); + QTest::addColumn<QStringList>("scripts"); + + QTest::newRow("empty") + << "empty/qmldir" + << QStringList() + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("no-content") + << "no-content/qmldir" + << QStringList() + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("one-section") + << "one-section/qmldir" + << (QStringList() << "qmldir:1: a component declaration requires two or three arguments, but 1 were provided") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("four-sections") + << "four-sections/qmldir" + << (QStringList() << "qmldir:1:12: unexpected token" + << "qmldir:1: invalid qmldir directive contains too many tokens") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("incomplete-module") + << "incomplete-module/qmldir" + << (QStringList() << "qmldir:1: module directive requires one argument, but 0 were provided") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("excessive-module") + << "excessive-module/qmldir" + << (QStringList() << "qmldir:1: module directive requires one argument, but 2 were provided") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("repeated-module") + << "repeated-module/qmldir" + << (QStringList() << "qmldir:2: only one module directive may be defined in a qmldir file") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("non-first-module") + << "non-first-module/qmldir" + << (QStringList() << "qmldir:2: module directive must be the first directive in a qmldir file") + << (QStringList() << "foo|") + << QStringList() + << QStringList(); + + QTest::newRow("incomplete-plugin") + << "incomplete-plugin/qmldir" + << (QStringList() << "qmldir:1: plugin directive requires one or two arguments, but 0 were provided") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("excessive-plugin") + << "excessive-plugin/qmldir" + << (QStringList() << "qmldir:1:15: unexpected token" + << "qmldir:1: invalid qmldir directive contains too many tokens") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("name-plugin") + << "name-plugin/qmldir" + << QStringList() + << (QStringList() << "foo|") + << QStringList() + << QStringList(); + + QTest::newRow("name-path-plugin") + << "name-path-plugin/qmldir" + << QStringList() + << (QStringList() << "foo|bar") + << QStringList() + << QStringList(); + + QTest::newRow("unversioned-component") + << "unversioned-component/qmldir" + << QStringList() + << QStringList() + << (QStringList() << "foo|bar|-1|-1|false") + << QStringList(); + + QTest::newRow("invalid-versioned-component") + << "invalid-versioned-component/qmldir" + << (QStringList() << "qmldir:1: expected '.'") + << QStringList() + << QStringList() + << QStringList(); + + QTest::newRow("versioned-component") + << "versioned-component/qmldir" + << QStringList() + << QStringList() + << (QStringList() << "foo|bar|33|66|false") + << QStringList(); + + QTest::newRow("versioned-script") + << "versioned-script/qmldir" + << QStringList() + << QStringList() + << QStringList() + << (QStringList() << "foo|bar.js|33|66"); + + QTest::newRow("multiple") + << "multiple/qmldir" + << QStringList() + << (QStringList() << "PluginA|plugina.so") + << (QStringList() << "ComponentA|componenta-1_0.qml|1|0|false" + << "ComponentA|componenta-1_5.qml|1|5|false" + << "ComponentB|componentb-1_5.qml|1|5|false") + << (QStringList() << "ScriptA|scripta-1_0.js|1|0"); +} + +void tst_qqmldirparser::parse() +{ + QFETCH(QString, file); + QFETCH(QStringList, errors); + QFETCH(QStringList, plugins); + QFETCH(QStringList, components); + QFETCH(QStringList, scripts); + + QFile f(testFile(file)); + f.open(QIODevice::ReadOnly); + + QQmlDirParser p; + p.parse(f.readAll()); + + if (errors.isEmpty()) { + QCOMPARE(p.hasError(), false); + } else { + QCOMPARE(p.hasError(), true); + QCOMPARE(toStringList(p.errors("qmldir")), errors); + } + + QCOMPARE(toStringList(p.plugins()), plugins); + QCOMPARE(toStringList(p.components()), components); + QCOMPARE(toStringList(p.scripts()), scripts); +} + +QTEST_MAIN(tst_qqmldirparser) + +#include "tst_qqmldirparser.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt index 9cafb78740..08492af787 100644 --- a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt +++ b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt @@ -1,3 +1,4 @@ 1:12:unexpected token -1:-1:expected '.' +1:-1:invalid qmldir directive contains too many tokens 2:17:unexpected token +2:-1:invalid qmldir directive contains too many tokens diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/invalidNamespaceModule.pro b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/invalidNamespaceModule.pro new file mode 100644 index 0000000000..36b054064c --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/invalidNamespaceModule.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/com/nokia/InvalidNamespaceModule + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp new file mode 100644 index 0000000000..d682510153 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT +public: + MyPluginType(QObject *parent=0) : QObject(parent) {} +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.InvalidStrictModule"); + qmlRegisterType<MyPluginType>("com.nokia.SomeOtherModule", 1, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/qmldir new file mode 100644 index 0000000000..5f349709f2 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/qmldir @@ -0,0 +1,2 @@ +module com.nokia.AwesomeModule +plugin invalidNamespaceModule diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/invalidStrictModule.pro b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/invalidStrictModule.pro new file mode 100644 index 0000000000..7caa6c4605 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/invalidStrictModule.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/com/nokia/InvalidStrictModule + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp new file mode 100644 index 0000000000..d682510153 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT +public: + MyPluginType(QObject *parent=0) : QObject(parent) {} +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.InvalidStrictModule"); + qmlRegisterType<MyPluginType>("com.nokia.SomeOtherModule", 1, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/qmldir new file mode 100644 index 0000000000..45752a9bca --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/qmldir @@ -0,0 +1,2 @@ +module com.nokia.InvalidStrictModule +plugin invalidStrictModule diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/nonstrictModule.pro b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/nonstrictModule.pro new file mode 100644 index 0000000000..e29578483b --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/nonstrictModule.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/com/nokia/NonstrictModule + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp new file mode 100644 index 0000000000..73e1056d6f --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT +public: + MyPluginType(QObject *parent=0) : QObject(parent) {} +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.NonstrictModule"); + + // Install into a namespace that should be protected + qmlRegisterType<MyPluginType>("com.nokia.StrictModule", 1, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/qmldir new file mode 100644 index 0000000000..7371ee759f --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/qmldir @@ -0,0 +1 @@ +plugin nonstrictModule diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp new file mode 100644 index 0000000000..f7f7c77bb5 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT +public: + MyPluginType(QObject *parent=0) : QObject(parent) {} +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.PreemptedStrictModule"); + qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/preemptedStrictModule.pro b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/preemptedStrictModule.pro new file mode 100644 index 0000000000..76934e7657 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/preemptedStrictModule.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/com/nokia/PreemptedStrictModule + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/qmldir new file mode 100644 index 0000000000..c82acd2fd3 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/qmldir @@ -0,0 +1,2 @@ +module com.nokia.PreemptedStrictModule +plugin preemptedStrictModule diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp new file mode 100644 index 0000000000..0b3dd78e79 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT +public: + MyPluginType(QObject *parent=0) : QObject(parent) {} +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.PreemptiveModule"); + qmlRegisterType<MyPluginType>("com.nokia.PreemptiveModule", 1, 0, "MyPluginType"); + + // Install into another namespace that should be protected + qmlRegisterType<MyPluginType>("com.nokia.PreemptedStrictModule", 1, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/preemptiveModule.pro b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/preemptiveModule.pro new file mode 100644 index 0000000000..e50c722543 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/preemptiveModule.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/com/nokia/PreemptiveModule + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/qmldir new file mode 100644 index 0000000000..d240cafac9 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/qmldir @@ -0,0 +1 @@ +plugin preemptiveModule diff --git a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro index 6da88320cd..c020ce955d 100644 --- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro +++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro @@ -1,6 +1,21 @@ QT = core TEMPLATE = subdirs -SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase pluginWithQmlFile pluginMixed pluginVersion nestedPlugin +SUBDIRS =\ + plugin\ + plugin.2\ + plugin.2.1\ + pluginWrongCase\ + pluginWithQmlFile\ + pluginMixed\ + pluginVersion\ + nestedPlugin\ + strictModule\ + invalidStrictModule\ + nonstrictModule\ + preemptiveModule\ + preemptedStrictModule\ + invalidNamespaceModule + tst_qqmlmoduleplugin_pro.depends += plugin SUBDIRS += tst_qqmlmoduleplugin.pro diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp new file mode 100644 index 0000000000..4bc8108901 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT +public: + MyPluginType(QObject *parent=0) : QObject(parent) {} +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyPlugin() {} + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.StrictModule"); + qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/strictModule/qmldir new file mode 100644 index 0000000000..ff06446fbd --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/qmldir @@ -0,0 +1,2 @@ +module com.nokia.StrictModule +plugin strictModule diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/strictModule.pro b/tests/auto/qml/qqmlmoduleplugin/strictModule/strictModule.pro new file mode 100644 index 0000000000..9c6d83f7a3 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/strictModule.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/com/nokia/StrictModule + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index 67b3d00196..99e2874060 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -50,6 +50,10 @@ #define SERVER_ADDR "http://127.0.0.1:14456" #define SERVER_PORT 14456 +// Note: this test does not use module directives in the qmldir files, because +// it would result in repeated attempts to insert types into the same namespace. +// This occurs because type registration is process-global, while the test +// cases should really be run in proper per-process isolation. class tst_qqmlmoduleplugin : public QQmlDataTest { @@ -74,6 +78,8 @@ private slots: void importsNested_data(); void importLocalModule(); void importLocalModule_data(); + void importStrictModule(); + void importStrictModule_data(); private: QString m_importsDirectory; @@ -135,6 +141,7 @@ void tst_qqmlmoduleplugin::importsPlugin() engine.addImportPath(m_importsDirectory); QTest::ignoreMessage(QtWarningMsg, "plugin created"); QTest::ignoreMessage(QtWarningMsg, "import worked"); + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestQmlPluginType' does not contain a module directive - it cannot be protected from external registrations."); QQmlComponent component(&engine, testFileUrl(QStringLiteral("works.qml"))); foreach (QQmlError err, component.errors()) qWarning() << err; @@ -151,6 +158,7 @@ void tst_qqmlmoduleplugin::importsPlugin2() engine.addImportPath(m_importsDirectory); QTest::ignoreMessage(QtWarningMsg, "plugin2 created"); QTest::ignoreMessage(QtWarningMsg, "import2 worked"); + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestQmlPluginType' does not contain a module directive - it cannot be protected from external registrations."); QQmlComponent component(&engine, testFileUrl(QStringLiteral("works2.qml"))); foreach (QQmlError err, component.errors()) qWarning() << err; @@ -167,6 +175,7 @@ void tst_qqmlmoduleplugin::importsPlugin21() engine.addImportPath(m_importsDirectory); QTest::ignoreMessage(QtWarningMsg, "plugin2.1 created"); QTest::ignoreMessage(QtWarningMsg, "import2.1 worked"); + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestQmlPluginType' does not contain a module directive - it cannot be protected from external registrations."); QQmlComponent component(&engine, testFileUrl(QStringLiteral("works21.qml"))); foreach (QQmlError err, component.errors()) qWarning() << err; @@ -215,6 +224,8 @@ void tst_qqmlmoduleplugin::importPluginWithQmlFile() QQmlEngine engine; engine.addImportPath(path); + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestPluginWithQmlFile' does not contain a module directive - it cannot be protected from external registrations."); + QQmlComponent component(&engine, testFileUrl(QStringLiteral("pluginWithQmlFile.qml"))); foreach (QQmlError err, component.errors()) qWarning() << err; @@ -275,6 +286,8 @@ void tst_qqmlmoduleplugin::importsMixedQmlCppPlugin() QQmlEngine engine; engine.addImportPath(m_importsDirectory); + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestQmlMixedPluginType' does not contain a module directive - it cannot be protected from external registrations."); + { QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.qml"))); @@ -314,6 +327,10 @@ void tst_qqmlmoduleplugin::versionNotInstalled() QQmlEngine engine; engine.addImportPath(m_importsDirectory); + static int count = 0; + if (++count == 1) + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestQmlVersionPluginType' does not contain a module directive - it cannot be protected from external registrations."); + QQmlComponent component(&engine, testFileUrl(file)); VERIFY_ERRORS(errorFile.toLatin1().constData()); } @@ -382,6 +399,10 @@ void tst_qqmlmoduleplugin::importsNested() QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready"); } + static int count = 0; + if (++count == 1) + QTest::ignoreMessage(QtWarningMsg, "Module 'com.nokia.AutoTestQmlNestedPluginType' does not contain a module directive - it cannot be protected from external registrations."); + QQmlComponent component(&engine, testFile(file)); QObject *obj = component.create(); @@ -446,6 +467,71 @@ void tst_qqmlmoduleplugin::importLocalModule_data() << 2 << 0; } +void tst_qqmlmoduleplugin::importStrictModule() +{ + QFETCH(QString, qml); + QFETCH(QString, warning); + QFETCH(QString, error); + + if (!warning.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); + + QQmlEngine engine; + engine.addImportPath(m_importsDirectory); + + QUrl url(testFileUrl("empty.qml")); + + QQmlComponent component(&engine); + component.setData(qml.toUtf8(), url); + + if (error.isEmpty()) { + QScopedPointer<QObject> object(component.create()); + QVERIFY(object != 0); + } else { + QVERIFY(!component.isReady()); + QCOMPARE(component.errors().count(), 1); + QCOMPARE(component.errors().first().toString(), url.toString() + error); + } +} + +void tst_qqmlmoduleplugin::importStrictModule_data() +{ + QTest::addColumn<QString>("qml"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("success") + << "import com.nokia.StrictModule 1.0\n" + "MyPluginType {}" + << QString() + << QString(); + + QTest::newRow("wrong target") + << "import com.nokia.InvalidStrictModule 1.0\n" + "MyPluginType {}" + << QString() + << ":1:1: plugin cannot be loaded for module \"com.nokia.InvalidStrictModule\": Cannot install element 'MyPluginType' into unregistered namespace 'com.nokia.SomeOtherModule'"; + + QTest::newRow("non-strict clash") + << "import com.nokia.NonstrictModule 1.0\n" + "MyPluginType {}" + << "Module 'com.nokia.NonstrictModule' does not contain a module directive - it cannot be protected from external registrations." + << ":1:1: plugin cannot be loaded for module \"com.nokia.NonstrictModule\": Cannot install element 'MyPluginType' into protected namespace 'com.nokia.StrictModule'"; + + QTest::newRow("non-strict preemption") + << "import com.nokia.PreemptiveModule 1.0\n" + "import com.nokia.PreemptedStrictModule 1.0\n" + "MyPluginType {}" + << "Module 'com.nokia.PreemptiveModule' does not contain a module directive - it cannot be protected from external registrations." + << ":2:1: plugin cannot be loaded for module \"com.nokia.PreemptedStrictModule\": Namespace 'com.nokia.PreemptedStrictModule' has already been used for type registration"; + + QTest::newRow("invalid namespace") + << "import com.nokia.InvalidNamespaceModule 1.0\n" + "MyPluginType {}" + << QString() + << ":1:1: plugin cannot be loaded for module \"com.nokia.InvalidNamespaceModule\": Module namespace 'com.nokia.AwesomeModule' does not match import URI 'com.nokia.InvalidNamespaceModule'"; +} + QTEST_MAIN(tst_qqmlmoduleplugin) #include "tst_qqmlmoduleplugin.moc" diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index b5ab04cccd..56fb1e9c00 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -642,7 +642,13 @@ void tst_qquickanimations::resume() QVERIFY(!animation.isPaused()); QCOMPARE(spy.count(), 2); - qmlRegisterType<QQuickPropertyAnimation>("QtQuick",2,0,"PropertyAnimation"); //make sure QQuickPropertyAnimation has correct qml type name + // Load QtQuick to ensure that QQuickPropertyAnimation is registered as PropertyAnimation + { + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nQtObject {}\n", QUrl()); + } + QByteArray message = "<Unknown File>: QML PropertyAnimation: setPaused() cannot be used when animation isn't running."; QTest::ignoreMessage(QtWarningMsg, message); animation.pause(); diff --git a/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml b/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml index dfc4159f4e..4b892b2b84 100644 --- a/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml +++ b/tests/auto/quick/qquickwindow/data/ownershipRootItem.qml @@ -1,5 +1,6 @@ import QtQuick 2.0 import QtQuick.Window 2.0 as Window +import Test 1.0 Window.Window { RootItemAccessor { diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 01d60361b4..f29df6910b 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -1046,7 +1046,7 @@ void tst_qquickwindow::ignoreUnhandledMouseEvents() void tst_qquickwindow::ownershipRootItem() { - qmlRegisterType<RootItemAccessor>("QtQuick", 2, 0, "RootItemAccessor"); + qmlRegisterType<RootItemAccessor>("Test", 1, 0, "RootItemAccessor"); QQmlEngine engine; QQmlComponent component(&engine); |