From 8803b53ca8aabdd3284927ea7783514ec6a58947 Mon Sep 17 00:00:00 2001 From: "taylor.smock" Date: Thu, 5 Sep 2024 16:38:11 +0000 Subject: [PATCH] Add @Plugins annotation to clean up after plugins have been loaded in tests This should help reduce the issues related to plugins not being unloaded after PluginHandlerTestIT when tests are run locally with a UI -- the primary cause of problems is the SDS plugin though. git-svn-id: https://josm.openstreetmap.de/svn/trunk@19209 0c6e7542-c601-0410-84e7-c038aed88b3b --- .../josm/gui/MainApplicationTest.java | 2 + .../josm/plugins/PluginHandlerTestIT.java | 4 ++ .../josm/testutils/annotations/Plugins.java | 62 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 test/unit/org/openstreetmap/josm/testutils/annotations/Plugins.java diff --git a/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java b/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java index 8a33fa5091c..f95fa849199 100644 --- a/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java +++ b/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java @@ -57,6 +57,7 @@ import org.openstreetmap.josm.testutils.annotations.HTTPS; import org.openstreetmap.josm.testutils.annotations.Main; import org.openstreetmap.josm.testutils.annotations.OsmApi; +import org.openstreetmap.josm.testutils.annotations.Plugins; import org.openstreetmap.josm.testutils.annotations.Projection; import org.openstreetmap.josm.tools.Logging; import org.openstreetmap.josm.tools.PlatformManager; @@ -170,6 +171,7 @@ void testParamType() { * Test of {@link MainApplication#updateAndLoadEarlyPlugins} and {@link MainApplication#loadLatePlugins} methods. * @throws PluginListParseException if an error occurs */ + @Plugins @Test void testUpdateAndLoadPlugins() throws PluginListParseException { final String old = System.getProperty("josm.plugins"); diff --git a/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTestIT.java b/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTestIT.java index ee3f52da1c8..b3108b5ff02 100644 --- a/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTestIT.java +++ b/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTestIT.java @@ -42,8 +42,10 @@ import org.openstreetmap.josm.testutils.annotations.BasicPreferences; import org.openstreetmap.josm.testutils.annotations.HTTPS; import org.openstreetmap.josm.testutils.annotations.Main; +import org.openstreetmap.josm.testutils.annotations.Plugins; import org.openstreetmap.josm.testutils.annotations.Projection; import org.openstreetmap.josm.testutils.annotations.Territories; +import org.openstreetmap.josm.testutils.annotations.ThreadSync; import org.openstreetmap.josm.tools.Destroyable; import org.openstreetmap.josm.tools.Logging; import org.openstreetmap.josm.tools.Utils; @@ -57,6 +59,8 @@ @Projection @Territories @Timeout(value = 10, unit = TimeUnit.MINUTES) +@ThreadSync +@Plugins public class PluginHandlerTestIT { private static final List errorsToIgnore = new ArrayList<>(); diff --git a/test/unit/org/openstreetmap/josm/testutils/annotations/Plugins.java b/test/unit/org/openstreetmap/josm/testutils/annotations/Plugins.java new file mode 100644 index 00000000000..ee73fdc2b97 --- /dev/null +++ b/test/unit/org/openstreetmap/josm/testutils/annotations/Plugins.java @@ -0,0 +1,62 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.testutils.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.openstreetmap.josm.io.AbstractReader; +import org.openstreetmap.josm.io.OsmServerReadPostprocessor; +import org.openstreetmap.josm.plugins.PluginHandler; +import org.openstreetmap.josm.plugins.PluginInformation; +import org.openstreetmap.josm.tools.Destroyable; + +/** + * Cleanup plugins if they've been loaded + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(Plugins.PluginExtension.class) +public @interface Plugins { + /** + * The extension to clean up after plugin installs + */ + class PluginExtension implements AfterEachCallback { + + @Override + public void afterEach(ExtensionContext context) throws Exception { + // We want to clean up as much as possible using "standard" methods + for (PluginInformation plugin : PluginHandler.getPlugins()) { + Object root = PluginHandler.getPlugin(plugin.name); + if (root instanceof Destroyable) { + ((Destroyable) root).destroy(); + PluginHandler.removePlugins(Collections.singletonList(plugin)); + } + } + final Field pluginListField = PluginHandler.class.getDeclaredField("pluginList"); + final Field classLoadersField = PluginHandler.class.getDeclaredField("classLoaders"); + final Field postprocessorsField = AbstractReader.class.getDeclaredField("postprocessors"); + org.openstreetmap.josm.tools.ReflectionUtils.setObjectsAccessible(classLoadersField, postprocessorsField, + pluginListField); + ((List) pluginListField.get(null)).clear(); + ((Map) classLoadersField.get(null)).clear(); + // Needed due to SDS + final Object postprocessors = postprocessorsField.get(null); + if (postprocessors instanceof Collection) { + for (OsmServerReadPostprocessor pp : new ArrayList<>((Collection) postprocessors)) { + AbstractReader.deregisterPostprocessor(pp); + } + } + } + } +}