1 /* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.javafx.css; 27 28 import com.sun.javafx.css.*; 29 30 import java.io.ByteArrayInputStream; 31 import java.io.ByteArrayOutputStream; 32 import java.io.DataInputStream; 33 import java.io.DataOutputStream; 34 import java.io.IOException; 35 import java.util.Arrays; 36 import java.util.List; 37 import java.util.Map; 38 import javafx.css.CssParser; 39 import javafx.css.CssParserShim; 40 import javafx.css.Declaration; 41 import javafx.css.FontFace; 42 43 import javafx.css.ParsedValue; 44 import javafx.css.ParsedValue; 45 import javafx.css.Rule; 46 import javafx.css.RuleShim; 47 import javafx.css.Stylesheet; 48 import javafx.scene.paint.Color; 49 import javafx.scene.paint.LinearGradient; 50 import javafx.scene.paint.Paint; 51 import javafx.scene.paint.Stop; 52 import javafx.scene.text.Font; 53 import javafx.util.Duration; 54 import org.junit.Test; 55 import static org.junit.Assert.*; 56 57 58 public class CssParserTest { 59 60 @Test 61 public void testRT_16959() { 62 63 CssParser instance = new CssParser(); 64 65 // RT-16959 is an infinite loop on incomplete linear gradient 66 ParsedValue result = new CssParserShim(instance) 67 .parseExpr("-fx-background-color", "linear-gradient(from 0% 0% to 0% 100%, )"); 68 assertNull("parseExpr", result); 69 70 // The bad syntax should be skipped. The stylesheet should have one 71 // linear gradient with colors red, white, blue. 72 Stylesheet ss = instance.parse( 73 "* { " 74 + "-fx-background-color: linear-gradient(from 0% 0% to 0% 100%, ); " 75 + "-fx-background-color: linear-gradient(from 0% 0% to 0% 100%, red, white, blue); " 76 + "}" 77 ); 78 79 assertNotNull(ss); 80 List<Rule> rules = ss.getRules(); 81 assertEquals(1,rules.size(),0); 82 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 83 assertTrue(decls.size()==1); 84 Declaration decl = decls.get(0); 85 ParsedValue value = decl.getParsedValue(); 86 assertTrue(value != null); 87 88 Paint[] layers = (Paint[])value.convert(null); 89 assertTrue(layers.length == 1); 90 91 LinearGradient lg = (LinearGradient)layers[0]; 92 List<Stop> stops = lg.getStops(); 93 assertTrue(stops.size()==3); 94 assertEquals(Color.RED, stops.get(0).getColor()); 95 assertEquals(Color.WHITE, stops.get(1).getColor()); 96 assertEquals(Color.BLUE, stops.get(2).getColor()); 97 98 } 99 100 101 @Test 102 public void testRT_17770() { 103 104 // RT-17770 is an infinite loop on a dangling comma. 105 // Missing term should be ignored 106 String stylesheetText = 107 "* {" 108 + "-fx-background-color: linear-gradient( " 109 + "to right, " 110 + "rgba(141, 138, 125, 0.0), " 111 + "rgba(248, 248, 246, 0.3) 45%, " 112 + "rgba(248, 248, 246, 0.8) 50%, " 113 + "rgba(248, 248, 246, 0.3) 55%, " 114 + "rgba(141, 138, 125, 0.0), " 115 + "); " 116 + "}"; 117 118 CssParser instance = new CssParser(); 119 120 Stylesheet ss = instance.parse(stylesheetText); 121 122 assertNotNull(ss); 123 List<Rule> rules = ss.getRules(); 124 assertEquals(1,rules.size(),0); 125 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 126 assertTrue(decls.size()==1); 127 Declaration decl = decls.get(0); 128 ParsedValue value = decl.getParsedValue(); 129 assertTrue(value != null); 130 131 Paint[] layers = (Paint[])value.convert(null); 132 assertTrue(layers.length == 1); 133 134 LinearGradient lg = (LinearGradient)layers[0]; 135 List<Stop> stops = lg.getStops(); 136 assertTrue(stops.size()==5); 137 assertEquals(Color.rgb(141, 138, 125, 0.0), stops.get(0).getColor()); 138 assertEquals(Color.rgb(248, 248, 246, 0.3), stops.get(1).getColor()); 139 assertEquals(Color.rgb(248, 248, 246, 0.8), stops.get(2).getColor()); 140 assertEquals(Color.rgb(248, 248, 246, 0.3), stops.get(3).getColor()); 141 assertEquals(Color.rgb(141, 138, 125, 0.0), stops.get(4).getColor()); 142 143 } 144 145 @Test 146 public void testParseSizeWithInvalidDigits() { 147 148 CssParser instance = new CssParser(); 149 150 // RT-16959 is an infinite loop on incomplete linear gradient 151 ParsedValue result = new CssParserShim(instance).parseExpr("-fx-font-size", "10ptx"); 152 assertNull("parseExpr", result); 153 154 // The bad syntax should be skipped. 155 Stylesheet ss = instance.parse( 156 "* {" 157 + "-fx-font-size: 10ptx; " 158 + "-fx-font-size: 12px; " 159 + "}" 160 ); 161 162 assertNotNull(ss); 163 List<Rule> rules = ss.getRules(); 164 assertEquals(1,rules.size(),0); 165 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 166 assertTrue(decls.size()==1); 167 Declaration decl = decls.get(0); 168 ParsedValue value = decl.getParsedValue(); 169 assertTrue(value != null); 170 171 Double size = (Double)value.convert(Font.font("Amble", 12)); 172 assertTrue(Double.compare(size, 12) == 0); 173 } 174 175 176 @Test 177 public void testRT_17830() { 178 179 CssParser instance = new CssParser(); 180 181 // The empty declaration should be skipped. The stylesheet should have 182 // two declarations. 183 Stylesheet ss = instance.parse(".rt17830 {-fx-fill: red;; -fx-stroke: yellow; }"); 184 185 assertNotNull(ss); 186 List<Rule> rules = ss.getRules(); 187 assertEquals(1,rules.size(),0); 188 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 189 assertEquals(2,decls.size(),0); 190 191 Declaration decl = decls.get(0); 192 ParsedValue value = decl.getParsedValue(); 193 assertTrue(value != null); 194 Paint paint = (Paint)value.convert(null); 195 assertEquals(Color.RED, paint); 196 197 decl = decls.get(1); 198 value = decl.getParsedValue(); 199 assertTrue(value != null); 200 paint = (Paint)value.convert(null); 201 assertEquals(Color.YELLOW, paint); 202 } 203 204 @Test 205 public void testRT_20311() { 206 207 CssParser instance = new CssParser(); 208 209 try { 210 instance.parse(".rt-20311 { -fx-background-color:red\n-fx-border-color:black; }"); 211 } catch (Exception e) { 212 fail(e.toString()); 213 } 214 215 } 216 217 @Test public void testFontFace() { 218 219 // http://fonts.googleapis.com/css?family=Bree+Serif 220 String css = "@font-face {\n" + 221 "font-family: 'Bree Serif';\n" + 222 "font-style: normal;\n" + 223 "font-weight: 400;\n" + 224 "src: local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff');\n"+ 225 "}"; 226 227 Stylesheet stylesheet = new CssParser().parse(css); 228 229 int nFontFaceSrcs = checkFontFace(stylesheet); 230 231 assertEquals(3, nFontFaceSrcs); 232 } 233 234 @Test public void testFontFaceMoreThanOneSrc() { 235 236 // http://fonts.googleapis.com/css?family=Bree+Serif 237 String css = "@font-face {\n" + 238 "font-family: 'Bree Serif';\n" + 239 "font-style: normal;\n" + 240 "font-weight: 400;\n" + 241 "src: local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff'),\n"+ 242 " local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff');\n"+ 243 "}"; 244 245 Stylesheet stylesheet = new CssParser().parse(css); 246 247 int nFontFaceSrcs = checkFontFace(stylesheet); 248 assertEquals(6, nFontFaceSrcs); 249 } 250 251 public static int checkFontFace(Stylesheet stylesheet) { 252 253 List<FontFace> fontFaces = stylesheet.getFontFaces(); 254 assertNotNull(fontFaces); 255 assertEquals(1, fontFaces.size()); 256 257 FontFaceImpl fontFace = (FontFaceImpl)fontFaces.get(0); 258 259 Map<String,String> descriptors = fontFace.getDescriptors(); 260 assertEquals("'Bree Serif'", descriptors.get("font-family")); 261 assertEquals("normal", descriptors.get("font-style")); 262 assertEquals("400", descriptors.get("font-weight")); 263 264 List<FontFaceImpl.FontFaceSrc> fontFaceSrcs = fontFace.getSources(); 265 266 int nFontFaceSrcs = fontFaceSrcs != null ? fontFaceSrcs.size() : 0; 267 268 for(int n=0; n<nFontFaceSrcs; n++) { 269 FontFaceImpl.FontFaceSrc fontFaceSrc = fontFaceSrcs.get(n); 270 FontFaceImpl.FontFaceSrcType type = fontFaceSrc.getType(); 271 switch(type) { 272 case LOCAL: { 273 String src = fontFaceSrc.getSrc(); 274 assertTrue("Bree Serif".equals(src) || "BreeSerif-Regular".equals(src)); 275 assertNull(fontFaceSrc.getFormat()); 276 break; 277 } 278 case URL: { 279 String src = fontFaceSrc.getSrc(); 280 assertEquals(src, "http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff"); 281 assertEquals(fontFaceSrc.getFormat(), "woff"); 282 break; 283 } 284 case REFERENCE: 285 default: 286 fail(); 287 } 288 } 289 290 return nFontFaceSrcs; 291 } 292 293 @Test public void testRT_32522() { 294 295 ParsedValue value = new CssParserShim().parseExpr("foo", "1 2em 3 4;"); 296 Object obj = value.convert(Font.font(13)); 297 assert obj instanceof Number[]; 298 assertArrayEquals(new Number[] {1d, 26d, 3d, 4d}, (Number[])obj); 299 300 value = new CssParserShim().parseExpr("foo", "1;"); 301 obj = value.convert(null); 302 assert obj instanceof Number; 303 assertEquals(1d, (Number)obj); 304 305 } 306 307 @Test public void testRT_38483() { 308 309 Duration expected = Duration.millis(42); 310 ParsedValue value = new CssParserShim().parseExpr("foo", "42ms;"); 311 Object observed = value.convert(null); 312 assertEquals(expected, observed); 313 314 value = new CssParserShim().parseExpr("foo", "indefinite;"); 315 observed = value.convert(null); 316 assertEquals(Duration.INDEFINITE, observed); 317 } 318 }