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