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

Last change on this file since 14219 was 14149, checked in by Don-vip, 6 years ago

see #15229 - deprecate Main.pref

File size: 7.9 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.lang3.exception.ExceptionUtils;
19import org.junit.Rule;
20import org.junit.Test;
21import org.openstreetmap.josm.data.Preferences;
22import org.openstreetmap.josm.data.gpx.GpxData;
23import org.openstreetmap.josm.data.osm.DataSet;
24import org.openstreetmap.josm.gui.MainApplication;
25import org.openstreetmap.josm.gui.layer.GpxLayer;
26import org.openstreetmap.josm.gui.layer.Layer;
27import org.openstreetmap.josm.gui.layer.OsmDataLayer;
28import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
29import org.openstreetmap.josm.spi.preferences.Config;
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().main().projection().preferences().timeout(10*60*1000);
45
46 /**
47 * Test that available plugins rules can be loaded.
48 */
49 @Test
50 public void testValidityOfAvailablePlugins() {
51 loadAllPlugins();
52
53 Map<String, Throwable> loadingExceptions = PluginHandler.pluginLoadingExceptions.entrySet().stream()
54 .collect(Collectors.toMap(e -> e.getKey(), e -> ExceptionUtils.getRootCause(e.getValue())));
55
56 List<PluginInformation> loadedPlugins = PluginHandler.getPlugins();
57 Map<String, List<String>> invalidManifestEntries = loadedPlugins.stream().filter(pi -> !pi.invalidManifestEntries.isEmpty())
58 .collect(Collectors.toMap(pi -> pi.name, pi -> pi.invalidManifestEntries));
59
60 // Add/remove layers twice to test basic plugin good behaviour
61 Map<String, Throwable> layerExceptions = new HashMap<>();
62 for (int i = 0; i < 2; i++) {
63 OsmDataLayer layer = new OsmDataLayer(new DataSet(), "Layer "+i, null);
64 testPlugin(MainApplication.getLayerManager()::addLayer, layer, layerExceptions, loadedPlugins);
65 testPlugin(MainApplication.getLayerManager()::removeLayer, layer, layerExceptions, loadedPlugins);
66 }
67 for (int i = 0; i < 2; i++) {
68 GpxLayer layer = new GpxLayer(new GpxData(), "Layer "+i);
69 testPlugin(MainApplication.getLayerManager()::addLayer, layer, layerExceptions, loadedPlugins);
70 testPlugin(MainApplication.getLayerManager()::removeLayer, layer, layerExceptions, loadedPlugins);
71 }
72
73 debugPrint(invalidManifestEntries);
74 debugPrint(loadingExceptions);
75 debugPrint(layerExceptions);
76 String msg = Arrays.toString(invalidManifestEntries.entrySet().toArray()) + '\n' +
77 Arrays.toString(loadingExceptions.entrySet().toArray()) + '\n' +
78 Arrays.toString(layerExceptions.entrySet().toArray());
79 assertTrue(msg, invalidManifestEntries.isEmpty() && loadingExceptions.isEmpty() && layerExceptions.isEmpty());
80 }
81
82 private static void debugPrint(Map<String, ?> invalidManifestEntries) {
83 System.out.println(invalidManifestEntries.entrySet()
84 .stream()
85 .map(e -> e.getKey() + "=\"" + e.getValue() + "\"")
86 .collect(Collectors.joining(", ")));
87 }
88
89 /**
90 * Downloads and loads all JOSM plugins.
91 */
92 public static void loadAllPlugins() {
93 // Download complete list of plugins
94 ReadRemotePluginInformationTask pluginInfoDownloadTask = new ReadRemotePluginInformationTask(
95 Preferences.main().getOnlinePluginSites());
96 pluginInfoDownloadTask.run();
97 List<PluginInformation> plugins = pluginInfoDownloadTask.getAvailablePlugins();
98 System.out.println("Original plugin list contains " + plugins.size() + " plugins");
99 assertFalse(plugins.isEmpty());
100 PluginInformation info = plugins.get(0);
101 assertFalse(info.getName().isEmpty());
102 assertFalse(info.getClass().getName().isEmpty());
103
104 // Filter deprecated and unmaintained ones, or those not responsive enough to match our continuous integration needs
105 List<String> uncooperatingPlugins = Arrays.asList("ebdirigo", "scoutsigns", "josm-config");
106 Set<String> deprecatedPlugins = PluginHandler.getDeprecatedAndUnmaintainedPlugins();
107 for (Iterator<PluginInformation> it = plugins.iterator(); it.hasNext();) {
108 PluginInformation pi = it.next();
109 if (deprecatedPlugins.contains(pi.name) || uncooperatingPlugins.contains(pi.name)) {
110 System.out.println("Ignoring " + pi.name + " (deprecated, unmaintained, or uncooperative)");
111 it.remove();
112 }
113 }
114 System.out.println("Filtered plugin list contains " + plugins.size() + " plugins");
115
116 // Download plugins
117 downloadPlugins(plugins);
118
119 // Load early plugins
120 PluginHandler.loadEarlyPlugins(null, plugins, null);
121
122 // Load late plugins
123 PluginHandler.loadLatePlugins(null, plugins, null);
124 }
125
126 void testPlugin(Consumer<Layer> consumer, Layer layer,
127 Map<String, Throwable> layerExceptions, Collection<PluginInformation> loadedPlugins) {
128 try {
129 consumer.accept(layer);
130 } catch (Exception | LinkageError t) {
131 Throwable root = ExceptionUtils.getRootCause(t);
132 root.printStackTrace();
133 layerExceptions.put(findFaultyPlugin(loadedPlugins, root), root);
134 }
135 }
136
137 private static String findFaultyPlugin(Collection<PluginInformation> plugins, Throwable root) {
138 for (PluginInformation p : plugins) {
139 try {
140 ClassLoader cl = PluginHandler.getPluginClassLoader(p.getName());
141 String pluginPackage = cl.loadClass(p.className).getPackage().getName();
142 for (StackTraceElement e : root.getStackTrace()) {
143 try {
144 String stackPackage = cl.loadClass(e.getClassName()).getPackage().getName();
145 if (stackPackage.startsWith(pluginPackage)) {
146 return p.name;
147 }
148 } catch (ClassNotFoundException ex) {
149 System.err.println(ex.getMessage());
150 continue;
151 }
152 }
153 } catch (ClassNotFoundException ex) {
154 System.err.println(ex.getMessage());
155 continue;
156 }
157 }
158 return "<unknown>";
159 }
160
161 /**
162 * Download plugins
163 * @param plugins plugins to download
164 */
165 public static void downloadPlugins(Collection<PluginInformation> plugins) {
166 // Update the locally installed plugins
167 PluginDownloadTask pluginDownloadTask = new PluginDownloadTask(NullProgressMonitor.INSTANCE, plugins, null);
168 // Increase default timeout to avoid random network errors on big jar files
169 int defTimeout = Config.getPref().getInt("socket.timeout.read", 30);
170 Config.getPref().putInt("socket.timeout.read", 2 * defTimeout);
171 pluginDownloadTask.run();
172 // Restore default timeout
173 Config.getPref().putInt("socket.timeout.read", defTimeout);
174 assertTrue(pluginDownloadTask.getFailedPlugins().toString(), pluginDownloadTask.getFailedPlugins().isEmpty());
175 assertEquals(plugins.size(), pluginDownloadTask.getDownloadedPlugins().size());
176
177 // Update Plugin info for downloaded plugins
178 PluginHandler.refreshLocalUpdatedPluginInfo(pluginDownloadTask.getDownloadedPlugins());
179 }
180}
Note: See TracBrowser for help on using the repository browser.