forked from qt-creator/qt-creator
Load only tested plugins when invoked with -test
By default, a clean settings path is used for test environment. All the default plugins are loaded, although they're not needed. This change significantly improves loading time for tests. Change-Id: I24254f3e538e3f0e6d233d0989738dc1ce238209 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com> Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
This commit is contained in:
committed by
Eike Ziller
parent
da67c7c6c9
commit
044eeacde5
@@ -199,8 +199,9 @@
|
|||||||
\row
|
\row
|
||||||
\li Type
|
\li Type
|
||||||
\li String
|
\li String
|
||||||
\li Optional. Value \c Required or \c Optional. Defines if the dependency is
|
\li Optional. Value \c Required, \c Optional, or \c Test. Defines if the dependency is
|
||||||
a hard requirement or optional. Defaults to \c{Required}.
|
a hard requirement, optional, or required for running the plugin's tests.
|
||||||
|
Defaults to \c{Required}.
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
\section3 Optional Dependencies
|
\section3 Optional Dependencies
|
||||||
@@ -223,6 +224,18 @@
|
|||||||
ExtensionSystem::PluginManager::getObjectByClassName(), and use QMetaObject functions to call
|
ExtensionSystem::PluginManager::getObjectByClassName(), and use QMetaObject functions to call
|
||||||
functions on it.
|
functions on it.
|
||||||
|
|
||||||
|
\section3 Test Dependencies
|
||||||
|
|
||||||
|
When the user runs the application with the \c{-test} command line argument, only
|
||||||
|
the specified plugins and their dependencies are loaded. This is done in order to
|
||||||
|
speed up the execution of tests by avoiding the loading of unneeded plugins.
|
||||||
|
|
||||||
|
A plugin can specify additional dependencies that are required for running its
|
||||||
|
tests, but not for its normal execution, by declaring dependencies with
|
||||||
|
\c {"Type" : "Test"}. Test dependencies are force loaded, and do not affect load order.
|
||||||
|
|
||||||
|
This type of dependency is not transitive.
|
||||||
|
|
||||||
\section2 Command Line Arguments
|
\section2 Command Line Arguments
|
||||||
|
|
||||||
Plugins can register command line arguments that the user can give
|
Plugins can register command line arguments that the user can give
|
||||||
|
@@ -8,6 +8,7 @@ QtcProduct {
|
|||||||
|
|
||||||
property var pluginJsonReplacements
|
property var pluginJsonReplacements
|
||||||
property var pluginRecommends: []
|
property var pluginRecommends: []
|
||||||
|
property var pluginTestDepends: []
|
||||||
|
|
||||||
property string minimumQtVersion: "5.3.1"
|
property string minimumQtVersion: "5.3.1"
|
||||||
condition: QtcFunctions.versionIsAtLeast(Qt.core.version, minimumQtVersion)
|
condition: QtcFunctions.versionIsAtLeast(Qt.core.version, minimumQtVersion)
|
||||||
|
@@ -36,6 +36,7 @@ Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd.plugin_recommends = product.pluginRecommends
|
cmd.plugin_recommends = product.pluginRecommends
|
||||||
|
cmd.plugin_test_depends = product.pluginTestDepends
|
||||||
|
|
||||||
cmd.sourceCode = function() {
|
cmd.sourceCode = function() {
|
||||||
var i;
|
var i;
|
||||||
@@ -57,6 +58,9 @@ Module {
|
|||||||
for (i in plugin_recommends) {
|
for (i in plugin_recommends) {
|
||||||
deplist.push(" { \"Name\" : \"" + plugin_recommends[i] + "\", \"Version\" : \"" + project.qtcreator_version + "\", \"Type\" : \"optional\" }");
|
deplist.push(" { \"Name\" : \"" + plugin_recommends[i] + "\", \"Version\" : \"" + project.qtcreator_version + "\", \"Type\" : \"optional\" }");
|
||||||
}
|
}
|
||||||
|
for (i in plugin_test_depends) {
|
||||||
|
deplist.push(" { \"Name\" : \"" + plugin_test_depends[i] + "\", \"Version\" : \"" + project.qtcreator_version + "\", \"Type\" : \"test\" }");
|
||||||
|
}
|
||||||
deplist = deplist.join(",\n")
|
deplist = deplist.join(",\n")
|
||||||
vars['dependencyList'] = "\"Dependencies\" : [\n" + deplist + "\n ]";
|
vars['dependencyList'] = "\"Dependencies\" : [\n" + deplist + "\n ]";
|
||||||
for (i in vars) {
|
for (i in vars) {
|
||||||
|
@@ -91,6 +91,7 @@ bool OptionsParser::parse()
|
|||||||
}
|
}
|
||||||
if (m_isDependencyRefreshNeeded)
|
if (m_isDependencyRefreshNeeded)
|
||||||
m_pmPrivate->resolveDependencies();
|
m_pmPrivate->resolveDependencies();
|
||||||
|
m_pmPrivate->enableOnlyTestedSpecs();
|
||||||
return !m_hasError;
|
return !m_hasError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -98,8 +98,16 @@ void PluginDetailsView::update(PluginSpec *spec)
|
|||||||
QString depString = dep.name;
|
QString depString = dep.name;
|
||||||
depString += QLatin1String(" (");
|
depString += QLatin1String(" (");
|
||||||
depString += dep.version;
|
depString += dep.version;
|
||||||
if (dep.type == PluginDependency::Optional)
|
switch (dep.type) {
|
||||||
|
case PluginDependency::Required:
|
||||||
|
break;
|
||||||
|
case PluginDependency::Optional:
|
||||||
depString += QLatin1String(", optional");
|
depString += QLatin1String(", optional");
|
||||||
|
break;
|
||||||
|
case PluginDependency::Test:
|
||||||
|
depString += QLatin1String(", test");
|
||||||
|
break;
|
||||||
|
}
|
||||||
depString += QLatin1Char(')');
|
depString += QLatin1Char(')');
|
||||||
depStrings.append(depString);
|
depStrings.append(depString);
|
||||||
}
|
}
|
||||||
|
@@ -1255,7 +1255,14 @@ bool PluginManagerPrivate::loadQueue(PluginSpec *spec, QList<PluginSpec *> &queu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add dependencies
|
// add dependencies
|
||||||
foreach (PluginSpec *depSpec, spec->dependencySpecs()) {
|
QHashIterator<PluginDependency, PluginSpec *> it(spec->dependencySpecs());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
// Skip test dependencies since they are not real dependencies but just force-loaded
|
||||||
|
// plugins when running tests
|
||||||
|
if (it.key().type == PluginDependency::Test)
|
||||||
|
continue;
|
||||||
|
PluginSpec *depSpec = it.value();
|
||||||
if (!loadQueue(depSpec, queue, circularityCheckQueue)) {
|
if (!loadQueue(depSpec, queue, circularityCheckQueue)) {
|
||||||
spec->d->hasError = true;
|
spec->d->hasError = true;
|
||||||
spec->d->errorString =
|
spec->d->errorString =
|
||||||
@@ -1299,7 +1306,7 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
|
|||||||
QHashIterator<PluginDependency, PluginSpec *> it(spec->dependencySpecs());
|
QHashIterator<PluginDependency, PluginSpec *> it(spec->dependencySpecs());
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
if (it.key().type == PluginDependency::Optional)
|
if (it.key().type != PluginDependency::Required)
|
||||||
continue;
|
continue;
|
||||||
PluginSpec *depSpec = it.value();
|
PluginSpec *depSpec = it.value();
|
||||||
if (depSpec->state() != destState) {
|
if (depSpec->state() != destState) {
|
||||||
@@ -1423,6 +1430,35 @@ void PluginManagerPrivate::resolveDependencies()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PluginManagerPrivate::enableOnlyTestedSpecs()
|
||||||
|
{
|
||||||
|
if (testSpecs.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QList<PluginSpec *> specsForTests;
|
||||||
|
foreach (const TestSpec &testSpec, testSpecs) {
|
||||||
|
QList<PluginSpec *> circularityCheckQueue;
|
||||||
|
loadQueue(testSpec.pluginSpec, specsForTests, circularityCheckQueue);
|
||||||
|
// add plugins that must be force loaded when running tests for the plugin
|
||||||
|
// (aka "test dependencies")
|
||||||
|
QHashIterator<PluginDependency, PluginSpec *> it(testSpec.pluginSpec->dependencySpecs());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
if (it.key().type != PluginDependency::Test)
|
||||||
|
continue;
|
||||||
|
PluginSpec *depSpec = it.value();
|
||||||
|
circularityCheckQueue.clear();
|
||||||
|
loadQueue(depSpec, specsForTests, circularityCheckQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (PluginSpec *spec, pluginSpecs)
|
||||||
|
spec->setForceDisabled(true);
|
||||||
|
foreach (PluginSpec *spec, specsForTests) {
|
||||||
|
spec->setForceDisabled(false);
|
||||||
|
spec->setForceEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Look in argument descriptions of the specs for the option.
|
// Look in argument descriptions of the specs for the option.
|
||||||
PluginSpec *PluginManagerPrivate::pluginForOption(const QString &option, bool *requiresArgument) const
|
PluginSpec *PluginManagerPrivate::pluginForOption(const QString &option, bool *requiresArgument) const
|
||||||
{
|
{
|
||||||
|
@@ -73,6 +73,7 @@ public:
|
|||||||
QList<PluginSpec *> loadQueue();
|
QList<PluginSpec *> loadQueue();
|
||||||
void loadPlugin(PluginSpec *spec, PluginSpec::State destState);
|
void loadPlugin(PluginSpec *spec, PluginSpec::State destState);
|
||||||
void resolveDependencies();
|
void resolveDependencies();
|
||||||
|
void enableOnlyTestedSpecs();
|
||||||
void initProfiling();
|
void initProfiling();
|
||||||
void profilingSummary() const;
|
void profilingSummary() const;
|
||||||
void profilingReport(const char *what, const PluginSpec *spec = 0);
|
void profilingReport(const char *what, const PluginSpec *spec = 0);
|
||||||
|
@@ -86,6 +86,8 @@
|
|||||||
Dependency is not necessarily needed. You need to make sure that
|
Dependency is not necessarily needed. You need to make sure that
|
||||||
the plugin is able to load without this dependency installed, so
|
the plugin is able to load without this dependency installed, so
|
||||||
for example you may not link to the dependency's library.
|
for example you may not link to the dependency's library.
|
||||||
|
\value Test
|
||||||
|
Dependency needs to be force-loaded for running tests of the plugin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -471,6 +473,7 @@ namespace {
|
|||||||
const char DEPENDENCY_TYPE[] = "Type";
|
const char DEPENDENCY_TYPE[] = "Type";
|
||||||
const char DEPENDENCY_TYPE_SOFT[] = "optional";
|
const char DEPENDENCY_TYPE_SOFT[] = "optional";
|
||||||
const char DEPENDENCY_TYPE_HARD[] = "required";
|
const char DEPENDENCY_TYPE_HARD[] = "required";
|
||||||
|
const char DEPENDENCY_TYPE_TEST[] = "test";
|
||||||
const char ARGUMENTS[] = "Arguments";
|
const char ARGUMENTS[] = "Arguments";
|
||||||
const char ARGUMENT_NAME[] = "Name";
|
const char ARGUMENT_NAME[] = "Name";
|
||||||
const char ARGUMENT_PARAMETER[] = "Parameter";
|
const char ARGUMENT_PARAMETER[] = "Parameter";
|
||||||
@@ -763,6 +766,8 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &metaData)
|
|||||||
dep.type = PluginDependency::Required;
|
dep.type = PluginDependency::Required;
|
||||||
} else if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_SOFT)) {
|
} else if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_SOFT)) {
|
||||||
dep.type = PluginDependency::Optional;
|
dep.type = PluginDependency::Optional;
|
||||||
|
} else if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_TEST)) {
|
||||||
|
dep.type = PluginDependency::Test;
|
||||||
} else {
|
} else {
|
||||||
return reportError(tr("Dependency: \"%1\" must be \"%2\" or \"%3\" (is \"%4\")")
|
return reportError(tr("Dependency: \"%1\" must be \"%2\" or \"%3\" (is \"%4\")")
|
||||||
.arg(QLatin1String(DEPENDENCY_TYPE),
|
.arg(QLatin1String(DEPENDENCY_TYPE),
|
||||||
@@ -917,7 +922,7 @@ void PluginSpecPrivate::disableIndirectlyIfDependencyDisabled()
|
|||||||
QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs);
|
QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
if (it.key().type == PluginDependency::Optional)
|
if (it.key().type != PluginDependency::Required)
|
||||||
continue;
|
continue;
|
||||||
PluginSpec *dependencySpec = it.value();
|
PluginSpec *dependencySpec = it.value();
|
||||||
if (!dependencySpec->isEffectivelyEnabled()) {
|
if (!dependencySpec->isEffectivelyEnabled()) {
|
||||||
|
@@ -55,7 +55,8 @@ struct EXTENSIONSYSTEM_EXPORT PluginDependency
|
|||||||
{
|
{
|
||||||
enum Type {
|
enum Type {
|
||||||
Required,
|
Required,
|
||||||
Optional
|
Optional,
|
||||||
|
Test
|
||||||
};
|
};
|
||||||
|
|
||||||
PluginDependency() : type(Required) {}
|
PluginDependency() : type(Required) {}
|
||||||
|
@@ -16,6 +16,10 @@ QtcPlugin {
|
|||||||
|
|
||||||
Depends { name: "app_version_header" }
|
Depends { name: "app_version_header" }
|
||||||
|
|
||||||
|
pluginTestDepends: [
|
||||||
|
"QmakeProjectManager",
|
||||||
|
]
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
"cppautocompleter.cpp", "cppautocompleter.h",
|
"cppautocompleter.cpp", "cppautocompleter.h",
|
||||||
"cppcanonicalsymbol.cpp", "cppcanonicalsymbol.h",
|
"cppcanonicalsymbol.cpp", "cppcanonicalsymbol.h",
|
||||||
|
@@ -9,3 +9,5 @@ QTC_PLUGIN_DEPENDS += \
|
|||||||
coreplugin \
|
coreplugin \
|
||||||
cpptools \
|
cpptools \
|
||||||
projectexplorer
|
projectexplorer
|
||||||
|
QTC_TEST_DEPENDS += \
|
||||||
|
qmakeprojectmanager
|
||||||
|
@@ -14,6 +14,11 @@ QtcPlugin {
|
|||||||
Depends { name: "ProjectExplorer" }
|
Depends { name: "ProjectExplorer" }
|
||||||
Depends { name: "app_version_header" }
|
Depends { name: "app_version_header" }
|
||||||
|
|
||||||
|
pluginTestDepends: [
|
||||||
|
"CppEditor",
|
||||||
|
"QmakeProjectManager",
|
||||||
|
]
|
||||||
|
|
||||||
cpp.defines: base
|
cpp.defines: base
|
||||||
Properties {
|
Properties {
|
||||||
condition: qbs.toolchain.contains("msvc")
|
condition: qbs.toolchain.contains("msvc")
|
||||||
|
@@ -8,3 +8,6 @@ QTC_PLUGIN_DEPENDS += \
|
|||||||
coreplugin \
|
coreplugin \
|
||||||
projectexplorer \
|
projectexplorer \
|
||||||
texteditor
|
texteditor
|
||||||
|
QTC_TEST_DEPENDS += \
|
||||||
|
cppeditor \
|
||||||
|
qmakeprojectmanager
|
||||||
|
@@ -10,6 +10,7 @@ exists($$depfile) {
|
|||||||
TARGET = $$QTC_PLUGIN_NAME
|
TARGET = $$QTC_PLUGIN_NAME
|
||||||
|
|
||||||
plugin_deps = $$QTC_PLUGIN_DEPENDS
|
plugin_deps = $$QTC_PLUGIN_DEPENDS
|
||||||
|
plugin_test_deps = $$QTC_TEST_DEPENDS
|
||||||
plugin_recmds = $$QTC_PLUGIN_RECOMMENDS
|
plugin_recmds = $$QTC_PLUGIN_RECOMMENDS
|
||||||
|
|
||||||
include(../qtcreator.pri)
|
include(../qtcreator.pri)
|
||||||
@@ -36,6 +37,9 @@ for(dep, plugin_deps) {
|
|||||||
for(dep, plugin_recmds) {
|
for(dep, plugin_recmds) {
|
||||||
dependencyList += " { \"Name\" : \"$$dependencyName($$dep)\", \"Version\" : \"$$QTCREATOR_VERSION\", \"Type\" : \"optional\" }"
|
dependencyList += " { \"Name\" : \"$$dependencyName($$dep)\", \"Version\" : \"$$QTCREATOR_VERSION\", \"Type\" : \"optional\" }"
|
||||||
}
|
}
|
||||||
|
for(dep, plugin_test_deps) {
|
||||||
|
dependencyList += " { \"Name\" : \"$$dependencyName($$dep)\", \"Version\" : \"$$QTCREATOR_VERSION\", \"Type\" : \"test\" }"
|
||||||
|
}
|
||||||
dependencyList = $$join(dependencyList, ",$$escape_expand(\\n)")
|
dependencyList = $$join(dependencyList, ",$$escape_expand(\\n)")
|
||||||
|
|
||||||
dependencyList = "\"Dependencies\" : [$$escape_expand(\\n)$$dependencyList$$escape_expand(\\n) ]"
|
dependencyList = "\"Dependencies\" : [$$escape_expand(\\n)$$dependencyList$$escape_expand(\\n) ]"
|
||||||
|
Reference in New Issue
Block a user