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

Last change on this file since 17275 was 17195, checked in by simon04, 4 years ago

see #15102 - see #16637 - Use WireMockServer.url()

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