aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmlmoduleplugin
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-02-12 13:26:55 +0100
committerLiang Qi <liang.qi@qt.io>2018-02-12 16:31:13 +0100
commit4d525de33e2ee55e69bb6c90fc11049a0f8b36b5 (patch)
treec9808baeabb1121f488a7b59ffff314cc62d80e8 /tests/auto/qml/qqmlmoduleplugin
parent47cd9da96371ccd495f6caabe1c6853258210ebb (diff)
parent3e3c6717ba634825a65069541500c40645a808ee (diff)
Merge remote-tracking branch 'origin/5.10' into 5.11
Conflicts: src/imports/shapes/qquickshape.cpp src/imports/shapes/qquickshape_p_p.h src/qml/compiler/qqmlpropertycachecreator_p.h src/qml/jsruntime/qv4value_p.h src/quick/items/qquickloader_p.h tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp tools/qmlprofiler/qmlprofilerapplication.cpp Change-Id: Iafc66ae84bf78630ed72a986acb678e9d19e3a69
Diffstat (limited to 'tests/auto/qml/qqmlmoduleplugin')
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp119
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro8
4 files changed, 131 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir
new file mode 100644
index 0000000000..104c4bf673
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir
@@ -0,0 +1,2 @@
+module moduleWithStaticPlugin
+plugin secondStaticPlugin
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir
new file mode 100644
index 0000000000..45a02b2ffe
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir
@@ -0,0 +1,2 @@
+module moduleWithWaitingPlugin
+plugin pluginThatWaits
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index edfbf57e76..85e4918b61 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -29,6 +29,9 @@
#include <qdir.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonarray.h>
#include <QDebug>
#if defined(Q_OS_MAC)
@@ -73,12 +76,80 @@ private slots:
void importsChildPlugin();
void importsChildPlugin2();
void importsChildPlugin21();
+ void parallelPluginImport();
private:
QString m_importsDirectory;
QString m_dataImportsDirectory;
};
+class PluginThatWaits : public QQmlExtensionPlugin
+{
+public:
+ static QByteArray metaData;
+
+ static QMutex initializeEngineEntered;
+ static QWaitCondition waitingForInitializeEngineEntry;
+ static QMutex leavingInitializeEngine;
+ static QWaitCondition waitingForInitializeEngineLeave;
+
+ void registerTypes(const char *uri) override
+ {
+ qmlRegisterModule(uri, 1, 0);
+ }
+
+ void initializeEngine(QQmlEngine *engine, const char *uri) override
+ {
+ initializeEngineEntered.lock();
+ leavingInitializeEngine.lock();
+ waitingForInitializeEngineEntry.wakeOne();
+ initializeEngineEntered.unlock();
+ waitingForInitializeEngineLeave.wait(&leavingInitializeEngine);
+ leavingInitializeEngine.unlock();
+ }
+};
+QByteArray PluginThatWaits::metaData;
+QMutex PluginThatWaits::initializeEngineEntered;
+QWaitCondition PluginThatWaits::waitingForInitializeEngineEntry;
+QMutex PluginThatWaits::leavingInitializeEngine;
+QWaitCondition PluginThatWaits::waitingForInitializeEngineLeave;
+
+class SecondStaticPlugin : public QQmlExtensionPlugin
+{
+public:
+ static QByteArray metaData;
+
+ void registerTypes(const char *uri) override
+ {
+ qmlRegisterModule(uri, 1, 0);
+ }
+};
+QByteArray SecondStaticPlugin::metaData;
+
+template <typename PluginType>
+void registerStaticPlugin(const char *uri)
+{
+ QStaticPlugin plugin;
+ plugin.instance = []() {
+ static PluginType plugin;
+ return static_cast<QObject*>(&plugin);
+ };
+
+ QJsonObject md;
+ md.insert(QStringLiteral("IID"), QQmlExtensionInterface_iid);
+ QJsonArray uris;
+ uris.append(uri);
+ md.insert(QStringLiteral("uri"), uris);
+
+ PluginType::metaData.append(QLatin1String("QTMETADATA "));
+ PluginType::metaData.append(QJsonDocument(md).toBinaryData());
+
+ plugin.rawMetaData = []() {
+ return PluginType::metaData.constData();
+ };
+ qRegisterStaticPluginFunction(plugin);
+};
+
void tst_qqmlmoduleplugin::initTestCase()
{
QQmlDataTest::initTestCase();
@@ -88,6 +159,9 @@ void tst_qqmlmoduleplugin::initTestCase()
m_dataImportsDirectory = directory() + QStringLiteral("/imports");
QVERIFY2(QFileInfo(m_dataImportsDirectory).isDir(),
qPrintable(QString::fromLatin1("Imports directory '%1' does not exist.").arg(m_dataImportsDirectory)));
+
+ registerStaticPlugin<PluginThatWaits>("moduleWithWaitingPlugin");
+ registerStaticPlugin<SecondStaticPlugin>("moduleWithStaticPlugin");
}
#define VERIFY_ERRORS(errorfile) \
@@ -629,6 +703,51 @@ void tst_qqmlmoduleplugin::importsChildPlugin21()
delete object;
}
+void tst_qqmlmoduleplugin::parallelPluginImport()
+{
+ QMutexLocker locker(&PluginThatWaits::initializeEngineEntered);
+
+ QThread worker;
+ QObject::connect(&worker, &QThread::started, [&worker](){
+ // Engines in separate threads are tricky, but as long as we do not create a graphical
+ // object and move objects created by the engines across thread boundaries, this is safe.
+ // At the same time this allows us to place the engine's loader thread into the position
+ // where, without the fix for this bug, the global lock is acquired.
+ QQmlEngine engineInThread;
+
+ QQmlComponent component(&engineInThread);
+ component.setData("import moduleWithWaitingPlugin 1.0\nimport QtQml 2.0\nQtObject {}",
+ QUrl());
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+
+ worker.quit();
+ });
+ worker.start();
+
+ PluginThatWaits::waitingForInitializeEngineEntry.wait(&PluginThatWaits::initializeEngineEntered);
+
+ {
+ // After acquiring this lock, the engine in the other thread as well as its type loader
+ // thread are blocked. However they should not hold the global plugin lock
+ // qmlEnginePluginsWithRegisteredTypes()->mutex in qqmllimports.cpp, allowing for the load
+ // of a component in a different engine with its own plugin to proceed.
+ QMutexLocker continuationLock(&PluginThatWaits::leavingInitializeEngine);
+
+ QQmlEngine secondEngine;
+ QQmlComponent secondComponent(&secondEngine);
+ secondComponent.setData("import moduleWithStaticPlugin 1.0\nimport QtQml 2.0\nQtObject {}",
+ QUrl());
+ QScopedPointer<QObject> o(secondComponent.create());
+ QVERIFY(!o.isNull());
+
+ PluginThatWaits::waitingForInitializeEngineLeave.wakeOne();
+ }
+
+ worker.wait();
+}
+
QTEST_MAIN(tst_qqmlmoduleplugin)
#include "tst_qqmlmoduleplugin.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro
index 43bd112415..118ca26ee9 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro
@@ -10,4 +10,12 @@ include (../../shared/util.pri)
TESTDATA = data/* imports/* $$OUT_PWD/imports/*
+waitingPlugin.files = moduleWithWaitingPlugin
+waitingPlugin.prefix = /qt-project.org/imports/
+RESOURCES += waitingPlugin
+
+staticPlugin.files = moduleWithStaticPlugin
+staticPlugin.prefix = /qt-project.org/imports/
+RESOURCES += staticPlugin
+
QT += core-private gui-private qml-private network testlib