Package com.google.caja.parser.css

Source Code of com.google.caja.parser.css.CssParserTest

// Copyright (C) 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.caja.parser.css;

import com.google.caja.lexer.CharProducer;
import com.google.caja.lexer.CssTokenType;
import com.google.caja.lexer.FilePosition;
import com.google.caja.lexer.InputSource;
import com.google.caja.lexer.ParseException;
import com.google.caja.lexer.Token;
import com.google.caja.parser.ParseTreeNode;
import com.google.caja.parser.css.CssTree.StyleSheet;
import com.google.caja.reporting.Message;
import com.google.caja.reporting.MessageContext;
import com.google.caja.reporting.MessageLevel;
import com.google.caja.reporting.MessagePart;
import com.google.caja.reporting.MessageType;
import com.google.caja.reporting.SnippetProducer;
import com.google.caja.util.CajaTestCase;
import com.google.caja.util.Join;
import com.google.caja.util.Name;
import com.google.caja.util.TestUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
*
* @author mikesamuel@gmail.com
*/
public class CssParserTest extends CajaTestCase {

  public final void testBadHashValue() {
    throwsParseException("h1 { color: #OOOOOO}")// Letters instead of zeroes
  }

  public final void testUnescape() {
    FilePosition pos = FilePosition.startOfFile(is);
    assertEquals("", CssParser.unescape(
        Token.instance("", CssTokenType.IDENT, pos)));
    assertEquals("foo", CssParser.unescape(
        Token.instance("foo", CssTokenType.IDENT, pos)));
    assertEquals("foo", CssParser.unescape(
        Token.instance("f\\oo", CssTokenType.IDENT, pos)));
    assertEquals("!important", CssParser.unescape(
        Token.instance("! important", CssTokenType.IDENT, pos)));
    assertEquals("!important", CssParser.unescape(
        Token.instance("!   important", CssTokenType.IDENT, pos)));
    assertEquals("'foo bar'", CssParser.unescape(
        Token.instance("'foo bar'", CssTokenType.STRING, pos)));
    assertEquals("'foo bar'", CssParser.unescape(
        Token.instance("'foo\\ bar'", CssTokenType.STRING, pos)));
    assertEquals("'foo bar'", CssParser.unescape(
        Token.instance("'foo\\ b\\\nar'", CssTokenType.STRING, pos)));
    assertEquals("'foo bar'", CssParser.unescape(
        Token.instance("'foo\\ b\\\rar'", CssTokenType.STRING, pos)));
    assertEquals("'ffoo bar'", CssParser.unescape(
        Token.instance("'\\66 foo bar'", CssTokenType.STRING, pos)));
    assertEquals("foo-bar", CssParser.unescape(
        Token.instance("\\66oo-ba\\0072", CssTokenType.IDENT, pos)));
    assertEquals("\\66oo-bar", CssParser.unescape(
        Token.instance("\\\\66oo-ba\\0072", CssTokenType.IDENT, pos)));
  }

  public final void testCssParser1() throws Exception {
    runTestCssParser("cssparserinput1.css", "cssparsergolden1.txt", false);
  }

  public final void testCssParser2() throws Exception {
    runTestCssParser("cssparserinput2.css", "cssparsergolden2.txt", false);
  }

  public final void testCssParser3() throws Exception {
    runTestCssParser("cssparserinput3.css", "cssparsergolden3.txt", false);
  }

  public final void testCssParser4() throws Exception {
    runTestCssParser("cssparserinput4.css", "cssparsergolden4.txt", false);
  }

  public final void testTolerantParsing5() throws Exception {
    runTolerantParsing(
        "cssparserinput5.css", "cssparsergolden5.txt", "csssnippets5.txt");
  }

  public final void testCssParser6() throws Exception {
    runTestCssParser("cssparserinput6.css", "cssparsergolden6.txt", false);
  }

