EMMA Coverage Report (generated Mon Nov 01 16:48:29 PDT 2010)
[all classes][com.google.caja.parser.html]

COVERAGE SUMMARY FOR SOURCE FILE [NodesTest.java]

nameclass, %method, %block, %line, %
NodesTest.java100% (1/1)100% (19/19)79%  (616/780)74%  (126.8/172)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NodesTest100% (1/1)100% (19/19)79%  (616/780)74%  (126.8/172)
NodesTest (): void 100% (1/1)100% (3/3)100% (1/1)
benchmark (int, Element): int 100% (1/1)100% (22/22)100% (3/3)
testBadProcessingInstructions (): void 100% (1/1)73%  (74/102)62%  (6.8/11)
testDecode (): void 100% (1/1)100% (215/215)100% (54/54)
testHtmlNamesNormalized (): void 100% (1/1)100% (51/51)100% (11/11)
testNoSneakyNamespaceDecls1 (): void 100% (1/1)16%  (7/45)25%  (4/16)
testNoSneakyNamespaceDecls2 (): void 100% (1/1)16%  (7/45)25%  (4/16)
testNoSneakyNamespaceDecls3 (): void 100% (1/1)6%   (2/31)20%  (2/10)
testProcessingInstructionInHtml (): void 100% (1/1)6%   (2/33)18%  (2/11)
testProcessingInstructions (): void 100% (1/1)100% (15/15)100% (4/4)
testRenderModes (): void 100% (1/1)100% (27/27)100% (5/5)
testRenderOfEmbeddedXml (): void 100% (1/1)100% (29/29)100% (3/3)
testRenderSpeed (): void 100% (1/1)100% (35/35)100% (6/6)
testRenderWithBrokenNekoDom (): void 100% (1/1)100% (21/21)100% (3/3)
testRenderWithMaskedInputNamespace1 (): void 100% (1/1)100% (16/16)100% (3/3)
testRenderWithMaskedInputNamespace2 (): void 100% (1/1)100% (16/16)100% (3/3)
testRenderWithMaskedOutputNamespace1 (): void 100% (1/1)100% (44/44)100% (8/8)
testRenderWithNonstandardNamespaces (): void 100% (1/1)100% (15/15)100% (2/2)
testRenderWithUnknownNamespace (): void 100% (1/1)100% (15/15)100% (2/2)

