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

Last change on this file since 7124 was 7124, checked in by simon04, 10 years ago

MapCSS parsing: warn on unknown base selectors

File size: 15.3 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.TestUtils
10import org.openstreetmap.josm.data.coor.LatLon
11import org.openstreetmap.josm.data.osm.DataSet
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(TestUtils.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, TestUtils.createPrimitive("way highway=path"), 1, null, 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, TestUtils.createPrimitive("way highway=residential"), 1, null, 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, TestUtils.createPrimitive("way highway=footway"), 1, null, 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 testStandardKeyCondition() throws Exception {
125 def c1 = (Condition.KeyCondition) getParser("[ highway ]").condition(Condition.Context.PRIMITIVE)
126 assert c1.matchType == null
127 assert c1.applies(getEnvironment("highway", "unclassified"))
128 assert !c1.applies(getEnvironment("railway", "rail"))
129 def c2 = (Condition.KeyCondition) getParser("[\"/slash/\"]").condition(Condition.Context.PRIMITIVE)
130 assert c2.matchType == null
131 assert c2.applies(getEnvironment("/slash/", "yes"))
132 assert !c2.applies(getEnvironment("\"slash\"", "no"))
133 }
134
135 @Test
136 public void testYesNoKeyCondition() throws Exception {
137 def c1 = (Condition.KeyCondition) getParser("[oneway?]").condition(Condition.Context.PRIMITIVE)
138 def c2 = (Condition.KeyCondition) getParser("[oneway?!]").condition(Condition.Context.PRIMITIVE)
139 def c3 = (Condition.KeyCondition) getParser("[!oneway?]").condition(Condition.Context.PRIMITIVE)
140 def c4 = (Condition.KeyCondition) getParser("[!oneway?!]").condition(Condition.Context.PRIMITIVE)
141 def yes = getEnvironment("oneway", "yes")
142 def no = getEnvironment("oneway", "no")
143 def none = getEnvironment("no-oneway", "foo")
144 assert c1.applies(yes)
145 assert !c1.applies(no)
146 assert !c1.applies(none)
147 assert !c2.applies(yes)
148 assert c2.applies(no)
149 assert !c2.applies(none)
150 assert !c3.applies(yes)
151 assert c3.applies(no)
152 assert c3.applies(none)
153 assert c4.applies(yes)
154 assert !c4.applies(no)
155 assert c4.applies(none)
156 }
157
158 @Test
159 public void testRegexKeyCondition() throws Exception {
160 def c1 = (Condition.KeyCondition) getParser("[/.*:(backward|forward)\$/]").condition(Condition.Context.PRIMITIVE)
161 assert Condition.KeyMatchType.REGEX.equals(c1.matchType)
162 assert !c1.applies(getEnvironment("lanes", "3"))
163 assert c1.applies(getEnvironment("lanes:forward", "3"))
164 assert c1.applies(getEnvironment("lanes:backward", "3"))
165 assert !c1.applies(getEnvironment("lanes:foobar", "3"))
166 }
167
168 @Test
169 public void testNRegexKeyConditionSelector() throws Exception {
170 def s1 = getParser("*[sport][tourism != hotel]").selector()
171 assert s1.matches(new Environment().withPrimitive(TestUtils.createPrimitive("node sport=foobar")))
172 assert !s1.matches(new Environment().withPrimitive(TestUtils.createPrimitive("node sport=foobar tourism=hotel")))
173 def s2 = getParser("*[sport][tourism != hotel][leisure !~ /^(sports_centre|stadium|)\$/]").selector()
174 assert s2.matches(new Environment().withPrimitive(TestUtils.createPrimitive("node sport=foobar")))
175 assert !s2.matches(new Environment().withPrimitive(TestUtils.createPrimitive("node sport=foobar tourism=hotel")))
176 assert !s2.matches(new Environment().withPrimitive(TestUtils.createPrimitive("node sport=foobar leisure=stadium")))
177 }
178
179 @Test
180 public void testKeyKeyCondition() throws Exception {
181 def c1 = (Condition.KeyValueCondition) getParser("[foo = *bar]").condition(Condition.Context.PRIMITIVE)
182 def w1 = new Way()
183 w1.put("foo", "123")
184 w1.put("bar", "456")
185 assert !c1.applies(new Environment().withPrimitive(w1))
186 w1.put("bar", "123")
187 assert c1.applies(new Environment().withPrimitive(w1))
188 def c2 = (Condition.KeyValueCondition) getParser("[foo =~ */bar/]").condition(Condition.Context.PRIMITIVE)
189 def w2 = new Way(w1)
190 w2.put("bar", "[0-9]{3}")
191 assert c2.applies(new Environment().withPrimitive(w2))
192 w2.put("bar", "[0-9]")
193 assert c2.applies(new Environment().withPrimitive(w2))
194 w2.put("bar", "^[0-9]\$")
195 assert !c2.applies(new Environment().withPrimitive(w2))
196 }
197
198 @Test
199 public void testTicket8568() throws Exception {
200 def sheet = new MapCSSStyleSource("" +
201 "way { width: 5; }\n" +
202 "way[keyA], way[keyB] { width: eval(prop(width)+10); }")
203 sheet.loadStyleSource()
204 def mc = new MultiCascade()
205 sheet.apply(mc, TestUtils.createPrimitive("way foo=bar"), 20, null, false)
206 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 5
207 sheet.apply(mc, TestUtils.createPrimitive("way keyA=true"), 20, null, false)
208 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 15
209 sheet.apply(mc, TestUtils.createPrimitive("way keyB=true"), 20, null, false)
210 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 15
211 sheet.apply(mc, TestUtils.createPrimitive("way keyA=true keyB=true"), 20, null, false)
212 assert mc.getCascade(Environment.DEFAULT_LAYER).get("width") == 15
213 }
214
215 @Test
216 public void testTicket8071() throws Exception {
217 def sheet = new MapCSSStyleSource("" +
218 "*[rcn_ref], *[name] {text: concat(tag(rcn_ref), \" \", tag(name)); }")
219 sheet.loadStyleSource()
220 def mc = new MultiCascade()
221 sheet.apply(mc, TestUtils.createPrimitive("way name=Foo"), 20, null, false)
222 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == " Foo"
223 sheet.apply(mc, TestUtils.createPrimitive("way rcn_ref=15"), 20, null, false)
224 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == "15 "
225 sheet.apply(mc, TestUtils.createPrimitive("way rcn_ref=15 name=Foo"), 20, null, false)
226 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == "15 Foo"
227
228 sheet = new MapCSSStyleSource("" +
229 "*[rcn_ref], *[name] {text: join(\" - \", tag(rcn_ref), tag(ref), tag(name)); }")
230 sheet.loadStyleSource()
231 sheet.apply(mc, TestUtils.createPrimitive("way rcn_ref=15 ref=1.5 name=Foo"), 20, null, false)
232 assert mc.getCascade(Environment.DEFAULT_LAYER).get("text") == "15 - 1.5 - Foo"
233 }
234
235 @Test
236 public void testColorNameTicket9191() throws Exception {
237 def e = new Environment(null, new MultiCascade(), Environment.DEFAULT_LAYER, null)
238 getParser("{color: testcolour1#88DD22}").declaration().instructions.get(0).execute(e)
239 def expected = new Color(0x88DD22)
240 assert e.getCascade(Environment.DEFAULT_LAYER).get("color") == expected
241 assert Main.pref.getDefaultColor("mappaint.mapcss.testcolour1") == expected
242 }
243
244 @Test
245 public void testColorNameTicket9191Alpha() throws Exception {
246 def e = new Environment(null, new MultiCascade(), Environment.DEFAULT_LAYER, null)
247 getParser("{color: testcolour2#12345678}").declaration().instructions.get(0).execute(e)
248 def expected = new Color(0x12, 0x34, 0x56, 0x78)
249 assert e.getCascade(Environment.DEFAULT_LAYER).get("color") == expected
250 assert Main.pref.getDefaultColor("mappaint.mapcss.testcolour2") == expected
251 }
252
253 @Test
254 public void testColorParsing() throws Exception {
255 assert ColorHelper.html2color("#12345678") == new Color(0x12, 0x34, 0x56, 0x78)
256 }
257
258 @Test
259 public void testSiblingSelector() throws Exception {
260 def s1 = (Selector.ChildOrParentSelector) getParser("*[a?][parent_tag(\"highway\")=\"unclassified\"] + *[b?]").child_selector()
261 def ds = new DataSet()
262 def n1 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1, 2))
263 n1.put("a", "true")
264 def n2 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1.1, 2.2))
265 n2.put("b", "true")
266 def w = new Way()
267 w.put("highway", "unclassified")
268 ds.addPrimitive(n1)
269 ds.addPrimitive(n2)
270 ds.addPrimitive(w)
271 w.addNode(n1)
272 w.addNode(n2)
273
274 def e = new Environment().withPrimitive(n2)
275 assert s1.matches(e)
276 assert e.osm == n2
277 assert e.child == n1
278 assert e.parent == w
279 assert !s1.matches(new Environment().withPrimitive(n1))
280 assert !s1.matches(new Environment().withPrimitive(w))
281 }
282
283 @Test
284 public void testSiblingSelectorInterpolation() throws Exception {
285 def s1 = (Selector.ChildOrParentSelector) getParser(
286 "*[tag(\"addr:housenumber\") > child_tag(\"addr:housenumber\")][regexp_test(\"even|odd\", parent_tag(\"addr:interpolation\"))]" +
287 " + *[addr:housenumber]").child_selector()
288 def ds = new DataSet()
289 def n1 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1, 2))
290 n1.put("addr:housenumber", "10")
291 def n2 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1.1, 2.2))
292 n2.put("addr:housenumber", "100")
293 def n3 = new org.openstreetmap.josm.data.osm.Node(new LatLon(1.2, 2.3))
294 n3.put("addr:housenumber", "20")
295 def w = new Way()
296 w.put("addr:interpolation", "even")
297 ds.addPrimitive(n1)
298 ds.addPrimitive(n2)
299 ds.addPrimitive(n3)
300 ds.addPrimitive(w)
301 w.addNode(n1)
302 w.addNode(n2)
303 w.addNode(n3)
304
305 assert s1.right.matches(new Environment().withPrimitive(n3))
306 assert s1.left.matches(new Environment().withPrimitive(n2).withChild(n3).withParent(w))
307 assert s1.matches(new Environment().withPrimitive(n3))
308 assert !s1.matches(new Environment().withPrimitive(n1))
309 assert !s1.matches(new Environment().withPrimitive(n2))
310 assert !s1.matches(new Environment().withPrimitive(w))
311 }
312
313 @Test
314 public void testInvalidBaseSelector() throws Exception {
315 def css = new MapCSSStyleSource("invalid_base[key=value] {}")
316 css.loadStyleSource()
317 assert !css.getErrors().isEmpty()
318 assert css.getErrors().iterator().next().toString().contains("Unknown MapCSS base selector invalid_base")
319 }
320}
Note: See TracBrowser for help on using the repository browser.