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.Declaration; 40 import javafx.css.FontFace; 41 42 import javafx.css.ParsedValue; 43 import javafx.css.ParsedValue; 44 import javafx.css.Rule; 45 import javafx.css.RuleShim; 46 import javafx.css.Stylesheet; 47 import javafx.scene.paint.Color; 48 import javafx.scene.paint.LinearGradient; 49 import javafx.scene.paint.Paint; 50 import javafx.scene.paint.Stop; 51 import javafx.scene.text.Font; 52 import javafx.util.Duration; 53 import org.junit.Test; 54 import static org.junit.Assert.*; 55 56 57 public class CssParserTest { 58 59 @Test 60 public void testRT_16959() { 61 62 CssParser instance = new CssParser(); 63 64 // RT-16959 is an infinite loop on incomplete linear gradient 65 ParsedValue result = instance.parseExpr("-fx-background-color", "linear-gradient(from 0% 0% to 0% 100%, )"); 66 assertNull("parseExpr", result); 67 68 // The bad syntax should be skipped. The stylesheet should have one 69 // linear gradient with colors red, white, blue. 70 Stylesheet ss = instance.parse( 71 "* { " 72 + "-fx-background-color: linear-gradient(from 0% 0% to 0% 100%, ); " 73 + "-fx-background-color: linear-gradient(from 0% 0% to 0% 100%, red, white, blue); " 74 + "}" 75 ); 76 77 assertNotNull(ss); 78 List<Rule> rules = ss.getRules(); 79 assertEquals(1,rules.size(),0); 80 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 81 assertTrue(decls.size()==1); 82 Declaration decl = decls.get(0); 83 ParsedValue value = decl.getParsedValue(); 84 assertTrue(value != null); 85 86 Paint[] layers = (Paint[])value.convert(null); 87 assertTrue(layers.length == 1); 88 89 LinearGradient lg = (LinearGradient)layers[0]; 90 List<Stop> stops = lg.getStops(); 91 assertTrue(stops.size()==3); 92 assertEquals(Color.RED, stops.get(0).getColor()); 93 assertEquals(Color.WHITE, stops.get(1).getColor()); 94 assertEquals(Color.BLUE, stops.get(2).getColor()); 95 96 } 97 98 99 @Test 100 public void testRT_17770() { 101 102 // RT-17770 is an infinite loop on a dangling comma. 103 // Missing term should be ignored 104 String stylesheetText = 105 "* {" 106 + "-fx-background-color: linear-gradient( " 107 + "to right, " 108 + "rgba(141, 138, 125, 0.0), " 109 + "rgba(248, 248, 246, 0.3) 45%, " 110 + "rgba(248, 248, 246, 0.8) 50%, " 111 + "rgba(248, 248, 246, 0.3) 55%, " 112 + "rgba(141, 138, 125, 0.0), " 113 + "); " 114 + "}"; 115 116 CssParser instance = new CssParser(); 117 118 Stylesheet ss = instance.parse(stylesheetText); 119 120 assertNotNull(ss); 121 List<Rule> rules = ss.getRules(); 122 assertEquals(1,rules.size(),0); 123 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 124 assertTrue(decls.size()==1); 125 Declaration decl = decls.get(0); 126 ParsedValue value = decl.getParsedValue(); 127 assertTrue(value != null); 128 129 Paint[] layers = (Paint[])value.convert(null); 130 assertTrue(layers.length == 1); 131 132 LinearGradient lg = (LinearGradient)layers[0]; 133 List<Stop> stops = lg.getStops(); 134 assertTrue(stops.size()==5); 135 assertEquals(Color.rgb(141, 138, 125, 0.0), stops.get(0).getColor()); 136 assertEquals(Color.rgb(248, 248, 246, 0.3), stops.get(1).getColor()); 137 assertEquals(Color.rgb(248, 248, 246, 0.8), stops.get(2).getColor()); 138 assertEquals(Color.rgb(248, 248, 246, 0.3), stops.get(3).getColor()); 139 assertEquals(Color.rgb(141, 138, 125, 0.0), stops.get(4).getColor()); 140 141 } 142 143 @Test 144 public void testParseSizeWithInvalidDigits() { 145 146 CssParser instance = new CssParser(); 147 148 // RT-16959 is an infinite loop on incomplete linear gradient 149 ParsedValue result = instance.parseExpr("-fx-font-size", "10ptx"); 150 assertNull("parseExpr", result); 151 152 // The bad syntax should be skipped. 153 Stylesheet ss = instance.parse( 154 "* {" 155 + "-fx-font-size: 10ptx; " 156 + "-fx-font-size: 12px; " 157 + "}" 158 ); 159 160 assertNotNull(ss); 161 List<Rule> rules = ss.getRules(); 162 assertEquals(1,rules.size(),0); 163 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 164 assertTrue(decls.size()==1); 165 Declaration decl = decls.get(0); 166 ParsedValue value = decl.getParsedValue(); 167 assertTrue(value != null); 168 169 Double size = (Double)value.convert(Font.font("Amble", 12)); 170 assertTrue(Double.compare(size, 12) == 0); 171 } 172 173 174 @Test 175 public void testRT_17830() { 176 177 CssParser instance = new CssParser(); 178 179 // The empty declaration should be skipped. The stylesheet should have 180 // two declarations. 181 Stylesheet ss = instance.parse(".rt17830 {-fx-fill: red;; -fx-stroke: yellow; }"); 182 183 assertNotNull(ss); 184 List<Rule> rules = ss.getRules(); 185 assertEquals(1,rules.size(),0); 186 List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0)); 187 assertEquals(2,decls.size(),0); 188 189 Declaration decl = decls.get(0); 190 ParsedValue value = decl.getParsedValue(); 191 assertTrue(value != null); 192 Paint paint = (Paint)value.convert(null); 193 assertEquals(Color.RED, paint); 194 195 decl = decls.get(1); 196 value = decl.getParsedValue(); 197 assertTrue(value != null); 198 paint = (Paint)value.convert(null); 199 assertEquals(Color.YELLOW, paint); 200 } 201 202 @Test 203 public void testRT_20311() { 204 205 CssParser instance = new CssParser(); 206 207 try { 208 instance.parse(".rt-20311 { -fx-background-color:red\n-fx-border-color:black; }"); 209 } catch (Exception e) { 210 fail(e.toString()); 211 } 212 213 } 214 215 @Test public void testFontFace() { 216 217 // http://fonts.googleapis.com/css?family=Bree+Serif 218 String css = "@font-face {\n" + 219 "font-family: 'Bree Serif';\n" + 220 "font-style: normal;\n" + 221 "font-weight: 400;\n" + 222 "src: local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff');\n"+ 223 "}"; 224 225 Stylesheet stylesheet = new CssParser().parse(css); 226 227 int nFontFaceSrcs = checkFontFace(stylesheet); 228 229 assertEquals(3, nFontFaceSrcs); 230 } 231 232 @Test public void testFontFaceMoreThanOneSrc() { 233 234 // http://fonts.googleapis.com/css?family=Bree+Serif 235 String css = "@font-face {\n" + 236 "font-family: 'Bree Serif';\n" + 237 "font-style: normal;\n" + 238 "font-weight: 400;\n" + 239 "src: local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff'),\n"+ 240 " local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff');\n"+ 241 "}"; 242 243 Stylesheet stylesheet = new CssParser().parse(css); 244 245 int nFontFaceSrcs = checkFontFace(stylesheet); 246 assertEquals(6, nFontFaceSrcs); 247 } 248 249 public static int checkFontFace(Stylesheet stylesheet) { 250 251 List<FontFace> fontFaces = stylesheet.getFontFaces(); 252 assertNotNull(fontFaces); 253 assertEquals(1, fontFaces.size()); 254 255 FontFaceImpl fontFace = (FontFaceImpl)fontFaces.get(0); 256 257 Map<String,String> descriptors = fontFace.getDescriptors(); 258 assertEquals("'Bree Serif'", descriptors.get("font-family")); 259 assertEquals("normal", descriptors.get("font-style")); 260 assertEquals("400", descriptors.get("font-weight")); 261 262 List<FontFaceImpl.FontFaceSrc> fontFaceSrcs = fontFace.getSources(); 263 264 int nFontFaceSrcs = fontFaceSrcs != null ? fontFaceSrcs.size() : 0; 265 266 for(int n=0; n<nFontFaceSrcs; n++) { 267 FontFaceImpl.FontFaceSrc fontFaceSrc = fontFaceSrcs.get(n); 268 FontFaceImpl.FontFaceSrcType type = fontFaceSrc.getType(); 269 switch(type) { 270 case LOCAL: { 271 String src = fontFaceSrc.getSrc(); 272 assertTrue("Bree Serif".equals(src) || "BreeSerif-Regular".equals(src)); 273 assertNull(fontFaceSrc.getFormat()); 274 break; 275 } 276 case URL: { 277 String src = fontFaceSrc.getSrc(); 278 assertEquals(src, "http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff"); 279 assertEquals(fontFaceSrc.getFormat(), "woff"); 280 break; 281 } 282 case REFERENCE: 283 default: 284 fail(); 285 } 286 } 287 288 return nFontFaceSrcs; 289 } 290 291 @Test public void testRT_32522() { 292 293 ParsedValue value = new CssParser().parseExpr("foo", "1 2em 3 4;"); 294 Object obj = value.convert(Font.font(13)); 295 assert obj instanceof Number[]; 296 assertArrayEquals(new Number[] {1d, 26d, 3d, 4d}, (Number[])obj); 297 298 value = new CssParser().parseExpr("foo", "1;"); 299 obj = value.convert(null); 300 assert obj instanceof Number; 301 assertEquals(1d, (Number)obj); 302 303 } 304 305 @Test public void testRT_38483() { 306 307 Duration expected = Duration.millis(42); 308 ParsedValue value = new CssParser().parseExpr("foo", "42ms;"); 309 Object observed = value.convert(null); 310 assertEquals(expected, observed); 311 312 value = new CssParser().parseExpr("foo", "indefinite;"); 313 observed = value.convert(null); 314 assertEquals(Duration.INDEFINITE, observed); 315 } 316 }