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

Last change on this file since 15888 was 15888, checked in by simon04, 4 years ago

fix #18740 - Tag checker: whitelist a few phonetic characters

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