Changeset 19201 in josm for trunk


Ignore:
Timestamp:
2024-08-19T23:47:08+02:00 (5 months ago)
Author:
taylor.smock
Message:

Fix #23290: Exclude incomplete relations from region checks

Also rework TagCheckerTest to use parameterized tests.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

    r19195 r19201  
    184184    private static final int MAX_LEVENSHTEIN_DISTANCE = 2;
    185185
     186    /* Common string values */
     187    private static final String FIXME_STR = marktr("fixme");
     188    private static final String MULTIPOLYGON_TAGS = marktr("Multipolygon tags");
     189    private static final String SEAMARK_TYPE = "seamark:type";
     190
    186191    protected boolean includeOtherSeverity;
    187192
     
    293298                BufferedReader reader = cf.getContentReader()
    294299            ) {
    295                 String okValue = null;
    296                 boolean tagcheckerfile = false;
    297                 boolean ignorefile = false;
    298                 boolean isFirstLine = true;
    299                 String line;
    300                 while ((line = reader.readLine()) != null) {
    301                     if (line.isEmpty()) {
    302                         // ignore
    303                     } else if (line.startsWith("#")) {
    304                         if (line.startsWith("# JOSM TagChecker")) {
    305                             tagcheckerfile = true;
    306                             Logging.error(tr("Ignoring {0}. Support was dropped", source));
    307                         } else
    308                         if (line.startsWith("# JOSM IgnoreTags")) {
    309                             ignorefile = true;
    310                             if (!DEFAULT_SOURCES.contains(source)) {
    311                                 Logging.info(tr("Adding {0} to ignore tags", source));
    312                             }
    313                         }
    314                     } else if (ignorefile) {
    315                         parseIgnoreFileLine(source, line);
    316                     } else if (tagcheckerfile) {
    317                         // ignore
    318                     } else if (line.charAt(0) == '+') {
    319                         okValue = line.substring(1);
    320                     } else if (line.charAt(0) == '-' && okValue != null) {
    321                         String hk = harmonizeKey(line.substring(1));
    322                         if (!okValue.equals(hk) && harmonizedKeys.put(hk, okValue) != null && Logging.isDebugEnabled()) {
    323                             Logging.debug("Line was ignored: " + line);
    324                         }
    325                     } else {
    326                         Logging.error(tr("Invalid spellcheck line: {0}", line));
    327                     }
    328                     if (isFirstLine) {
    329                         isFirstLine = false;
    330                         if (!(tagcheckerfile || ignorefile) && !DEFAULT_SOURCES.contains(source)) {
    331                             Logging.info(tr("Adding {0} to spellchecker", source));
    332                         }
    333                     }
    334                 }
     300                parseSource(source, reader);
    335301            } catch (IOException e) {
    336302                Logging.error(e);
     
    343309                    "Could not access data file:\n{0}",
    344310                    "Could not access data files:\n{0}", errorSources.length(), errorSources));
     311    }
     312
     313    private static void parseSource(String source, BufferedReader reader) throws IOException {
     314        String okValue = null;
     315        boolean tagcheckerfile = false;
     316        boolean ignorefile = false;
     317        boolean isFirstLine = true;
     318        String line;
     319        while ((line = reader.readLine()) != null) {
     320            if (line.isEmpty()) {
     321                // ignore
     322            } else if (line.startsWith("#")) {
     323                if (line.startsWith("# JOSM TagChecker")) {
     324                    tagcheckerfile = true;
     325                    Logging.error(tr("Ignoring {0}. Support was dropped", source));
     326                } else
     327                if (line.startsWith("# JOSM IgnoreTags")) {
     328                    ignorefile = true;
     329                    if (!DEFAULT_SOURCES.contains(source)) {
     330                        Logging.info(tr("Adding {0} to ignore tags", source));
     331                    }
     332                }
     333            } else if (ignorefile) {
     334                parseIgnoreFileLine(source, line);
     335            } else if (tagcheckerfile) {
     336                // ignore
     337            } else if (line.charAt(0) == '+') {
     338                okValue = line.substring(1);
     339            } else if (line.charAt(0) == '-' && okValue != null) {
     340                String hk = harmonizeKey(line.substring(1));
     341                if (!okValue.equals(hk) && harmonizedKeys.put(hk, okValue) != null && Logging.isDebugEnabled()) {
     342                    Logging.debug("Line was ignored: " + line);
     343                }
     344            } else {
     345                Logging.error(tr("Invalid spellcheck line: {0}", line));
     346            }
     347            if (isFirstLine) {
     348                isFirstLine = false;
     349                if (!(tagcheckerfile || ignorefile) && !DEFAULT_SOURCES.contains(source)) {
     350                    Logging.info(tr("Adding {0} to spellchecker", source));
     351                }
     352            }
     353        }
    345354    }
    346355
     
    435444        additionalPresetsValueData.addAll(Config.getPref().getList(
    436445                ValidatorPrefHelper.PREFIX + ".knownkeys",
    437                 Arrays.asList("is_in", "int_ref", "fixme", "population")));
     446                Arrays.asList("is_in", "int_ref", FIXME_STR, "population")));
    438447    }
    439448
     
    584593     * @deprecated since 18281 -- use {@link TaggingPresets#isKeyInPresets(String)} instead
    585594     */
    586     @Deprecated
     595    @Deprecated(since = "18281", forRemoval = true)
    587596    public static boolean isKeyInPresets(String key) {
    588597        return TaggingPresets.isKeyInPresets(key);
     
    667676            if (checkFixmes && key != null && !Utils.isEmpty(value) && isFixme(key, value) && !withErrors.contains(p, "FIXME")) {
    668677                errors.add(TestError.builder(this, Severity.OTHER, FIXME)
    669                         .message(tr("fixme"))
     678                        .message(tr(FIXME_STR))
    670679                        .primitives(p)
    671680                        .build());
     
    867876            return ((IWay<?>) primitive).getNodes().stream().anyMatch(n -> primitiveInRegions(n, regions, excludeRegions));
    868877        } else if (primitive instanceof IRelation) {
    869             return ((IRelation<?>) primitive).getMemberPrimitivesList().stream().anyMatch(p -> primitiveInRegions(p, regions, excludeRegions));
     878            final IRelation<?> relation = (IRelation<?>) primitive;
     879            if (relation.hasIncompleteMembers()) {
     880                return true; // Assume that the relation has members in a valid area. See #23290.
     881            }
     882            return relation.getMemberPrimitivesList().stream().anyMatch(p -> primitiveInRegions(p, regions, excludeRegions));
    870883        }
    871884        throw new IllegalArgumentException("Unknown primitive type: " + primitive);
     
    904917            // accept often used tag surface=* as area tag
    905918            builder = TestError.builder(this, Severity.OTHER, MULTIPOLYGON_INCOMPLETE)
    906                     .message(tr("Multipolygon tags"), marktr("only {0} tag"), "surface");
     919                    .message(tr(MULTIPOLYGON_TAGS), marktr("only {0} tag"), "surface");
    907920        } else {
    908921            Map<String, String> filteredTags = p.getInterestingTags();
     
    913926            if (filteredTags.isEmpty()) {
    914927                builder = TestError.builder(this, Severity.ERROR, MULTIPOLYGON_NO_AREA)
    915                         .message(tr("Multipolygon tags"), marktr("tag describing the area is missing"), new Object());
     928                        .message(tr(MULTIPOLYGON_TAGS), marktr("tag describing the area is missing"), new Object());
    916929
    917930            }
     
    920933            // multipolygon has either no area tag or a rarely used one
    921934            builder = TestError.builder(this, Severity.WARNING, MULTIPOLYGON_MAYBE_NO_AREA)
    922                     .message(tr("Multipolygon tags"), marktr("tag describing the area might be missing"), new Object());
     935                    .message(tr(MULTIPOLYGON_TAGS), marktr("tag describing the area might be missing"), new Object());
    923936        }
    924937        errors.add(builder.primitives(p).build());
     
    984997                || p.hasTag("indoor", "corridor", "room", "area")
    985998                || p.hasTag("power", "substation", "generator", "plant", "switchgear", "converter", "sub_station")
    986                 || p.hasTag("seamark:type", "harbour", "fairway", "anchorage", "landmark", "berth", "harbour_basin",
     999                || p.hasTag(SEAMARK_TYPE, "harbour", "fairway", "anchorage", "landmark", "berth", "harbour_basin",
    9871000                        "separation_zone")
    988                 || (p.get("seamark:type") != null && p.get("seamark:type").matches(".*\\_(area|zone)$")))
     1001                || (p.get(SEAMARK_TYPE) != null && p.get(SEAMARK_TYPE).matches(".*\\_(area|zone)$")))
    9891002            return true;
    9901003        return p.hasTag("harbour", OsmUtils.TRUE_VALUE)
     
    12591272
    12601273    private static boolean isFixme(String key, String value) {
    1261         return key.toLowerCase(Locale.ENGLISH).contains("fixme") || key.contains("todo")
    1262           || value.toLowerCase(Locale.ENGLISH).contains("fixme") || value.contains("check and delete");
     1274        return key.toLowerCase(Locale.ENGLISH).contains(FIXME_STR) || key.contains("todo")
     1275          || value.toLowerCase(Locale.ENGLISH).contains(FIXME_STR) || value.contains("check and delete");
    12631276    }
    12641277
  • trunk/test/unit/org/openstreetmap/josm/data/validation/tests/TagCheckerTest.java

    r19195 r19201  
    77
    88import java.io.IOException;
     9import java.text.MessageFormat;
    910import java.util.Collections;
    1011import java.util.List;
    1112import java.util.function.Consumer;
    1213import java.util.stream.Collectors;
     14import java.util.stream.Stream;
    1315
    1416import org.junit.jupiter.api.Assertions;
    15 import org.junit.jupiter.api.Disabled;
    1617import org.junit.jupiter.api.Test;
     18import org.junit.jupiter.params.ParameterizedTest;
     19import org.junit.jupiter.params.provider.Arguments;
     20import org.junit.jupiter.params.provider.MethodSource;
    1721import org.openstreetmap.josm.TestUtils;
     22import org.openstreetmap.josm.data.coor.LatLon;
     23import org.openstreetmap.josm.data.osm.DataSet;
     24import org.openstreetmap.josm.data.osm.Node;
    1825import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1926import org.openstreetmap.josm.data.osm.OsmUtils;
     27import org.openstreetmap.josm.data.osm.Relation;
     28import org.openstreetmap.josm.data.osm.RelationMember;
    2029import org.openstreetmap.josm.data.osm.Tag;
     30import org.openstreetmap.josm.data.osm.Way;
    2131import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
    2232import org.openstreetmap.josm.data.validation.Severity;
     
    4454        checker.initialize();
    4555        checker.startTest(null);
    46         checker.check(TestUtils.addFakeDataSet(primitive));
     56        if (primitive.getDataSet() == null) {
     57            TestUtils.addFakeDataSet(primitive);
     58        }
     59        checker.check(primitive);
    4760        return checker.getErrors();
    4861    }
    4962
    50     /**
    51      * Check for misspelled key.
    52      * @throws IOException if any I/O error occurs
    53      */
    54     @Test
    55     void testMisspelledKey1() throws IOException {
    56         final List<TestError> errors = test(OsmUtils.createPrimitive("node Name=Main"));
     63    static Stream<Arguments> testTags() {
     64        final String misspelled = "Misspelled property key";
     65        final String unknown = "Unknown property value";
     66        final String noPropertyValue = "Presets do not contain property value";
     67        final String looksLike = "Key ''{0}'' looks like ''{1}''.";
     68        final String invalidPreset = "Key from a preset is invalid in this region";
     69        return Stream.of(
     70                // Check for misspelled key.
     71                Arguments.of("testMisspelledKey1", "node Name=Main", misspelled,
     72                        MessageFormat.format(looksLike, "Name", "name"), Severity.WARNING, true),
     73                // Check for misspelled key.
     74                Arguments.of("testMisspelledKey2", "node landuse;=forest", misspelled,
     75                        MessageFormat.format(looksLike, "landuse;", "landuse"), Severity.WARNING, true),
     76                // Check for misspelled key where the suggested alternative is in use. The error should not be fixable.
     77                Arguments.of("testMisspelledKeyButAlternativeInUse", "node amenity=fuel brand=bah Brand=foo", misspelled,
     78                        MessageFormat.format(looksLike, "Brand", "brand"), Severity.WARNING, false),
     79                // Check for misspelled key where the suggested alternative is given with prefix E: in ignoreTags.cfg.
     80                // The error should be fixable.
     81                // ticket 17468
     82                Arguments.of("testUpperCaseIgnoredKey", "node wheelchair:Description=bla", misspelled,
     83                        MessageFormat.format(looksLike, "wheelchair:Description", "wheelchair:description"), Severity.WARNING, true),
     84                // Check for misspelled key where the suggested alternative is given with prefix K: in ignoreTags.cfg.
     85                // The error should be fixable.
     86                // ticket 17468
     87                Arguments.of("testUpperCaseInKeyIgnoredTag", "node land_Area=administrative", misspelled,
     88                        MessageFormat.format(looksLike, "land_Area", "land_area"), Severity.WARNING, true),
     89                // Check for unknown key
     90                Arguments.of("testTranslatedNameKey", "node namez=Baz",
     91                        "Presets do not contain property key", "Key 'namez' not in presets.", Severity.OTHER, false),
     92                // Check for misspelled value
     93                Arguments.of("testMisspelledTag", "node landuse=forrest", unknown,
     94                        "Value 'forrest' for key 'landuse' is unknown, maybe 'forest' is meant?", Severity.WARNING, false),
     95                // Check for misspelled value with multiple alternatives in presets.
     96                Arguments.of("testMisspelledTag2", "node highway=servics", unknown,
     97                        "Value 'servics' for key 'highway' is unknown, maybe one of [service, services] is meant?", Severity.WARNING, false),
     98                // Check for misspelled value.
     99                Arguments.of("testMisspelledTag3", "node highway=residentail", unknown,
     100                        "Value 'residentail' for key 'highway' is unknown, maybe 'residential' is meant?", Severity.WARNING, false),
     101                // Check for misspelled value.
     102                Arguments.of("testShortValNotInPreset2", "node shop=abs", noPropertyValue,
     103                        "Value 'abs' for key 'shop' not in presets.", Severity.OTHER, false),
     104                // Check regression: Don't fix surface=u -> surface=mud.
     105                Arguments.of("testTooShortToFix", "node surface=u", noPropertyValue,
     106                        "Value 'u' for key 'surface' not in presets.", Severity.OTHER, false),
     107                // Check value with upper case
     108                Arguments.of("testValueDifferentCase", "node highway=Residential", unknown,
     109                        "Value 'Residential' for key 'highway' is unknown, maybe 'residential' is meant?", Severity.WARNING, false),
     110                Arguments.of("testRegionKey", "node payment:ep_avant=yes", invalidPreset,
     111                        "Preset Payment Methods should not have the key payment:ep_avant", Severity.WARNING, false),
     112                Arguments.of("testRegionTag", "relation type=waterway gnis:feature_id=123456", invalidPreset,
     113                        "Preset Waterway should not have the key gnis:feature_id", Severity.WARNING, false),
     114                // Key in presets but not in ignored.cfg. Caused a NPE with r14727.
     115                Arguments.of("testRegression17246", "node access=privat", unknown,
     116                        "Value 'privat' for key 'access' is unknown, maybe 'private' is meant?", Severity.WARNING, false)
     117        );
     118    }
     119
     120    /**
     121     * Test tags
     122     * @param name The name of the test
     123     * @param primitive The primitive definition to use
     124     * @param expectedMessage The expected error message
     125     * @param expectedDescription The expected error description
     126     * @param severity The expected severity
     127     * @param isFixable {@code true} if the error should be fixable
     128     * @throws IOException See {@link #test(OsmPrimitive)}
     129     */
     130    @ParameterizedTest(name = "{0}")
     131    @MethodSource("testTags")
     132    void testTags(String name, String primitive, String expectedMessage, String expectedDescription, Severity severity, boolean isFixable)
     133            throws IOException {
     134        final List<TestError> errors = test(OsmUtils.createPrimitive(primitive));
    57135        assertEquals(1, errors.size());
    58         assertEquals("Misspelled property key", errors.get(0).getMessage());
    59         assertEquals("Key 'Name' looks like 'name'.", errors.get(0).getDescription());
    60         assertTrue(errors.get(0).isFixable());
    61     }
    62 
    63     /**
    64      * Check for misspelled key.
    65      * @throws IOException if any I/O error occurs
    66      */
    67     @Test
    68     void testMisspelledKey2() throws IOException {
    69         final List<TestError> errors = test(OsmUtils.createPrimitive("node landuse;=forest"));
    70         assertEquals(1, errors.size());
    71         assertEquals("Misspelled property key", errors.get(0).getMessage());
    72         assertEquals("Key 'landuse;' looks like 'landuse'.", errors.get(0).getDescription());
    73         assertTrue(errors.get(0).isFixable());
    74     }
    75 
    76     /**
    77      * Check for misspelled key where the suggested alternative is in use. The error should not be fixable.
    78      * @throws IOException if any I/O error occurs
    79      */
    80     @Test
    81     void testMisspelledKeyButAlternativeInUse() throws IOException {
    82         // ticket 12329
    83         final List<TestError> errors = test(OsmUtils.createPrimitive("node amenity=fuel brand=bah Brand=foo"));
    84         assertEquals(1, errors.size());
    85         assertEquals("Misspelled property key", errors.get(0).getMessage());
    86         assertEquals("Key 'Brand' looks like 'brand'.", errors.get(0).getDescription());
    87         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    88         assertFalse(errors.get(0).isFixable());
    89     }
    90 
    91     /**
    92      * Check for misspelled key where the suggested alternative is given with prefix E: in ignoreTags.cfg.
    93      * The error should be fixable.
    94      * @throws IOException if any I/O error occurs
    95      */
    96     @Test
    97     void testUpperCaseIgnoredKey() throws IOException {
    98         // ticket 17468
    99         final List<TestError> errors = test(OsmUtils.createPrimitive("node wheelchair:Description=bla"));
    100         assertEquals(1, errors.size());
    101         assertEquals("Misspelled property key", errors.get(0).getMessage());
    102         assertEquals("Key 'wheelchair:Description' looks like 'wheelchair:description'.", errors.get(0).getDescription());
    103         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    104         assertTrue(errors.get(0).isFixable());
    105     }
    106 
    107     /**
    108      * Check for misspelled key where the suggested alternative is given with prefix K: in ignoreTags.cfg.
    109      * The error should be fixable.
    110      * @throws IOException if any I/O error occurs
    111      */
    112     @Test
    113     void testUpperCaseInKeyIgnoredTag() throws IOException {
    114         // ticket 17468
    115         final List<TestError> errors = test(OsmUtils.createPrimitive("node land_Area=administrative"));
    116         assertEquals(1, errors.size());
    117         assertEquals("Misspelled property key", errors.get(0).getMessage());
    118         assertEquals("Key 'land_Area' looks like 'land_area'.", errors.get(0).getDescription());
    119         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    120         assertTrue(errors.get(0).isFixable());
    121     }
    122 
    123     /**
    124      * Check for unknown key.
    125      * @throws IOException if any I/O error occurs
    126      */
    127     @Test
    128     void testTranslatedNameKey() throws IOException {
    129         final List<TestError> errors = test(OsmUtils.createPrimitive("node namez=Baz"));
    130         assertEquals(1, errors.size());
    131         assertEquals("Presets do not contain property key", errors.get(0).getMessage());
    132         assertEquals("Key 'namez' not in presets.", errors.get(0).getDescription());
    133         assertEquals(Severity.OTHER, errors.get(0).getSeverity());
    134         assertFalse(errors.get(0).isFixable());
    135     }
    136 
    137     /**
    138      * Check for misspelled value.
    139      * @throws IOException if any I/O error occurs
    140      */
    141     @Test
    142     void testMisspelledTag() throws IOException {
    143         final List<TestError> errors = test(OsmUtils.createPrimitive("node landuse=forrest"));
    144         assertEquals(1, errors.size());
    145         assertEquals("Unknown property value", errors.get(0).getMessage());
    146         assertEquals("Value 'forrest' for key 'landuse' is unknown, maybe 'forest' is meant?", errors.get(0).getDescription());
    147         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    148         assertFalse(errors.get(0).isFixable());
    149     }
    150 
    151     /**
    152      * Check for misspelled value with multiple alternatives in presets.
    153      * @throws IOException if any I/O error occurs
    154      */
    155     @Test
    156     void testMisspelledTag2() throws IOException {
    157         final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=servics"));
    158         assertEquals(1, errors.size());
    159         assertEquals("Unknown property value", errors.get(0).getMessage());
    160         assertEquals(
    161                 "Value 'servics' for key 'highway' is unknown, maybe one of [service, services] is meant?",
    162                 errors.get(0).getDescription());
    163         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    164         assertFalse(errors.get(0).isFixable());
    165     }
    166 
    167     /**
    168      * Check for misspelled value.
    169      * @throws IOException if any I/O error occurs
    170      */
    171     @Test
    172     void testMisspelledTag3() throws IOException {
    173         final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=residentail"));
    174         assertEquals(1, errors.size());
    175         assertEquals("Unknown property value", errors.get(0).getMessage());
    176         assertEquals("Value 'residentail' for key 'highway' is unknown, maybe 'residential' is meant?",
    177                 errors.get(0).getDescription());
    178         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    179         assertFalse(errors.get(0).isFixable());
    180     }
    181 
    182     /**
    183      * Check for misspelled value.
    184      * @throws IOException if any I/O error occurs
    185      */
    186     @Test
    187     void testShortValNotInPreset2() throws IOException {
    188         final List<TestError> errors = test(OsmUtils.createPrimitive("node shop=abs"));
    189         assertEquals(1, errors.size());
    190         assertEquals("Presets do not contain property value", errors.get(0).getMessage());
    191         assertEquals("Value 'abs' for key 'shop' not in presets.", errors.get(0).getDescription());
    192         assertEquals(Severity.OTHER, errors.get(0).getSeverity());
    193         assertFalse(errors.get(0).isFixable());
    194     }
     136        assertEquals(expectedMessage, errors.get(0).getMessage());
     137        assertEquals(expectedDescription, errors.get(0).getDescription());
     138        assertEquals(severity, errors.get(0).getSeverity());
     139        assertEquals(isFixable, errors.get(0).isFixable());
     140    }
     141
    195142
    196143    /**
     
    206153                .collect(Collectors.toList());
    207154        assertTrue(errors.isEmpty(), errors::toString);
    208     }
    209 
    210     /**
    211      * Check regression: Don't fix surface=u -> surface=mud.
    212      * @throws IOException if any I/O error occurs
    213      */
    214     @Test
    215     void testTooShortToFix() throws IOException {
    216         final List<TestError> errors = test(OsmUtils.createPrimitive("node surface=u"));
    217         assertEquals(1, errors.size());
    218         assertEquals("Presets do not contain property value", errors.get(0).getMessage());
    219         assertEquals("Value 'u' for key 'surface' not in presets.", errors.get(0).getDescription());
    220         assertEquals(Severity.OTHER, errors.get(0).getSeverity());
    221         assertFalse(errors.get(0).isFixable());
    222     }
    223 
    224     /**
    225      * Check value with upper case
    226      * @throws IOException if any I/O error occurs
    227      */
    228     @Test
    229     void testValueDifferentCase() throws IOException {
    230         final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=Residential"));
    231         assertEquals(1, errors.size());
    232         assertEquals("Unknown property value", errors.get(0).getMessage());
    233         assertEquals("Value 'Residential' for key 'highway' is unknown, maybe 'residential' is meant?",
    234                 errors.get(0).getDescription());
    235         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    236         assertFalse(errors.get(0).isFixable());
    237     }
    238 
    239     @Test
    240     void testRegionKey() throws IOException {
    241         final List<TestError> errors = test(OsmUtils.createPrimitive("node payment:ep_avant=yes"));
    242         assertEquals(1, errors.size());
    243         assertEquals("Key from a preset is invalid in this region", errors.get(0).getMessage());
    244         assertEquals("Preset Payment Methods should not have the key payment:ep_avant", errors.get(0).getDescription());
    245         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    246         assertFalse(errors.get(0).isFixable());
    247 
    248     }
    249 
    250     @Test
    251     void testRegionTag() throws IOException {
    252         final List<TestError> errors = test(OsmUtils.createPrimitive("relation type=waterway gnis:feature_id=123456"));
    253         assertEquals(1, errors.size());
    254         assertEquals("Key from a preset is invalid in this region", errors.get(0).getMessage());
    255         assertEquals("Preset Waterway should not have the key gnis:feature_id", errors.get(0).getDescription());
    256         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    257         assertFalse(errors.get(0).isFixable());
    258     }
    259 
    260     /**
    261      * Key in presets but not in ignored.cfg. Caused a NPE with r14727.
    262      * @throws IOException if any I/O error occurs
    263      */
    264     @Test
    265     void testRegression17246() throws IOException {
    266         final List<TestError> errors = test(OsmUtils.createPrimitive("node access=privat"));
    267         assertEquals(1, errors.size());
    268         assertEquals("Unknown property value", errors.get(0).getMessage());
    269         assertEquals("Value 'privat' for key 'access' is unknown, maybe 'private' is meant?",
    270                 errors.get(0).getDescription());
    271         assertEquals(Severity.WARNING, errors.get(0).getSeverity());
    272         assertFalse(errors.get(0).isFixable());
    273155    }
    274156
     
    388270     */
    389271    @Test
    390     @Disabled("broken, see #19519")
    391272    void testTicket19519() throws IOException {
    392273        List<TestError> errors = test(OsmUtils.createPrimitive("node amenity=restaurant cuisine=bavarian;beef_bowl"));
     
    420301        final List<TestError> errors = test(OsmUtils.createPrimitive("node power=tower ref=12"));
    421302        assertEquals(0, errors.size());
     303    }
     304
     305    /**
     306     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/23290">Bug #23290</a>
     307     */
     308    @Test
     309    void testTicket23290() throws IOException {
     310        final Node france1 = new Node(new LatLon(48.465638, 7.3677049));
     311        final Node france2 = new Node(new LatLon(48.4191768, 7.7275072));
     312        final Node german1 = new Node(new LatLon(48.3398223, 8.1683322));
     313        final Node german2 = new Node(new LatLon(48.4137076, 7.754287));
     314        final Way frenchRiver = TestUtils.newWay("waterway=river", france1, france2);
     315        final Way germanRiver = TestUtils.newWay("waterway=river", german1, german2);
     316        final Way incompleteWay = new Way(123, 0);
     317        final Relation riverRelation = TestUtils.newRelation("type=waterway waterway=river ref:sandre=A---0000 ref:fgkz=2",
     318                new RelationMember("", germanRiver));
     319        // Ensure they have the same dataset
     320        new DataSet(france1, france2, frenchRiver, german1, german2, germanRiver, incompleteWay, riverRelation);
     321        assertEquals(1, test(riverRelation).size());
     322        riverRelation.addMember(new RelationMember("", frenchRiver));
     323        assertEquals(0, test(riverRelation).size());
     324        riverRelation.removeMembersFor(frenchRiver);
     325        assertEquals(1, test(riverRelation).size());
     326        riverRelation.addMember(new RelationMember("", incompleteWay));
     327        assertEquals(0, test(riverRelation).size());
    422328    }
    423329
Note: See TracChangeset for help on using the changeset viewer.