Implement strict mode for qmldir modules
Allow a module's qmldir to contain a module directive, which when present specifies 'strict mode' import processing. In strict mode, type registrations are only permitted into the namespace identified in the qmldir file's module directive. In addition, any type registrations to that namespace originating from other modules are treated as error conditions. Task-number: QTBUG-26551 Change-Id: I081bde2d3b83d3f28524440177fb2cd1ccee34ad Reviewed-by: Chris Adams <christopher.adams@nokia.com> Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
parent
2e6accbbbb
commit
c9b7582a2e
|
@ -1 +1,2 @@
|
|||
module Qt.labs.folderlistmodel
|
||||
plugin qmlfolderlistmodelplugin
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
plugin qmllocalstorageplugin
|
||||
module QtQuick.LocalStorage
|
||||
plugin qmllocalstorageplugin
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
module QtQuick.Particles
|
||||
plugin particlesplugin
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
module QtQuick
|
||||
plugin qtquick2plugin
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
module QtTest
|
||||
plugin qmltestplugin
|
||||
TestCase 1.0 TestCase.qml
|
||||
SignalSpy 1.0 SignalSpy.qml
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
module QtQuick.Window
|
||||
plugin windowplugin
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
plugin qmlxmllistmodelplugin
|
||||
module QtQuick.XmlListModel
|
||||
plugin qmlxmllistmodelplugin
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
module bundletest
|
||||
plugin plugin1
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module foo bar
|
|
@ -0,0 +1 @@
|
|||
plugin foo bar baz
|
|
@ -0,0 +1 @@
|
|||
foo bar baz qux
|
|
@ -0,0 +1 @@
|
|||
module
|
|
@ -0,0 +1 @@
|
|||
plugin
|
|
@ -0,0 +1 @@
|
|||
foo 100 bar
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
plugin foo bar
|
|
@ -0,0 +1 @@
|
|||
plugin foo
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
# only empty lines
|
||||
# and comments
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
plugin foo
|
||||
module bar
|
|
@ -0,0 +1 @@
|
|||
foo
|
|
@ -0,0 +1,2 @@
|
|||
module foo
|
||||
module bar
|
|
@ -0,0 +1 @@
|
|||
foo bar
|
|
@ -0,0 +1 @@
|
|||
foo 33.66 bar
|
|
@ -0,0 +1 @@
|
|||
foo 33.66 bar.js
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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"
|
|
@ -0,0 +1,2 @@
|
|||
module com.nokia.AwesomeModule
|
||||
plugin invalidNamespaceModule
|
|
@ -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)
|
|
@ -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"
|
|
@ -0,0 +1,2 @@
|
|||
module com.nokia.InvalidStrictModule
|
||||
plugin invalidStrictModule
|
|
@ -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)
|
|
@ -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"
|
|
@ -0,0 +1 @@
|
|||
plugin nonstrictModule
|
|
@ -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"
|
|
@ -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)
|
|
@ -0,0 +1,2 @@
|
|||
module com.nokia.PreemptedStrictModule
|
||||
plugin preemptedStrictModule
|
|
@ -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"
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
plugin preemptiveModule
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -0,0 +1,2 @@
|
|||
module com.nokia.StrictModule
|
||||
plugin strictModule
|
|
@ -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)
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Window 2.0 as Window
|
||||
import Test 1.0
|
||||
|
||||
Window.Window {
|
||||
RootItemAccessor {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue