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 testXmlContentEscaper()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 testXmlAttributeEscaper()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	b
c
d", xmlAttributeEscaper.escape("a\tb\nc\rd")); 55 } 56 57 // Helper to assert common properties of xml escapers. assertBasicXmlEscaper(CharEscaper xmlEscaper, boolean shouldEscapeQuotes, boolean shouldEscapeWhitespaceChars)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 & test & test", 63 xmlEscaper.escape("test & test & test")); 64 assertEquals("test << 1", xmlEscaper.escape("test << 1")); 65 assertEquals("test >> 1", xmlEscaper.escape("test >> 1")); 66 assertEquals("<tab>", 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, "&", ch); 95 } else if (ch == '<') { 96 assertEscaping(xmlEscaper, "<", ch); 97 } else if (ch == '>') { 98 assertEscaping(xmlEscaper, ">", ch); 99 } else if (shouldEscapeQuotes && ch == '\'') { 100 assertEscaping(xmlEscaper, "'", ch); 101 } else if (shouldEscapeQuotes && ch == '"') { 102 assertEscaping(xmlEscaper, """, 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