Home | History | Annotate | Download | only in xml
      1 /*
      2  * Copyright (C) 2009 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.xml;
     18 
     19 import static com.google.common.escape.testing.EscaperAsserts.assertEscaping;
     20 import static com.google.common.escape.testing.EscaperAsserts.assertUnescaped;
     21 
     22 import com.google.common.annotations.GwtCompatible;
     23 import com.google.common.escape.CharEscaper;
     24 
     25 import junit.framework.TestCase;
     26 
     27 /**
     28  * Tests for the {@link XmlEscapers} class.
     29  *
     30  * @author Alex Matevossian
     31  * @author David Beaumont
     32  */
     33 @GwtCompatible
     34 public class XmlEscapersTest extends TestCase {
     35 
     36   public void testXmlContentEscaper() throws Exception {
     37     CharEscaper xmlContentEscaper = (CharEscaper) XmlEscapers.xmlContentEscaper();
     38     assertBasicXmlEscaper(xmlContentEscaper, false, false);
     39     // Test quotes are not escaped.
     40     assertEquals("\"test\"", xmlContentEscaper.escape("\"test\""));
     41     assertEquals("'test'", xmlContentEscaper.escape("'test'"));
     42   }
     43 
     44   public void testXmlAttributeEscaper() throws Exception {
     45     CharEscaper xmlAttributeEscaper = (CharEscaper) XmlEscapers.xmlAttributeEscaper();
     46     assertBasicXmlEscaper(xmlAttributeEscaper, true, true);
     47     // Test quotes are escaped.
     48     assertEquals(""test"", xmlAttributeEscaper.escape("\"test\""));
     49     assertEquals("'test'", xmlAttributeEscaper.escape("\'test'"));
     50     // Test all escapes
     51     assertEquals("a"b<c>d&e"f'",
     52         xmlAttributeEscaper.escape("a\"b<c>d&e\"f'"));
     53     // Test '\t', '\n' and '\r' are escaped.
     54     assertEquals("a&#x9;b&#xA;c&#xD;d", xmlAttributeEscaper.escape("a\tb\nc\rd"));
     55   }
     56 
     57   // Helper to assert common properties of xml escapers.
     58   private void assertBasicXmlEscaper(CharEscaper xmlEscaper,
     59       boolean shouldEscapeQuotes, boolean shouldEscapeWhitespaceChars) {
     60     // Simple examples (smoke tests)
     61     assertEquals("xxx", xmlEscaper.escape("xxx"));
     62     assertEquals("test &amp; test &amp; test",
     63         xmlEscaper.escape("test & test & test"));
     64     assertEquals("test &lt;&lt; 1", xmlEscaper.escape("test << 1"));
     65     assertEquals("test &gt;&gt; 1", xmlEscaper.escape("test >> 1"));
     66     assertEquals("&lt;tab&gt;", xmlEscaper.escape("<tab>"));
     67 
     68     // Test all non-escaped ASCII characters.
     69     String s = "!@#$%^*()_+=-/?\\|]}[{,.;:" +
     70         "abcdefghijklmnopqrstuvwxyz" +
     71         "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
     72         "1234567890";
     73     assertEquals(s, xmlEscaper.escape(s));
     74 
     75     // Test ASCII control characters.
     76     for (char ch = 0; ch < 0x20; ch++) {
     77       if (ch == '\t' || ch == '\n' || ch == '\r') {
     78         // Only these whitespace chars are permitted in XML,
     79         if (shouldEscapeWhitespaceChars) {
     80           assertEscaping(xmlEscaper, "&#x" + Integer.toHexString(ch).toUpperCase() + ";", ch);
     81         } else {
     82           assertUnescaped(xmlEscaper, ch);
     83         }
     84       } else {
     85         // and everything else is replaced with FFFD.
     86         assertEscaping(xmlEscaper, "\uFFFD", ch);
     87       }
     88     }
     89 
     90     // Test _all_ allowed characters (including surrogate values).
     91     for (char ch = 0x20; ch <= 0xFFFD; ch++) {
     92       // There are a small number of cases to consider, so just do it manually.
     93       if (ch == '&') {
     94         assertEscaping(xmlEscaper, "&amp;", ch);
     95       } else if (ch == '<') {
     96         assertEscaping(xmlEscaper, "&lt;", ch);
     97       } else if (ch == '>') {
     98         assertEscaping(xmlEscaper, "&gt;", ch);
     99       } else if (shouldEscapeQuotes && ch == '\'') {
    100         assertEscaping(xmlEscaper, "&apos;", ch);
    101       } else if (shouldEscapeQuotes && ch == '"') {
    102         assertEscaping(xmlEscaper, "&quot;", ch);
    103       } else {
    104         String input = String.valueOf(ch);
    105         String escaped = xmlEscaper.escape(input);
    106         assertEquals(
    107             "char 0x" + Integer.toString(ch, 16) + " should not be escaped",
    108             input, escaped);
    109       }
    110     }
    111 
    112     // Test that 0xFFFE and 0xFFFF are replaced with 0xFFFD
    113     assertEscaping(xmlEscaper, "\uFFFD", '\uFFFE');
    114     assertEscaping(xmlEscaper, "\uFFFD", '\uFFFF');
    115 
    116     assertEquals("0xFFFE is forbidden and should be replaced during escaping",
    117         "[\uFFFD]", xmlEscaper.escape("[\ufffe]"));
    118     assertEquals("0xFFFF is forbidden and should be replaced during escaping",
    119         "[\uFFFD]", xmlEscaper.escape("[\uffff]"));
    120   }
    121 }
    122