source: josm/trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerJOSMTooOldTest.java

Last change on this file was 19050, checked in by taylor.smock, 5 months ago

Revert most var changes from r19048, fix most new compile warnings and checkstyle issues

Also, document why various ErrorProne checks were originally disabled and fix
generic SonarLint issues.

  • Property svn:eol-style set to native
File size: 15.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins;
3
4import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
5import static org.junit.jupiter.api.Assertions.assertEquals;
6import static org.junit.jupiter.api.Assertions.assertFalse;
7import static org.junit.jupiter.api.Assertions.assertNotEquals;
8
9import java.io.File;
10import java.io.IOException;
11import java.nio.file.Files;
12import java.text.DecimalFormatSymbols;
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.Collections;
16import java.util.Comparator;
17import java.util.List;
18import java.util.stream.Collectors;
19
20import org.junit.jupiter.api.BeforeEach;
21import org.junit.jupiter.api.Test;
22import org.junit.jupiter.api.extension.RegisterExtension;
23import org.openstreetmap.josm.TestUtils;
24import org.openstreetmap.josm.data.Preferences;
25import org.openstreetmap.josm.gui.MainApplication;
26import org.openstreetmap.josm.spi.preferences.Config;
27import org.openstreetmap.josm.testutils.PluginServer;
28import org.openstreetmap.josm.testutils.annotations.AssumeRevision;
29import org.openstreetmap.josm.testutils.annotations.FullPreferences;
30import org.openstreetmap.josm.testutils.annotations.Main;
31import org.openstreetmap.josm.testutils.mockers.ExtendedDialogMocker;
32import org.openstreetmap.josm.testutils.mockers.HelpAwareOptionPaneMocker;
33
34import com.github.tomakehurst.wiremock.client.WireMock;
35import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
36
37/**
38 * Test parts of {@link PluginHandler} class when the reported JOSM version is too old for the plugin.
39 */
40@AssumeRevision("Revision: 6000\n")
41@FullPreferences
42@Main
43class PluginHandlerJOSMTooOldTest {
44 /**
45 * Plugin server mock.
46 */
47 @RegisterExtension
48 static WireMockExtension pluginServerRule = WireMockExtension.newInstance().options(
49 options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot())
50 ).build();
51
52 /**
53 * Setup test.
54 */
55 @BeforeEach
56 public void setUp() {
57 Config.getPref().putInt("pluginmanager.version", 999);
58 Config.getPref().put("pluginmanager.lastupdate", "999");
59 Config.getPref().putList("pluginmanager.sites",
60 Collections.singletonList(pluginServerRule.url("/plugins"))
61 );
62
63 this.referenceDummyJarOld = new File(TestUtils.getTestDataRoot(), "__files/plugin/dummy_plugin.v31701.jar");
64 this.referenceDummyJarNew = new File(TestUtils.getTestDataRoot(), "__files/plugin/dummy_plugin.v31772.jar");
65 this.referenceBazJarOld = new File(TestUtils.getTestDataRoot(), "__files/plugin/baz_plugin.v6.jar");
66 this.referenceBazJarNew = new File(TestUtils.getTestDataRoot(), "__files/plugin/baz_plugin.v7.jar");
67 this.referenceQuxJarOld = new File(TestUtils.getTestDataRoot(), "__files/" + referencePathQuxJarOld);
68 this.referenceQuxJarNewer = new File(TestUtils.getTestDataRoot(), "__files/" + referencePathQuxJarNewer);
69 this.pluginDir = Preferences.main().getPluginsDirectory();
70 this.targetDummyJar = new File(this.pluginDir, "dummy_plugin.jar");
71 this.targetDummyJarNew = new File(this.pluginDir, "dummy_plugin.jar.new");
72 this.targetBazJar = new File(this.pluginDir, "baz_plugin.jar");
73 this.targetBazJarNew = new File(this.pluginDir, "baz_plugin.jar.new");
74 this.targetQuxJar = new File(this.pluginDir, "qux_plugin.jar");
75 this.targetQuxJarNew = new File(this.pluginDir, "qux_plugin.jar.new");
76 this.pluginDir.mkdirs();
77 }
78
79 private static final String referencePathQuxJarOld = "plugin/qux_plugin.v345.jar";
80 private static final String referencePathQuxJarNewer = "plugin/qux_plugin.v432.jar";
81
82 private File pluginDir;
83 private File referenceDummyJarOld;
84 private File referenceDummyJarNew;
85 private File referenceBazJarOld;
86 private File referenceBazJarNew;
87 private File referenceQuxJarOld;
88 private File referenceQuxJarNewer;
89 private File targetDummyJar;
90 private File targetDummyJarNew;
91 private File targetBazJar;
92 private File targetBazJarNew;
93 private File targetQuxJar;
94 private File targetQuxJarNew;
95
96 private final String bazPluginVersionReqString = u202f("JOSM version 8\u202F001 required for plugin baz_plugin.");
97 private final String dummyPluginVersionReqString = u202f("JOSM version 7\u202F001 required for plugin dummy_plugin.");
98 private final String dummyPluginFailedString = "<html>Updating the following plugin has failed:<ul><li>dummy_plugin</li></ul>"
99 + "Please open the Preference Dialog after JOSM has started and try to update it manually.</html>";
100
101 private static String u202f(String s) {
102 return s.replace('\u202F', DecimalFormatSymbols.getInstance().getGroupingSeparator());
103 }
104
105 /**
106 * test update of plugins when those plugins turn out to require a higher JOSM version, but the
107 * user chooses to update them anyway.
108 * @throws IOException never
109 */
110 @Test
111 void testUpdatePluginsDownloadBoth() throws IOException {
112 TestUtils.assumeWorkingJMockit();
113 final PluginServer pluginServer = new PluginServer(
114 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
115 new PluginServer.RemotePlugin(this.referenceBazJarNew)
116 );
117 pluginServer.applyToWireMockServer(pluginServerRule.getRuntimeInfo());
118 Config.getPref().putList("plugins", Arrays.asList("dummy_plugin", "baz_plugin"));
119
120 final ExtendedDialogMocker edMocker = new ExtendedDialogMocker();
121 edMocker.getMockResultMap().put(this.bazPluginVersionReqString, "Download Plugin");
122 edMocker.getMockResultMap().put(this.dummyPluginVersionReqString, "Download Plugin");
123
124 Files.copy(this.referenceDummyJarOld.toPath(), this.targetDummyJar.toPath());
125 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
126
127 final List<PluginInformation> updatedPlugins = PluginHandler.updatePlugins(
128 MainApplication.getMainFrame(),
129 null,
130 null,
131 false
132 ).stream().sorted(Comparator.comparing(a -> a.name)).collect(Collectors.toList());
133
134 assertEquals(
135 Arrays.asList(
136 this.dummyPluginVersionReqString,
137 this.bazPluginVersionReqString
138 ),
139 edMocker.getInvocationLog().stream().map(
140 invocationEntry -> invocationEntry[1]
141 ).sorted().collect(Collectors.toList())
142 );
143
144 assertEquals(2, updatedPlugins.size());
145
146 assertEquals(updatedPlugins.get(0).name, "baz_plugin");
147 assertEquals("7", updatedPlugins.get(0).localversion);
148
149 assertEquals(updatedPlugins.get(1).name, "dummy_plugin");
150 assertEquals("31772", updatedPlugins.get(1).localversion);
151
152 assertFalse(targetDummyJarNew.exists());
153 assertFalse(targetBazJarNew.exists());
154
155 TestUtils.assertFileContentsEqual(this.referenceDummyJarNew, this.targetDummyJar);
156 TestUtils.assertFileContentsEqual(this.referenceBazJarNew, this.targetBazJar);
157
158 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
159 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
160 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v7.jar")));
161
162 assertEquals(Config.getPref().getInt("pluginmanager.version", 111), 6000);
163 // not mocking the time so just check it's not its original value
164 assertNotEquals(Config.getPref().get("pluginmanager.lastupdate", "999"), "999");
165 }
166
167 /**
168 * test update of plugins when those plugins turn out to require a higher JOSM version, but the
169 * user chooses to update one and skip the other.
170 * @throws IOException never
171 */
172 @Test
173 void testUpdatePluginsSkipOne() throws IOException {
174 TestUtils.assumeWorkingJMockit();
175 final PluginServer pluginServer = new PluginServer(
176 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
177 new PluginServer.RemotePlugin(this.referenceBazJarNew)
178 );
179 pluginServer.applyToWireMockServer(pluginServerRule.getRuntimeInfo());
180 Config.getPref().putList("plugins", Arrays.asList("dummy_plugin", "baz_plugin"));
181
182 final ExtendedDialogMocker edMocker = new ExtendedDialogMocker();
183 edMocker.getMockResultMap().put(this.bazPluginVersionReqString, "Download Plugin");
184 edMocker.getMockResultMap().put(this.dummyPluginVersionReqString, "Skip Download");
185 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker();
186 haMocker.getMockResultMap().put(this.dummyPluginFailedString, "OK");
187
188 Files.copy(this.referenceDummyJarOld.toPath(), this.targetDummyJar.toPath());
189 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
190
191 final List<PluginInformation> updatedPlugins = PluginHandler.updatePlugins(
192 MainApplication.getMainFrame(),
193 null,
194 null,
195 false
196 ).stream().sorted(Comparator.comparing(a -> a.name)).collect(Collectors.toList());
197
198 assertEquals(
199 Arrays.asList(
200 this.dummyPluginVersionReqString,
201 this.bazPluginVersionReqString
202 ),
203 edMocker.getInvocationLog().stream().map(
204 invocationEntry -> invocationEntry[1]
205 ).sorted().collect(Collectors.toList())
206 );
207
208 assertEquals(Collections.singletonList(this.dummyPluginFailedString),
209 haMocker.getInvocationLog().stream().map(
210 invocationEntry -> invocationEntry[1]
211 ).sorted().collect(Collectors.toList())
212 );
213
214 assertEquals(2, updatedPlugins.size());
215
216 assertEquals(updatedPlugins.get(0).name, "baz_plugin");
217 assertEquals("7", updatedPlugins.get(0).localversion);
218
219 assertEquals(updatedPlugins.get(1).name, "dummy_plugin");
220 assertEquals("31701", updatedPlugins.get(1).localversion);
221
222 assertFalse(targetDummyJarNew.exists());
223 assertFalse(targetBazJarNew.exists());
224
225 TestUtils.assertFileContentsEqual(this.referenceDummyJarOld, this.targetDummyJar);
226 TestUtils.assertFileContentsEqual(this.referenceBazJarNew, this.targetBazJar);
227
228 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
229 pluginServerRule.verify(0, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
230 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v7.jar")));
231
232 // shouldn't have been updated
233 assertEquals(Config.getPref().getInt("pluginmanager.version", 111), 999);
234 assertEquals(Config.getPref().get("pluginmanager.lastupdate", "999"), "999");
235 }
236
237 /**
238 * When the plugin list suggests that the jar file at the provided URL *doesn't* require a newer JOSM
239 * but in fact the plugin served *does*, it is installed anyway.
240 *
241 * This is probably NOT desirable and should be fixed, however this test documents the behaviour.
242 * @throws IOException never
243 */
244 @Test
245 void testUpdatePluginsUnexpectedlyJOSMTooOld() throws IOException {
246 TestUtils.assumeWorkingJMockit();
247 final PluginServer pluginServer = new PluginServer(
248 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
249 new PluginServer.RemotePlugin(this.referenceBazJarNew, Collections.singletonMap("Plugin-Mainversion", "5500"))
250 );
251 pluginServer.applyToWireMockServer(pluginServerRule.getRuntimeInfo());
252 Config.getPref().putList("plugins", Collections.singletonList("baz_plugin"));
253
254 // setting up blank ExtendedDialogMocker which would raise an exception if any attempt to show
255 // and ExtendedDialog were made
256 new ExtendedDialogMocker();
257
258 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
259
260 final List<PluginInformation> updatedPlugins = new ArrayList<>(PluginHandler.updatePlugins(
261 MainApplication.getMainFrame(),
262 null,
263 null,
264 false
265 ));
266
267 // questionably correct
268 assertEquals(1, updatedPlugins.size());
269
270 // questionably correct
271 assertEquals(updatedPlugins.get(0).name, "baz_plugin");
272 assertEquals("7", updatedPlugins.get(0).localversion);
273
274 assertFalse(targetBazJarNew.exists());
275
276 // questionably correct
277 TestUtils.assertFileContentsEqual(this.referenceBazJarNew, this.targetBazJar);
278
279 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
280 // questionably correct
281 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v7.jar")));
282
283 // should have been updated
284 assertEquals(Config.getPref().getInt("pluginmanager.version", 111), 6000);
285 assertNotEquals(Config.getPref().get("pluginmanager.lastupdate", "999"), "999");
286 }
287
288 /**
289 * When a plugin advertises several versions for compatibility with older JOSMs, but even the
290 * oldest of those is newer than our JOSM version, the user is prompted to upgrade to the newest
291 * version anyway.
292 *
293 * While this behaviour is not incorrect, it's probably less helpful than it could be - the
294 * version that's most likely to work best in this case will be the "oldest" still-available
295 * version, however this test documents the behaviour.
296 * @throws IOException never
297 */
298 @Test
299 @AssumeRevision("Revision: 7200\n")
300 void testUpdatePluginsMultiVersionInsufficient() throws IOException {
301 TestUtils.assumeWorkingJMockit();
302
303 final PluginServer pluginServer = new PluginServer(
304 new PluginServer.RemotePlugin(this.referenceBazJarOld),
305 new PluginServer.RemotePlugin(this.referenceQuxJarNewer, Collections.singletonMap(
306 "7499_Plugin-Url", "346;" + pluginServerRule.url("/dont/bother.jar")
307 ))
308 );
309 pluginServer.applyToWireMockServer(pluginServerRule.getRuntimeInfo());
310 Config.getPref().putList("plugins", Arrays.asList("qux_plugin", "baz_plugin"));
311
312 new ExtendedDialogMocker(Collections.singletonMap(u202f("JOSM version 7\u202F500 required for plugin qux_plugin."), "Download Plugin"));
313
314 Files.copy(this.referenceQuxJarOld.toPath(), this.targetQuxJar.toPath());
315 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
316
317 final List<PluginInformation> updatedPlugins = PluginHandler.updatePlugins(
318 MainApplication.getMainFrame(),
319 null,
320 null,
321 false
322 ).stream().sorted(Comparator.comparing(a -> a.name)).collect(Collectors.toList());
323
324 assertEquals(2, updatedPlugins.size());
325
326 assertEquals("baz_plugin", updatedPlugins.get(0).name);
327 assertEquals("6", updatedPlugins.get(0).localversion);
328
329 assertEquals("qux_plugin", updatedPlugins.get(1).name);
330 // questionably correct
331 assertEquals("432", updatedPlugins.get(1).localversion);
332
333 assertFalse(targetQuxJarNew.exists());
334
335 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
336 // questionably correct
337 TestUtils.assertFileContentsEqual(this.referenceQuxJarNewer, this.targetQuxJar);
338
339 assertEquals(2, pluginServerRule.getAllServeEvents().size());
340 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
341 // questionably correct
342 pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/qux_plugin.v432.jar")));
343
344 assertEquals(7200, Config.getPref().getInt("pluginmanager.version", 111));
345 // not mocking the time so just check it's not its original value
346 assertNotEquals("999", Config.getPref().get("pluginmanager.lastupdate", "999"));
347 }
348}
Note: See TracBrowser for help on using the repository browser.