1// Copyright (C) 2009 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14 
15package com.google.caja.parser.html;
16 
17import com.google.caja.render.Concatenator;
18import com.google.caja.reporting.MarkupRenderMode;
19import com.google.caja.reporting.RenderContext;
20import com.google.caja.util.CajaTestCase;
21 
22import java.util.Arrays;
23 
24import org.w3c.dom.DOMException;
25import org.w3c.dom.Document;
26import org.w3c.dom.DocumentFragment;
27import org.w3c.dom.Element;
28import org.w3c.dom.ProcessingInstruction;
29 
30public class NodesTest extends CajaTestCase {
31  public final void testDecode() {
32    assertEquals(Nodes.decode("1 < 2 && 4 > "3""),
33                 "1 < 2 && 4 > \"3\"");
34    assertEquals("", Nodes.decode(""));
35    assertEquals("No entities here", Nodes.decode("No entities here"));
36    assertEquals("No entities here & there",
37                 Nodes.decode("No entities here & there"));
38    // Test that interrupted escapes and escapes at beginning and end of file
39    // are handled gracefully.
40    assertEquals("\\\\u000a", Nodes.decode("\\\\u000a"));
41    assertEquals("\n", Nodes.decode("&#x00000a;"));
42    assertEquals("\n", Nodes.decode("&#x0000a;"));
43    assertEquals("\n", Nodes.decode("&#x000a;"));
44    assertEquals("\n", Nodes.decode("&#x00a;"));
45    assertEquals("\n", Nodes.decode("&#x0a;"));
46    assertEquals("\n", Nodes.decode("&#xa;"));
47    assertEquals(String.valueOf(Character.toChars(0x10000)),
48                 Nodes.decode("&#x10000;"));
49    assertEquals("&#xa", Nodes.decode("&#xa"));
50    assertEquals("&#x00ziggy", Nodes.decode("&#x00ziggy"));
51    assertEquals("&#xa00z;", Nodes.decode("&#xa00z;"));
52    assertEquals("&#\n", Nodes.decode("&#&#x000a;"));
53    assertEquals("&#x\n", Nodes.decode("&#x&#x000a;"));
54    assertEquals("&#xa\n", Nodes.decode("&#xa&#x000a;"));
55    assertEquals("&#\n", Nodes.decode("&#&#xa;"));
56    assertEquals("&#x", Nodes.decode("&#x"));
57    assertEquals("&#x0", Nodes.decode("&#x0"));
58    assertEquals("&#", Nodes.decode("&#"));
59 
60    assertEquals("\\", Nodes.decode("\\"));
61    assertEquals("&", Nodes.decode("&"));
62 
63    assertEquals("&#000a;", Nodes.decode("&#000a;"));
64    assertEquals("\n", Nodes.decode("&#10;"));
65    assertEquals("\n", Nodes.decode("&#010;"));
66    assertEquals("\n", Nodes.decode("&#0010;"));
67    assertEquals("\n", Nodes.decode("&#00010;"));
68    assertEquals("\n", Nodes.decode("&#000010;"));
69    assertEquals("\n", Nodes.decode("&#0000010;"));
70    assertEquals("\t", Nodes.decode("&#9;"));
71 
72    assertEquals("&#10", Nodes.decode("&#10"));
73    assertEquals("&#00ziggy", Nodes.decode("&#00ziggy"));
74    assertEquals("&#\n", Nodes.decode("&#&#010;"));
75    assertEquals("&#0\n", Nodes.decode("&#0&#010;"));
76    assertEquals("&#01\n", Nodes.decode("&#01&#10;"));
77    assertEquals("&#\n", Nodes.decode("&#&#10;"));
78    assertEquals("&#1", Nodes.decode("&#1"));
79    assertEquals("&#10", Nodes.decode("&#10"));
80 
81    // test the named escapes
82    assertEquals("<", Nodes.decode("&lt;"));
83    assertEquals(">", Nodes.decode("&gt;"));
84    assertEquals("\"", Nodes.decode("&quot;"));
85    assertEquals("'", Nodes.decode("&apos;"));
86    assertEquals("&", Nodes.decode("&amp;"));
87    assertEquals("&lt;", Nodes.decode("&amp;lt;"));
88    assertEquals("&", Nodes.decode("&AMP;"));
89    assertEquals("&AMP", Nodes.decode("&AMP"));
90    assertEquals("&", Nodes.decode("&AmP;"));
91    assertEquals("\u0391", Nodes.decode("&Alpha;"));
92    assertEquals("\u03b1", Nodes.decode("&alpha;"));
93 
94    assertEquals("&;", Nodes.decode("&;"));
95    assertEquals("&bogus;", Nodes.decode("&bogus;"));
96  }
97 
98  public final void testRenderOfEmbeddedXml() throws Exception {
99    assertEquals(
100        "<td width=\"10\"><svg:Rect width=\"50\"></svg:Rect></td>",
101        Nodes.render(
102            xmlFragment(fromString(
103                "<html:td width='10'><svg:Rect width='50'/></html:td>")),
104            MarkupRenderMode.HTML));
105    assertEquals(
106        "<td width=\"10\"><svg:Rect width=\"50\" /></td>",
107        Nodes.render(
108            xmlFragment(fromString(
109                "<html:td width='10'><svg:Rect width='50'/></html:td>")),
110            MarkupRenderMode.XML));
111  }
112 
113  public final void testRenderWithNonstandardNamespaces() throws Exception {
114    assertEquals(
115        "<td width=\"10\"><svg:Rect width=\"50\" /></td>",
116        Nodes.render(xmlFragment(fromString(
117            ""
118            + "<html:td width='10' xmlns:s='http://www.w3.org/2000/svg'>"
119            + "<s:Rect width='50'/>"
120            + "</html:td>")),
121            MarkupRenderMode.XML));
122  }
123 
124  public final void testRenderWithUnknownNamespace() throws Exception {
125    assertEquals(
126        ""
127        + "<xml:foo>"
128        + "<_ns1:baz xmlns:_ns1=\"http://bobs.house.of/XML&amp;BBQ\""
129        + " boo=\"howdy\" xml:lang=\"es\" />"
130        + "</xml:foo>",
131        Nodes.render(xmlFragment(fromString(
132            ""
133            + "<foo xmlns='http://www.w3.org/XML/1998/namespace'"
134            + " xmlns:bar='http://bobs.house.of/XML&BBQ'>"
135            + "<bar:baz boo='howdy' xml:lang='es'/>"
136            + "</foo>")),
137            MarkupRenderMode.XML));
138  }
139 
140  public final void testRenderWithMaskedInputNamespace1() throws Exception {
141    DocumentFragment fragment = xmlFragment(fromString(
142        "<svg:foo><svg:bar xmlns:svg='" + Namespaces.HTML_NAMESPACE_URI
143        + "'/></svg:foo>"));
144    assertEquals("<svg:foo><bar></bar></svg:foo>", Nodes.render(fragment));
145  }
146 
147  public final void testRenderWithMaskedInputNamespace2() throws Exception {
148    DocumentFragment fragment = xmlFragment(fromString(
149        "<svg:foo><svg:bar xmlns:svg='http://foo/'/></svg:foo>"));
150    assertEquals(
151        "<svg:foo><_ns1:bar xmlns:_ns1=\"http://foo/\"></_ns1:bar></svg:foo>",
152        Nodes.render(fragment));
153  }
154 
155  public final void testRenderWithMaskedOutputNamespace1() throws Exception {
156    DocumentFragment fragment = xmlFragment(fromString(
157        "<svg:foo><xml:bar/></svg:foo>"));
158    Namespaces ns = new Namespaces(
159        Namespaces.HTML_DEFAULT, "svg", Namespaces.XML_NAMESPACE_URI);
160    StringBuilder sb = new StringBuilder();
161    RenderContext rc = new RenderContext(new Concatenator(sb))
162        .withMarkupRenderMode(MarkupRenderMode.XML);
163    Nodes.render(fragment, ns, rc);
164    rc.getOut().noMoreTokens();
165    assertEquals(
166        ""
167        + "<_ns2:foo xmlns:_ns2=\"http://www.w3.org/2000/svg\">"
168        + "<svg:bar /></_ns2:foo>",
169        sb.toString());
170  }
171 
172  public final void testHtmlNamesNormalized() throws Exception {
173    Document doc = DomParser.makeDocument(null, null);
174    Element el = doc.createElementNS(Namespaces.HTML_NAMESPACE_URI, "SPAN");
175    el.setAttributeNS(Namespaces.HTML_NAMESPACE_URI, "TITLE", "Howdy");
176 
177    assertEquals("<span title=\"Howdy\"></span>", Nodes.render(el));
178 
179    Namespaces ns = new Namespaces(
180        Namespaces.HTML_DEFAULT, "html", Namespaces.HTML_NAMESPACE_URI);
181    StringBuilder sb = new StringBuilder();
182    RenderContext rc = new RenderContext(new Concatenator(sb))
183        .withMarkupRenderMode(MarkupRenderMode.HTML);
184    Nodes.render(el, ns, rc);
185    rc.getOut().noMoreTokens();
186    assertEquals("<html:span title=\"Howdy\"></html:span>", sb.toString());
187  }
188 
189  public final void testNoSneakyNamespaceDecls1() throws Exception {
190    Document doc = DomParser.makeDocument(null, null);
191    Element el = doc.createElementNS(Namespaces.SVG_NAMESPACE_URI, "span");
192    try {
193      el.setAttributeNS(
194          Namespaces.SVG_NAMESPACE_URI, "xmlns", Namespaces.HTML_NAMESPACE_URI);
195    } catch (Exception ex) {
196      try {
197        el.setAttributeNS(
198            Namespaces.HTML_NAMESPACE_URI, "xmlns",
199            Namespaces.HTML_NAMESPACE_URI);
200      } catch (Exception ex2) {
201        el.setAttribute("xmlns", Namespaces.HTML_NAMESPACE_URI);
202      }
203    }
204    el.appendChild(doc.createElementNS(Namespaces.SVG_NAMESPACE_URI, "br"));
205    String rendered;
206    try {
207      rendered = Nodes.render(el, MarkupRenderMode.XML);
208    } catch (RuntimeException ex) {
209      return;  // Failure is an option.
210    }
211    assertEquals("<svg:span><svg:br /></svg:span>", rendered);
212  }
213 
214  public final void testNoSneakyNamespaceDecls2() throws Exception {
215    Document doc = DomParser.makeDocument(null, null);
216    Element el = doc.createElementNS(Namespaces.SVG_NAMESPACE_URI, "span");
217    try {
218      el.setAttributeNS(
219          Namespaces.XMLNS_NAMESPACE_URI, "svg", Namespaces.HTML_NAMESPACE_URI);
220    } catch (Exception ex) {
221      try {
222        el.setAttributeNS(
223            Namespaces.HTML_NAMESPACE_URI, "xmlns:svg",
224            Namespaces.HTML_NAMESPACE_URI);
225      } catch (Exception ex2) {
226        el.setAttribute("xmlns:svg", Namespaces.HTML_NAMESPACE_URI);
227      }
228    }
229    el.appendChild(doc.createElementNS(Namespaces.SVG_NAMESPACE_URI, "br"));
230    String rendered;
231    try {
232      rendered = Nodes.render(el, MarkupRenderMode.XML);
233    } catch (RuntimeException ex) {
234      return;  // Failure is an option.
235    }
236    assertEquals("<svg:span><svg:br /></svg:span>", rendered);
237  }
238 
239  public final void testNoSneakyNamespaceDecls3() throws Exception {
240    Document doc = DomParser.makeDocument(null, null);
241    Element el = doc.createElementNS(
242        Namespaces.SVG_NAMESPACE_URI, "span");
243    // Override a definition used elsewhere.
244    el.setAttribute("xmlns:svg", Namespaces.HTML_NAMESPACE_URI);
245 
246    el.appendChild(doc.createElementNS(Namespaces.SVG_NAMESPACE_URI, "br"));
247    String rendered;
248    try {
249      rendered = Nodes.render(el, MarkupRenderMode.XML);
250    } catch (RuntimeException ex) {
251      return;  // Failure is an option.
252    }
253    assertEquals("<svg:span><svg:br /></svg:span>", rendered);
254  }
255 
256  public final void testProcessingInstructions() {
257    Document doc = DomParser.makeDocument(null, null);
258    ProcessingInstruction pi = doc.createProcessingInstruction("foo", "bar");
259    assertEquals("<?foo bar?>", Nodes.render(pi, MarkupRenderMode.XML));
260  }
261 
262  public final void testBadProcessingInstructions() {
263    Document doc = DomParser.makeDocument(null, null);
264    for (String[] badPi : new String[][] {
265           { "xml", "foo" }, { "XmL", "foo" },
266           { "foo?><script>alert(1)</script>", "<?bar baz" },
267           { "ok", "foo?><script>alert(1)</script><?foo bar" },
268         }) {
269      try {
270        ProcessingInstruction pi = doc.createProcessingInstruction(
271            badPi[0], badPi[1]);
272        Nodes.render(pi, MarkupRenderMode.XML);
273      } catch (IllegalStateException ex) {
274        continue;  // OK
275      } catch (DOMException ex) {
276        continue;  // OK
277      }
278      fail("Rendered " + Arrays.toString(badPi));
279    }
280  }
281 
282  public final void testProcessingInstructionInHtml() {
283    Document doc = DomParser.makeDocument(null, null);
284    ProcessingInstruction pi = doc.createProcessingInstruction(
285        "foo", "<script>alert(1)</script>");
286    Element el = doc.createElementNS(Namespaces.HTML_NAMESPACE_URI, "div");
287    el.appendChild(pi);
288    assertEquals(
289        "<div><?foo <script>alert(1)</script>?></div>",
290        Nodes.render(el, MarkupRenderMode.XML));
291    try {
292      Nodes.render(el, MarkupRenderMode.HTML);
293    } catch (IllegalStateException ex) {
294      // OK
295      return;
296    }
297    fail("Rendered in html");
298  }
299 
300  public final void testRenderWithBrokenNekoDom() throws Exception {
301    Element el = html(fromString("<a href='foo.html'>bar</a>"));
302    assertEquals(
303        "<html><head></head><body><a href=\"foo.html\">bar</a></body></html>",
304        Nodes.render(new NullLocalNameMembrane().wrap(el, Element.class)));
305  }
306 
307  public final void testRenderModes() throws Exception {
308    DocumentFragment f = htmlFragment(fromString(
309        "<input checked name=foo type=checkbox>"));
310    assertEquals(
311        "<input checked=\"checked\" name=\"foo\" type=\"checkbox\" />",
312        Nodes.render(f, MarkupRenderMode.XML));
313    assertEquals(
314        "<input checked=\"checked\" name=\"foo\" type=\"checkbox\" />",
315        Nodes.render(f, MarkupRenderMode.HTML));
316    assertEquals(
317        "<input checked name=\"foo\" type=\"checkbox\">",
318        Nodes.render(f, MarkupRenderMode.HTML4_BACKWARDS_COMPAT));
319  }
320 
321 
322  public final void testRenderSpeed() throws Exception {
323    Element doc = html(fromResource("amazon.com.html"));
324    benchmark(100, doc);  // prime the JIT
325    Thread.sleep(250);  // Let the JIT kick-in.
326    int microsPerRun = benchmark(250, doc);
327    // See extractVarZ in "tools/dashboard/dashboard.pl".
328    System.out.println(
329        " VarZ:" + getClass().getName() + ".msPerRun=" + microsPerRun);
330  }
331 
332  private int benchmark(int nRuns, Element el) {
333    long t0 = System.nanoTime();
334    for (int i = nRuns; --i >= 0;) { Nodes.render(el); }
335    return (int) ((((double) (System.nanoTime() - t0)) / nRuns) / 1e3);
336  }
337}

[all classes][com.google.caja.parser.html]
EMMA 2.0.5312 (C) Vladimir Roubtsov