Changeset 18875 in josm


Ignore:
Timestamp:
2023-10-23T21:06:35+02:00 (13 months ago)
Author:
taylor.smock
Message:

Fix #23238: Some MapCSS functions cause NPEs when part of fixAdd

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Functions.java

    r18829 r18875  
    4343import org.openstreetmap.josm.tools.RightAndLefthandTraffic;
    4444import org.openstreetmap.josm.tools.RotationAngle;
     45import org.openstreetmap.josm.tools.RotationAngle.WayDirectionRotationAngle;
    4546import org.openstreetmap.josm.tools.StreamUtils;
    4647import org.openstreetmap.josm.tools.Territories;
    4748import org.openstreetmap.josm.tools.Utils;
    48 import org.openstreetmap.josm.tools.RotationAngle.WayDirectionRotationAngle;
    4949
    5050/**
     
    411411     */
    412412    public static List<String> tag_regex(final Environment env, String keyRegex, String flags) {
     413        if (env.osm == null) {
     414            return Collections.emptyList();
     415        }
    413416        int f = parse_regex_flags(flags);
    414417        Pattern compiled = Pattern.compile(keyRegex, f);
     
    626629     */
    627630    public static boolean has_tag_key(final Environment env, String key) {
    628         return env.osm.hasKey(key);
     631        return env.osm != null ? env.osm.hasKey(key) : false;
    629632    }
    630633
     
    941944     */
    942945    public static long osm_id(final Environment env) {
    943         return env.osm.getUniqueId();
     946        return env.osm != null ? env.osm.getUniqueId() : 0;
    944947    }
    945948
     
    952955     */
    953956    public static String osm_user_name(final Environment env) {
    954         return env.osm.getUser().getName();
     957        return env.osm != null ? env.osm.getUser().getName() : null;
    955958    }
    956959
     
    963966     */
    964967    public static long osm_user_id(final Environment env) {
    965         return env.osm.getUser().getId();
     968        return env.osm != null ? env.osm.getUser().getId() : 0;
    966969    }
    967970
     
    974977     */
    975978    public static int osm_version(final Environment env) {
    976         return env.osm.getVersion();
     979        return env.osm != null ? env.osm.getVersion() : 0;
    977980    }
    978981
     
    985988     */
    986989    public static int osm_changeset_id(final Environment env) {
    987         return env.osm.getChangesetId();
     990        return env.osm != null ? env.osm.getChangesetId() : 0;
    988991    }
    989992
     
    996999     */
    9971000    public static int osm_timestamp(final Environment env) {
    998         return env.osm.getRawTimestamp();
     1001        return env.osm != null ? env.osm.getRawTimestamp() : 0;
    9991002    }
    10001003
     
    11971200     */
    11981201    public static boolean is_right_hand_traffic(Environment env) {
    1199         return RightAndLefthandTraffic.isRightHandTraffic(center(env));
     1202        final LatLon center = center(env);
     1203        if (center != null) {
     1204            return RightAndLefthandTraffic.isRightHandTraffic(center);
     1205        }
     1206        return false;
    12001207    }
    12011208
     
    12611268     */
    12621269    public static int number_of_tags(Environment env) {
    1263         return env.osm.getNumKeys();
     1270        return env.osm != null ? env.osm.getNumKeys() : 0;
    12641271    }
    12651272
     
    12711278     */
    12721279    public static Object setting(Environment env, String key) {
    1273         return env.source.settingValues.get(key);
     1280        return env.source != null ? env.source.settingValues.get(key) : null;
    12741281    }
    12751282
     
    12811288     */
    12821289    public static LatLon center(Environment env) {
    1283         return env.osm instanceof Node ? ((Node) env.osm).getCoor() : env.osm.getBBox().getCenter();
     1290        if (env.osm instanceof ILatLon) {
     1291            return new LatLon(((ILatLon) env.osm).lat(), ((ILatLon) env.osm).lon());
     1292        } else if (env.osm != null) {
     1293            return env.osm.getBBox().getCenter();
     1294        }
     1295        return null;
    12841296    }
    12851297
     
    13161328     */
    13171329    public static boolean at(Environment env, double lat, double lon) {
    1318         return new LatLon(lat, lon).equalsEpsilon(center(env), ILatLon.MAX_SERVER_PRECISION);
     1330        final ILatLon center = center(env);
     1331        if (center != null) {
     1332            return new LatLon(lat, lon).equalsEpsilon(center, ILatLon.MAX_SERVER_PRECISION);
     1333        }
     1334        return false;
    13191335    }
    13201336
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/FunctionsTest.java

    r18870 r18875  
    33
    44import static org.junit.jupiter.api.Assertions.assertAll;
     5import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    56import static org.junit.jupiter.api.Assertions.assertEquals;
    67import static org.junit.jupiter.api.Assertions.assertFalse;
     
    910import static org.junit.jupiter.api.Assertions.assertSame;
    1011import static org.junit.jupiter.api.Assertions.assertTrue;
     12import static org.junit.jupiter.api.Assertions.fail;
    1113import static org.openstreetmap.josm.data.osm.OsmPrimitiveType.NODE;
    1214
     15import java.lang.reflect.Method;
     16import java.lang.reflect.Modifier;
    1317import java.util.Arrays;
    1418import java.util.Collections;
    1519import java.util.List;
    1620import java.util.Objects;
    17 
     21import java.util.stream.Stream;
     22
     23import org.junit.jupiter.api.AfterAll;
    1824import org.junit.jupiter.api.Test;
     25import org.junit.jupiter.params.ParameterizedTest;
     26import org.junit.jupiter.params.provider.MethodSource;
    1927import org.openstreetmap.josm.TestUtils;
    2028import org.openstreetmap.josm.data.coor.LatLon;
     
    3038import org.openstreetmap.josm.data.preferences.NamedColorProperty;
    3139import org.openstreetmap.josm.gui.mappaint.Environment;
     40import org.openstreetmap.josm.gui.mappaint.MultiCascade;
    3241import org.openstreetmap.josm.gui.util.GuiHelper;
    3342import org.openstreetmap.josm.spi.preferences.Config;
     
    3544import org.openstreetmap.josm.testutils.annotations.MapPaintStyles;
    3645import org.openstreetmap.josm.testutils.annotations.Projection;
     46import org.openstreetmap.josm.testutils.annotations.Territories;
    3747
    3848/**
     
    6272            return new Environment(osm);
    6373        }
     74    }
     75
     76    private static Method[] FUNCTIONS;
     77
     78    static Stream<Method> getFunctions() {
     79        if (FUNCTIONS == null) {
     80            FUNCTIONS = Stream.of(Functions.class.getDeclaredMethods())
     81                    .filter(m -> Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers()))
     82                    .toArray(Method[]::new);
     83        }
     84        return Stream.of(FUNCTIONS);
     85    }
     86
     87    @AfterAll
     88    static void tearDown() {
     89        FUNCTIONS = null;
    6490    }
    6591
     
    231257        assertTrue(Functions.parent_osm_primitives(env, "type2").isEmpty());
    232258    }
     259
     260    /**
     261     * Non-regression test for #23238: NPE when env.osm is null
     262     */
     263    @ParameterizedTest
     264    @MethodSource("getFunctions")
     265    @Territories // needed for inside, outside, is_right_hand_traffic
     266    void testNonRegression23238(Method function) {
     267        if (function.getParameterCount() >= 1 && function.getParameterTypes()[0].isAssignableFrom(Environment.class)
     268         && !function.getParameterTypes()[0].equals(Object.class)) {
     269            Environment nullOsmEnvironment = new Environment();
     270            nullOsmEnvironment.mc = new MultiCascade();
     271            Object[] args = new Object[function.getParameterCount()];
     272            args[0] = nullOsmEnvironment;
     273            for (int i = 1; i < function.getParameterCount(); i++) {
     274                final Class<?> type = function.getParameterTypes()[i];
     275                if (String.class.isAssignableFrom(type)) {
     276                    args[i] = "";
     277                } else if (String[].class.isAssignableFrom(type)) {
     278                    args[i] = new String[] {"{0}", ""}; // join and tr require at least 2 arguments
     279                } else if (Double.class.isAssignableFrom(type) || double.class.isAssignableFrom(type)) {
     280                    args[i] = 0d;
     281                } else if (Object.class.isAssignableFrom(type)) {
     282                    args[i] = new Object[0];
     283                } else {
     284                    fail(type.getCanonicalName());
     285                }
     286            }
     287            assertDoesNotThrow(() -> function.invoke(null, args));
     288        }
     289    }
    233290}
Note: See TracChangeset for help on using the changeset viewer.