mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
add test that class loader is properly configured if one plugin depends on another one
GitOrigin-RevId: ef32f6f4272d0c3683eed3cc4c2ae398fb3b43cd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
21f426e155
commit
af4666ea5b
@@ -1133,8 +1133,10 @@ public final class PluginManagerCore {
|
||||
public static List<? extends IdeaPluginDescriptor> testLoadDescriptorsFromDir(@NotNull Path dir)
|
||||
throws ExecutionException, InterruptedException {
|
||||
PluginLoadingResult result = new PluginLoadingResult(Collections.emptyMap());
|
||||
loadDescriptorsFromDir(dir, result, true, new DescriptorListLoadingContext(0, Collections.emptySet(), result));
|
||||
loadDescriptorsFromDir(dir, result, true, DescriptorListLoadingContext.createSingleDescriptorContext(Collections.emptySet()));
|
||||
result.finishLoading();
|
||||
|
||||
initializePlugins(result, UrlClassLoader.build().get(), false, true);
|
||||
return result.plugins;
|
||||
}
|
||||
|
||||
@@ -1620,7 +1622,7 @@ public final class PluginManagerCore {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
static void initializePlugins(@NotNull PluginLoadingResult loadResult, @NotNull ClassLoader coreLoader, boolean checkEssentialPlugins) {
|
||||
static void initializePlugins(@NotNull PluginLoadingResult loadResult, @NotNull ClassLoader coreLoader, boolean checkEssentialPlugins, boolean usePluginClassLoader) {
|
||||
List<String> errors = new ArrayList<>(loadResult.errors);
|
||||
Map<PluginId, IdeaPluginDescriptorImpl> idMap = loadResult.idMap;
|
||||
|
||||
@@ -1631,7 +1633,7 @@ public final class PluginManagerCore {
|
||||
}
|
||||
|
||||
IdeaPluginDescriptorImpl coreDescriptor = idMap.get(CORE_ID);
|
||||
if (coreDescriptor == null) {
|
||||
if (checkEssentialPlugins && coreDescriptor == null) {
|
||||
throw new EssentialPluginMissingException(Collections.singletonList(CORE_ID + " (platform prefix: " + System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY) + ")"));
|
||||
}
|
||||
|
||||
@@ -1674,7 +1676,7 @@ public final class PluginManagerCore {
|
||||
}
|
||||
|
||||
mergeOptionalConfigs(enabledPlugins, idMap);
|
||||
configureClassLoaders(coreLoader, graph, coreDescriptor, enabledPlugins);
|
||||
configureClassLoaders(coreLoader, graph, coreDescriptor, enabledPlugins, usePluginClassLoader);
|
||||
|
||||
if (checkEssentialPlugins) {
|
||||
checkEssentialPluginsAreAvailable(idMap);
|
||||
@@ -1685,8 +1687,9 @@ public final class PluginManagerCore {
|
||||
|
||||
private static void configureClassLoaders(@NotNull ClassLoader coreLoader,
|
||||
@NotNull CachingSemiGraph<IdeaPluginDescriptorImpl> graph,
|
||||
@NotNull IdeaPluginDescriptor coreDescriptor,
|
||||
@NotNull List<IdeaPluginDescriptorImpl> enabledPlugins) {
|
||||
@Nullable IdeaPluginDescriptor coreDescriptor,
|
||||
@NotNull List<IdeaPluginDescriptorImpl> enabledPlugins,
|
||||
boolean usePluginClassLoader) {
|
||||
ArrayList<ClassLoader> loaders = new ArrayList<>();
|
||||
ClassLoader[] emptyClassLoaderArray = new ClassLoader[0];
|
||||
for (IdeaPluginDescriptorImpl rootDescriptor : enabledPlugins) {
|
||||
@@ -1695,7 +1698,7 @@ public final class PluginManagerCore {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isUnitTestMode && !ourUnitTestWithBundledPlugins) {
|
||||
if (!usePluginClassLoader) {
|
||||
rootDescriptor.setLoader(null);
|
||||
continue;
|
||||
}
|
||||
@@ -1876,7 +1879,7 @@ public final class PluginManagerCore {
|
||||
try {
|
||||
Activity loadPluginsActivity = StartUpMeasurer.startActivity("plugin initialization");
|
||||
result = loadDescriptors(isRunningFromSources());
|
||||
initializePlugins(result, coreLoader, !isUnitTestMode);
|
||||
initializePlugins(result, coreLoader, !isUnitTestMode, !isUnitTestMode || ourUnitTestWithBundledPlugins);
|
||||
|
||||
ourPlugins = result.getSortedPlugins();
|
||||
if (!result.incompletePlugins.isEmpty()) {
|
||||
|
||||
@@ -13,8 +13,10 @@ import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
@@ -33,7 +35,9 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
*/
|
||||
public final class PluginClassLoader extends UrlClassLoader {
|
||||
static {
|
||||
if (registerAsParallelCapable()) markParallelCapable(PluginClassLoader.class);
|
||||
if (registerAsParallelCapable()) {
|
||||
markParallelCapable(PluginClassLoader.class);
|
||||
}
|
||||
}
|
||||
|
||||
private final ClassLoader[] myParents;
|
||||
@@ -422,4 +426,12 @@ public final class PluginClassLoader extends UrlClassLoader {
|
||||
return myEnumerations[myIndex].nextElement();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@TestOnly
|
||||
@ApiStatus.Internal
|
||||
public List<ClassLoader> _getParents() {
|
||||
//noinspection SSBasedInspection
|
||||
return Collections.unmodifiableList(Arrays.asList(myParents));
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
import com.intellij.ide.plugins.cl.PluginClassLoader
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
@@ -15,11 +16,11 @@ import com.intellij.util.io.write
|
||||
import com.intellij.util.lang.UrlClassLoader
|
||||
import junit.framework.TestCase
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Files
|
||||
@@ -125,8 +126,7 @@ class PluginDescriptorTest {
|
||||
urls.add(path.toUri().toURL())
|
||||
}
|
||||
}
|
||||
val descriptors = PluginManagerCore.testLoadDescriptorsFromClassPath(
|
||||
URLClassLoader(urls.toTypedArray(), null))
|
||||
val descriptors = PluginManagerCore.testLoadDescriptorsFromClassPath(URLClassLoader(urls.toTypedArray(), null))
|
||||
// core and com.intellij.workspace
|
||||
assertThat(descriptors).hasSize(1)
|
||||
}
|
||||
@@ -135,8 +135,7 @@ class PluginDescriptorTest {
|
||||
@Throws(Exception::class)
|
||||
fun testProduction2() {
|
||||
assumeTrue(SystemInfo.isMac && !UsefulTestCase.IS_UNDER_TEAMCITY)
|
||||
val descriptors = PluginManagerCore.testLoadDescriptorsFromDir(
|
||||
Paths.get("/Volumes/data/plugins"))
|
||||
val descriptors = PluginManagerCore.testLoadDescriptorsFromDir(Paths.get("/Volumes/data/plugins"))
|
||||
assertThat(descriptors).isNotEmpty()
|
||||
}
|
||||
|
||||
@@ -158,7 +157,6 @@ class PluginDescriptorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(IOException::class)
|
||||
fun releaseDate() {
|
||||
val pluginFile = inMemoryFs.fs.getPath("plugin/META-INF/plugin.xml")
|
||||
pluginFile.write("""
|
||||
@@ -173,6 +171,63 @@ class PluginDescriptorTest {
|
||||
assertThat(SimpleDateFormat("yyyyMMdd", Locale.US).format(descriptor.releaseDate)).isEqualTo("20190811")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun classLoader() {
|
||||
val pluginDir = inMemoryFs.fs.getPath("/plugins")
|
||||
writeDescriptor("foo", pluginDir, """
|
||||
<idea-plugin>
|
||||
<id>foo</id>
|
||||
<depends>bar</depends>
|
||||
<vendor>JetBrains</vendor>
|
||||
</idea-plugin>""")
|
||||
writeDescriptor("bar", pluginDir, """
|
||||
<idea-plugin>
|
||||
<id>bar</id>
|
||||
<vendor>JetBrains</vendor>
|
||||
</idea-plugin>""")
|
||||
|
||||
checkClassLoader(pluginDir)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `classLoader - optional dependency`() {
|
||||
val pluginDir = inMemoryFs.fs.getPath("/plugins")
|
||||
writeDescriptor("foo", pluginDir, """
|
||||
<idea-plugin>
|
||||
<id>foo</id>
|
||||
<depends optional="true" config-file="stream-debugger.xml">bar</depends>
|
||||
<vendor>JetBrains</vendor>
|
||||
</idea-plugin>""")
|
||||
|
||||
pluginDir.resolve("foo/META-INF/stream-debugger.xml").write("""
|
||||
<idea-plugin>
|
||||
<actions>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
""".trimIndent())
|
||||
|
||||
writeDescriptor("bar", pluginDir, """
|
||||
<idea-plugin>
|
||||
<id>bar</id>
|
||||
<vendor>JetBrains</vendor>
|
||||
</idea-plugin>""")
|
||||
|
||||
checkClassLoader(pluginDir)
|
||||
}
|
||||
|
||||
private fun checkClassLoader(pluginDir: Path) {
|
||||
val list = PluginManagerCore.testLoadDescriptorsFromDir(pluginDir)
|
||||
assertThat(list).hasSize(2)
|
||||
|
||||
val bar = list[0]
|
||||
assertThat(bar.pluginId.idString).isEqualTo("bar")
|
||||
|
||||
val foo = list[1]
|
||||
assertThat(foo.pluginId.idString).isEqualTo("foo")
|
||||
val fooClassLoader = foo.pluginClassLoader as PluginClassLoader
|
||||
assertThat(fooClassLoader._getParents()).containsExactly(bar.pluginClassLoader)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun componentConfig() {
|
||||
val pluginFile = inMemoryFs.fs.getPath("/plugin/META-INF/plugin.xml")
|
||||
@@ -243,4 +298,8 @@ class PluginDescriptorTest {
|
||||
TestCase.assertEquals(impl1.hashCode(), impl2.hashCode())
|
||||
TestCase.assertNotSame(impl1.name, impl2.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeDescriptor(id: String, pluginDir: Path, @Language("xml") data: String) {
|
||||
pluginDir.resolve("$id/META-INF/plugin.xml").write(data.trimIndent())
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public class PluginManagerTest {
|
||||
private static void doPluginSortTest(@NotNull String testDataName, boolean isBundled) throws IOException, JDOMException {
|
||||
PluginManagerCore.ourPluginError = null;
|
||||
PluginLoadingResult loadPluginResult = loadDescriptors(testDataName + ".xml", isBundled);
|
||||
PluginManagerCore.initializePlugins(loadPluginResult, PluginManagerTest.class.getClassLoader(), /* checkEssentialPlugins = */ false);
|
||||
PluginManagerCore.initializePlugins(loadPluginResult, PluginManagerTest.class.getClassLoader(), /* checkEssentialPlugins = */ false, false);
|
||||
String actual = StringUtil.join(loadPluginResult.getSortedPlugins(), o -> (o.isEnabled() ? "+ " : " ") + o.getPluginId().getIdString(), "\n") +
|
||||
"\n\n" + StringUtil.notNullize(PluginManagerCore.ourPluginError).replace("<p/>", "\n");
|
||||
PluginManagerCore.ourPluginError = null;
|
||||
|
||||
Reference in New Issue
Block a user