Changeset 14052 in josm for trunk/test/unit


Ignore:
Timestamp:
2018-07-26T22:01:31+02:00 (6 years ago)
Author:
Don-vip
Message:

see #16010 - use JMockit to enable more extensive test coverage (patch by ris, modified)

see https://github.com/openstreetmap/josm/pull/24/commits for details

Location:
trunk/test/unit/org/openstreetmap/josm
Files:
12 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/unit/org/openstreetmap/josm/TestUtils.java

    r13742 r14052  
    33
    44import static org.junit.Assert.assertEquals;
     5import static org.junit.Assert.assertArrayEquals;
     6import static org.junit.Assert.assertTrue;
    57import static org.junit.Assert.fail;
    68
     
    911import java.awt.Graphics2D;
    1012import java.io.File;
     13import java.io.FileInputStream;
    1114import java.io.IOException;
    1215import java.io.InputStream;
     
    2326import java.util.Comparator;
    2427import java.util.Objects;
     28import java.util.concurrent.ExecutionException;
     29import java.util.concurrent.ThreadPoolExecutor;
    2530import java.util.stream.Stream;
    2631
     
    3439import org.openstreetmap.josm.data.osm.RelationMember;
    3540import org.openstreetmap.josm.data.osm.Way;
     41import org.openstreetmap.josm.gui.MainApplication;
    3642import org.openstreetmap.josm.gui.progress.AbstractProgressMonitor;
    3743import org.openstreetmap.josm.gui.progress.CancelHandler;
    3844import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    3945import org.openstreetmap.josm.gui.progress.ProgressTaskId;
     46import org.openstreetmap.josm.gui.util.GuiHelper;
    4047import org.openstreetmap.josm.io.Compression;
    4148import org.openstreetmap.josm.testutils.FakeGraphics;
     
    4552import com.github.tomakehurst.wiremock.WireMockServer;
    4653import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
     54
     55import com.google.common.io.ByteStreams;
    4756
    4857import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    429438        return getHTTPDate(Instant.ofEpochMilli(time));
    430439    }
     440
     441    /**
     442     * Throws AssertionError if contents of both files are not equal
     443     * @param fileA File A
     444     * @param fileB File B
     445     */
     446    public static void assertFileContentsEqual(final File fileA, final File fileB) {
     447        assertTrue(fileA.exists());
     448        assertTrue(fileA.canRead());
     449        assertTrue(fileB.exists());
     450        assertTrue(fileB.canRead());
     451        try {
     452            try (
     453                FileInputStream streamA = new FileInputStream(fileA);
     454                FileInputStream streamB = new FileInputStream(fileB);
     455            ) {
     456                assertArrayEquals(
     457                    ByteStreams.toByteArray(streamA),
     458                    ByteStreams.toByteArray(streamB)
     459                );
     460            }
     461        } catch (IOException e) {
     462            fail(e.toString());
     463        }
     464    }
     465
     466    /**
     467     * Waits until any asynchronous operations launched by the test on the EDT or worker threads have
     468     * (almost certainly) completed.
     469     */
     470    public static void syncEDTAndWorkerThreads() {
     471        boolean workerQueueEmpty = false;
     472        while (!workerQueueEmpty) {
     473            try {
     474                // once our own task(s) have made it to the front of their respective queue(s),
     475                // they're both executing at the same time and we know there aren't any outstanding
     476                // worker tasks, then presumably the only way there could be incomplete operations
     477                // is if the EDT had launched a deferred task to run on itself or perhaps set up a
     478                // swing timer - neither are particularly common patterns in JOSM (?)
     479                //
     480                // there shouldn't be a risk of creating a deadlock in doing this as there shouldn't
     481                // (...couldn't?) be EDT operations waiting on the results of a worker task.
     482                workerQueueEmpty = MainApplication.worker.submit(
     483                    () -> GuiHelper.runInEDTAndWaitAndReturn(
     484                        () -> ((ThreadPoolExecutor) MainApplication.worker).getQueue().isEmpty()
     485                    )
     486                ).get();
     487            } catch (InterruptedException | ExecutionException e) {
     488                // inconclusive - retry...
     489                workerQueueEmpty = false;
     490            }
     491        }
     492    }
    431493}
  • trunk/test/unit/org/openstreetmap/josm/actions/ExitActionTest.java

    r11101 r14052  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.actions;
     3
     4import static org.junit.Assert.assertTrue;
    35
    46import org.junit.Rule;
    57import org.junit.Test;
    68import org.junit.contrib.java.lang.system.ExpectedSystemExit;
     9import org.openstreetmap.josm.gui.MainApplication;
     10import org.openstreetmap.josm.gui.progress.swing.ProgressMonitorExecutor;
    711import org.openstreetmap.josm.testutils.JOSMTestRules;
     12import org.openstreetmap.josm.tools.ImageProvider;
     13
     14import mockit.Invocation;
     15import mockit.Mock;
     16import mockit.MockUp;
    817
    918import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    3342    public void testActionPerformed() {
    3443        exit.expectSystemExitWithStatus(0);
     44
     45        boolean[] workerShutdownCalled = {false};
     46        boolean[] workerShutdownNowCalled = {false};
     47        boolean[] imageProviderShutdownCalled = {false};
     48
     49        // critically we don't proceed into the actual implementation in any of these mock methods -
     50        // that would be quite annoying for tests following this one which were expecting to use any
     51        // of these
     52        new MockUp<ProgressMonitorExecutor>() {
     53            @Mock
     54            private void shutdown(Invocation invocation) {
     55                if (invocation.getInvokedInstance() == MainApplication.worker) {
     56                    workerShutdownCalled[0] = true;
     57                }
     58            }
     59
     60            @Mock
     61            private void shutdownNow(Invocation invocation) {
     62                if (invocation.getInvokedInstance() == MainApplication.worker) {
     63                    // regular shutdown should have been called first
     64                    assertTrue(workerShutdownCalled[0]);
     65                    workerShutdownNowCalled[0] = true;
     66                }
     67            }
     68        };
     69        new MockUp<ImageProvider>() {
     70            @Mock
     71            private void shutdown(Invocation invocation) {
     72                imageProviderShutdownCalled[0] = true;
     73            }
     74        };
     75
    3576        // No layer
     77
    3678        new ExitAction().actionPerformed(null);
     79
     80        assertTrue(workerShutdownCalled[0]);
     81        assertTrue(workerShutdownNowCalled[0]);
     82        assertTrue(imageProviderShutdownCalled[0]);
    3783    }
    3884}
  • trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PluginDownloadTaskTest.java

    r13300 r14052  
    5656    @Test
    5757    public void testUpdatePluginValid() throws Exception {
    58         this.pluginPath = "plugin/dummy_plugin.jar";
     58        this.pluginPath = "plugin/dummy_plugin.v31772.jar";
    5959        this.mockHttp();
    6060
     
    7474
    7575        // get PluginInformation from jar file
    76         final PluginInformation pluginInformation = new PluginInformation(srcPluginFile);
     76        final PluginInformation pluginInformation = new PluginInformation(srcPluginFile, "dummy_plugin");
    7777        // ...and grafting on the downloadlink
    7878        pluginInformation.downloadlink = this.getRemoteFileUrl();
     
    8787        // the ".jar.new" file should have been deleted
    8888        assertFalse(pluginFileNew.exists());
    89         // the ".jar" file should still exist
    90         assertTrue(pluginFile.exists());
    91         try (
    92             FileInputStream pluginDirPluginStream = new FileInputStream(pluginFile);
    93             FileInputStream srcPluginStream = new FileInputStream(srcPluginFile);
    94         ) {
    95             // and its contents should equal those that were served to the task
    96             assertArrayEquals(
    97                 ByteStreams.toByteArray(pluginDirPluginStream),
    98                 ByteStreams.toByteArray(srcPluginStream)
    99             );
    100         }
     89        // the ".jar" file should still exist and its contents should equal those that were served to the task
     90        TestUtils.assertFileContentsEqual(pluginFile, srcPluginFile);
    10191    }
    10292
     
    140130        }
    141131
    142         // the ".jar.new" file should exist, even though invalid
    143         assertTrue(pluginFileNew.exists());
     132        // assert that the "corrupt" jar file made it through in tact
     133        TestUtils.assertFileContentsEqual(pluginFileNew, srcPluginFile);
    144134        // the ".jar" file should still exist
    145135        assertTrue(pluginFile.exists());
    146136        try (
    147             FileInputStream pluginDirPluginNewStream = new FileInputStream(pluginFileNew);
    148137            FileInputStream pluginDirPluginStream = new FileInputStream(pluginFile);
    149             FileInputStream srcPluginStream = new FileInputStream(srcPluginFile);
    150138        ) {
    151139            // the ".jar" file's contents should be as before
     
    154142                ByteStreams.toByteArray(pluginDirPluginStream)
    155143            );
    156             // just assert that the "corrupt" jar file made it through in tact
    157             assertArrayEquals(
    158                 ByteStreams.toByteArray(pluginDirPluginNewStream),
    159                 ByteStreams.toByteArray(srcPluginStream)
    160             );
    161144        }
    162145    }
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java

    r13181 r14052  
    33
    44import static java.util.concurrent.TimeUnit.MILLISECONDS;
     5import static org.openstreetmap.josm.tools.I18n.tr;
    56import static org.junit.Assert.assertEquals;
    67import static org.junit.Assert.assertFalse;
     
    1920
    2021import javax.swing.JMenuItem;
     22import javax.swing.JCheckBoxMenuItem;
    2123import javax.swing.JPopupMenu;
    2224
     
    2729import org.openstreetmap.josm.TestUtils;
    2830import org.openstreetmap.josm.data.Bounds;
     31import org.openstreetmap.josm.data.DataSource;
     32import org.openstreetmap.josm.data.osm.DataSet;
    2933import org.openstreetmap.josm.data.projection.Projections;
    3034import org.openstreetmap.josm.gui.MainApplication;
     
    3236import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
    3337import org.openstreetmap.josm.gui.bbox.SourceButton;
     38import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    3439import org.openstreetmap.josm.gui.layer.LayerManagerTest.TestLayer;
    3540import org.openstreetmap.josm.gui.util.GuiHelper;
     
    8792                break;
    8893            } else {
    89                 boolean equalText = ((JMenuItem) c).getText() == label;
     94                boolean equalText = ((JMenuItem) c).getText().equals(label);
    9095                boolean isSelected = ((JMenuItem) c).isSelected();
    9196                assertEquals(equalText, isSelected);
     
    297302
    298303        Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder()
    299             .put(0xffffffff, "w")
    300             .put(0xff000000, "b")
    301             .put(0xfff0d1d1, "p")
     304            .put(0xffffffff, "w")  // white
     305            .put(0xff000000, "b")  // black
     306            .put(0xfff0d1d1, "p")  // pink
    302307            .build();
    303308
     
    385390        );
    386391    }
     392
     393    protected JCheckBoxMenuItem getShowDownloadedAreaMenuItem() {
     394        JPopupMenu menu = this.sourceButton.getPopupMenu();
     395        boolean afterSeparator = false;
     396        for (Component c: menu.getComponents()) {
     397            if (JPopupMenu.Separator.class.isInstance(c)) {
     398                assertFalse("More than one separator before target item", afterSeparator);
     399                afterSeparator = true;
     400            } else if (((JMenuItem) c).getText().equals(tr("Show downloaded area"))) {
     401                assertTrue("Separator not found before target item", afterSeparator);
     402                assertTrue("Target item doesn't appear to be a JCheckBoxMenuItem", JCheckBoxMenuItem.class.isInstance(c));
     403                return (JCheckBoxMenuItem) c;
     404            }
     405        }
     406        fail("'Show downloaded area' menu item not found");
     407        return null;
     408    }
     409
     410    /**
     411     * test downloaded area is shown shaded
     412     * @throws Exception if any error occurs
     413     */
     414    @Test
     415    public void testShowDownloadedArea() throws Exception {
     416        Main.pref.put("slippy_map_chooser.mapstyle", "Green Tiles");
     417        Main.pref.putBoolean("slippy_map_chooser.show_downloaded_area", false);
     418
     419        DataSet dataSet = new DataSet();
     420        dataSet.addDataSource(new DataSource(new Bounds(51.725, -0.0209, 51.746, 0.0162), "Somewhere"));
     421
     422        OsmDataLayer dataLayer = new OsmDataLayer(
     423            dataSet,
     424            "Test Layer 123",
     425            null
     426        );
     427        MainApplication.getLayerManager().addLayer(dataLayer);
     428        MainApplication.getLayerManager().setActiveLayer(dataLayer);
     429
     430        MapView mapView = MainApplication.getMap().mapView;
     431        GuiHelper.runInEDTAndWaitWithException(() -> {
     432            mapView.setVisible(true);
     433            mapView.addNotify();
     434            mapView.doLayout();
     435            mapView.setBounds(0, 0, 500, 500);
     436        });
     437
     438        this.setUpMiniMap();
     439
     440        // assert "show downloaded areas" checkbox is unchecked
     441        assertFalse(this.getShowDownloadedAreaMenuItem().isSelected());
     442
     443        // we won't end up with exactly this viewport as it doesn't *precisely* match the aspect ratio
     444        mapView.zoomTo(new Bounds(51.732, -0.0269, 51.753, 0.0102));
     445
     446        // an initial paint operation is required to trigger the tile fetches
     447        this.paintSlippyMap();
     448
     449        Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
     450
     451        this.paintSlippyMap();
     452
     453        Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder()
     454            .put(0xff00ff00, "g")  // green
     455            .put(0xff000000, "b")  // black
     456            .put(0xff8ad16b, "v")  // viewport marker inner (pink+green mix)
     457            .put(0xff00df00, "d")  // (shaded green)
     458            .put(0xff8ac46b, "q")  // (shaded pink+green mix)
     459            .build();
     460
     461        // assert downloaded areas are not drawn
     462        ImagePatternMatching.rowMatch(
     463            paintedSlippyMap,
     464            paintedSlippyMap.getHeight()/2,
     465            paletteMap,
     466            "^g+bv+bg+$",
     467            true
     468        );
     469        ImagePatternMatching.columnMatch(
     470            paintedSlippyMap,
     471            paintedSlippyMap.getWidth()/2,
     472            paletteMap,
     473            "^g+bv+bg+$",
     474            true
     475        );
     476
     477        // enable "show downloaded areas"
     478        GuiHelper.runInEDTAndWaitWithException(() -> this.getShowDownloadedAreaMenuItem().doClick());
     479        assertTrue(this.getShowDownloadedAreaMenuItem().isSelected());
     480
     481        // assert downloaded areas are drawn
     482        this.paintSlippyMap();
     483
     484        ImagePatternMatching.rowMatch(
     485            paintedSlippyMap,
     486            paintedSlippyMap.getHeight()/2,
     487            paletteMap,
     488            "^d+bq+v+bg+d+$",
     489            true
     490        );
     491        ImagePatternMatching.columnMatch(
     492            paintedSlippyMap,
     493            paintedSlippyMap.getWidth()/2,
     494            paletteMap,
     495            "^d+bq+v+bg+d+$",
     496            true
     497        );
     498
     499        // also assert the leftmost column doesn't (yet) have any downloaded area marks (i.e. fully shaded)
     500        ImagePatternMatching.columnMatch(
     501            paintedSlippyMap,
     502            0,
     503            paletteMap,
     504            "^d+$",
     505            true
     506        );
     507
     508        // add another downloaded area, going off the left of the widget
     509        dataSet.addDataSource(new DataSource(new Bounds(51.745, -1., 51.765, 0.0162), "Somewhere else"));
     510        // and redraw
     511        this.paintSlippyMap();
     512
     513        // the middle row should be as before
     514        ImagePatternMatching.rowMatch(
     515            paintedSlippyMap,
     516            paintedSlippyMap.getHeight()/2,
     517            paletteMap,
     518            "^d+bq+v+bg+d+$",
     519            true
     520        );
     521        // the middle column should have its unshaded region extended beyond the viewport marker
     522        ImagePatternMatching.columnMatch(
     523            paintedSlippyMap,
     524            paintedSlippyMap.getWidth()/2,
     525            paletteMap,
     526            "^d+g+bv+bg+d+$",
     527            true
     528        );
     529        // but the leftmost column should now have an unshaded mark
     530        ImagePatternMatching.columnMatch(
     531            paintedSlippyMap,
     532            0,
     533            paletteMap,
     534            "^d+g+d+$",
     535            true
     536        );
     537        // and the rightmost column should be untouched
     538        ImagePatternMatching.columnMatch(
     539            paintedSlippyMap,
     540            paintedSlippyMap.getWidth()-1,
     541            paletteMap,
     542            "^d+$",
     543            true
     544        );
     545
     546        // and now if we pan to the left (in EastNorth units)
     547        mapView.zoomTo(mapView.getCenter().add(-5000., 0.));
     548        // and redraw
     549        this.paintSlippyMap();
     550
     551        // the middle row should have its unshaded region outside the viewport marker
     552        ImagePatternMatching.rowMatch(
     553            paintedSlippyMap,
     554            paintedSlippyMap.getHeight()/2,
     555            paletteMap,
     556            "^d+bq+bd+g+d*$",
     557            true
     558        );
     559        // the middle column should have a shaded region inside the viewport marker
     560        ImagePatternMatching.columnMatch(
     561            paintedSlippyMap,
     562            paintedSlippyMap.getWidth()/2,
     563            paletteMap,
     564            "^d+g+bv+q+bd+$",
     565            true
     566        );
     567    }
     568
     569    /**
     570     * test display of downloaded area follows active layer switching
     571     * @throws Exception if any error occurs
     572     */
     573    @Test
     574    public void testShowDownloadedAreaLayerSwitching() throws Exception {
     575        Main.pref.put("slippy_map_chooser.mapstyle", "Green Tiles");
     576        Main.pref.putBoolean("slippy_map_chooser.show_downloaded_area", true);
     577
     578        DataSet dataSetA = new DataSet();
     579        // dataSetA has a long thin horizontal downloaded area (extending off the left & right of the map)
     580        dataSetA.addDataSource(new DataSource(new Bounds(-18., -61.02, -15., -60.98), "Elsewhere"));
     581
     582        OsmDataLayer dataLayerA = new OsmDataLayer(
     583            dataSetA,
     584            "Test Layer A",
     585            null
     586        );
     587        MainApplication.getLayerManager().addLayer(dataLayerA);
     588
     589        DataSet dataSetB = new DataSet();
     590        // dataSetB has a long thin vertical downloaded area (extending off the top & bottom of the map)
     591        dataSetB.addDataSource(new DataSource(new Bounds(-16.38, -62., -16.34, -60.), "Nowhere"));
     592
     593        OsmDataLayer dataLayerB = new OsmDataLayer(
     594            dataSetB,
     595            "Test Layer B",
     596            null
     597        );
     598        MainApplication.getLayerManager().addLayer(dataLayerB);
     599
     600        MainApplication.getLayerManager().setActiveLayer(dataLayerB);
     601
     602        MapView mapView = MainApplication.getMap().mapView;
     603        GuiHelper.runInEDTAndWaitWithException(() -> {
     604            mapView.setVisible(true);
     605            mapView.addNotify();
     606            mapView.doLayout();
     607            mapView.setBounds(0, 0, 400, 400);
     608        });
     609
     610        this.setUpMiniMap();
     611
     612        // assert "show downloaded areas" checkbox is checked
     613        assertTrue(this.getShowDownloadedAreaMenuItem().isSelected());
     614
     615        // again, we won't end up with exactly this viewport as it doesn't *precisely* match the aspect ratio
     616        mapView.zoomTo(new Bounds(-16.423, -61.076, -16.299, -60.932));
     617
     618        // an initial paint operation is required to trigger the tile fetches
     619        this.paintSlippyMap();
     620
     621        Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
     622
     623        this.paintSlippyMap();
     624
     625        Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder()
     626            .put(0xff00ff00, "g")  // green
     627            .put(0xff000000, "b")  // black
     628            .put(0xff8ad16b, "v")  // viewport marker inner (pink+green mix)
     629            .put(0xff00df00, "d")  // (shaded green)
     630            .put(0xff8ac46b, "q")  // (shaded pink+green mix)
     631            .build();
     632
     633        // the middle row should be entirely unshaded
     634        ImagePatternMatching.rowMatch(
     635            paintedSlippyMap,
     636            paintedSlippyMap.getHeight()/2,
     637            paletteMap,
     638            "^g+bv+bg+$",
     639            true
     640        );
     641        // the middle column should have an unshaded band within the viewport marker
     642        Matcher centerMatcher = ImagePatternMatching.columnMatch(
     643            paintedSlippyMap,
     644            paintedSlippyMap.getWidth()/2,
     645            paletteMap,
     646            "^(d+bq+)(v+)(q+bd+)$",
     647            true
     648        );
     649        // the leftmost and rightmost columns should have an unshaded band
     650        Matcher leftMatcher = ImagePatternMatching.columnMatch(
     651            paintedSlippyMap,
     652            0,
     653            paletteMap,
     654            "^(d+)(g+)(d+)$",
     655            true
     656        );
     657        Matcher rightMatcher = ImagePatternMatching.columnMatch(
     658            paintedSlippyMap,
     659            paintedSlippyMap.getWidth()-1,
     660            paletteMap,
     661            "^(d+)(g+)(d+)$",
     662            true
     663        );
     664        // the three columns should have the unshaded band in the same place
     665        assertEquals(centerMatcher.group(1).length(), leftMatcher.group(1).length());
     666        assertEquals(centerMatcher.group(1).length(), rightMatcher.group(1).length());
     667        assertEquals(centerMatcher.group(2).length(), leftMatcher.group(2).length());
     668        assertEquals(centerMatcher.group(2).length(), rightMatcher.group(2).length());
     669
     670        // switch active layer
     671        MainApplication.getLayerManager().setActiveLayer(dataLayerA);
     672        this.paintSlippyMap();
     673
     674        // the middle column should be entirely unshaded
     675        ImagePatternMatching.columnMatch(
     676            paintedSlippyMap,
     677            paintedSlippyMap.getWidth()/2,
     678            paletteMap,
     679            "^g+bv+bg+$",
     680            true
     681        );
     682        // the middle row should have an unshaded band within the viewport marker
     683        centerMatcher = ImagePatternMatching.rowMatch(
     684            paintedSlippyMap,
     685            paintedSlippyMap.getHeight()/2,
     686            paletteMap,
     687            "^(d+bq+)(v+)(q+bd+)$",
     688            true
     689        );
     690        // the topmost and bottommost rows should have an unshaded band
     691        Matcher topMatcher = ImagePatternMatching.rowMatch(
     692            paintedSlippyMap,
     693            0,
     694            paletteMap,
     695            "^(d+)(g+)(d+)$",
     696            true
     697        );
     698        Matcher BottomMatcher = ImagePatternMatching.rowMatch(
     699            paintedSlippyMap,
     700            paintedSlippyMap.getHeight()-1,
     701            paletteMap,
     702            "^(d+)(g+)(d+)$",
     703            true
     704        );
     705        // the three rows should have the unshaded band in the same place
     706        assertEquals(centerMatcher.group(1).length(), topMatcher.group(1).length());
     707        assertEquals(centerMatcher.group(1).length(), BottomMatcher.group(1).length());
     708        assertEquals(centerMatcher.group(2).length(), topMatcher.group(2).length());
     709        assertEquals(centerMatcher.group(2).length(), BottomMatcher.group(2).length());
     710
     711        // deleting dataLayerA should hopefully switch our active layer back to dataLayerB
     712        MainApplication.getLayerManager().removeLayer(dataLayerA);
     713        this.paintSlippyMap();
     714
     715        // now we're really just repeating the same assertions we made originally when dataLayerB was active
     716        // the middle row should be entirely unshaded
     717        ImagePatternMatching.rowMatch(
     718            paintedSlippyMap,
     719            paintedSlippyMap.getHeight()/2,
     720            paletteMap,
     721            "^g+bv+bg+$",
     722            true
     723        );
     724        // the middle column should have an unshaded band within the viewport marker
     725        centerMatcher = ImagePatternMatching.columnMatch(
     726            paintedSlippyMap,
     727            paintedSlippyMap.getWidth()/2,
     728            paletteMap,
     729            "^(d+bq+)(v+)(q+bd+)$",
     730            true
     731        );
     732        // the leftmost and rightmost columns should have an unshaded band
     733        leftMatcher = ImagePatternMatching.columnMatch(
     734            paintedSlippyMap,
     735            0,
     736            paletteMap,
     737            "^(d+)(g+)(d+)$",
     738            true
     739        );
     740        rightMatcher = ImagePatternMatching.columnMatch(
     741            paintedSlippyMap,
     742            paintedSlippyMap.getWidth()-1,
     743            paletteMap,
     744            "^(d+)(g+)(d+)$",
     745            true
     746        );
     747        // the three columns should have the unshaded band in the same place
     748        assertEquals(centerMatcher.group(1).length(), leftMatcher.group(1).length());
     749        assertEquals(centerMatcher.group(1).length(), rightMatcher.group(1).length());
     750        assertEquals(centerMatcher.group(2).length(), leftMatcher.group(2).length());
     751        assertEquals(centerMatcher.group(2).length(), rightMatcher.group(2).length());
     752
     753        // but now if we expand its downloaded area to cover most of the southern hemisphere...
     754        dataSetB.addDataSource(new DataSource(new Bounds(-75., -100., 0., 100.), "Everywhere"));
     755        this.paintSlippyMap();
     756
     757        // we should see it all as unshaded.
     758        ImagePatternMatching.rowMatch(
     759            paintedSlippyMap,
     760            0,
     761            paletteMap,
     762            "^g+$",
     763            true
     764        );
     765        ImagePatternMatching.rowMatch(
     766            paintedSlippyMap,
     767            paintedSlippyMap.getHeight()/2,
     768            paletteMap,
     769            "^g+bv+bg+$",
     770            true
     771        );
     772        ImagePatternMatching.rowMatch(
     773            paintedSlippyMap,
     774            paintedSlippyMap.getHeight()-1,
     775            paletteMap,
     776            "^g+$",
     777            true
     778        );
     779        ImagePatternMatching.columnMatch(
     780            paintedSlippyMap,
     781            0,
     782            paletteMap,
     783            "^g+$",
     784            true
     785        );
     786        ImagePatternMatching.columnMatch(
     787            paintedSlippyMap,
     788            paintedSlippyMap.getWidth()/2,
     789            paletteMap,
     790            "^g+bv+bg+$",
     791            true
     792        );
     793        ImagePatternMatching.columnMatch(
     794            paintedSlippyMap,
     795            paintedSlippyMap.getWidth()-1,
     796            paletteMap,
     797            "^g+$",
     798            true
     799        );
     800    }
    387801}
  • trunk/test/unit/org/openstreetmap/josm/gui/io/AsynchronousUploadPrimitivesTaskTest.java

    r13219 r14052  
    33
    44import java.util.Optional;
     5
     6import javax.swing.JOptionPane;
    57
    68import org.junit.After;
     
    1820import org.openstreetmap.josm.io.UploadStrategySpecification;
    1921import org.openstreetmap.josm.testutils.JOSMTestRules;
     22import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
     23
     24import com.google.common.collect.ImmutableMap;
    2025
    2126import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    3742    @Rule
    3843    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    39     public JOSMTestRules test = new JOSMTestRules();
     44    public JOSMTestRules test = new JOSMTestRules().assertionsInEDT();
    4045
     46    /**
     47     * Bootstrap.
     48     */
    4149    @Before
    4250    public void bootStrap() {
     51        new JOptionPaneSimpleMocker(ImmutableMap.of(
     52            "A background upload is already in progress. Kindly wait for it to finish before uploading new changes", JOptionPane.OK_OPTION
     53        ));
     54
    4355        DataSet dataSet = new DataSet();
    4456        Node node1 = new Node();
     
    6072    }
    6173
     74    /**
     75     * Tear down.
     76     */
    6277    @After
    6378    public void tearDown() {
     
    7085    }
    7186
     87    /**
     88     * Test single upload instance.
     89     */
    7290    @Test
    7391    public void testSingleUploadInstance() {
  • trunk/test/unit/org/openstreetmap/josm/gui/preferences/advanced/ExportProfileActionTest.java

    r10378 r14052  
    22package org.openstreetmap.josm.gui.preferences.advanced;
    33
    4 import org.junit.BeforeClass;
     4import javax.swing.JOptionPane;
     5
     6import org.junit.Rule;
    57import org.junit.Test;
    6 import org.openstreetmap.josm.JOSMFixture;
    78import org.openstreetmap.josm.Main;
     9import org.openstreetmap.josm.testutils.JOSMTestRules;
     10import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
     11
     12import com.google.common.collect.ImmutableMap;
     13
     14import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    815
    916/**
     
    1118 */
    1219public class ExportProfileActionTest {
    13 
    1420    /**
    15      * Setup test.
     21     * Setup tests
    1622     */
    17     @BeforeClass
    18     public static void setUpBeforeClass() {
    19         JOSMFixture.createUnitTestFixture().init();
    20     }
     23    @Rule
     24    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     25    public JOSMTestRules test = new JOSMTestRules().preferences().assertionsInEDT();
    2126
    2227    /**
     
    2530    @Test
    2631    public void testAction() {
     32        new JOptionPaneSimpleMocker(ImmutableMap.of(
     33            "All the preferences of this group are default, nothing to save", JOptionPane.OK_OPTION
     34        ));
    2735        new ExportProfileAction(Main.pref, "foo", "bar").actionPerformed(null);
    2836        new ExportProfileAction(Main.pref, "expert", "expert").actionPerformed(null);
  • trunk/test/unit/org/openstreetmap/josm/gui/preferences/advanced/PreferencesTableTest.java

    r12884 r14052  
    99import java.util.Arrays;
    1010
    11 import org.junit.BeforeClass;
     11import javax.swing.JOptionPane;
     12
     13import org.junit.Rule;
    1214import org.junit.Test;
    13 import org.openstreetmap.josm.JOSMFixture;
     15import org.openstreetmap.josm.gui.ExtendedDialog;
     16import org.openstreetmap.josm.gui.preferences.advanced.PreferencesTable.AllSettingsTableModel;
    1417import org.openstreetmap.josm.spi.preferences.StringSetting;
    15 import org.openstreetmap.josm.gui.preferences.advanced.PreferencesTable.AllSettingsTableModel;
     18import org.openstreetmap.josm.testutils.JOSMTestRules;
     19import org.openstreetmap.josm.testutils.mockers.ExtendedDialogMocker;
     20import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
     21
     22import com.google.common.collect.ImmutableMap;
     23
     24import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    1625
    1726/**
     
    1928 */
    2029public class PreferencesTableTest {
    21 
    2230    /**
    23      * Setup test.
     31     * Setup tests
    2432     */
    25     @BeforeClass
    26     public static void setUpBeforeClass() {
    27         JOSMFixture.createUnitTestFixture().init();
    28     }
     33    @Rule
     34    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     35    public JOSMTestRules test = new JOSMTestRules().preferences().assertionsInEDT();
    2936
    3037    private static PrefEntry newPrefEntry(String value) {
     
    4350    @Test
    4451    public void testPreferencesTable() {
     52        new JOptionPaneSimpleMocker(ImmutableMap.of(
     53            "Please select the row to edit.", JOptionPane.OK_OPTION,
     54            "Please select the row to delete.", JOptionPane.OK_OPTION
     55        ));
     56        new ExtendedDialogMocker() {
     57            @Override
     58            protected int getMockResult(final ExtendedDialog instance) {
     59                if (instance.getTitle().equals("Add setting")) {
     60                    return 1 + this.getButtonPositionFromLabel(instance, "Cancel");
     61                } else {
     62                    return super.getMockResult(instance);
     63                }
     64            }
     65        };
    4566        PreferencesTable t = newTable();
    4667        t.fireDataChanged();
  • trunk/test/unit/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferenceTest.java

    r11974 r14052  
    1010import java.util.Collections;
    1111
    12 import org.junit.BeforeClass;
     12import org.junit.Rule;
    1313import org.junit.Test;
    14 import org.openstreetmap.josm.JOSMFixture;
    1514import org.openstreetmap.josm.TestUtils;
    1615import org.openstreetmap.josm.gui.preferences.PreferencesTestUtils;
     
    1918import org.openstreetmap.josm.plugins.PluginException;
    2019import org.openstreetmap.josm.plugins.PluginInformation;
     20import org.openstreetmap.josm.testutils.mockers.HelpAwareOptionPaneMocker;
     21import org.openstreetmap.josm.testutils.JOSMTestRules;
     22
     23import com.google.common.collect.ImmutableMap;
     24
     25import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    2126
    2227/**
     
    2429 */
    2530public class PluginPreferenceTest {
    26 
    2731    /**
    2832     * Setup test.
    2933     */
    30     @BeforeClass
    31     public static void setUpBeforeClass() {
    32         JOSMFixture.createUnitTestFixture().init();
    33     }
     34    @Rule
     35    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     36    public JOSMTestRules test = new JOSMTestRules().preferences().assertionsInEDT().platform();
    3437
    3538    /**
     
    4851    public static PluginInformation getDummyPluginInformation() throws PluginException {
    4952        return new PluginInformation(
    50                 new File(TestUtils.getTestDataRoot() + "plugin/dummy_plugin.jar"), "dummy_plugin");
     53                new File(TestUtils.getTestDataRoot() + "__files/plugin/dummy_plugin.v31772.jar"), "dummy_plugin");
    5154    }
    5255
     
    8992    @Test
    9093    public void testNotifyDownloadResults() {
     94        new HelpAwareOptionPaneMocker(ImmutableMap.<String, Object>builder()
     95            .put("<html></html>", "OK")  // (buildDownloadSummary() output was empty)
     96            .put("<html>Please restart JOSM to activate the downloaded plugins.</html>", "OK")
     97            .build()
     98        );
     99
    91100        PluginDownloadTask task = new PluginDownloadTask(NullProgressMonitor.INSTANCE, Collections.<PluginInformation>emptyList(), "");
    92101        PluginPreference.notifyDownloadResults(null, task, false);
  • trunk/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java

    r13812 r14052  
    33
    44import java.awt.Color;
     5import java.awt.Window;
     6import java.awt.event.WindowEvent;
    57import java.io.ByteArrayInputStream;
    68import java.io.File;
     
    810import java.security.GeneralSecurityException;
    911import java.text.MessageFormat;
     12import java.util.Arrays;
     13import java.util.Map;
    1014import java.util.TimeZone;
     15import java.util.logging.Handler;
    1116
    1217import org.junit.rules.TemporaryFolder;
     
    3742import org.openstreetmap.josm.io.OsmTransferCanceledException;
    3843import org.openstreetmap.josm.spi.preferences.Config;
     44import org.openstreetmap.josm.spi.preferences.Setting;
     45import org.openstreetmap.josm.testutils.mockers.EDTAssertionMocker;
     46import org.openstreetmap.josm.testutils.mockers.WindowlessMapViewStateMocker;
     47import org.openstreetmap.josm.testutils.mockers.WindowlessNavigatableComponentMocker;
    3948import org.openstreetmap.josm.tools.I18n;
    4049import org.openstreetmap.josm.tools.JosmRuntimeException;
     
    4453import org.openstreetmap.josm.tools.Territories;
    4554import org.openstreetmap.josm.tools.date.DateUtils;
     55
     56import org.awaitility.Awaitility;
    4657
    4758import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    6475    private String assumeRevisionString;
    6576    private Version originalVersion;
     77    private Runnable mapViewStateMockingRunnable;
     78    private Runnable navigableComponentMockingRunnable;
     79    private Runnable edtAssertionMockingRunnable;
    6680    private boolean platform;
    6781    private boolean useProjection;
     
    256270        territories();
    257271        rlTraffic = true;
     272        return this;
     273    }
     274
     275    /**
     276     * Re-raise AssertionErrors thrown in the EDT where they would have normally been swallowed.
     277     * @return this instance, for easy chaining
     278     */
     279    public JOSMTestRules assertionsInEDT() {
     280        return this.assertionsInEDT(EDTAssertionMocker::new);
     281    }
     282
     283    /**
     284     * Re-raise AssertionErrors thrown in the EDT where they would have normally been swallowed.
     285     * @param edtAssertionMockingRunnable Runnable for initializing this functionality
     286     *
     287     * @return this instance, for easy chaining
     288     */
     289    public JOSMTestRules assertionsInEDT(final Runnable edtAssertionMockingRunnable) {
     290        this.edtAssertionMockingRunnable = edtAssertionMockingRunnable;
    258291        return this;
    259292    }
     
    297330     */
    298331    public JOSMTestRules main() {
     332        return this.main(
     333            WindowlessMapViewStateMocker::new,
     334            WindowlessNavigatableComponentMocker::new
     335        );
     336    }
     337
     338    /**
     339     * Use the {@link Main#main}, {@code Main.contentPanePrivate}, {@code Main.mainPanel},
     340     *         global variables in this test.
     341     * @param mapViewStateMockingRunnable Runnable to use for mocking out any required parts of
     342     *        {@link org.openstreetmap.josm.gui.MapViewState}, null to skip.
     343     * @param navigableComponentMockingRunnable Runnable to use for mocking out any required parts
     344     *        of {@link org.openstreetmap.josm.gui.NavigatableComponent}, null to skip.
     345     *
     346     * @return this instance, for easy chaining
     347     */
     348    public JOSMTestRules main(
     349        final Runnable mapViewStateMockingRunnable,
     350        final Runnable navigableComponentMockingRunnable
     351    ) {
    299352        platform();
    300         main = true;
     353        this.main = true;
     354        this.mapViewStateMockingRunnable = mapViewStateMockingRunnable;
     355        this.navigableComponentMockingRunnable = navigableComponentMockingRunnable;
    301356        return this;
    302357    }
     
    344399     */
    345400    protected void before() throws InitializationError, ReflectiveOperationException {
    346         // Tests are running headless by default.
    347         System.setProperty("java.awt.headless", "true");
    348 
    349401        cleanUpFromJosmFixture();
    350402
     
    355407        }
    356408
     409        // Add JOSM home
     410        if (josmHome != null) {
     411            try {
     412                File home = josmHome.newFolder();
     413                System.setProperty("josm.home", home.getAbsolutePath());
     414                JosmBaseDirectories.getInstance().clearMemos();
     415            } catch (IOException e) {
     416                throw new InitializationError(e);
     417            }
     418        }
     419
    357420        Config.setPreferencesInstance(Main.pref);
    358421        Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance());
    359422        // All tests use the same timezone.
    360423        TimeZone.setDefault(DateUtils.UTC);
     424
     425        // Force log handers to reacquire reference to (junit's fake) stdout/stderr
     426        for (Handler handler : Logging.getLogger().getHandlers()) {
     427            if (handler instanceof Logging.ReacquiringConsoleHandler) {
     428                handler.flush();
     429                ((Logging.ReacquiringConsoleHandler) handler).reacquireOutputStream();
     430            }
     431        }
    361432        // Set log level to info
    362433        Logging.setLogLevel(Logging.LEVEL_INFO);
     434
    363435        // Assume anonymous user
    364436        UserIdentityManager.getInstance().setAnonymous();
     
    373445        }
    374446
    375         // Add JOSM home
    376         if (josmHome != null) {
    377             try {
    378                 File home = josmHome.newFolder();
    379                 System.setProperty("josm.home", home.getAbsolutePath());
    380             } catch (IOException e) {
    381                 throw new InitializationError(e);
    382             }
    383         }
    384 
    385447        // Add preferences
    386448        if (usePreferences) {
     449            @SuppressWarnings("unchecked")
     450            final Map<String, Setting<?>> defaultsMap = (Map<String, Setting<?>>) TestUtils.getPrivateField(Main.pref, "defaultsMap");
     451            defaultsMap.clear();
    387452            Main.pref.resetToInitialState();
    388453            Main.pref.enableSaveOnPut(false);
     
    448513        }
    449514
     515        if (this.edtAssertionMockingRunnable != null) {
     516            this.edtAssertionMockingRunnable.run();
     517        }
     518
    450519        if (commands) {
    451520            // TODO: Implement a more selective version of this once Main is restructured.
     
    453522        } else {
    454523            if (main) {
     524                // apply mockers to MapViewState and NavigableComponent whether we're headless or not
     525                // as we generally don't create the josm main window even in non-headless mode.
     526                if (this.mapViewStateMockingRunnable != null) {
     527                    this.mapViewStateMockingRunnable.run();
     528                }
     529                if (this.navigableComponentMockingRunnable != null) {
     530                    this.navigableComponentMockingRunnable.run();
     531                }
     532
    455533                new MainApplication();
    456534                JOSMFixture.initContentPane();
     
    500578    protected void after() throws ReflectiveOperationException {
    501579        // Sync AWT Thread
    502         GuiHelper.runInEDTAndWait(new Runnable() {
    503             @Override
    504             public void run() {
    505             }
    506         });
     580        GuiHelper.runInEDTAndWait(() -> { });
     581        // Sync worker thread
     582        final boolean[] queueEmpty = {false};
     583        MainApplication.worker.submit(() -> queueEmpty[0] = true);
     584        Awaitility.await().forever().until(() -> queueEmpty[0]);
    507585        // Remove all layers
    508586        cleanLayerEnvironment();
     
    517595            TestUtils.setPrivateStaticField(Version.class, "instance", this.originalVersion);
    518596        }
     597
     598        Window[] windows = Window.getWindows();
     599        if (windows.length != 0) {
     600            Logging.info(
     601                "Attempting to close {0} windows left open by tests: {1}",
     602                windows.length,
     603                Arrays.toString(windows)
     604            );
     605        }
     606        GuiHelper.runInEDTAndWait(() -> {
     607            for (Window window : windows) {
     608                window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING));
     609                window.dispose();
     610            }
     611        });
    519612
    520613        // Parts of JOSM uses weak references - destroy them.
     
    570663                    throw exception;
    571664                } else {
     665                    Logging.debug("Thread state at timeout: {0}", Thread.getAllStackTraces());
    572666                    throw new Exception(MessageFormat.format("Test timed out after {0}ms", timeout));
    573667                }
Note: See TracChangeset for help on using the changeset viewer.