Ticket #15599: v1-0006-add-ImagePatternMatching-testutil-example-use-in-.patch

File v1-0006-add-ImagePatternMatching-testutil-example-use-in-.patch, 12.3 KB (added by ris, 8 years ago)
  • test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java

    From bd836670c8280e65323d8bacbab67389ec084b6c Mon Sep 17 00:00:00 2001
    From: Robert Scott <code@humanleg.org.uk>
    Date: Sat, 25 Nov 2017 23:55:46 +0000
    Subject: [PATCH v1 6/6] add ImagePatternMatching testutil, example use in
     MinimapDialogTest
    
    ---
     .../josm/gui/dialogs/MinimapDialogTest.java        | 123 ++++++++++++
     .../josm/testutils/ImagePatternMatching.java       | 212 +++++++++++++++++++++
     2 files changed, 335 insertions(+)
     create mode 100644 test/unit/org/openstreetmap/josm/testutils/ImagePatternMatching.java
    
    diff --git a/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java b/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java
    index 4ef49923a..cf7ad372c 100644
    a b import static java.util.concurrent.TimeUnit.MILLISECONDS;  
    1111import java.awt.Color;
    1212import java.awt.Component;
    1313import java.awt.Graphics2D;
     14import java.awt.event.ComponentEvent;
    1415import java.awt.image.BufferedImage;
    1516
    1617import javax.swing.JMenuItem;
    1718import javax.swing.JPopupMenu;
    1819
     20import java.util.Arrays;
     21import java.util.Map;
    1922import java.util.concurrent.Callable;
     23import java.util.regex.Matcher;
    2024
    2125import org.junit.Rule;
    2226import org.junit.Test;
    2327import org.openstreetmap.josm.Main;
    2428import org.openstreetmap.josm.TestUtils;
     29import org.openstreetmap.josm.data.Bounds;
    2530import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
    2631import org.openstreetmap.josm.gui.bbox.SourceButton;
     32import org.openstreetmap.josm.gui.MainApplication;
     33import org.openstreetmap.josm.gui.MapView;
    2734import org.openstreetmap.josm.gui.util.GuiHelper;
     35import org.openstreetmap.josm.testutils.ImagePatternMatching;
    2836import org.openstreetmap.josm.testutils.JOSMTestRules;
    2937
    3038import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    3139
    3240import org.awaitility.Awaitility;
    3341
     42import com.google.common.collect.ImmutableMap;
     43
    3444/**
    3545 * Unit tests of {@link MinimapDialog} class.
    3646 */
    public class MinimapDialogTest {  
    251261
    252262        assertEquals(0xffffffff, paintedSlippyMap.getRGB(0, 0));
    253263    }
     264
     265    /**
     266     * ...
     267     * @throws Exception if any error occurs
     268     */
     269    @Test
     270    public void testViewportAspectRatio() throws Exception {
     271        Main.pref.put("slippy_map_chooser.mapstyle", "White Tiles");
     272
     273        MapView mapView = MainApplication.getMap().mapView;
     274        GuiHelper.runInEDTAndWaitWithException(() -> {
     275            mapView.setVisible(true);
     276            mapView.addNotify();
     277            mapView.doLayout();
     278            // ensure we have a square mapView viewport
     279            mapView.setBounds(0, 0, 350, 350);
     280            // TODO ensure we're in the right projection
     281        });
     282
     283        this.setUpMiniMap();
     284
     285        // attempt to set viewport to cover a non-square area
     286        mapView.zoomTo(new Bounds(26.27, -18.23, 26.275, -18.229));
     287
     288        // an initial paint operation is required to trigger the tile fetches
     289        this.paintSlippyMap();
     290
     291        Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
     292
     293        this.paintSlippyMap();
     294
     295        Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder()
     296            .put(0xffffffff, "w")
     297            .put(0xff000000, "b")
     298            .put(0xfff0d1d1, "p")
     299            .build();
     300
     301        Matcher rowMatcher = ImagePatternMatching.rowMatch(
     302            paintedSlippyMap,
     303            paintedSlippyMap.getHeight()/2,
     304            paletteMap,
     305            "^(w+)b(p+)b(w+)$",
     306            true
     307        );
     308
     309        // (within a tolerance for numerical error) the number of pixels on the left of the viewport marker
     310        // should equal the number on the right
     311        assertTrue(
     312            "Viewport marker not horizontally centered",
     313            Math.abs(rowMatcher.group(1).length() - rowMatcher.group(3).length()) < 4
     314        );
     315
     316        Matcher colMatcher = ImagePatternMatching.columnMatch(
     317            paintedSlippyMap,
     318            paintedSlippyMap.getWidth()/2,
     319            paletteMap,
     320            "^(w+)b(p+)b(w+)$",
     321            true
     322        );
     323
     324        // (within a tolerance for numerical error) the number of pixels on the top of the viewport marker
     325        // should equal the number on the bottom
     326        assertTrue(
     327            "Viewport marker not vertically centered",
     328            Math.abs(colMatcher.group(1).length() - colMatcher.group(3).length()) < 4
     329        );
     330
     331        // (within a tolerance for numerical error) the viewport marker should be square
     332        assertTrue(
     333            "Viewport marker not square",
     334            Math.abs(colMatcher.group(2).length() - rowMatcher.group(2).length()) < 4
     335        );
     336
     337        GuiHelper.runInEDTAndWaitWithException(() -> {
     338            mapView.setBounds(0, 0, 150, 300);
     339            Arrays.stream(mapView.getComponentListeners()).forEach(
     340                cl -> cl.componentResized(new ComponentEvent(mapView, ComponentEvent.COMPONENT_RESIZED))
     341            );
     342        });
     343        // minimap doesn't (yet?) listen for component resize events to update its viewport marker, so
     344        // trigger a zoom change
     345        mapView.zoomTo(mapView.getCenter());
     346        this.paintSlippyMap();
     347
     348        rowMatcher = ImagePatternMatching.rowMatch(
     349            paintedSlippyMap,
     350            paintedSlippyMap.getHeight()/2,
     351            paletteMap,
     352            "^(w+)b(p+)b(w+)$",
     353            true
     354        );
     355        assertTrue(
     356            "Viewport marker not horizontally centered",
     357            Math.abs(rowMatcher.group(1).length() - rowMatcher.group(3).length()) < 4
     358        );
     359
     360        colMatcher = ImagePatternMatching.columnMatch(
     361            paintedSlippyMap,
     362            paintedSlippyMap.getWidth()/2,
     363            paletteMap,
     364            "^(w+)b(p+)b(w+)$",
     365            true
     366        );
     367        assertTrue(
     368            "Viewport marker not vertically centered",
     369            Math.abs(colMatcher.group(1).length() - colMatcher.group(3).length()) < 4
     370        );
     371
     372        assertTrue(
     373            "Viewport marker not 2:1 aspect ratio",
     374            Math.abs(colMatcher.group(2).length() - (rowMatcher.group(2).length()*2.0)) < 5
     375        );
     376    }
    254377}
  • new file test/unit/org/openstreetmap/josm/testutils/ImagePatternMatching.java

    diff --git a/test/unit/org/openstreetmap/josm/testutils/ImagePatternMatching.java b/test/unit/org/openstreetmap/josm/testutils/ImagePatternMatching.java
    new file mode 100644
    index 000000000..035627bfc
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.testutils;
     3
     4import static org.junit.Assert.fail;
     5
     6import java.awt.image.BufferedImage;
     7
     8import java.util.Arrays;
     9import java.util.HashMap;
     10import java.util.Map;
     11import java.util.Optional;
     12import java.util.function.IntFunction;
     13import java.util.regex.Matcher;
     14import java.util.regex.Pattern;
     15import java.util.stream.Collectors;
     16
     17/**
     18 * Utilities to aid in making assertions about images using regular expressions.
     19 */
     20public final class ImagePatternMatching {
     21    private ImagePatternMatching() {}
     22
     23    private static final Map<String, Pattern> patternCache = new HashMap<String, Pattern>();
     24
     25    private static Matcher imageStripPatternMatchInner(
     26        final BufferedImage image,
     27        final int columnOrRowIndex,
     28        IntFunction<String> paletteMapFn,
     29        final Map<Integer, String> paletteMap,
     30        Pattern pattern,
     31        final String patternString,
     32        final boolean isColumn,
     33        final boolean assertMatch
     34    ) {
     35        paletteMapFn = Optional.ofNullable(paletteMapFn)
     36            // using "#" as the default "unmapped" character as it can be used in regexes without escaping
     37            .orElse(i -> paletteMap.getOrDefault(i, "#"));
     38        pattern = Optional.ofNullable(pattern)
     39            .orElseGet(() -> patternCache.computeIfAbsent(patternString, k -> Pattern.compile(k)));
     40
     41        int[] columnOrRow = isColumn
     42            ? image.getRGB(columnOrRowIndex, 0, 1, image.getHeight(), null, 0, 1)
     43            : image.getRGB(0, columnOrRowIndex, image.getWidth(), 1, null, 0, image.getWidth());
     44
     45        String stringRepr = Arrays.stream(columnOrRow).mapToObj(paletteMapFn).collect(Collectors.joining());
     46        Matcher result = pattern.matcher(stringRepr);
     47
     48        if (assertMatch && !result.matches()) {
     49            System.err.println(String.format("Full strip failing to match pattern %s: %s", pattern, stringRepr));
     50            fail(String.format(
     51                "%s %d failed to match pattern %s",
     52                isColumn ? "Column" : "Row",
     53                columnOrRowIndex,
     54                pattern
     55            ));
     56        }
     57
     58        return result;
     59    }
     60
     61    public static Matcher columnMatch(
     62        final BufferedImage image,
     63        final int rowNumber,
     64        final Map<Integer, String> paletteMap,
     65        final String patternString,
     66        final boolean assertMatch
     67    ) {
     68        return imageStripPatternMatchInner(
     69            image,
     70            rowNumber,
     71            null,
     72            paletteMap,
     73            null,
     74            patternString,
     75            true,
     76            true
     77        );
     78    }
     79
     80    public static Matcher columnMatch(
     81        final BufferedImage image,
     82        final int rowNumber,
     83        final IntFunction<String> paletteMapFn,
     84        final String patternString,
     85        final boolean assertMatch
     86    ) {
     87        return imageStripPatternMatchInner(
     88            image,
     89            rowNumber,
     90            paletteMapFn,
     91            null,
     92            null,
     93            patternString,
     94            true,
     95            true
     96        );
     97    }
     98
     99    public static Matcher columnMatch(
     100        final BufferedImage image,
     101        final int rowNumber,
     102        final Map<Integer, String> paletteMap,
     103        final Pattern pattern,
     104        final boolean assertMatch
     105    ) {
     106        return imageStripPatternMatchInner(
     107            image,
     108            rowNumber,
     109            null,
     110            paletteMap,
     111            pattern,
     112            null,
     113            true,
     114            true
     115        );
     116    }
     117
     118    public static Matcher columnMatch(
     119        final BufferedImage image,
     120        final int rowNumber,
     121        final IntFunction<String> paletteMapFn,
     122        final Pattern pattern,
     123        final boolean assertMatch
     124    ) {
     125        return imageStripPatternMatchInner(
     126            image,
     127            rowNumber,
     128            paletteMapFn,
     129            null,
     130            pattern,
     131            null,
     132            true,
     133            true
     134        );
     135    }
     136
     137    public static Matcher rowMatch(
     138        final BufferedImage image,
     139        final int rowNumber,
     140        final Map<Integer, String> paletteMap,
     141        final String patternString,
     142        final boolean assertMatch
     143    ) {
     144        return imageStripPatternMatchInner(
     145            image,
     146            rowNumber,
     147            null,
     148            paletteMap,
     149            null,
     150            patternString,
     151            false,
     152            true
     153        );
     154    }
     155
     156    public static Matcher rowMatch(
     157        final BufferedImage image,
     158        final int rowNumber,
     159        final IntFunction<String> paletteMapFn,
     160        final String patternString,
     161        final boolean assertMatch
     162    ) {
     163        return imageStripPatternMatchInner(
     164            image,
     165            rowNumber,
     166            paletteMapFn,
     167            null,
     168            null,
     169            patternString,
     170            false,
     171            true
     172        );
     173    }
     174
     175    public static Matcher rowMatch(
     176        final BufferedImage image,
     177        final int rowNumber,
     178        final Map<Integer, String> paletteMap,
     179        final Pattern pattern,
     180        final boolean assertMatch
     181    ) {
     182        return imageStripPatternMatchInner(
     183            image,
     184            rowNumber,
     185            null,
     186            paletteMap,
     187            pattern,
     188            null,
     189            false,
     190            true
     191        );
     192    }
     193
     194    public static Matcher rowMatch(
     195        final BufferedImage image,
     196        final int rowNumber,
     197        final IntFunction<String> paletteMapFn,
     198        final Pattern pattern,
     199        final boolean assertMatch
     200    ) {
     201        return imageStripPatternMatchInner(
     202            image,
     203            rowNumber,
     204            paletteMapFn,
     205            null,
     206            pattern,
     207            null,
     208            false,
     209            true
     210        );
     211    }
     212}