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); + } + } + } + } +}