source: josm/trunk/test/unit/org/openstreetmap/josm/data/osm/search/SearchCompilerTest.java@ 13317

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

fix #15755 - Unprocessed HTML in search error box

  • Property svn:eol-style set to native
File size: 26.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.search;
3
4import static org.junit.Assert.assertEquals;
5import static org.junit.Assert.assertFalse;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertTrue;
8import static org.junit.Assert.fail;
9
10import java.lang.reflect.Field;
11import java.nio.charset.StandardCharsets;
12import java.nio.file.Files;
13import java.nio.file.Paths;
14import java.util.Arrays;
15import java.util.Collection;
16import java.util.Collections;
17
18import org.junit.Rule;
19import org.junit.Test;
20import org.junit.rules.ExpectedException;
21import 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;
25import org.openstreetmap.josm.data.osm.OsmPrimitive;
26import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
27import org.openstreetmap.josm.data.osm.Relation;
28import org.openstreetmap.josm.data.osm.RelationData;
29import org.openstreetmap.josm.data.osm.RelationMember;
30import org.openstreetmap.josm.data.osm.Tag;
31import org.openstreetmap.josm.data.osm.User;
32import org.openstreetmap.josm.data.osm.Way;
33import org.openstreetmap.josm.data.osm.WayData;
34import org.openstreetmap.josm.data.osm.search.SearchCompiler.ExactKeyValue;
35import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
36import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
37import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetMenu;
38import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType;
39import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
40import org.openstreetmap.josm.gui.tagging.presets.items.Key;
41import org.openstreetmap.josm.testutils.JOSMTestRules;
42import org.openstreetmap.josm.tools.date.DateUtils;
43
44import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
45
46/**
47 * Unit tests for class {@link SearchCompiler}.
48 */
49public class SearchCompilerTest {
50
51 /**
52 * We need prefs for this. We access preferences when creating OSM primitives.
53 */
54 @Rule
55 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
56 public JOSMTestRules test = new JOSMTestRules().preferences();
57
58 /**
59 * Rule to assert exception message.
60 */
61 @Rule
62 public ExpectedException expectedEx = ExpectedException.none();
63
64 private static final class SearchContext {
65 final DataSet ds = new DataSet();
66 final Node n1 = new Node(LatLon.ZERO);
67 final Node n2 = new Node(new LatLon(5, 5));
68 final Way w1 = new Way();
69 final Way w2 = new Way();
70 final Relation r1 = new Relation();
71 final Relation r2 = new Relation();
72
73 private final Match m;
74 private final Match n;
75
76 private SearchContext(String state) throws SearchParseError {
77 m = SearchCompiler.compile(state);
78 n = SearchCompiler.compile('-' + state);
79 ds.addPrimitive(n1);
80 ds.addPrimitive(n2);
81 w1.addNode(n1);
82 w1.addNode(n2);
83 w2.addNode(n1);
84 w2.addNode(n2);
85 ds.addPrimitive(w1);
86 ds.addPrimitive(w2);
87 r1.addMember(new RelationMember("", w1));
88 r1.addMember(new RelationMember("", w2));
89 r2.addMember(new RelationMember("", w1));
90 r2.addMember(new RelationMember("", w2));
91 ds.addPrimitive(r1);
92 ds.addPrimitive(r2);
93 }
94
95 private void match(OsmPrimitive p, boolean cond) {
96 if (cond) {
97 assertTrue(p.toString(), m.match(p));
98 assertFalse(p.toString(), n.match(p));
99 } else {
100 assertFalse(p.toString(), m.match(p));
101 assertTrue(p.toString(), n.match(p));
102 }
103 }
104 }
105
106 private static OsmPrimitive newPrimitive(String key, String value) {
107 final Node p = new Node();
108 p.put(key, value);
109 return p;
110 }
111
112 /**
113 * Search anything.
114 * @throws SearchParseError if an error has been encountered while compiling
115 */
116 @Test
117 public void testAny() throws SearchParseError {
118 final SearchCompiler.Match c = SearchCompiler.compile("foo");
119 assertTrue(c.match(newPrimitive("foobar", "true")));
120 assertTrue(c.match(newPrimitive("name", "hello-foo-xy")));
121 assertFalse(c.match(newPrimitive("name", "X")));
122 assertEquals("foo", c.toString());
123 }
124
125 /**
126 * Search by equality key=value.
127 * @throws SearchParseError if an error has been encountered while compiling
128 */
129 @Test
130 public void testEquals() throws SearchParseError {
131 final SearchCompiler.Match c = SearchCompiler.compile("foo=bar");
132 assertFalse(c.match(newPrimitive("foobar", "true")));
133 assertTrue(c.match(newPrimitive("foo", "bar")));
134 assertFalse(c.match(newPrimitive("fooX", "bar")));
135 assertFalse(c.match(newPrimitive("foo", "barX")));
136 assertEquals("foo=bar", c.toString());
137 }
138
139 /**
140 * Search by comparison.
141 * @throws SearchParseError if an error has been encountered while compiling
142 */
143 @Test
144 public void testCompare() throws SearchParseError {
145 final SearchCompiler.Match c1 = SearchCompiler.compile("start_date>1950");
146 assertTrue(c1.match(newPrimitive("start_date", "1950-01-01")));
147 assertTrue(c1.match(newPrimitive("start_date", "1960")));
148 assertFalse(c1.match(newPrimitive("start_date", "1950")));
149 assertFalse(c1.match(newPrimitive("start_date", "1000")));
150 assertTrue(c1.match(newPrimitive("start_date", "101010")));
151
152 final SearchCompiler.Match c2 = SearchCompiler.compile("start_date<1960");
153 assertTrue(c2.match(newPrimitive("start_date", "1950-01-01")));
154 assertFalse(c2.match(newPrimitive("start_date", "1960")));
155 assertTrue(c2.match(newPrimitive("start_date", "1950")));
156 assertTrue(c2.match(newPrimitive("start_date", "1000")));
157 assertTrue(c2.match(newPrimitive("start_date", "200")));
158
159 final SearchCompiler.Match c3 = SearchCompiler.compile("name<I");
160 assertTrue(c3.match(newPrimitive("name", "Alpha")));
161 assertFalse(c3.match(newPrimitive("name", "Sigma")));
162
163 final SearchCompiler.Match c4 = SearchCompiler.compile("\"start_date\"<1960");
164 assertTrue(c4.match(newPrimitive("start_date", "1950-01-01")));
165 assertFalse(c4.match(newPrimitive("start_date", "2000")));
166
167 final SearchCompiler.Match c5 = SearchCompiler.compile("height>180");
168 assertTrue(c5.match(newPrimitive("height", "200")));
169 assertTrue(c5.match(newPrimitive("height", "99999")));
170 assertFalse(c5.match(newPrimitive("height", "50")));
171 assertFalse(c5.match(newPrimitive("height", "-9999")));
172 assertFalse(c5.match(newPrimitive("height", "fixme")));
173
174 final SearchCompiler.Match c6 = SearchCompiler.compile("name>C");
175 assertTrue(c6.match(newPrimitive("name", "Delta")));
176 assertFalse(c6.match(newPrimitive("name", "Alpha")));
177 }
178
179 /**
180 * Search by nth.
181 * @throws SearchParseError if an error has been encountered while compiling
182 */
183 @Test
184 public void testNth() throws SearchParseError {
185 final DataSet dataSet = new DataSet();
186 final Way way = new Way();
187 final Node node0 = new Node(new LatLon(1, 1));
188 final Node node1 = new Node(new LatLon(2, 2));
189 final Node node2 = new Node(new LatLon(3, 3));
190 dataSet.addPrimitive(way);
191 dataSet.addPrimitive(node0);
192 dataSet.addPrimitive(node1);
193 dataSet.addPrimitive(node2);
194 way.addNode(node0);
195 way.addNode(node1);
196 way.addNode(node2);
197 assertFalse(SearchCompiler.compile("nth:2").match(node1));
198 assertTrue(SearchCompiler.compile("nth:1").match(node1));
199 assertFalse(SearchCompiler.compile("nth:0").match(node1));
200 assertTrue(SearchCompiler.compile("nth:0").match(node0));
201 assertTrue(SearchCompiler.compile("nth:2").match(node2));
202 assertTrue(SearchCompiler.compile("nth:-1").match(node2));
203 assertTrue(SearchCompiler.compile("nth:-2").match(node1));
204 assertTrue(SearchCompiler.compile("nth:-3").match(node0));
205 }
206
207 /**
208 * Search by negative nth.
209 * @throws SearchParseError if an error has been encountered while compiling
210 */
211 @Test
212 public void testNthParseNegative() throws SearchParseError {
213 assertEquals("Nth{nth=-1, modulo=false}", SearchCompiler.compile("nth:-1").toString());
214 }
215
216 /**
217 * Search by modified status.
218 * @throws SearchParseError if an error has been encountered while compiling
219 */
220 @Test
221 public void testModified() throws SearchParseError {
222 SearchContext sc = new SearchContext("modified");
223 // Not modified but new
224 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
225 assertFalse(p.toString(), p.isModified());
226 assertTrue(p.toString(), p.isNewOrUndeleted());
227 sc.match(p, true);
228 }
229 // Modified and new
230 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
231 p.setModified(true);
232 assertTrue(p.toString(), p.isModified());
233 assertTrue(p.toString(), p.isNewOrUndeleted());
234 sc.match(p, true);
235 }
236 // Modified but not new
237 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
238 p.setOsmId(1, 1);
239 assertTrue(p.toString(), p.isModified());
240 assertFalse(p.toString(), p.isNewOrUndeleted());
241 sc.match(p, true);
242 }
243 // Not modified nor new
244 for (OsmPrimitive p : new OsmPrimitive[]{sc.n2, sc.w2, sc.r2}) {
245 p.setOsmId(2, 2);
246 assertFalse(p.toString(), p.isModified());
247 assertFalse(p.toString(), p.isNewOrUndeleted());
248 sc.match(p, false);
249 }
250 }
251
252 /**
253 * Search by selected status.
254 * @throws SearchParseError if an error has been encountered while compiling
255 */
256 @Test
257 public void testSelected() throws SearchParseError {
258 SearchContext sc = new SearchContext("selected");
259 // Not selected
260 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
261 assertFalse(p.toString(), p.isSelected());
262 sc.match(p, false);
263 }
264 // Selected
265 for (OsmPrimitive p : new OsmPrimitive[]{sc.n2, sc.w2, sc.r2}) {
266 sc.ds.addSelected(p);
267 assertTrue(p.toString(), p.isSelected());
268 sc.match(p, true);
269 }
270 }
271
272 /**
273 * Search by incomplete status.
274 * @throws SearchParseError if an error has been encountered while compiling
275 */
276 @Test
277 public void testIncomplete() throws SearchParseError {
278 SearchContext sc = new SearchContext("incomplete");
279 // Not incomplete
280 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
281 assertFalse(p.toString(), p.isIncomplete());
282 sc.match(p, false);
283 }
284 // Incomplete
285 sc.n2.setCoor(null);
286 WayData wd = new WayData();
287 wd.setIncomplete(true);
288 sc.w2.load(wd);
289 RelationData rd = new RelationData();
290 rd.setIncomplete(true);
291 sc.r2.load(rd);
292 for (OsmPrimitive p : new OsmPrimitive[]{sc.n2, sc.w2, sc.r2}) {
293 assertTrue(p.toString(), p.isIncomplete());
294 sc.match(p, true);
295 }
296 }
297
298 /**
299 * Search by untagged status.
300 * @throws SearchParseError if an error has been encountered while compiling
301 */
302 @Test
303 public void testUntagged() throws SearchParseError {
304 SearchContext sc = new SearchContext("untagged");
305 // Untagged
306 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
307 assertFalse(p.toString(), p.isTagged());
308 sc.match(p, true);
309 }
310 // Tagged
311 for (OsmPrimitive p : new OsmPrimitive[]{sc.n2, sc.w2, sc.r2}) {
312 p.put("foo", "bar");
313 assertTrue(p.toString(), p.isTagged());
314 sc.match(p, false);
315 }
316 }
317
318 /**
319 * Search by closed status.
320 * @throws SearchParseError if an error has been encountered while compiling
321 */
322 @Test
323 public void testClosed() throws SearchParseError {
324 SearchContext sc = new SearchContext("closed");
325 // Closed
326 sc.w1.addNode(sc.n1);
327 for (Way w : new Way[]{sc.w1}) {
328 assertTrue(w.toString(), w.isClosed());
329 sc.match(w, true);
330 }
331 // Unclosed
332 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w2, sc.r1, sc.r2}) {
333 sc.match(p, false);
334 }
335 }
336
337 /**
338 * Search by new status.
339 * @throws SearchParseError if an error has been encountered while compiling
340 */
341 @Test
342 public void testNew() throws SearchParseError {
343 SearchContext sc = new SearchContext("new");
344 // New
345 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.w1, sc.r1}) {
346 assertTrue(p.toString(), p.isNew());
347 sc.match(p, true);
348 }
349 // Not new
350 for (OsmPrimitive p : new OsmPrimitive[]{sc.n2, sc.w2, sc.r2}) {
351 p.setOsmId(2, 2);
352 assertFalse(p.toString(), p.isNew());
353 sc.match(p, false);
354 }
355 }
356
357 /**
358 * Search for node objects.
359 * @throws SearchParseError if an error has been encountered while compiling
360 */
361 @Test
362 public void testTypeNode() throws SearchParseError {
363 final SearchContext sc = new SearchContext("type:node");
364 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w1, sc.w2, sc.r1, sc.r2}) {
365 sc.match(p, OsmPrimitiveType.NODE.equals(p.getType()));
366 }
367 }
368
369 /**
370 * Search for way objects.
371 * @throws SearchParseError if an error has been encountered while compiling
372 */
373 @Test
374 public void testTypeWay() throws SearchParseError {
375 final SearchContext sc = new SearchContext("type:way");
376 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w1, sc.w2, sc.r1, sc.r2}) {
377 sc.match(p, OsmPrimitiveType.WAY.equals(p.getType()));
378 }
379 }
380
381 /**
382 * Search for relation objects.
383 * @throws SearchParseError if an error has been encountered while compiling
384 */
385 @Test
386 public void testTypeRelation() throws SearchParseError {
387 final SearchContext sc = new SearchContext("type:relation");
388 for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w1, sc.w2, sc.r1, sc.r2}) {
389 sc.match(p, OsmPrimitiveType.RELATION.equals(p.getType()));
390 }
391 }
392
393 /**
394 * Search for users.
395 * @throws SearchParseError if an error has been encountered while compiling
396 */
397 @Test
398 public void testUser() throws SearchParseError {
399 final SearchContext foobar = new SearchContext("user:foobar");
400 foobar.n1.setUser(User.createLocalUser("foobar"));
401 foobar.match(foobar.n1, true);
402 foobar.match(foobar.n2, false);
403 final SearchContext anonymous = new SearchContext("user:anonymous");
404 anonymous.n1.setUser(User.createLocalUser("foobar"));
405 anonymous.match(anonymous.n1, false);
406 anonymous.match(anonymous.n2, true);
407 }
408
409 /**
410 * Compiles "foo type bar" and tests the parse error message
411 */
412 @Test
413 public void testFooTypeBar() {
414 try {
415 SearchCompiler.compile("foo type bar");
416 fail();
417 } catch (SearchParseError parseError) {
418 assertEquals("<html>Expecting <code>:</code> after <i>type</i>", parseError.getMessage());
419 }
420 }
421
422 /**
423 * Search for primitive timestamps.
424 * @throws SearchParseError if an error has been encountered while compiling
425 */
426 @Test
427 public void testTimestamp() throws SearchParseError {
428 final Match search = SearchCompiler.compile("timestamp:2010/2011");
429 final Node n1 = new Node();
430 n1.setTimestamp(DateUtils.fromString("2010-01-22"));
431 assertTrue(search.match(n1));
432 n1.setTimestamp(DateUtils.fromString("2016-01-22"));
433 assertFalse(search.match(n1));
434 }
435
436 /**
437 * Tests the implementation of the Boolean logic.
438 * @throws SearchParseError if an error has been encountered while compiling
439 */
440 @Test
441 public void testBooleanLogic() throws SearchParseError {
442 final SearchCompiler.Match c1 = SearchCompiler.compile("foo AND bar AND baz");
443 assertTrue(c1.match(newPrimitive("foobar", "baz")));
444 assertEquals("foo && bar && baz", c1.toString());
445 final SearchCompiler.Match c2 = SearchCompiler.compile("foo AND (bar OR baz)");
446 assertTrue(c2.match(newPrimitive("foobar", "yes")));
447 assertTrue(c2.match(newPrimitive("foobaz", "yes")));
448 assertEquals("foo && (bar || baz)", c2.toString());
449 final SearchCompiler.Match c3 = SearchCompiler.compile("foo OR (bar baz)");
450 assertEquals("foo || (bar && baz)", c3.toString());
451 final SearchCompiler.Match c4 = SearchCompiler.compile("foo1 OR (bar1 bar2 baz1 XOR baz2) OR foo2");
452 assertEquals("foo1 || (bar1 && bar2 && (baz1 ^ baz2)) || foo2", c4.toString());
453 final SearchCompiler.Match c5 = SearchCompiler.compile("foo1 XOR (baz1 XOR (bar baz))");
454 assertEquals("foo1 ^ baz1 ^ (bar && baz)", c5.toString());
455 final SearchCompiler.Match c6 = SearchCompiler.compile("foo1 XOR ((baz1 baz2) XOR (bar OR baz))");
456 assertEquals("foo1 ^ (baz1 && baz2) ^ (bar || baz)", c6.toString());
457 }
458
459 /**
460 * Tests {@code buildSearchStringForTag}.
461 * @throws SearchParseError if an error has been encountered while compiling
462 */
463 @Test
464 public void testBuildSearchStringForTag() throws SearchParseError {
465 final Tag tag1 = new Tag("foo=", "bar\"");
466 final Tag tag2 = new Tag("foo=", "=bar");
467 final String search1 = SearchCompiler.buildSearchStringForTag(tag1.getKey(), tag1.getValue());
468 assertEquals("\"foo=\"=\"bar\\\"\"", search1);
469 assertTrue(SearchCompiler.compile(search1).match(tag1));
470 assertFalse(SearchCompiler.compile(search1).match(tag2));
471 final String search2 = SearchCompiler.buildSearchStringForTag(tag1.getKey(), "");
472 assertEquals("\"foo=\"=*", search2);
473 assertTrue(SearchCompiler.compile(search2).match(tag1));
474 assertTrue(SearchCompiler.compile(search2).match(tag2));
475 }
476
477 /**
478 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/13870">Bug #13870</a>.
479 * @throws SearchParseError always
480 */
481 @Test(expected = SearchParseError.class)
482 public void testPattern13870() throws SearchParseError {
483 // https://bugs.openjdk.java.net/browse/JI-9044959
484 SearchSetting setting = new SearchSetting();
485 setting.regexSearch = true;
486 setting.text = "[";
487 SearchCompiler.compile(setting);
488 }
489
490 /**
491 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/14217">Bug #14217</a>.
492 * @throws Exception never
493 */
494 @Test
495 public void testTicket14217() throws Exception {
496 assertNotNull(SearchCompiler.compile(new String(Files.readAllBytes(
497 Paths.get(TestUtils.getRegressionDataFile(14217, "filter.txt"))), StandardCharsets.UTF_8)));
498 }
499
500 /**
501 * Unit test of {@link SearchCompiler.ExactKeyValue.Mode} enum.
502 */
503 @Test
504 public void testEnumExactKeyValueMode() {
505 TestUtils.superficialEnumCodeCoverage(ExactKeyValue.Mode.class);
506 }
507
508 /**
509 * Robustness test for preset searching. Ensures that the query 'preset:' is not accepted.
510 * @throws SearchParseError always
511 * @since 12464
512 */
513 @Test(expected = SearchParseError.class)
514 public void testPresetSearchMissingValue() throws SearchParseError {
515 SearchSetting settings = new SearchSetting();
516 settings.text = "preset:";
517 settings.mapCSSSearch = false;
518
519 TaggingPresets.readFromPreferences();
520
521 SearchCompiler.compile(settings);
522 }
523
524 /**
525 * Robustness test for preset searching. Validates that it is not possible to search for
526 * non existing presets.
527 * @throws SearchParseError always
528 * @since 12464
529 */
530 @Test(expected = SearchParseError.class)
531 public void testPresetNotExist() throws SearchParseError {
532 String testPresetName = "groupnamethatshouldnotexist/namethatshouldnotexist";
533 SearchSetting settings = new SearchSetting();
534 settings.text = "preset:" + testPresetName;
535 settings.mapCSSSearch = false;
536
537 // load presets
538 TaggingPresets.readFromPreferences();
539
540 SearchCompiler.compile(settings);
541 }
542
543 /**
544 * Robustness tests for preset searching. Ensures that combined preset names (having more than
545 * 1 word) must be enclosed with " .
546 * @throws SearchParseError always
547 * @since 12464
548 */
549 @Test(expected = SearchParseError.class)
550 public void testPresetMultipleWords() throws SearchParseError {
551 TaggingPreset testPreset = new TaggingPreset();
552 testPreset.name = "Test Combined Preset Name";
553 testPreset.group = new TaggingPresetMenu();
554 testPreset.group.name = "TestGroupName";
555
556 String combinedPresetname = testPreset.getRawName();
557 SearchSetting settings = new SearchSetting();
558 settings.text = "preset:" + combinedPresetname;
559 settings.mapCSSSearch = false;
560
561 // load presets
562 TaggingPresets.readFromPreferences();
563
564 SearchCompiler.compile(settings);
565 }
566
567
568 /**
569 * Ensures that correct presets are stored in the {@link org.openstreetmap.josm.data.osm.search.SearchCompiler.Preset}
570 * class against which the osm primitives are tested.
571 * @throws SearchParseError if an error has been encountered while compiling
572 * @throws NoSuchFieldException if there is no field called 'presets'
573 * @throws IllegalAccessException if cannot access the field where all matching presets are stored
574 * @since 12464
575 */
576 @Test
577 public void testPresetLookup() throws SearchParseError, NoSuchFieldException, IllegalAccessException {
578 TaggingPreset testPreset = new TaggingPreset();
579 testPreset.name = "Test Preset Name";
580 testPreset.group = new TaggingPresetMenu();
581 testPreset.group.name = "Test Preset Group Name";
582
583 String query = "preset:" +
584 "\"" + testPreset.getRawName() + "\"";
585 SearchSetting settings = new SearchSetting();
586 settings.text = query;
587 settings.mapCSSSearch = false;
588
589 // load presets and add the test preset
590 TaggingPresets.readFromPreferences();
591 TaggingPresets.addTaggingPresets(Collections.singletonList(testPreset));
592
593 Match match = SearchCompiler.compile(settings);
594
595 // access the private field where all matching presets are stored
596 // and ensure that indeed the correct ones are there
597 Field field = match.getClass().getDeclaredField("presets");
598 field.setAccessible(true);
599 @SuppressWarnings("unchecked")
600 Collection<TaggingPreset> foundPresets = (Collection<TaggingPreset>) field.get(match);
601
602 assertEquals(1, foundPresets.size());
603 assertTrue(foundPresets.contains(testPreset));
604 }
605
606 /**
607 * Ensures that the wildcard search works and that correct presets are stored in
608 * the {@link org.openstreetmap.josm.data.osm.search.SearchCompiler.Preset} class against which
609 * the osm primitives are tested.
610 * @throws SearchParseError if an error has been encountered while compiling
611 * @throws NoSuchFieldException if there is no field called 'presets'
612 * @throws IllegalAccessException if cannot access the field where all matching presets are stored
613 * @since 12464
614 */
615 @Test
616 public void testPresetLookupWildcard() throws SearchParseError, NoSuchFieldException, IllegalAccessException {
617 TaggingPresetMenu group = new TaggingPresetMenu();
618 group.name = "TestPresetGroup";
619
620 TaggingPreset testPreset1 = new TaggingPreset();
621 testPreset1.name = "TestPreset1";
622 testPreset1.group = group;
623
624 TaggingPreset testPreset2 = new TaggingPreset();
625 testPreset2.name = "TestPreset2";
626 testPreset2.group = group;
627
628 TaggingPreset testPreset3 = new TaggingPreset();
629 testPreset3.name = "TestPreset3";
630 testPreset3.group = group;
631
632 String query = "preset:" + "\"" + group.getRawName() + "/*\"";
633 SearchSetting settings = new SearchSetting();
634 settings.text = query;
635 settings.mapCSSSearch = false;
636
637 TaggingPresets.readFromPreferences();
638 TaggingPresets.addTaggingPresets(Arrays.asList(testPreset1, testPreset2, testPreset3));
639
640 Match match = SearchCompiler.compile(settings);
641
642 // access the private field where all matching presets are stored
643 // and ensure that indeed the correct ones are there
644 Field field = match.getClass().getDeclaredField("presets");
645 field.setAccessible(true);
646 @SuppressWarnings("unchecked")
647 Collection<TaggingPreset> foundPresets = (Collection<TaggingPreset>) field.get(match);
648
649 assertEquals(3, foundPresets.size());
650 assertTrue(foundPresets.contains(testPreset1));
651 assertTrue(foundPresets.contains(testPreset2));
652 assertTrue(foundPresets.contains(testPreset3));
653 }
654
655 /**
656 * Ensures that correct primitives are matched against the specified preset.
657 * @throws SearchParseError if an error has been encountered while compiling
658 * @since 12464
659 */
660 @Test
661 public void testPreset() throws SearchParseError {
662 final String presetName = "Test Preset Name";
663 final String presetGroupName = "Test Preset Group";
664 final String key = "test_key1";
665 final String val = "test_val1";
666
667 Key key1 = new Key();
668 key1.key = key;
669 key1.value = val;
670
671 TaggingPreset testPreset = new TaggingPreset();
672 testPreset.name = presetName;
673 testPreset.types = Collections.singleton(TaggingPresetType.NODE);
674 testPreset.data.add(key1);
675 testPreset.group = new TaggingPresetMenu();
676 testPreset.group.name = presetGroupName;
677
678 TaggingPresets.readFromPreferences();
679 TaggingPresets.addTaggingPresets(Collections.singleton(testPreset));
680
681 String query = "preset:" + "\"" + testPreset.getRawName() + "\"";
682
683 SearchContext ctx = new SearchContext(query);
684 ctx.n1.put(key, val);
685 ctx.n2.put(key, val);
686
687 for (OsmPrimitive osm : new OsmPrimitive[] {ctx.n1, ctx.n2}) {
688 ctx.match(osm, true);
689 }
690
691 for (OsmPrimitive osm : new OsmPrimitive[] {ctx.r1, ctx.r2, ctx.w1, ctx.w2}) {
692 ctx.match(osm, false);
693 }
694 }
695
696 /**
697 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/15755">Bug #15755</a>.
698 * @throws SearchParseError always
699 */
700 @Test
701 public void testTicket15755() throws SearchParseError {
702 expectedEx.expect(SearchParseError.class);
703 expectedEx.expectMessage("<html>Expecting <code>:</code> after <i>type</i></html>");
704 SearchCompiler.compile("public_transport=stop_area -type");
705 }
706}
Note: See TracBrowser for help on using the repository browser.