source: josm/trunk/test/unit/org/openstreetmap/josm/data/validation/tests/TagCheckerTest.java@ 19025

Last change on this file since 19025 was 19025, checked in by taylor.smock, 7 weeks ago

Fix #23177: Change ref:gnis to gnis:feature_id in the waterway tagging options

ref:gnis, gnis:id, tiger:PLACENS, NHS:GNIS_ID, and nhs:gnis_id have
been merged into gnis:feature_id.

The wiki pages have been stable for 6 months, and the changes were discussed on
the OSM forum.

File size: 18.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.junit.jupiter.api.Assertions.assertEquals;
5import static org.junit.jupiter.api.Assertions.assertFalse;
6import static org.junit.jupiter.api.Assertions.assertTrue;
7
8import java.io.IOException;
9import java.util.List;
10import java.util.function.Consumer;
11import java.util.stream.Collectors;
12
13import org.junit.jupiter.api.Assertions;
14import org.junit.jupiter.api.Disabled;
15import org.junit.jupiter.api.Test;
16import org.openstreetmap.josm.TestUtils;
17import org.openstreetmap.josm.data.osm.OsmPrimitive;
18import org.openstreetmap.josm.data.osm.OsmUtils;
19import org.openstreetmap.josm.data.osm.Tag;
20import org.openstreetmap.josm.data.validation.Severity;
21import org.openstreetmap.josm.data.validation.TestError;
22import org.openstreetmap.josm.testutils.annotations.I18n;
23import org.openstreetmap.josm.testutils.annotations.TaggingPresets;
24
25/**
26 * JUnit Test of {@link TagChecker}.
27 */
28@I18n
29@TaggingPresets
30class TagCheckerTest {
31 List<TestError> test(OsmPrimitive primitive) throws IOException {
32 final TagChecker checker = new TagChecker() {
33 @Override
34 protected boolean includeOtherSeverityChecks() {
35 return true;
36 }
37 };
38 checker.initialize();
39 checker.startTest(null);
40 checker.check(TestUtils.addFakeDataSet(primitive));
41 return checker.getErrors();
42 }
43
44 /**
45 * Check for misspelled key.
46 * @throws IOException if any I/O error occurs
47 */
48 @Test
49 void testMisspelledKey1() throws IOException {
50 final List<TestError> errors = test(OsmUtils.createPrimitive("node Name=Main"));
51 assertEquals(1, errors.size());
52 assertEquals("Misspelled property key", errors.get(0).getMessage());
53 assertEquals("Key 'Name' looks like 'name'.", errors.get(0).getDescription());
54 assertTrue(errors.get(0).isFixable());
55 }
56
57 /**
58 * Check for misspelled key.
59 * @throws IOException if any I/O error occurs
60 */
61 @Test
62 void testMisspelledKey2() throws IOException {
63 final List<TestError> errors = test(OsmUtils.createPrimitive("node landuse;=forest"));
64 assertEquals(1, errors.size());
65 assertEquals("Misspelled property key", errors.get(0).getMessage());
66 assertEquals("Key 'landuse;' looks like 'landuse'.", errors.get(0).getDescription());
67 assertTrue(errors.get(0).isFixable());
68 }
69
70 /**
71 * Check for misspelled key where the suggested alternative is in use. The error should not be fixable.
72 * @throws IOException if any I/O error occurs
73 */
74 @Test
75 void testMisspelledKeyButAlternativeInUse() throws IOException {
76 // ticket 12329
77 final List<TestError> errors = test(OsmUtils.createPrimitive("node amenity=fuel brand=bah Brand=foo"));
78 assertEquals(1, errors.size());
79 assertEquals("Misspelled property key", errors.get(0).getMessage());
80 assertEquals("Key 'Brand' looks like 'brand'.", errors.get(0).getDescription());
81 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
82 assertFalse(errors.get(0).isFixable());
83 }
84
85 /**
86 * Check for misspelled key where the suggested alternative is given with prefix E: in ignoreTags.cfg.
87 * The error should be fixable.
88 * @throws IOException if any I/O error occurs
89 */
90 @Test
91 void testUpperCaseIgnoredKey() throws IOException {
92 // ticket 17468
93 final List<TestError> errors = test(OsmUtils.createPrimitive("node wheelchair:Description=bla"));
94 assertEquals(1, errors.size());
95 assertEquals("Misspelled property key", errors.get(0).getMessage());
96 assertEquals("Key 'wheelchair:Description' looks like 'wheelchair:description'.", errors.get(0).getDescription());
97 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
98 assertTrue(errors.get(0).isFixable());
99 }
100
101 /**
102 * Check for misspelled key where the suggested alternative is given with prefix K: in ignoreTags.cfg.
103 * The error should be fixable.
104 * @throws IOException if any I/O error occurs
105 */
106 @Test
107 void testUpperCaseInKeyIgnoredTag() throws IOException {
108 // ticket 17468
109 final List<TestError> errors = test(OsmUtils.createPrimitive("node land_Area=administrative"));
110 assertEquals(1, errors.size());
111 assertEquals("Misspelled property key", errors.get(0).getMessage());
112 assertEquals("Key 'land_Area' looks like 'land_area'.", errors.get(0).getDescription());
113 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
114 assertTrue(errors.get(0).isFixable());
115 }
116
117 /**
118 * Check for unknown key.
119 * @throws IOException if any I/O error occurs
120 */
121 @Test
122 void testTranslatedNameKey() throws IOException {
123 final List<TestError> errors = test(OsmUtils.createPrimitive("node namez=Baz"));
124 assertEquals(1, errors.size());
125 assertEquals("Presets do not contain property key", errors.get(0).getMessage());
126 assertEquals("Key 'namez' not in presets.", errors.get(0).getDescription());
127 assertEquals(Severity.OTHER, errors.get(0).getSeverity());
128 assertFalse(errors.get(0).isFixable());
129 }
130
131 /**
132 * Check for misspelled value.
133 * @throws IOException if any I/O error occurs
134 */
135 @Test
136 void testMisspelledTag() throws IOException {
137 final List<TestError> errors = test(OsmUtils.createPrimitive("node landuse=forrest"));
138 assertEquals(1, errors.size());
139 assertEquals("Unknown property value", errors.get(0).getMessage());
140 assertEquals("Value 'forrest' for key 'landuse' is unknown, maybe 'forest' is meant?", errors.get(0).getDescription());
141 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
142 assertFalse(errors.get(0).isFixable());
143 }
144
145 /**
146 * Check for misspelled value with multiple alternatives in presets.
147 * @throws IOException if any I/O error occurs
148 */
149 @Test
150 void testMisspelledTag2() throws IOException {
151 final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=servics"));
152 assertEquals(1, errors.size());
153 assertEquals("Unknown property value", errors.get(0).getMessage());
154 assertEquals(
155 "Value 'servics' for key 'highway' is unknown, maybe one of [service, services] is meant?",
156 errors.get(0).getDescription());
157 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
158 assertFalse(errors.get(0).isFixable());
159 }
160
161 /**
162 * Check for misspelled value.
163 * @throws IOException if any I/O error occurs
164 */
165 @Test
166 void testMisspelledTag3() throws IOException {
167 final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=residentail"));
168 assertEquals(1, errors.size());
169 assertEquals("Unknown property value", errors.get(0).getMessage());
170 assertEquals("Value 'residentail' for key 'highway' is unknown, maybe 'residential' is meant?",
171 errors.get(0).getDescription());
172 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
173 assertFalse(errors.get(0).isFixable());
174 }
175
176 /**
177 * Check for misspelled value.
178 * @throws IOException if any I/O error occurs
179 */
180 @Test
181 void testShortValNotInPreset2() throws IOException {
182 final List<TestError> errors = test(OsmUtils.createPrimitive("node shop=abs"));
183 assertEquals(1, errors.size());
184 assertEquals("Presets do not contain property value", errors.get(0).getMessage());
185 assertEquals("Value 'abs' for key 'shop' not in presets.", errors.get(0).getDescription());
186 assertEquals(Severity.OTHER, errors.get(0).getSeverity());
187 assertFalse(errors.get(0).isFixable());
188 }
189
190 /**
191 * Checks that tags specifically ignored are effectively not in internal presets.
192 * @throws IOException if any I/O error occurs
193 */
194 @Test
195 void testIgnoredTagsNotInPresets() throws IOException {
196 new TagChecker().initialize();
197 List<String> errors = TagChecker.getIgnoredTags().stream()
198 .filter(tag -> TagChecker.isTagInPresets(tag.getKey(), tag.getValue()))
199 .map(Tag::toString)
200 .collect(Collectors.toList());
201 assertTrue(errors.isEmpty(), errors::toString);
202 }
203
204 /**
205 * Check regression: Don't fix surface=u -> surface=mud.
206 * @throws IOException if any I/O error occurs
207 */
208 @Test
209 void testTooShortToFix() throws IOException {
210 final List<TestError> errors = test(OsmUtils.createPrimitive("node surface=u"));
211 assertEquals(1, errors.size());
212 assertEquals("Presets do not contain property value", errors.get(0).getMessage());
213 assertEquals("Value 'u' for key 'surface' not in presets.", errors.get(0).getDescription());
214 assertEquals(Severity.OTHER, errors.get(0).getSeverity());
215 assertFalse(errors.get(0).isFixable());
216 }
217
218 /**
219 * Check value with upper case
220 * @throws IOException if any I/O error occurs
221 */
222 @Test
223 void testValueDifferentCase() throws IOException {
224 final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=Residential"));
225 assertEquals(1, errors.size());
226 assertEquals("Unknown property value", errors.get(0).getMessage());
227 assertEquals("Value 'Residential' for key 'highway' is unknown, maybe 'residential' is meant?",
228 errors.get(0).getDescription());
229 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
230 assertFalse(errors.get(0).isFixable());
231 }
232
233 @Test
234 void testRegionKey() throws IOException {
235 final List<TestError> errors = test(OsmUtils.createPrimitive("node highway=crossing crossing_ref=zebra"));
236 assertEquals(1, errors.size());
237 assertEquals("Key from a preset is invalid in this region", errors.get(0).getMessage());
238 assertEquals("Preset Pedestrian Crossing should not have the key crossing_ref", errors.get(0).getDescription());
239 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
240 assertFalse(errors.get(0).isFixable());
241
242 }
243
244 @Test
245 void testRegionTag() throws IOException {
246 final List<TestError> errors = test(OsmUtils.createPrimitive("relation type=waterway gnis:feature_id=123456"));
247 assertEquals(1, errors.size());
248 assertEquals("Key from a preset is invalid in this region", errors.get(0).getMessage());
249 assertEquals("Preset Waterway should not have the key gnis:feature_id", errors.get(0).getDescription());
250 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
251 assertFalse(errors.get(0).isFixable());
252 }
253
254 /**
255 * Key in presets but not in ignored.cfg. Caused a NPE with r14727.
256 * @throws IOException if any I/O error occurs
257 */
258 @Test
259 void testRegression17246() throws IOException {
260 final List<TestError> errors = test(OsmUtils.createPrimitive("node access=privat"));
261 assertEquals(1, errors.size());
262 assertEquals("Unknown property value", errors.get(0).getMessage());
263 assertEquals("Value 'privat' for key 'access' is unknown, maybe 'private' is meant?",
264 errors.get(0).getDescription());
265 assertEquals(Severity.WARNING, errors.get(0).getSeverity());
266 assertFalse(errors.get(0).isFixable());
267 }
268
269 /**
270 * Checks for unwanted non printing control characters
271 * @param s String to test
272 * @param assertionC assertion on the result (true/false)
273 * @param expected expected fixed value
274 */
275 private static void doTestUnwantedNonprintingControlCharacters(String s, Consumer<Boolean> assertionC, String expected) {
276 assertionC.accept(TagChecker.containsUnwantedNonPrintingControlCharacter(s));
277 assertEquals(expected, TagChecker.removeUnwantedNonPrintingControlCharacters(s));
278 }
279
280 private static void doTestUnwantedNonprintingControlCharacters(String s) {
281 doTestUnwantedNonprintingControlCharacters(s, Assertions::assertTrue, "");
282 }
283
284 /**
285 * Unit test of {@link TagChecker#containsUnwantedNonPrintingControlCharacter}
286 * / {@link TagChecker#removeUnwantedNonPrintingControlCharacters}
287 */
288 @Test
289 void testContainsRemoveUnwantedNonprintingControlCharacters() {
290 // Check empty string is handled
291 doTestUnwantedNonprintingControlCharacters("", Assertions::assertFalse, "");
292 // Check 65 ASCII control characters are removed, except new lines
293 for (char c = 0x0; c < 0x20; c++) {
294 if (c != '\r' && c != '\n') {
295 doTestUnwantedNonprintingControlCharacters(Character.toString(c));
296 } else {
297 doTestUnwantedNonprintingControlCharacters(Character.toString(c), Assertions::assertFalse, Character.toString(c));
298 }
299 }
300 doTestUnwantedNonprintingControlCharacters(Character.toString((char) 0x7F));
301 // Check 7 Unicode bidi control characters are removed
302 for (char c = 0x200e; c <= 0x200f; c++) {
303 doTestUnwantedNonprintingControlCharacters(Character.toString(c));
304 }
305 for (char c = 0x202a; c <= 0x202e; c++) {
306 doTestUnwantedNonprintingControlCharacters(Character.toString(c));
307 }
308 // Check joining characters are removed if located at the beginning or end of the string
309 for (char c = 0x200c; c <= 0x200d; c++) {
310 final String s = Character.toString(c);
311 doTestUnwantedNonprintingControlCharacters(s);
312 doTestUnwantedNonprintingControlCharacters(s + s);
313 doTestUnwantedNonprintingControlCharacters(s + 'a' + s, Assertions::assertTrue, "a");
314 final String ok = 'a' + s + 'b';
315 doTestUnwantedNonprintingControlCharacters(ok, Assertions::assertFalse, ok);
316 doTestUnwantedNonprintingControlCharacters(s + ok, Assertions::assertTrue, ok);
317 doTestUnwantedNonprintingControlCharacters(ok + s, Assertions::assertTrue, ok);
318 doTestUnwantedNonprintingControlCharacters(s + ok + s, Assertions::assertTrue, ok);
319 }
320 }
321
322 /**
323 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/17667">Bug #17667</a>.
324 */
325 @Test
326 void testTicket17667() {
327 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name", "Bus 118: Berlin, Rathaus Zehlendorf => Potsdam, Drewitz Stern-Center"));
328 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name", "Καρδίτσα → Λάρισα"));
329 assertFalse(TagChecker.containsUnusualUnicodeCharacter("traffic_sign", "FI:871[← Lippuautomaatti]"));
330 assertFalse(TagChecker.containsUnusualUnicodeCharacter("traffic_sign", "FI:871[↑ Nostopaikka ↑]"));
331 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name", "Cinderella II - Strandvägen ↔ Hagede"));
332 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name", "Tallinn — Narva"));
333 }
334
335 /**
336 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/18322">Bug #18322</a>.
337 */
338 @Test
339 void testTicket18322() {
340 assertTrue(TagChecker.containsUnusualUnicodeCharacter("name", "D36ᴬ"));
341 assertFalse(TagChecker.containsUnusualUnicodeCharacter("ref", "D36ᴬ"));
342 assertFalse(TagChecker.containsUnusualUnicodeCharacter("old_ref", "D36ᴬ"));
343 assertFalse(TagChecker.containsUnusualUnicodeCharacter("old_ref", "D36ᵂ"));
344 assertTrue(TagChecker.containsUnusualUnicodeCharacter("old_ref", "D36ᴫ"));
345 assertTrue(TagChecker.containsUnusualUnicodeCharacter("old_ref", "D36ᵃ"));
346 }
347
348 /**
349 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/18449">Bug #18449</a>.
350 */
351 @Test
352 void testTicket18449() {
353 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name", "Hökumət Evi"));
354 }
355
356 /**
357 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/18740">Bug #18740</a>.
358 */
359 @Test
360 void testTicket18740() {
361 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name:ak", "Frɛnkyeman"));
362 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name:bm", "Esipaɲi"));
363 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name:oym", "Wɨlapaleya Ɨtu"));
364 }
365
366 /**
367 * Detects objects with types not supported by their presets.
368 * @throws IOException in case of I/O error
369 */
370 @Test
371 void testObjectTypeNotSupportedByPreset() throws IOException {
372 List<TestError> errors = test(OsmUtils.createPrimitive("relation waterway=river"));
373 assertEquals(1, errors.size());
374 assertEquals(TagChecker.INVALID_PRESETS_TYPE, errors.get(0).getCode());
375 errors = test(OsmUtils.createPrimitive("relation type=waterway waterway=river"));
376 assertTrue(errors.isEmpty(), errors::toString);
377 }
378
379 /**
380 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/19519">Bug #19519</a>.
381 * @throws IOException ignored
382 */
383 @Test
384 @Disabled("broken, see #19519")
385 void testTicket19519() throws IOException {
386 List<TestError> errors = test(OsmUtils.createPrimitive("node amenity=restaurant cuisine=bavarian;beef_bowl"));
387 assertEquals(0, errors.size());
388 }
389
390 /**
391 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/20437">Bug #20437</a>.
392 */
393 @Test
394 void testTicket20437() {
395 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name:kbp", "Wasɩŋtɔŋ"));
396 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name:kbp", "Kalɩfɔrnii"));
397 }
398
399 /**
400 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/20754">Bug #20754</a>.
401 */
402 @Test
403 void testTicket20754() {
404 assertFalse(TagChecker.containsUnusualUnicodeCharacter("name", "Yuułuʔiłʔatḥ Lands"));
405 }
406
407 /**
408 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/21348">Bug #21348</a>.
409 * Key ref is in presets but without any value.
410 * @throws IOException if any I/O error occurs
411 */
412 @Test
413 void testTicket21348() throws IOException {
414 final List<TestError> errors = test(OsmUtils.createPrimitive("node power=tower ref=12"));
415 assertEquals(0, errors.size());
416 }
417}
Note: See TracBrowser for help on using the repository browser.