  public final void testTolerantParsing7() throws Exception {
    runTolerantParsing(
        "cssparserinput7.css", "cssparsergolden7.txt", "csssnippets7.txt");
  }

  public final void testFilters() throws Exception {
    runTestCssParser(
        "cssparserinput-filters.css", "cssparsergolden-filters.txt", true);
    assertMessagesLessSevereThan(MessageLevel.WARNING);
  }

  public final void testUserAgentHacks() throws Exception {
    runTestCssParser(
        "cssparserinput-uahacks.css", "cssparsergolden-uahacks.txt", true);
    assertMessagesLessSevereThan(MessageLevel.WARNING);
  }

  public final void testFilterFilePositions() throws Exception {
    CssTree.DeclarationGroup ss = cssDecls(
        // Character in file indices used in assertFilePosition below.
        //          0        1         2         3         4         5
        //          1234567890123456789012345678901234567890123456789012345
        fromString("filter:progid:foo.bar.baz(a=1) progid:foo.bar.baz(a=2)"));
    assertMessagesLessSevereThan(MessageLevel.WARNING);

    assertEquals(1, ss.children().size());
    CssTree.PropertyDeclaration d
        = (CssTree.PropertyDeclaration) ss.children().get(0);
    assertFilePosition(1, 55, d);
    CssTree.Property p = d.getProperty();
    assertFilePosition(1, 7, p);
    assertEquals(Name.css("filter"), p.getPropertyName());
    CssTree.Expr e = d.getExpr();
    assertFilePosition(8, 55, e);
    assertEquals(2, e.getNTerms());
    CssTree.Term t0 = e.getNthTerm(0);
    assertFilePosition(8, 31, t0);
    CssTree.ProgId progId0 = (CssTree.ProgId) t0.getExprAtom();
    assertFilePosition(8, 31, progId0);
    assertEquals(Name.css("foo.bar.baz"), progId0.getName());
    assertEquals(1, progId0.children().size());
    CssTree.ProgIdAttribute a0 = progId0.children().get(0);
    assertFilePosition(27, 30, a0);
    assertEquals(Name.css("a"), a0.getName());
    CssTree.Term v0 = a0.getPropertyValue();
    assertFilePosition(29, 30, v0);
    CssTree.QuantityLiteral vl0 = (CssTree.QuantityLiteral) v0.getExprAtom();
    assertFilePosition(29, 30, vl0);
    assertEquals("1", vl0.getValue());
    CssTree.Term t1 = e.getNthTerm(1);
    assertFilePosition(32, 55, t1);
    CssTree.ProgId progId1 = (CssTree.ProgId) t1.getExprAtom();
    assertFilePosition(32, 55, progId1);
    assertEquals(Name.css("foo.bar.baz"), progId1.getName());
    assertEquals(1, progId1.children().size());
    CssTree.ProgIdAttribute a1 = progId1.children().get(0);
    assertFilePosition(51, 54, a1);
    assertEquals(Name.css("a"), a1.getName());
    CssTree.Term v1 = a1.getPropertyValue();
    assertFilePosition(53, 54, v1);
    CssTree.QuantityLiteral vl1 = (CssTree.QuantityLiteral) v1.getExprAtom();
    assertFilePosition(53, 54, vl1);
    assertEquals("2", vl1.getValue());
  }

  // TODO(jasvir): Should whitespace after the units in quantities be escaped
  // S 4.3.10 of CSS2 spec says no, but 4/4 browsers say yes.
  public final void testUnexpectedErrors() throws Exception {
    throwsParseException("div { top:58px\\9;}");
  }

  public final void testErrorMessages() throws Exception {
    runTestCssParser(
        fromString("p { color:e# }"),
        fromString(Join.join(
            "\n",
            "StyleSheet",
            "  RuleSet",
            "    Selector",
            "      SimpleSelector",
            "        IdentLiteral : p")),
        true);
    assertMessage(
        true, MessageType.EXPECTED_TOKEN, MessageLevel.WARNING,
        MessagePart.Factory.valueOf(";"), MessagePart.Factory.valueOf("#"));
    assertMessage(true, MessageType.SKIPPING, MessageLevel.WARNING);
    assertMessagesLessSevereThan(MessageLevel.WARNING);
  }

