source: josm/trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTestIT.java @ 12842

Last change on this file since 12842 was 12842, checked in by bastiK, 15 months ago

see #15229 - fix test deprecations

File size: 7.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins;
3
4import static org.junit.Assert.assertEquals;
5import static org.junit.Assert.assertFalse;
6import static org.junit.Assert.assertTrue;
7
8import java.util.Arrays;
9import java.util.Collection;
10import java.util.HashMap;
11import java.util.Iterator;
12import java.util.List;
13import java.util.Map;
14import java.util.Set;
15import java.util.function.Consumer;
16import java.util.stream.Collectors;
17
18import org.apache.commons.collections.MapUtils;
19import org.apache.commons.lang.exception.ExceptionUtils;
20import org.junit.Rule;
21import org.junit.Test;
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.data.gpx.GpxData;
24import org.openstreetmap.josm.data.osm.DataSet;
25import org.openstreetmap.josm.gui.MainApplication;
26import org.openstreetmap.josm.gui.layer.GpxLayer;
27import org.openstreetmap.josm.gui.layer.Layer;
28import org.openstreetmap.josm.gui.layer.OsmDataLayer;
29import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
30import org.openstreetmap.josm.testutils.JOSMTestRules;
31
32import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
33
34/**
35 * Integration tests of {@link PluginHandler} class.
36 */
37public class PluginHandlerTestIT {
38
39    /**
40     * Setup test.
41     */
42    @Rule
43    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
44    public JOSMTestRules test = new JOSMTestRules().platform().main().projection().timeout(10*60*1000);
45
46    /**
47     * Test that available plugins rules can be loaded.
48     */
49    @Test
50    public void testValidityOfAvailablePlugins() {
51        // Download complete list of plugins
52        ReadRemotePluginInformationTask pluginInfoDownloadTask = new ReadRemotePluginInformationTask(
53                Main.pref.getOnlinePluginSites());
54        pluginInfoDownloadTask.run();
55        List<PluginInformation> plugins = pluginInfoDownloadTask.getAvailablePlugins();
56        System.out.println("Original plugin list contains " + plugins.size() + " plugins");
57        assertFalse(plugins.isEmpty());
58        PluginInformation info = plugins.get(0);
59        assertFalse(info.getName().isEmpty());
60        assertFalse(info.getClass().getName().isEmpty());
61
62        // Filter deprecated and unmaintained ones, or those not responsive enough to match our continuous integration needs
63        List<String> uncooperatingPlugins = Arrays.asList("ebdirigo", "scoutsigns", "josm-config");
64        Set<String> deprecatedPlugins = PluginHandler.getDeprecatedAndUnmaintainedPlugins();
65        for (Iterator<PluginInformation> it = plugins.iterator(); it.hasNext();) {
66            PluginInformation pi = it.next();
67            if (deprecatedPlugins.contains(pi.name) || uncooperatingPlugins.contains(pi.name)) {
68                System.out.println("Ignoring " + pi.name + " (deprecated, unmaintained, or uncooperative)");
69                it.remove();
70            }
71        }
72        System.out.println("Filtered plugin list contains " + plugins.size() + " plugins");
73
74        // Download plugins
75        downloadPlugins(plugins);
76
77        // Load early plugins
78        PluginHandler.loadEarlyPlugins(null, plugins, null);
79
80        // Load late plugins
81        PluginHandler.loadLatePlugins(null, plugins, null);
82
83        Map<String, Throwable> loadingExceptions = PluginHandler.pluginLoadingExceptions.entrySet().stream()
84                .collect(Collectors.toMap(e -> e.getKey(), e -> ExceptionUtils.getRootCause(e.getValue())));
85
86        // Add/remove layers twice to test basic plugin good behaviour
87        Map<String, Throwable> layerExceptions = new HashMap<>();
88        List<PluginInformation> loadedPlugins = PluginHandler.getPlugins();
89        for (int i = 0; i < 2; i++) {
90            OsmDataLayer layer = new OsmDataLayer(new DataSet(), "Layer "+i, null);
91            testPlugin(MainApplication.getLayerManager()::addLayer, layer, layerExceptions, loadedPlugins);
92            testPlugin(MainApplication.getLayerManager()::removeLayer, layer, layerExceptions, loadedPlugins);
93        }
94        for (int i = 0; i < 2; i++) {
95            GpxLayer layer = new GpxLayer(new GpxData());
96            testPlugin(MainApplication.getLayerManager()::addLayer, layer, layerExceptions, loadedPlugins);
97            testPlugin(MainApplication.getLayerManager()::removeLayer, layer, layerExceptions, loadedPlugins);
98        }
99
100        MapUtils.debugPrint(System.out, null, loadingExceptions);
101        MapUtils.debugPrint(System.out, null, layerExceptions);
102        String msg = Arrays.toString(loadingExceptions.entrySet().toArray()) + '\n' +
103                     Arrays.toString(layerExceptions.entrySet().toArray());
104        assertTrue(msg, loadingExceptions.isEmpty() && layerExceptions.isEmpty());
105    }
106
107    void testPlugin(Consumer<Layer> consumer, Layer layer,
108            Map<String, Throwable> layerExceptions, Collection<PluginInformation> loadedPlugins) {
109        try {
110            consumer.accept(layer);
111        } catch (Exception | LinkageError t) {
112            Throwable root = ExceptionUtils.getRootCause(t);
113            root.printStackTrace();
114            layerExceptions.put(findFaultyPlugin(loadedPlugins, root), root);
115        }
116    }
117
118    private static String findFaultyPlugin(Collection<PluginInformation> plugins, Throwable root) {
119        for (PluginInformation p : plugins) {
120            try {
121                ClassLoader cl = PluginHandler.getPluginClassLoader(p.getName());
122                String pluginPackage = cl.loadClass(p.className).getPackage().getName();
123                for (StackTraceElement e : root.getStackTrace()) {
124                    try {
125                        String stackPackage = cl.loadClass(e.getClassName()).getPackage().getName();
126                        if (stackPackage.startsWith(pluginPackage)) {
127                            return p.name;
128                        }
129                    } catch (ClassNotFoundException ex) {
130                        System.err.println(ex.getMessage());
131                        continue;
132                    }
133                }
134            } catch (ClassNotFoundException ex) {
135                System.err.println(ex.getMessage());
136                continue;
137            }
138        }
139        return "<unknown>";
140    }
141
142    /**
143     * Download plugins
144     * @param plugins plugins to download
145     */
146    public static void downloadPlugins(Collection<PluginInformation> plugins) {
147        // Update the locally installed plugins
148        PluginDownloadTask pluginDownloadTask = new PluginDownloadTask(NullProgressMonitor.INSTANCE, plugins, null);
149        // Increase default timeout to avoid random network errors on big jar files
150        int defTimeout = Main.pref.getInt("socket.timeout.read", 30);
151        Main.pref.putInt("socket.timeout.read", 2 * defTimeout);
152        pluginDownloadTask.run();
153        // Restore default timeout
154        Main.pref.putInt("socket.timeout.read", defTimeout);
155        assertTrue(pluginDownloadTask.getFailedPlugins().toString(), pluginDownloadTask.getFailedPlugins().isEmpty());
156        assertEquals(plugins.size(), pluginDownloadTask.getDownloadedPlugins().size());
157
158        // Update Plugin info for downloaded plugins
159        PluginHandler.refreshLocalUpdatedPluginInfo(pluginDownloadTask.getDownloadedPlugins());
160    }
161}
Note: See TracBrowser for help on using the repository browser.