18403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Copyright (c) 2011, Mike Samuel
28403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// All rights reserved.
38403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel//
48403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistribution and use in source and binary forms, with or without
58403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// modification, are permitted provided that the following conditions
68403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// are met:
78403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel//
88403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistributions of source code must retain the above copyright
98403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// notice, this list of conditions and the following disclaimer.
108403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistributions in binary form must reproduce the above copyright
118403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// notice, this list of conditions and the following disclaimer in the
128403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// documentation and/or other materials provided with the distribution.
138403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Neither the name of the OWASP nor the names of its contributors may
148403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// be used to endorse or promote products derived from this software
158403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// without specific prior written permission.
168403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
178403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
198403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
208403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
218403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
228403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
248403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
268403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
278403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// POSSIBILITY OF SUCH DAMAGE.
288403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel
294e867904c8295537803c1c8a076e130df5674b58mikesamuelpackage org.owasp.html;
304e867904c8295537803c1c8a076e130df5674b58mikesamuel
314e867904c8295537803c1c8a076e130df5674b58mikesamuelimport java.util.List;
32b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel
33b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuelimport org.junit.Test;
344e867904c8295537803c1c8a076e130df5674b58mikesamuel
354e867904c8295537803c1c8a076e130df5674b58mikesamuelimport com.google.common.base.Joiner;
364e867904c8295537803c1c8a076e130df5674b58mikesamuelimport com.google.common.collect.Lists;
374e867904c8295537803c1c8a076e130df5674b58mikesamuel
384e867904c8295537803c1c8a076e130df5674b58mikesamuelimport junit.framework.TestCase;
394e867904c8295537803c1c8a076e130df5674b58mikesamuel
404e867904c8295537803c1c8a076e130df5674b58mikesamuelpublic class CssGrammarTest extends TestCase {
41b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel  @Test
42b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel  public static final void testLex() throws Exception {
43b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel    CssTokens tokens = CssTokens.lex(Joiner.on('\n').join(
444e867904c8295537803c1c8a076e130df5674b58mikesamuel        "/* A comment */",
454e867904c8295537803c1c8a076e130df5674b58mikesamuel        "words with-dashes #hashes .dots. -and-leading-dashes",
464e867904c8295537803c1c8a076e130df5674b58mikesamuel        "quantities: 3px 4ex -.5pt 12.5%",
47b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel        "punctuation: { ( } / , ;",
48b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel        "[ url( http://example.com )",
494e867904c8295537803c1c8a076e130df5674b58mikesamuel        "rgb(255, 127, 127)",
50b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel        "'strings' \"oh \\\"my\" 'foo bar'",
514e867904c8295537803c1c8a076e130df5674b58mikesamuel        ""));
524e867904c8295537803c1c8a076e130df5674b58mikesamuel
534e867904c8295537803c1c8a076e130df5674b58mikesamuel    List<String> actualTokens = Lists.newArrayList();
54b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel    for (CssTokens.TokenIterator it = tokens.iterator(); it.hasNext();) {
55b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel      CssTokens.TokenType type = it.type();
56b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel      String token = it.next();
57b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel      if (!" ".equals(token)) {
58b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel        actualTokens.add(token + ":" + type.name());
594e867904c8295537803c1c8a076e130df5674b58mikesamuel      }
604e867904c8295537803c1c8a076e130df5674b58mikesamuel    }
614e867904c8295537803c1c8a076e130df5674b58mikesamuel
624e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals(
634e867904c8295537803c1c8a076e130df5674b58mikesamuel        Joiner.on('\n').join(
64b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            // "/* A comment */",  // Comments are elided.
65b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "words:IDENT",
66b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "with-dashes:IDENT",
67b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "#hashes:HASH_ID",
68b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            ".dots:DOT_IDENT",
69b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            ".:DELIM",
70b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "-and-leading-dashes:IDENT",
71b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "quantities:IDENT",
72b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "::COLON",
73b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "3px:DIMENSION",
74b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "4ex:DIMENSION",
75b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "-0.5pt:DIMENSION",
76b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "12.5%:PERCENTAGE",
77b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "punctuation:IDENT",
78b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "::COLON",
79b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "{:LEFT_CURLY",
80b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "(:LEFT_PAREN",  // Explicit
81b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "):RIGHT_PAREN",  // Implicit closing bracket to keep balance.
82b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "}:RIGHT_CURLY",
83b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "/:DELIM",
84b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            ",:COMMA",
85b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            ";:SEMICOLON",
86b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "[:LEFT_SQUARE",
87b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "url('http://example.com'):URL",
88b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "rgb(:FUNCTION",
89b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "255:NUMBER",
90b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            ",:COMMA",
91b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "127:NUMBER",
92b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            ",:COMMA",
93b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "127:NUMBER",
94b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "):RIGHT_PAREN",
95b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "'strings':STRING",
96b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "'oh \\22my':STRING",
97b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "'foo bar':STRING",
98b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel            "]:RIGHT_SQUARE"
994e867904c8295537803c1c8a076e130df5674b58mikesamuel            ),
1004e867904c8295537803c1c8a076e130df5674b58mikesamuel        Joiner.on('\n').join(actualTokens));
1014e867904c8295537803c1c8a076e130df5674b58mikesamuel  }
1024e867904c8295537803c1c8a076e130df5674b58mikesamuel
103b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel  @Test
104b600c3cd7edfb02d79c264fd83b1306e94053b7emikesamuel  public static final void testCssContent() {
1054e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("", CssGrammar.cssContent(""));
1064e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("azimuth", CssGrammar.cssContent("\\61zimuth"));
1074e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("table-cell", CssGrammar.cssContent("t\\61\tble-cell"));
1084e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("foo", CssGrammar.cssContent("foo"));
1094e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("foo", CssGrammar.cssContent("'foo'"));
1104e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("foo", CssGrammar.cssContent("\"foo\""));
1114e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("'", CssGrammar.cssContent("'"));
1124e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("\"", CssGrammar.cssContent("\""));
1134e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("\"\"", CssGrammar.cssContent("\"\\22\\22\""));
1144e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("\"\"", CssGrammar.cssContent("\"\\22 \\22\""));
1154e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("\"\"", CssGrammar.cssContent("\\22\\22"));
1164e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("\\", CssGrammar.cssContent("'\\\\'"));
1174e867904c8295537803c1c8a076e130df5674b58mikesamuel    assertEquals("\n", CssGrammar.cssContent("'\\a'"));
1184e867904c8295537803c1c8a076e130df5674b58mikesamuel  }
1194e867904c8295537803c1c8a076e130df5674b58mikesamuel}
120