  private void runTolerantParsing(
      String cssFile, String goldenFile, String snippetFile) throws Exception {
    InputSource inputSource = new InputSource(
        TestUtil.getResource(getClass(), cssFile));
    runTestCssParser(cssFile, goldenFile, true);
    assertEquals(
        TestUtil.readResource(getClass(), snippetFile).trim(),
        renderSnippets(
            Collections.singletonMap(
                inputSource,
                TestUtil.readResource(getClass(), cssFile))));
  }

  private void runTestCssParser(
      String cssFile, String goldenFile, boolean tolerant)
      throws Exception {
    runTestCssParser(fromResource(cssFile), fromResource(goldenFile), tolerant);
  }

  private void runTestCssParser(
      CharProducer css, CharProducer golden, boolean tolerant)
      throws Exception {
    MessageLevel lvl = tolerant
        ? MessageLevel.WARNING : MessageLevel.FATAL_ERROR;
    CssTree.StyleSheet stylesheet = new CssParser(
        CssParser.makeTokenQueue(css.clone(), mq, false), mq, lvl)
        .parseStyleSheet();
    assertCloneable(stylesheet);
    StringBuilder sb = new StringBuilder();
    stylesheet.format(new MessageContext(), sb);
    assertEquals(golden.toString().trim(), sb.toString().trim());

    if (!tolerant) {
      // run in tolerant mode to make sure being tolerant doesn't introduce
      // failures.
      runTestCssParser(css, golden.clone(), true);
    }
  }

  private void throwsParseException(String fuzzString) {
    try {
      parseString(fuzzString);
    } catch (ParseException e) {
      // ParseException thrown - parser worked
      return;
    } catch (Throwable e) {
      // any other kind of exception means the parser broke
      e.printStackTrace();
      fail();
    }
  }

  private StyleSheet parseString(String fuzzString) throws Exception {
    return css(fromString(fuzzString));
  }

  private String renderSnippets(Map<InputSource, String> srcs) {
    SnippetProducer sr = new SnippetProducer(srcs, mc, 80);
    List<Message> messages = new ArrayList<Message>(mq.getMessages());
    Collections.sort(messages, new Comparator<Message>() {
      public int compare(Message a, Message b) {
        FilePosition fpa = firstFilePosition(a.getMessageParts());
        FilePosition fpb = firstFilePosition(b.getMessageParts());
        int delta = fpa.startCharInFile() - fpb.startCharInFile();
        if (delta == 0) {
          delta = fpa.endCharInFile() - fpb.endCharInFile();
        }
        return delta;
      }
      private FilePosition firstFilePosition(List<MessagePart> parts) {
        if (parts.isEmpty()) { return FilePosition.UNKNOWN; }
        MessagePart p0 = parts.get(0);
        return p0 instanceof FilePosition
            ? (FilePosition) p0
            : FilePosition.UNKNOWN;
      }
    });
    List<String> snippets = new ArrayList<String>();
    for (Message msg : messages) {
      snippets.add(msg.getMessageLevel() + " : " + msg.format(mc));
      snippets.add(sr.getSnippet(msg));
    }
    return Join.join("\n", snippets);
  }

  private void assertFilePosition(
      int startCharInFile, int endCharInFile, ParseTreeNode n) {
    FilePosition pos = n.getFilePosition();
    assertEquals("source", is, pos.source());
    assertEquals("start of " + pos, startCharInFile, pos.startCharInFile());
    assertEquals("end of " + pos, endCharInFile, pos.endCharInFile());
  }
}
TOP

Related Classes of com.google.caja.parser.css.CssParserTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.