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

Last change on this file since 15667 was 15667, checked in by Don-vip, 4 years ago

fix #18455 - smarter error detection, should lead to less false positives

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