source: josm/trunk/test/unit/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferenceHighLevelTest.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: 41.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.plugin;
3
4import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
5import static java.util.concurrent.TimeUnit.MILLISECONDS;
6import static org.junit.Assert.assertEquals;
7import static org.junit.Assert.assertFalse;
8import static org.junit.Assert.assertTrue;
9
10import java.awt.Component;
11import java.io.File;
12import java.nio.file.Files;
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.Collection;
16import java.util.Collections;
17import java.util.stream.Collectors;
18
19import javax.swing.JOptionPane;
20
21import org.awaitility.Awaitility;
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Rule;
25import org.junit.Test;
26import org.openstreetmap.josm.TestUtils;
27import org.openstreetmap.josm.data.Preferences;
28import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
29import org.openstreetmap.josm.gui.util.GuiHelper;
30import org.openstreetmap.josm.plugins.PluginHandler;
31import org.openstreetmap.josm.plugins.PluginInformation;
32import org.openstreetmap.josm.plugins.PluginProxy;
33import org.openstreetmap.josm.spi.preferences.Config;
34import org.openstreetmap.josm.testutils.JOSMTestRules;
35import org.openstreetmap.josm.testutils.PluginServer;
36import org.openstreetmap.josm.testutils.mockers.HelpAwareOptionPaneMocker;
37import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
38
39import com.github.tomakehurst.wiremock.client.WireMock;
40import com.github.tomakehurst.wiremock.junit.WireMockRule;
41
42import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
43import mockit.MockUp;
44
45/**
46 * Higher level tests of {@link PluginPreference} class.
47 */
48public class PluginPreferenceHighLevelTest {
49 /**
50 * Setup test.
51 */
52 @Rule
53 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
54 public JOSMTestRules test = new JOSMTestRules().assumeRevision(
55 "Revision: 10000\n"
56 ).preferences().main().assertionsInEDT();
57
58 /**
59 * Plugin server mock.
60 */
61 @Rule
62 public WireMockRule pluginServerRule = new WireMockRule(
63 options().dynamicPort().usingFilesUnderDirectory(TestUtils.getTestDataRoot())
64 );
65
66 /**
67 * Setup test.
68 * @throws ReflectiveOperationException never
69 */
70 @Before
71 public void setUp() throws ReflectiveOperationException {
72
73 // some other tests actually go ahead and load plugins (notably at time of writing,
74 // MainApplicationTest$testUpdateAndLoadPlugins), which really isn't a reversible operation.
75 // it is, however, possible to pretend to our tests temporarily that they *aren't* loaded by
76 // setting the PluginHandler#pluginList to empty for the duration of this test. ideally these
77 // other tests wouldn't be so badly behaved or would at least do this from a separate batch
78 // but this works for now
79 @SuppressWarnings("unchecked")
80 final Collection<PluginProxy> pluginList = (Collection<PluginProxy>) TestUtils.getPrivateStaticField(
81 PluginHandler.class,
82 "pluginList"
83 );
84 this.originalPluginList = new ArrayList<>(pluginList);
85 pluginList.clear();
86
87 Config.getPref().putInt("pluginmanager.version", 999);
88 Config.getPref().put("pluginmanager.lastupdate", "999");
89 Config.getPref().putList("pluginmanager.sites",
90 Collections.singletonList(this.pluginServerRule.url("/plugins"))
91 );
92
93 this.referenceDummyJarOld = new File(TestUtils.getTestDataRoot(), "__files/plugin/dummy_plugin.v31701.jar");
94 this.referenceDummyJarNew = new File(TestUtils.getTestDataRoot(), "__files/plugin/dummy_plugin.v31772.jar");
95 this.referenceBazJarOld = new File(TestUtils.getTestDataRoot(), "__files/plugin/baz_plugin.v6.jar");
96 this.referenceBazJarNew = new File(TestUtils.getTestDataRoot(), "__files/plugin/baz_plugin.v7.jar");
97 this.pluginDir = Preferences.main().getPluginsDirectory();
98 this.targetDummyJar = new File(this.pluginDir, "dummy_plugin.jar");
99 this.targetDummyJarNew = new File(this.pluginDir, "dummy_plugin.jar.new");
100 this.targetBazJar = new File(this.pluginDir, "baz_plugin.jar");
101 this.targetBazJarNew = new File(this.pluginDir, "baz_plugin.jar.new");
102 this.pluginDir.mkdirs();
103 }
104
105 /**
106 * Tear down.
107 * @throws ReflectiveOperationException never
108 */
109 @After
110 public void tearDown() throws ReflectiveOperationException {
111 // restore actual PluginHandler#pluginList
112 @SuppressWarnings("unchecked")
113 final Collection<PluginProxy> pluginList = (Collection<PluginProxy>) TestUtils.getPrivateStaticField(
114 PluginHandler.class,
115 "pluginList"
116 );
117 pluginList.clear();
118 pluginList.addAll(this.originalPluginList);
119 }
120
121 private Collection<PluginProxy> originalPluginList;
122
123 private File pluginDir;
124 private File referenceDummyJarOld;
125 private File referenceDummyJarNew;
126 private File referenceBazJarOld;
127 private File referenceBazJarNew;
128 private File targetDummyJar;
129 private File targetDummyJarNew;
130 private File targetBazJar;
131 private File targetBazJarNew;
132
133 /**
134 * Tests choosing a new plugin to install without upgrading an already-installed plugin
135 * @throws Exception never
136 */
137 @Test
138 public void testInstallWithoutUpdate() throws Exception {
139 final PluginServer pluginServer = new PluginServer(
140 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
141 new PluginServer.RemotePlugin(this.referenceBazJarOld),
142 new PluginServer.RemotePlugin(null, Collections.singletonMap("Plugin-Version", "2"), "irrelevant_plugin")
143 );
144 pluginServer.applyToWireMockServer(this.pluginServerRule);
145 Config.getPref().putList("plugins", Collections.singletonList("dummy_plugin"));
146
147 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker(
148 Collections.singletonMap(
149 "<html>The following plugin has been downloaded <strong>successfully</strong>:"
150 + "<ul><li>baz_plugin (6)</li></ul>"
151 + "You have to restart JOSM for some settings to take effect."
152 + "<br/><br/>Would you like to restart now?</html>",
153 "Cancel"
154 )
155 );
156
157 Files.copy(this.referenceDummyJarOld.toPath(), this.targetDummyJar.toPath());
158
159 final PreferenceTabbedPane tabbedPane = new PreferenceTabbedPane();
160
161 tabbedPane.buildGui();
162 // PluginPreference is already added to PreferenceTabbedPane by default
163 tabbedPane.selectTabByPref(PluginPreference.class);
164
165 GuiHelper.runInEDTAndWait(
166 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "downloadListButton")).doClick()
167 );
168
169 Awaitility.await().atMost(2000, MILLISECONDS).until(() -> Config.getPref().getInt("pluginmanager.version", 999) != 999);
170
171 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
172 WireMock.resetAllRequests();
173
174 final PluginPreferencesModel model = (PluginPreferencesModel) TestUtils.getPrivateField(
175 tabbedPane.getPluginPreference(),
176 "model"
177 );
178
179 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
180 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
181 // questionably correct
182 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
183 assertEquals(model.getDisplayedPlugins(), model.getAvailablePlugins());
184
185 assertEquals(
186 Arrays.asList("baz_plugin", "dummy_plugin", "irrelevant_plugin"),
187 model.getAvailablePlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
188 );
189 assertEquals(
190 Collections.singletonList("dummy_plugin"),
191 model.getSelectedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
192 );
193 assertEquals(
194 Arrays.asList("(null)", "31701", "(null)"),
195 model.getAvailablePlugins().stream().map(
196 (pi) -> pi.localversion == null ? "(null)" : pi.localversion
197 ).collect(Collectors.toList())
198 );
199 assertEquals(
200 Arrays.asList("6", "31772", "2"),
201 model.getAvailablePlugins().stream().map((pi) -> pi.version).collect(Collectors.toList())
202 );
203
204 // now we're going to choose to install baz_plugin
205 model.setPluginSelected("baz_plugin", true);
206
207 assertEquals(
208 Collections.singletonList("baz_plugin"),
209 model.getNewlyActivatedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
210 );
211 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
212 assertEquals(
213 Collections.singletonList("baz_plugin"),
214 model.getPluginsScheduledForUpdateOrDownload().stream().map(PluginInformation::getName).collect(Collectors.toList())
215 );
216
217 tabbedPane.savePreferences();
218
219 TestUtils.syncEDTAndWorkerThreads();
220
221 assertEquals(1, haMocker.getInvocationLog().size());
222 Object[] invocationLogEntry = haMocker.getInvocationLog().get(0);
223 assertEquals(1, (int) invocationLogEntry[0]);
224 assertEquals("Restart", invocationLogEntry[2]);
225
226 // dummy_plugin jar shouldn't have been updated
227 TestUtils.assertFileContentsEqual(this.referenceDummyJarOld, this.targetDummyJar);
228 // baz_plugin jar should have been installed
229 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
230
231 // neither of these .jar.new files should have been left hanging round
232 assertFalse(targetDummyJarNew.exists());
233 assertFalse(targetBazJarNew.exists());
234
235 // the advertized version of dummy_plugin shouldn't have been fetched
236 this.pluginServerRule.verify(0, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
237 // but the advertized version of baz_plugin *should* have
238 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v6.jar")));
239
240 // pluginmanager.version has been set to the current version
241 // questionably correct
242 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
243 // however pluginmanager.lastupdate hasn't been updated
244 // questionably correct
245 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
246
247 // baz_plugin should have been added to the plugins list
248 assertEquals(
249 Arrays.asList("baz_plugin", "dummy_plugin"),
250 Config.getPref().getList("plugins", null).stream().sorted().collect(Collectors.toList())
251 );
252 }
253
254 /**
255 * Tests a plugin being disabled without applying available upgrades
256 * @throws Exception never
257 */
258 @Test
259 public void testDisablePluginWithUpdatesAvailable() throws Exception {
260 final PluginServer pluginServer = new PluginServer(
261 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
262 new PluginServer.RemotePlugin(this.referenceBazJarNew),
263 new PluginServer.RemotePlugin(null, null, "irrelevant_plugin")
264 );
265 pluginServer.applyToWireMockServer(this.pluginServerRule);
266 Config.getPref().putList("plugins", Arrays.asList("baz_plugin", "dummy_plugin"));
267
268 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker(
269 Collections.singletonMap(
270 "<html>You have to restart JOSM for some settings to take effect."
271 + "<br/><br/>Would you like to restart now?</html>",
272 "Cancel"
273 )
274 );
275
276 Files.copy(this.referenceDummyJarOld.toPath(), this.targetDummyJar.toPath());
277 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
278
279 final PreferenceTabbedPane tabbedPane = new PreferenceTabbedPane();
280
281 tabbedPane.buildGui();
282 // PluginPreference is already added to PreferenceTabbedPane by default
283 tabbedPane.selectTabByPref(PluginPreference.class);
284
285 GuiHelper.runInEDTAndWait(
286 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "downloadListButton")).doClick()
287 );
288
289 Awaitility.await().atMost(2000, MILLISECONDS).until(() -> Config.getPref().getInt("pluginmanager.version", 999) != 999);
290
291 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
292 WireMock.resetAllRequests();
293
294 final PluginPreferencesModel model = (PluginPreferencesModel) TestUtils.getPrivateField(
295 tabbedPane.getPluginPreference(),
296 "model"
297 );
298
299 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
300 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
301 // questionably correct
302 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
303 assertEquals(model.getDisplayedPlugins(), model.getAvailablePlugins());
304
305 assertEquals(
306 Arrays.asList("baz_plugin", "dummy_plugin", "irrelevant_plugin"),
307 model.getAvailablePlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
308 );
309 assertEquals(
310 Arrays.asList("baz_plugin", "dummy_plugin"),
311 model.getSelectedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
312 );
313 assertEquals(
314 Arrays.asList("6", "31701", "(null)"),
315 model.getAvailablePlugins().stream().map(
316 (pi) -> pi.localversion == null ? "(null)" : pi.localversion
317 ).collect(Collectors.toList())
318 );
319 assertEquals(
320 Arrays.asList("7", "31772", "(null)"),
321 model.getAvailablePlugins().stream().map(
322 (pi) -> pi.version == null ? "(null)" : pi.version
323 ).collect(Collectors.toList())
324 );
325
326 // now we're going to choose to disable baz_plugin
327 model.setPluginSelected("baz_plugin", false);
328
329 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
330 assertEquals(
331 Collections.singletonList("baz_plugin"),
332 model.getNewlyDeactivatedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
333 );
334 // questionably correct
335 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
336
337 tabbedPane.savePreferences();
338
339 TestUtils.syncEDTAndWorkerThreads();
340
341 assertEquals(1, haMocker.getInvocationLog().size());
342 Object[] invocationLogEntry = haMocker.getInvocationLog().get(0);
343 assertEquals(1, (int) invocationLogEntry[0]);
344 assertEquals("Restart", invocationLogEntry[2]);
345
346 // dummy_plugin jar shouldn't have been updated
347 TestUtils.assertFileContentsEqual(this.referenceDummyJarOld, this.targetDummyJar);
348 // baz_plugin jar shouldn't have been deleted
349 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
350
351 // neither of these .jar.new files have a reason to be here
352 assertFalse(targetDummyJarNew.exists());
353 assertFalse(targetBazJarNew.exists());
354
355 // neither of the new jars have been fetched
356 this.pluginServerRule.verify(0, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
357 this.pluginServerRule.verify(0, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v6.jar")));
358
359 // pluginmanager.version has been set to the current version
360 // questionably correct
361 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
362 // however pluginmanager.lastupdate hasn't been updated
363 // questionably correct
364 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
365
366 // baz_plugin should have been removed from the installed plugins list
367 assertEquals(
368 Collections.singletonList("dummy_plugin"),
369 Config.getPref().getList("plugins", null).stream().sorted().collect(Collectors.toList())
370 );
371 }
372
373 /**
374 * Demonstrates behaviour exhibited when attempting to update a single plugin when multiple updates
375 * are available by deselecting it before clicking the update button then reselecting it.
376 *
377 * This is probably NOT desirable and should be fixed, however this test documents the behaviour.
378 * @throws Exception never
379 */
380 @Test
381 public void testUpdateOnlySelectedPlugin() throws Exception {
382 TestUtils.assumeWorkingJMockit();
383 final PluginServer pluginServer = new PluginServer(
384 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
385 new PluginServer.RemotePlugin(this.referenceBazJarNew)
386 );
387 pluginServer.applyToWireMockServer(this.pluginServerRule);
388 Config.getPref().putList("plugins", Arrays.asList("baz_plugin", "dummy_plugin"));
389
390 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker();
391 final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker();
392
393 Files.copy(this.referenceDummyJarOld.toPath(), this.targetDummyJar.toPath());
394 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
395
396 final PreferenceTabbedPane tabbedPane = new PreferenceTabbedPane();
397
398 tabbedPane.buildGui();
399 // PluginPreference is already added to PreferenceTabbedPane by default
400 tabbedPane.selectTabByPref(PluginPreference.class);
401
402 GuiHelper.runInEDTAndWait(
403 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "downloadListButton")).doClick()
404 );
405
406 TestUtils.syncEDTAndWorkerThreads();
407
408 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
409 WireMock.resetAllRequests();
410
411 final PluginPreferencesModel model = (PluginPreferencesModel) TestUtils.getPrivateField(
412 tabbedPane.getPluginPreference(),
413 "model"
414 );
415
416 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
417 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
418 // questionably correct
419 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
420 assertEquals(model.getDisplayedPlugins(), model.getAvailablePlugins());
421
422 assertEquals(
423 Arrays.asList("baz_plugin", "dummy_plugin"),
424 model.getAvailablePlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
425 );
426 assertEquals(
427 Arrays.asList("baz_plugin", "dummy_plugin"),
428 model.getSelectedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
429 );
430 assertEquals(
431 Arrays.asList("6", "31701"),
432 model.getAvailablePlugins().stream().map(
433 (pi) -> pi.localversion == null ? "(null)" : pi.localversion
434 ).collect(Collectors.toList())
435 );
436 assertEquals(
437 Arrays.asList("7", "31772"),
438 model.getAvailablePlugins().stream().map((pi) -> pi.version).collect(Collectors.toList())
439 );
440
441 // now we're going to choose not to update baz_plugin
442 model.setPluginSelected("baz_plugin", false);
443
444 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
445 assertEquals(
446 Collections.singletonList("baz_plugin"),
447 model.getNewlyDeactivatedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
448 );
449 // questionably correct
450 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
451
452 // prepare haMocker to handle this message
453 haMocker.getMockResultMap().put(
454 "<html>The following plugin has been downloaded <strong>successfully</strong>:"
455 + "<ul><li>dummy_plugin (31772)</li></ul>Please restart JOSM to activate the "
456 + "downloaded plugins.</html>",
457 "OK"
458 );
459
460 GuiHelper.runInEDTAndWait(
461 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "updatePluginsButton")).doClick()
462 );
463
464 TestUtils.syncEDTAndWorkerThreads();
465
466 assertTrue(jopsMocker.getInvocationLog().isEmpty());
467 assertEquals(1, haMocker.getInvocationLog().size());
468 Object[] invocationLogEntry = haMocker.getInvocationLog().get(0);
469 assertEquals(0, (int) invocationLogEntry[0]);
470 assertEquals("Update plugins", invocationLogEntry[2]);
471
472 // dummy_plugin jar should have been updated
473 TestUtils.assertFileContentsEqual(this.referenceDummyJarNew, this.targetDummyJar);
474 // but baz_plugin jar shouldn't have been
475 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
476
477 // any .jar.new files should have been removed
478 assertFalse(targetDummyJarNew.exists());
479 assertFalse(targetBazJarNew.exists());
480
481 // the plugin list was rechecked
482 // questionably necessary
483 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
484 // dummy_plugin has been fetched
485 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
486 // baz_plugin has not
487 this.pluginServerRule.verify(0, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v7.jar")));
488 WireMock.resetAllRequests();
489
490 // pluginmanager.version has been set to the current version
491 // questionably correct
492 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
493 // however pluginmanager.lastupdate hasn't been updated
494 // questionably correct
495 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
496
497 // plugins list shouldn't have been altered, we haven't hit save yet
498 assertEquals(
499 Arrays.asList("baz_plugin", "dummy_plugin"),
500 Config.getPref().getList("plugins", null).stream().sorted().collect(Collectors.toList())
501 );
502
503 // the model's selection state should be largely as before
504 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
505 assertEquals(
506 Collections.singletonList("baz_plugin"),
507 model.getNewlyDeactivatedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
508 );
509 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
510
511 // but now we re-select baz_plugin so that it isn't removed/disabled
512 model.setPluginSelected("baz_plugin", true);
513
514 // this has caused baz_plugin to be interpreted as a plugin "for download"
515 // questionably correct
516 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
517 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
518 assertEquals(
519 Collections.singletonList("baz_plugin"),
520 model.getPluginsScheduledForUpdateOrDownload().stream().map(PluginInformation::getName).collect(Collectors.toList())
521 );
522
523 // prepare jopsMocker to handle this message
524 jopsMocker.getMockResultMap().put(
525 "<html>The following plugin has been downloaded <strong>successfully</strong>:"
526 + "<ul><li>baz_plugin (7)</li></ul></html>",
527 JOptionPane.OK_OPTION
528 );
529
530 tabbedPane.savePreferences();
531
532 TestUtils.syncEDTAndWorkerThreads();
533
534 // from previous haMocker invocation
535 assertEquals(1, haMocker.getInvocationLog().size());
536 // we've been alerted that (the new version of) baz_plugin was installed
537 // questionably correct
538 assertEquals(1, jopsMocker.getInvocationLog().size());
539 invocationLogEntry = jopsMocker.getInvocationLog().get(0);
540 assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
541 assertEquals("Warning", invocationLogEntry[2]);
542
543 // dummy_plugin jar is still the updated version
544 TestUtils.assertFileContentsEqual(this.referenceDummyJarNew, this.targetDummyJar);
545 // but now the baz_plugin jar has been too
546 // questionably correct
547 TestUtils.assertFileContentsEqual(this.referenceBazJarNew, this.targetBazJar);
548
549 // all .jar.new files have been deleted
550 assertFalse(targetDummyJarNew.exists());
551 assertFalse(targetBazJarNew.exists());
552
553 // dummy_plugin was not fetched
554 this.pluginServerRule.verify(0, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
555 // baz_plugin however was fetched
556 // questionably correct
557 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/baz_plugin.v7.jar")));
558
559 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
560 // questionably correct
561 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
562 }
563
564 /**
565 * Tests the effect of requesting a "plugin update" when everything is up to date
566 * @throws Exception never
567 */
568 @Test
569 public void testUpdateWithNoAvailableUpdates() throws Exception {
570 TestUtils.assumeWorkingJMockit();
571 final PluginServer pluginServer = new PluginServer(
572 new PluginServer.RemotePlugin(this.referenceDummyJarOld),
573 new PluginServer.RemotePlugin(this.referenceBazJarOld),
574 new PluginServer.RemotePlugin(null, Collections.singletonMap("Plugin-Version", "123"), "irrelevant_plugin")
575 );
576 pluginServer.applyToWireMockServer(this.pluginServerRule);
577 Config.getPref().putList("plugins", Arrays.asList("baz_plugin", "dummy_plugin"));
578
579 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker(
580 Collections.singletonMap(
581 "All installed plugins are up to date. JOSM does not have to download newer versions.",
582 "OK"
583 )
584 );
585 final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker();
586
587 Files.copy(this.referenceDummyJarOld.toPath(), this.targetDummyJar.toPath());
588 Files.copy(this.referenceBazJarOld.toPath(), this.targetBazJar.toPath());
589
590 final PreferenceTabbedPane tabbedPane = new PreferenceTabbedPane();
591
592 tabbedPane.buildGui();
593 // PluginPreference is already added to PreferenceTabbedPane by default
594 tabbedPane.selectTabByPref(PluginPreference.class);
595
596 GuiHelper.runInEDTAndWait(
597 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "downloadListButton")).doClick()
598 );
599
600 TestUtils.syncEDTAndWorkerThreads();
601
602 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
603 WireMock.resetAllRequests();
604
605 final PluginPreferencesModel model = (PluginPreferencesModel) TestUtils.getPrivateField(
606 tabbedPane.getPluginPreference(),
607 "model"
608 );
609
610 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
611 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
612 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
613 assertEquals(model.getDisplayedPlugins(), model.getAvailablePlugins());
614
615 assertEquals(
616 Arrays.asList("baz_plugin", "dummy_plugin", "irrelevant_plugin"),
617 model.getAvailablePlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
618 );
619 assertEquals(
620 Arrays.asList("baz_plugin", "dummy_plugin"),
621 model.getSelectedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
622 );
623 assertEquals(
624 Arrays.asList("6", "31701", "(null)"),
625 model.getAvailablePlugins().stream().map(
626 (pi) -> pi.localversion == null ? "(null)" : pi.localversion
627 ).collect(Collectors.toList())
628 );
629 assertEquals(
630 Arrays.asList("6", "31701", "123"),
631 model.getAvailablePlugins().stream().map((pi) -> pi.version).collect(Collectors.toList())
632 );
633
634 GuiHelper.runInEDTAndWait(
635 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "updatePluginsButton")).doClick()
636 );
637
638 TestUtils.syncEDTAndWorkerThreads();
639
640 assertTrue(jopsMocker.getInvocationLog().isEmpty());
641 assertEquals(1, haMocker.getInvocationLog().size());
642 Object[] invocationLogEntry = haMocker.getInvocationLog().get(0);
643 assertEquals(0, (int) invocationLogEntry[0]);
644 assertEquals("Plugins up to date", invocationLogEntry[2]);
645
646 // neither jar should have changed
647 TestUtils.assertFileContentsEqual(this.referenceDummyJarOld, this.targetDummyJar);
648 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
649
650 // no reason for any .jar.new files
651 assertFalse(targetDummyJarNew.exists());
652 assertFalse(targetBazJarNew.exists());
653
654 // the plugin list was rechecked
655 // questionably necessary
656 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
657 // that should have been the only request to our PluginServer
658 assertEquals(1, this.pluginServerRule.getAllServeEvents().size());
659 WireMock.resetAllRequests();
660
661 // pluginmanager.version has been set to the current version
662 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
663 // pluginmanager.lastupdate hasn't been updated
664 // questionably correct
665 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
666
667 // plugins list shouldn't have been altered
668 assertEquals(
669 Arrays.asList("baz_plugin", "dummy_plugin"),
670 Config.getPref().getList("plugins", null).stream().sorted().collect(Collectors.toList())
671 );
672
673 // the model's selection state should be largely as before
674 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
675 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
676 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
677
678 tabbedPane.savePreferences();
679
680 TestUtils.syncEDTAndWorkerThreads();
681
682 assertTrue(jopsMocker.getInvocationLog().isEmpty());
683 assertEquals(1, haMocker.getInvocationLog().size());
684
685 // both jars are still the original version
686 TestUtils.assertFileContentsEqual(this.referenceDummyJarOld, this.targetDummyJar);
687 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
688
689 // no reason for any .jar.new files
690 assertFalse(targetDummyJarNew.exists());
691 assertFalse(targetBazJarNew.exists());
692
693 // none of PluginServer's URLs should have been touched
694 assertEquals(0, this.pluginServerRule.getAllServeEvents().size());
695
696 // pluginmanager.version has been set to the current version
697 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
698 // pluginmanager.lastupdate hasn't been updated
699 // questionably correct
700 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
701 }
702
703 /**
704 * Tests installing a single plugin which is marked as "Canloadatruntime"
705 * @throws Exception never
706 */
707 @Test
708 public void testInstallWithoutRestartRequired() throws Exception {
709 TestUtils.assumeWorkingJMockit();
710 final boolean[] loadPluginsCalled = new boolean[] {false};
711 new MockUp<PluginHandler>() {
712 @mockit.Mock
713 private void loadPlugins(
714 final Component parent,
715 final Collection<org.openstreetmap.josm.plugins.PluginInformation> plugins,
716 final org.openstreetmap.josm.gui.progress.ProgressMonitor monitor
717 ) {
718 assertEquals(1, plugins.size());
719 assertEquals("dummy_plugin", plugins.iterator().next().name);
720 assertEquals("31772", plugins.iterator().next().localversion);
721 loadPluginsCalled[0] = true;
722 }
723 };
724
725 final PluginServer pluginServer = new PluginServer(
726 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
727 new PluginServer.RemotePlugin(this.referenceBazJarNew)
728 );
729 pluginServer.applyToWireMockServer(this.pluginServerRule);
730 Config.getPref().putList("plugins", Collections.emptyList());
731
732 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker();
733 final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(Collections.singletonMap(
734 "<html>The following plugin has been downloaded <strong>successfully</strong>:"
735 + "<ul><li>dummy_plugin (31772)</li></ul></html>",
736 JOptionPane.OK_OPTION
737 ));
738
739 final PreferenceTabbedPane tabbedPane = new PreferenceTabbedPane();
740
741 tabbedPane.buildGui();
742 // PluginPreference is already added to PreferenceTabbedPane by default
743 tabbedPane.selectTabByPref(PluginPreference.class);
744
745 GuiHelper.runInEDTAndWait(
746 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "downloadListButton")).doClick()
747 );
748
749 TestUtils.syncEDTAndWorkerThreads();
750
751 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
752 WireMock.resetAllRequests();
753
754 final PluginPreferencesModel model = (PluginPreferencesModel) TestUtils.getPrivateField(
755 tabbedPane.getPluginPreference(),
756 "model"
757 );
758
759 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
760 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
761 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
762 assertEquals(model.getDisplayedPlugins(), model.getAvailablePlugins());
763
764 assertEquals(
765 Arrays.asList("baz_plugin", "dummy_plugin"),
766 model.getAvailablePlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
767 );
768 assertTrue(model.getSelectedPlugins().isEmpty());
769 assertEquals(
770 Arrays.asList("(null)", "(null)"),
771 model.getAvailablePlugins().stream().map(
772 (pi) -> pi.localversion == null ? "(null)" : pi.localversion
773 ).collect(Collectors.toList())
774 );
775 assertEquals(
776 Arrays.asList("7", "31772"),
777 model.getAvailablePlugins().stream().map((pi) -> pi.version).collect(Collectors.toList())
778 );
779
780 // now we select dummy_plugin
781 model.setPluginSelected("dummy_plugin", true);
782
783 // model should now reflect this
784 assertEquals(
785 Collections.singletonList("dummy_plugin"),
786 model.getNewlyActivatedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
787 );
788 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
789
790 tabbedPane.savePreferences();
791
792 TestUtils.syncEDTAndWorkerThreads();
793
794 assertEquals(1, jopsMocker.getInvocationLog().size());
795 Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
796 assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
797 assertEquals("Warning", invocationLogEntry[2]);
798
799 assertTrue(haMocker.getInvocationLog().isEmpty());
800
801 // any .jar.new files should have been deleted
802 assertFalse(targetDummyJarNew.exists());
803 assertFalse(targetBazJarNew.exists());
804
805 // dummy_plugin was fetched
806 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugin/dummy_plugin.v31772.jar")));
807
808 // the dummy_plugin jar has been installed
809 TestUtils.assertFileContentsEqual(this.referenceDummyJarNew, this.targetDummyJar);
810 // the baz_plugin jar has not
811 assertFalse(this.targetBazJar.exists());
812
813 // loadPlugins(...) was called (with expected parameters)
814 assertTrue(loadPluginsCalled[0]);
815
816 // pluginmanager.version has been set to the current version
817 assertEquals(10000, Config.getPref().getInt("pluginmanager.version", 111));
818 // pluginmanager.lastupdate hasn't been updated
819 // questionably correct
820 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
821 }
822
823 /**
824 * Tests installing a single plugin which has multiple versions advertised, with our JOSM version
825 * preventing us from using the latest version
826 * @throws Exception on failure
827 */
828 @JOSMTestRules.OverrideAssumeRevision("Revision: 7000\n")
829 @Test
830 public void testInstallMultiVersion() throws Exception {
831 TestUtils.assumeWorkingJMockit();
832
833 final String bazOldServePath = "/baz/old.jar";
834 final PluginServer pluginServer = new PluginServer(
835 new PluginServer.RemotePlugin(this.referenceDummyJarNew),
836 new PluginServer.RemotePlugin(this.referenceBazJarNew, Collections.singletonMap(
837 "6800_Plugin-Url", "6;" + this.pluginServerRule.url(bazOldServePath)
838 ))
839 );
840 pluginServer.applyToWireMockServer(this.pluginServerRule);
841 // need to actually serve this older jar from somewhere
842 this.pluginServerRule.stubFor(
843 WireMock.get(WireMock.urlEqualTo(bazOldServePath)).willReturn(
844 WireMock.aResponse().withStatus(200).withHeader("Content-Type", "application/java-archive").withBodyFile(
845 "plugin/baz_plugin.v6.jar"
846 )
847 )
848 );
849 Config.getPref().putList("plugins", Collections.emptyList());
850
851 final HelpAwareOptionPaneMocker haMocker = new HelpAwareOptionPaneMocker(Collections.singletonMap(
852 "<html>The following plugin has been downloaded <strong>successfully</strong>:"
853 + "<ul><li>baz_plugin (6)</li></ul>"
854 + "You have to restart JOSM for some settings to take effect.<br/><br/>"
855 + "Would you like to restart now?</html>",
856 "Cancel"
857 ));
858 final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker();
859
860 final PreferenceTabbedPane tabbedPane = new PreferenceTabbedPane();
861
862 tabbedPane.buildGui();
863 // PluginPreference is already added to PreferenceTabbedPane by default
864 tabbedPane.selectTabByPref(PluginPreference.class);
865
866 GuiHelper.runInEDTAndWait(
867 () -> ((javax.swing.JButton) TestUtils.getComponentByName(tabbedPane, "downloadListButton")).doClick()
868 );
869
870 TestUtils.syncEDTAndWorkerThreads();
871
872 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/plugins")));
873 WireMock.resetAllRequests();
874
875 final PluginPreferencesModel model = (PluginPreferencesModel) TestUtils.getPrivateField(
876 tabbedPane.getPluginPreference(),
877 "model"
878 );
879
880 assertTrue(model.getNewlyActivatedPlugins().isEmpty());
881 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
882 assertTrue(model.getPluginsScheduledForUpdateOrDownload().isEmpty());
883 assertEquals(model.getDisplayedPlugins(), model.getAvailablePlugins());
884
885 assertEquals(
886 Arrays.asList("baz_plugin", "dummy_plugin"),
887 model.getAvailablePlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
888 );
889 assertTrue(model.getSelectedPlugins().isEmpty());
890 assertEquals(
891 Arrays.asList("(null)", "(null)"),
892 model.getAvailablePlugins().stream().map(
893 (pi) -> pi.localversion == null ? "(null)" : pi.localversion
894 ).collect(Collectors.toList())
895 );
896 assertEquals(
897 Arrays.asList("6", "31772"),
898 model.getAvailablePlugins().stream().map((pi) -> pi.version).collect(Collectors.toList())
899 );
900
901 // now we select dummy_plugin
902 model.setPluginSelected("baz_plugin", true);
903
904 // model should now reflect this
905 assertEquals(
906 Collections.singletonList("baz_plugin"),
907 model.getNewlyActivatedPlugins().stream().map(PluginInformation::getName).collect(Collectors.toList())
908 );
909 assertTrue(model.getNewlyDeactivatedPlugins().isEmpty());
910
911 tabbedPane.savePreferences();
912
913 TestUtils.syncEDTAndWorkerThreads();
914
915 assertEquals(1, haMocker.getInvocationLog().size());
916 Object[] invocationLogEntry = haMocker.getInvocationLog().get(0);
917 assertEquals(1, (int) invocationLogEntry[0]);
918 assertEquals("Restart", invocationLogEntry[2]);
919
920 assertTrue(jopsMocker.getInvocationLog().isEmpty());
921
922 // any .jar.new files should have been deleted
923 assertFalse(targetDummyJarNew.exists());
924 assertFalse(targetBazJarNew.exists());
925
926 // dummy_plugin was fetched
927 this.pluginServerRule.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo(bazOldServePath)));
928
929 // the "old" baz_plugin jar has been installed
930 TestUtils.assertFileContentsEqual(this.referenceBazJarOld, this.targetBazJar);
931 // the dummy_plugin jar has not
932 assertFalse(this.targetDummyJar.exists());
933
934 // pluginmanager.version has been set to the current version
935 assertEquals(7000, Config.getPref().getInt("pluginmanager.version", 111));
936 // pluginmanager.lastupdate hasn't been updated
937 // questionably correct
938 assertEquals("999", Config.getPref().get("pluginmanager.lastupdate", "111"));
939 }
940}
Note: See TracBrowser for help on using the repository browser.