source: josm/trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.groovy@ 7938

Last change on this file since 7938 was 7938, checked in by bastiK, 9 years ago

add more subversion property svn:eol=native

  • Property svn:eol-style set to native
File size: 17.8 KB
Line 
1package org.openstreetmap.josm.gui.mappaint.mapcss
2
3import java.awt.Color
4
5import org.junit.Before
6import org.junit.Test
7import org.openstreetmap.josm.JOSMFixture
8import org.openstreetmap.josm.Main
9import org.openstreetmap.josm.data.coor.LatLon
10import org.openstreetmap.josm.data.osm.DataSet
11import org.openstreetmap.josm.data.osm.OsmUtils
12import org.openstreetmap.josm.data.osm.Way
13import org.openstreetmap.josm.gui.mappaint.Environment
14import org.openstreetmap.josm.gui.mappaint.MultiCascade
15import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser
16import org.openstreetmap.josm.tools.ColorHelper
17
18class MapCSSParserTest {
19
20 protected static Environment getEnvironment(String key, String value) {
21 return new Environment().withPrimitive(OsmUtils.createPrimitive("way " + key + "=" + value))
22 }
23
24 protected static MapCSSParser getParser(String stringToParse) {
25 return new MapCSSParser(new StringReader(stringToParse));
26 }
27
28 @Before
29 public void setUp() throws Exception {
30 JOSMFixture.createUnitTestFixture().init();
31 }
32
33 @Test
34 public void testKothicStylesheets() throws Exception {
35 new MapCSSParser(new URL("http://kothic.googlecode.com/hg/src/styles/default.mapcss").openStream(), "UTF-8")
36 new MapCSSParser(new URL("http://kothic.googlecode.com/hg/src/styles/mapink.mapcss").openStream(), "UTF-8")
37 }
38
39 @Test
40 public void testDeclarations() {
41 getParser("{ opacity: 0.5; color: rgb(1.0, 0.0, 0.0); }").declaration()
42 getParser("{ set tag=value; }").declaration() //set a tag
43 getParser("{ set tag; }").declaration() // set a tag to 'yes'
44 getParser("{ opacity: eval(\"tag('population')/100000\"); }").declaration()
45 getParser("{ set width_in_metres=eval(\"tag('lanes')*3\"); }").declaration()
46 }
47
48 @Test
49 public void testClassCondition() throws Exception {
50 def conditions = ((Selector.GeneralSelector) getParser("way[name=X].highway:closed").selector()).conds
51 assert conditions.get(0) instanceof Condition.SimpleKeyValueCondition
52 assert conditions.get(0).applies(getEnvironment("name", "X"))
53 assert conditions.get(1) instanceof Condition.ClassCondition
54 assert conditions.get(2) instanceof Condition.PseudoClassCondition
55 }
56
57 @Test
58 public void testClassMatching() throws Exception {
59 def css = new MapCSSStyleSource("" +
60 "way[highway=footway] { set .path; color: #FF6644; width: 2; }\n" +
61 "way[highway=path] { set path; color: brown; width: 2; }\n" +
62 "way[\"set\"=escape] { }\n" +
63 "way.path { text:auto; text-color: green; text-position: line; text-offset: 5; }\n" +
64 "way!.path { color: orange; }\n"
65 )
66 css.loadStyleSource()
67 assert css.getErrors().isEmpty()
68 def mc1 = new MultiCascade()
69 css.apply(mc1, OsmUtils.createPrimitive("way highway=path"), 1, false);
70 assert "green".equals(mc1.getCascade("default").get("text-color", null, String.class))
71 assert "brown".equals(mc1.getCascade("default").get("color", null, String.class))
72 def mc2 = new MultiCascade()
73 css.apply(mc2, OsmUtils.createPrimitive("way highway=residential"), 1, false);
74 assert "orange".equals(mc2.getCascade("default").get("color", null, String.class))
75 assert mc2.getCascade("default").get("text-color", null, String.class) == null
76 def mc3 = new MultiCascade()
77 css.apply(mc3, OsmUtils.createPrimitive("way highway=footway"), 1, false);
78 assert ColorHelper.html2color("#FF6644").equals(mc3.getCascade("default").get("color", null, Color.class))
79 }
80
81 @Test
82 public void testEqualCondition() throws Exception {
83 def condition = (Condition.SimpleKeyValueCondition) getParser("[surface=paved]").condition(Condition.Context.PRIMITIVE)
84 assert condition instanceof Condition.SimpleKeyValueCondition
85 assert "surface".equals(condition.k)
86 assert "paved".equals(condition.v)
87 assert condition.applies(getEnvironment("surface", "paved"))
88 assert !condition.applies(getEnvironment("surface", "unpaved"))
89 }
90
91 @Test
92 public void testNotEqualCondition() throws Exception {
93 def condition = (Condition.KeyValueCondition) getParser("[surface!=paved]").condition(Condition.Context.PRIMITIVE)
94 assert Condition.Op.NEQ.equals(condition.op)
95 assert !condition.applies(getEnvironment("surface", "paved"))
96 assert condition.applies(getEnvironment("surface", "unpaved"))
97 }
98
99 @Test
100 public void testRegexCondition() throws Exception {
101 def condition = (Condition.KeyValueCondition) getParser("[surface=~/paved|unpaved/]").condition(Condition.Context.PRIMITIVE)
102 assert Condition.Op.REGEX.equals(condition.op)
103 assert condition.applies(getEnvironment("surface", "unpaved"))
104 assert !condition.applies(getEnvironment("surface", "grass"))
105 }
106
107 @Test
108 public void testRegexConditionParenthesis() throws Exception {
109 def condition = (Condition.KeyValueCondition) getParser("[name =~ /^\\(foo\\)/]").condition(Condition.Context.PRIMITIVE)
110 assert condition.applies(getEnvironment("name", "(foo)"))
111 assert !condition.applies(getEnvironment("name", "foo"))
112 assert !condition.applies(getEnvironment("name", "((foo))"))
113 }
114
115 @Test
116 public void testNegatedRegexCondition() throws Exception {
117 def condition = (Condition.KeyValueCondition) getParser("[surface!~/paved|unpaved/]").condition(Condition.Context.PRIMITIVE)
118 assert Condition.Op.NREGEX.equals(condition.op)
119 assert !condition.applies(getEnvironment("surface", "unpaved"))
120 assert condition.applies(getEnvironment("surface", "grass"))
121 }
122
123 @Test
124 public void testBeginsEndsWithCondition() throws Exception {
125 def condition = (Condition.KeyValueCondition) getParser('[foo ^= bar]').condition(Condition.Context.PRIMITIVE)
126 assert Condition.Op.BEGINS_WITH.equals(condition.op)
127 assert condition.applies(getEnvironment("foo", "bar123"))
128 assert !condition.applies(getEnvironment("foo", "123bar"))
129 assert !condition.applies(getEnvironment("foo", "123bar123"))
130 condition = (Condition.KeyValueCondition) getParser('[foo $= bar]').condition(Condition.Context.PRIMITIVE)
131 assert Condition.Op.ENDS_WITH.equals(condition.op)
132 assert !condition.applies(getEnvironment("foo", "bar123"))
133 assert condition.applies(getEnvironment("foo", "123bar"))
134 assert !condition.applies(getEnvironment("foo", "123bar123"))
135 }
136
137 @Test
138 public void testOneOfCondition() throws Exception {
139 def condition = getParser('[vending~=stamps]').condition(Condition.Context.PRIMITIVE)
140 assert condition.applies(getEnvironment("vending", "stamps"))
141 assert condition.applies(getEnvironment("vending", "bar;stamps;foo"))
142 assert !condition.applies(getEnvironment("vending", "every;thing;else"))
143 assert !condition.applies(getEnvironment("vending", "or_nothing"))
144 }
145
146 @Test
147 public void testStandardKeyCondition() throws Exception {
148 def c1 = (Condition.KeyCondition) getParser("[ highway ]").condition(Condition.Context.PRIMITIVE)
149 assert c1.matchType == null
150 assert c1.applies(getEnvironment("highway", "unclassified"))
151 assert !c1.applies(getEnvironment("railway", "rail"))
152 def c2 = (Condition.KeyCondition) getParser("[\"/slash/\"]").condition(Condition.Context.PRIMITIVE)
153 assert c2.matchType == null
154 assert c2.applies(getEnvironment("/slash/", "yes"))
155 assert !c2.applies(getEnvironment("\"slash\"", "no"))
156 }
157
158 @Test
159 public void testYesNoKeyCondition() throws Exception {
160 def c1 = (Condition.KeyCondition) getParser("[oneway?]").condition(Condition.Context.PRIMITIVE)
161 def c2 = (Condition.KeyCondition) getParser("[oneway?!]").condition(Condition.Context.PRIMITIVE)
162 def c3 = (Condition.KeyCondition) getParser("[!oneway?]").condition(Condition.Context.PRIMITIVE)
163 def c4 = (Condition.KeyCondition) getParser("[!oneway?!]").condition(Condition.Context.PRIMITIVE)
164 def yes = getEnvironment("oneway", "yes")
165 def no = getEnvironment("oneway", "no")
166 def none = getEnvironment("no-oneway", "foo")
167 assert c1.applies(yes)
168 assert !c1.applies(no)
169 assert !c1.applies(none)
170 assert !c2.applies(yes)
171 assert c2.applies(no)
172 assert !c2.applies(none)
173 assert !c3.applies(yes)
174 assert c3.applies(no)
175 assert c3.applies(none)
176 assert c4.applies(yes)
177 assert !c4.applies(no)
178 assert c4.applies(none)
179 }
180
181 @Test
182 public void testRegexKeyCondition() throws Exception {
183 def c1 = (Condition.KeyCondition) getParser("[/.*:(backward|forward)\$/]").condition(Condition.Context.PRIMITIVE)
184 assert Condition.KeyMatchType.REGEX.equals(c1.matchType)
185 assert !c1.applies(getEnvironment("lanes", "3"))
186 assert c1.applies(getEnvironment("lanes:forward", "3"))
187 assert c1.applies(getEnvironment("lanes:backward", "3"))
188 assert !c1.applies(getEnvironment("lanes:foobar", "3"))
189 }
190
191 @Test
192 public void testNRegexKeyConditionSelector() throws Exception {
193 def s1 = getParser("*[sport][tourism != hotel]").selector()
194 assert s1.matches(new Environment().withPrimitive(OsmUtils.createPrimitive("node sport=foobar")))
195 assert !s1.matches(new Environment().withPrimitive(OsmUtils.createPrimitive("node sport=foobar tourism=hotel")))
196 def s2 = getParser("*[sport][tourism != hotel][leisure !~ /^(sports_centre|stadium|)\$/]").selector()
197 assert s2.matches(new Environment().withPrimitive(OsmUtils.createPrimitive("node sport=foobar")))
198 assert !s2.matches(new Environment().withPrimitive(OsmUtils.createPrimitive("node sport=foobar tourism=hotel")))
199 assert !s2.matches(new Environment().withPrimitive(OsmUtils.createPrimitive("node sport=foobar leisure=stadium")))
200 }
201
202 @Test
203 public void testKeyKeyCondition() throws Exception {
204 def c1 = (Condition.KeyValueCondition) getParser("[foo = *bar]").condition(Condition.Context.PRIMITIVE)
205 def w1 = new Way()
206 w1.put("foo", "123")
207 w1.put("bar", "456")
208 assert !c1.applies(new Environment().withPrimitive(w1))
209 w1.put("bar", "123")
210 assert c1.applies(new Environment().withPrimitive(w1))
211 def c2 = (Condition.KeyValueCondition) getParser("[foo =~ */bar/]").condition(Condition.Context.PRIMITIVE)
212 def w2 = new Way(w1)
213 w2.put("bar", "[0-9]{3}")
214 assert c2.applies(new Environment().withPrimitive(w2))
215 w2.put("bar", "[0-9]")
216 assert c2.applies(new Environment().withPrimitive(w2))
217 w2.put("bar", "^[0-9]\$")
218 assert !c2.applies(new Environment().withPrimitive(w2))
219 }
220
221 @Test
222 public void testTicket8568() throws Exception {
223 def sheet = new MapCSSStyleSource("" +
224 "way { width: 5; }\n" +
225 "way[keyA], way[keyB] { width: eval(prop(width)+10); }")
226 sheet.loadStyleSource()
227 def mc = new MultiCascade()
228 sheet.apply(mc, OsmUtils.createPrimitive("way foo=bar"), 20, false)
229 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 5
230 sheet.apply(mc, OsmUtils.createPrimitive("way keyA=true"), 20, false)
231 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 15
232 sheet.apply(mc, OsmUtils.createPrimitive("way keyB=true"), 20, false)
233 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 15
234 sheet.apply(mc, OsmUtils.createPrimitive("way keyA=true keyB=true"), 20, false)
235 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 15
236 }
237
238 @Test
239 public void testTicket8071() throws Exception {
240 def sheet = new MapCSSStyleSource("" +
241 "*[rcn_ref], *[name] {text: concat(tag(rcn_ref), \" \", tag(name)); }")
242 sheet.loadStyleSource()
243 def mc = new MultiCascade()
244 sheet.apply(mc, OsmUtils.createPrimitive("way name=Foo"), 20, false)
245 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == " Foo"
246 sheet.apply(mc, OsmUtils.createPrimitive("way rcn_ref=15"), 20, false)
247 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == "15 "
248 sheet.apply(mc, OsmUtils.createPrimitive("way rcn_ref=15 name=Foo"), 20, false)
249 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == "15 Foo"
250
251 sheet = new MapCSSStyleSource("" +
252 "*[rcn_ref], *[name] {text: join(\" - \", tag(rcn_ref), tag(ref), tag(name)); }")
253 sheet.loadStyleSource()
254 sheet.apply(mc, OsmUtils.createPrimitive("way rcn_ref=15 ref=1.5 name=Foo"), 20, false)
255 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == "15 - 1.5 - Foo"
256 }
257
258 @Test
259 public void testColorNameTicket9191() throws Exception {
260 def e = new Environment(null, new MultiCascade(), Environment.DEFAULT_LAYER, null)
261 getParser("{color: testcolour1#88DD22}").declaration().instructions.get(0).execute(e)
262 def expected = new Color(0x88DD22)
263 assert e.getCascade(Environment.DEFAULT_LAYER).get("color") == expected
264 assert Main.pref.getDefaultColor("mappaint.mapcss.testcolour1") == expected
265 }
266
267 @Test
268 public void testColorNameTicket9191Alpha() throws Exception {
269 def e = new Environment(null, new MultiCascade(), Environment.DEFAULT_LAYER, null)
270 getParser("{color: testcolour2#12345678}").declaration().instructions.get(0).execute(e)
271 def expected = new Color(0x12, 0x34, 0x56, 0x78)
272 assert e.getCascade(Environment.DEFAULT_LAYER).get("color") == expected
273 assert Main.pref.getDefaultColor("mappaint.mapcss.testcolour2") == expected
274 }
275
276 @Test
277 public void testColorParsing() throws Exception {
278 assert ColorHelper.html2color("#12345678") == new Color(0x12, 0x34, 0x56, 0x78)
279 }
280
281 @Test
282 public void testChildSelectorGreaterThanSignIsOptional() throws Exception {
283 assert getParser("relation[type=route] way[highway]").child_selector().toString() ==
284 getParser("relation[type=route] > way[highway]").child_selector().toString()
285 }
286
287 @Test
288 public void testSiblingSelector() throws Exception {
289 def s1 = (Selector.ChildOrParentSelector) getParser("*[a?][parent_tag(\"highway\")=\"unclassified\"] + *[b?]").child_selector()
290 def ds = new DataSet()
291 def n1 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1, 2))
292 n1.put("a", "true")
293 def n2 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1.1, 2.2))
294 n2.put("b", "true")
295 def w = new Way()
296 w.put("highway", "unclassified")
297 ds.addPrimitive(n1)
298 ds.addPrimitive(n2)
299 ds.addPrimitive(w)
300 w.addNode(n1)
301 w.addNode(n2)
302
303 def e = new Environment().withPrimitive(n2)
304 assert s1.matches(e)
305 assert e.osm == n2
306 assert e.child == n1
307 assert e.parent == w
308 assert !s1.matches(new Environment().withPrimitive(n1))
309 assert !s1.matches(new Environment().withPrimitive(w))
310 }
311
312 @Test
313 public void testSiblingSelectorInterpolation() throws Exception {
314 def s1 = (Selector.ChildOrParentSelector) getParser(
315 "*[tag(\"addr:housenumber\") > child_tag(\"addr:housenumber\")][regexp_test(\"even|odd\", parent_tag(\"addr:interpolation\"))]" +
316 " + *[addr:housenumber]").child_selector()
317 def ds = new DataSet()
318 def n1 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1, 2))
319 n1.put("addr:housenumber", "10")
320 def n2 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1.1, 2.2))
321 n2.put("addr:housenumber", "100")
322 def n3 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1.2, 2.3))
323 n3.put("addr:housenumber", "20")
324 def w = new Way()
325 w.put("addr:interpolation", "even")
326 ds.addPrimitive(n1)
327 ds.addPrimitive(n2)
328 ds.addPrimitive(n3)
329 ds.addPrimitive(w)
330 w.addNode(n1)
331 w.addNode(n2)
332 w.addNode(n3)
333
334 assert s1.right.matches(new Environment().withPrimitive(n3))
335 assert s1.left.matches(new Environment().withPrimitive(n2).withChild(n3).withParent(w))
336 assert s1.matches(new Environment().withPrimitive(n3))
337 assert !s1.matches(new Environment().withPrimitive(n1))
338 assert !s1.matches(new Environment().withPrimitive(n2))
339 assert !s1.matches(new Environment().withPrimitive(w))
340 }
341
342 @Test
343 public void testInvalidBaseSelector() throws Exception {
344 def css = new MapCSSStyleSource("invalid_base[key=value] {}")
345 css.loadStyleSource()
346 assert !css.getErrors().isEmpty()
347 assert css.getErrors().iterator().next().toString().contains("Unknown MapCSS base selector invalid_base")
348 }
349
350 @Test
351 public void testMinMaxFunctions() throws Exception {
352 def sheet = new MapCSSStyleSource("* {" +
353 "min_value: min(tag(x), tag(y), tag(z)); " +
354 "max_value: max(tag(x), tag(y), tag(z)); " +
355 "max_split: max(split(\";\", tag(widths))); " +
356 "}")
357 sheet.loadStyleSource()
358 def mc = new MultiCascade()
359
360 sheet.apply(mc, OsmUtils.createPrimitive("way x=4 y=6 z=8 u=100"), 20, false)
361 assert mc.getCascade(Environment.DEFAULT_LAYER).get("min_value", Float.NaN, Float.class) == 4.0f
362 assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_value", Float.NaN, Float.class) == 8.0f
363
364 sheet.apply(mc, OsmUtils.createPrimitive("way x=4 y=6 widths=1;2;8;56;3;a"), 20, false)
365 assert mc.getCascade(Environment.DEFAULT_LAYER).get("min_value", -777f, Float.class) == 4
366 assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_value", -777f, Float.class) == 6
367 assert mc.getCascade(Environment.DEFAULT_LAYER).get("max_split", -777f, Float.class) == 56
368 }
369}
Note: See TracBrowser for help on using the repository browser.