001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.lang;
018:
019: import java.io.IOException;
020: import java.io.StringWriter;
021: import java.lang.reflect.Constructor;
022: import java.lang.reflect.Modifier;
023:
024: import junit.framework.Test;
025: import junit.framework.TestCase;
026: import junit.framework.TestSuite;
027: import junit.textui.TestRunner;
028:
029: /**
030: * Unit tests for {@link StringEscapeUtils}.
031: *
032: * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
033: * @version $Id: StringEscapeUtilsTest.java 496931 2007-01-17 03:56:33Z bayard $
034: */
035: public class StringEscapeUtilsTest extends TestCase {
036: private final static String FOO = "foo";
037:
038: public StringEscapeUtilsTest(String name) {
039: super (name);
040: }
041:
042: public static void main(String[] args) {
043: TestRunner.run(suite());
044: }
045:
046: public static Test suite() {
047: TestSuite suite = new TestSuite(StringEscapeUtilsTest.class);
048: suite.setName("StringEscapeUtilsTest Tests");
049: return suite;
050: }
051:
052: //-----------------------------------------------------------------------
053: public void testConstructor() {
054: assertNotNull(new StringEscapeUtils());
055: Constructor[] cons = StringEscapeUtils.class
056: .getDeclaredConstructors();
057: assertEquals(1, cons.length);
058: assertEquals(true, Modifier.isPublic(cons[0].getModifiers()));
059: assertEquals(true, Modifier.isPublic(StringEscapeUtils.class
060: .getModifiers()));
061: assertEquals(false, Modifier.isFinal(StringEscapeUtils.class
062: .getModifiers()));
063: }
064:
065: //-----------------------------------------------------------------------
066: public void testEscapeJava() throws IOException {
067: assertEquals(null, StringEscapeUtils.escapeJava(null));
068: try {
069: StringEscapeUtils.escapeJava(null, null);
070: fail();
071: } catch (IOException ex) {
072: fail();
073: } catch (IllegalArgumentException ex) {
074: }
075: try {
076: StringEscapeUtils.escapeJava(null, "");
077: fail();
078: } catch (IOException ex) {
079: fail();
080: } catch (IllegalArgumentException ex) {
081: }
082:
083: assertEscapeJava("empty string", "", "");
084: assertEscapeJava(FOO, FOO);
085: assertEscapeJava("tab", "\\t", "\t");
086: assertEscapeJava("backslash", "\\\\", "\\");
087: assertEscapeJava("single quote should not be escaped", "'", "'");
088: assertEscapeJava("\\\\\\b\\t\\r", "\\\b\t\r");
089: assertEscapeJava("\\u1234", "\u1234");
090: assertEscapeJava("\\u0234", "\u0234");
091: assertEscapeJava("\\u00EF", "\u00ef");
092: assertEscapeJava("\\u0001", "\u0001");
093: assertEscapeJava("Should use capitalized unicode hex",
094: "\\uABCD", "\uabcd");
095:
096: assertEscapeJava("He didn't say, \\\"stop!\\\"",
097: "He didn't say, \"stop!\"");
098: assertEscapeJava("non-breaking space",
099: "This space is non-breaking:" + "\\u00A0",
100: "This space is non-breaking:\u00a0");
101: assertEscapeJava("\\uABCD\\u1234\\u012C", "\uABCD\u1234\u012C");
102: }
103:
104: private void assertEscapeJava(String escaped, String original)
105: throws IOException {
106: assertEscapeJava(null, escaped, original);
107: }
108:
109: private void assertEscapeJava(String message, String expected,
110: String original) throws IOException {
111: String converted = StringEscapeUtils.escapeJava(original);
112: message = "escapeJava(String) failed"
113: + (message == null ? "" : (": " + message));
114: assertEquals(message, expected, converted);
115:
116: StringWriter writer = new StringWriter();
117: StringEscapeUtils.escapeJava(writer, original);
118: assertEquals(expected, writer.toString());
119: }
120:
121: public void testUnescapeJava() throws IOException {
122: assertEquals(null, StringEscapeUtils.unescapeJava(null));
123: try {
124: StringEscapeUtils.unescapeJava(null, null);
125: fail();
126: } catch (IOException ex) {
127: fail();
128: } catch (IllegalArgumentException ex) {
129: }
130: try {
131: StringEscapeUtils.unescapeJava(null, "");
132: fail();
133: } catch (IOException ex) {
134: fail();
135: } catch (IllegalArgumentException ex) {
136: }
137: try {
138: StringEscapeUtils.unescapeJava("\\u02-3");
139: fail();
140: } catch (RuntimeException ex) {
141: }
142:
143: assertUnescapeJava("", "");
144: assertUnescapeJava("test", "test");
145: assertUnescapeJava("\ntest\b", "\\ntest\\b");
146: assertUnescapeJava("\u123425foo\ntest\b",
147: "\\u123425foo\\ntest\\b");
148: assertUnescapeJava("'\foo\teste\r", "\\'\\foo\\teste\\r");
149: assertUnescapeJava("\\", "\\");
150: //foo
151: assertUnescapeJava("lowercase unicode", "\uABCDx", "\\uabcdx");
152: assertUnescapeJava("uppercase unicode", "\uABCDx", "\\uABCDx");
153: assertUnescapeJava("unicode as final character", "\uABCD",
154: "\\uabcd");
155: }
156:
157: private void assertUnescapeJava(String unescaped, String original)
158: throws IOException {
159: assertUnescapeJava(null, unescaped, original);
160: }
161:
162: private void assertUnescapeJava(String message, String unescaped,
163: String original) throws IOException {
164: String expected = unescaped;
165: String actual = StringEscapeUtils.unescapeJava(original);
166:
167: assertEquals("unescape(String) failed"
168: + (message == null ? "" : (": " + message))
169: + ": expected '"
170: + StringEscapeUtils.escapeJava(expected)
171: +
172: // we escape this so we can see it in the error message
173: "' actual '" + StringEscapeUtils.escapeJava(actual)
174: + "'", expected, actual);
175:
176: StringWriter writer = new StringWriter();
177: StringEscapeUtils.unescapeJava(writer, original);
178: assertEquals(unescaped, writer.toString());
179:
180: }
181:
182: public void testEscapeJavaScript() {
183: assertEquals(null, StringEscapeUtils.escapeJavaScript(null));
184: try {
185: StringEscapeUtils.escapeJavaScript(null, null);
186: fail();
187: } catch (IOException ex) {
188: fail();
189: } catch (IllegalArgumentException ex) {
190: }
191: try {
192: StringEscapeUtils.escapeJavaScript(null, "");
193: fail();
194: } catch (IOException ex) {
195: fail();
196: } catch (IllegalArgumentException ex) {
197: }
198:
199: assertEquals("He didn\\'t say, \\\"stop!\\\"",
200: StringEscapeUtils
201: .escapeJavaScript("He didn't say, \"stop!\""));
202: }
203:
204: // HTML and XML
205: //--------------------------------------------------------------
206:
207: String[][] htmlEscapes = {
208: { "no escaping", "plain text", "plain text" },
209: { "no escaping", "plain text", "plain text" },
210: { "empty string", "", "" },
211: { "null", null, null },
212: { "ampersand", "bread & butter", "bread & butter" },
213: { "quotes", ""bread" & butter",
214: "\"bread\" & butter" },
215: { "final character only", "greater than >",
216: "greater than >" },
217: { "first character only", "< less than", "< less than" },
218: { "apostrophe", "Huntington's chorea",
219: "Huntington's chorea" },
220: {
221: "languages",
222: "English,Français,日本語 (nihongo)",
223: "English,Fran\u00E7ais,\u65E5\u672C\u8A9E (nihongo)" },
224: { "8-bit ascii doesn't number-escape", "~\u007F",
225: "\u007E\u007F" },
226: { "8-bit ascii does number-escape", "€Ÿ",
227: "\u0080\u009F" }, };
228:
229: public void testEscapeHtml() {
230: for (int i = 0; i < htmlEscapes.length; ++i) {
231: String message = htmlEscapes[i][0];
232: String expected = htmlEscapes[i][1];
233: String original = htmlEscapes[i][2];
234: assertEquals(message, expected, StringEscapeUtils
235: .escapeHtml(original));
236: StringWriter sw = new StringWriter();
237: try {
238: StringEscapeUtils.escapeHtml(sw, original);
239: } catch (IOException e) {
240: }
241: String actual = original == null ? null : sw.toString();
242: assertEquals(message, expected, actual);
243: }
244: }
245:
246: public void testUnescapeHtml() {
247: for (int i = 0; i < htmlEscapes.length; ++i) {
248: String message = htmlEscapes[i][0];
249: String expected = htmlEscapes[i][2];
250: String original = htmlEscapes[i][1];
251: assertEquals(message, expected, StringEscapeUtils
252: .unescapeHtml(original));
253:
254: StringWriter sw = new StringWriter();
255: try {
256: StringEscapeUtils.unescapeHtml(sw, original);
257: } catch (IOException e) {
258: }
259: String actual = original == null ? null : sw.toString();
260: assertEquals(message, expected, actual);
261: }
262: // \u00E7 is a cedilla (c with wiggle under)
263: // note that the test string must be 7-bit-clean (unicode escaped) or else it will compile incorrectly
264: // on some locales
265: assertEquals("funny chars pass through OK", "Fran\u00E7ais",
266: StringEscapeUtils.unescapeHtml("Fran\u00E7ais"));
267:
268: assertEquals("Hello&;World", StringEscapeUtils
269: .unescapeHtml("Hello&;World"));
270: assertEquals("Hello&#;World", StringEscapeUtils
271: .unescapeHtml("Hello&#;World"));
272: assertEquals("Hello&# ;World", StringEscapeUtils
273: .unescapeHtml("Hello&# ;World"));
274: assertEquals("Hello&##;World", StringEscapeUtils
275: .unescapeHtml("Hello&##;World"));
276: }
277:
278: public void testUnescapeHexCharsHtml() {
279: // Simple easy to grok test
280: assertEquals("hex number unescape", "\u0080\u009F",
281: StringEscapeUtils.unescapeHtml("€Ÿ"));
282: assertEquals("hex number unescape", "\u0080\u009F",
283: StringEscapeUtils.unescapeHtml("€Ÿ"));
284: // Test all Character values:
285: for (char i = Character.MIN_VALUE; i < Character.MAX_VALUE; i++) {
286: Character c1 = new Character(i);
287: Character c2 = new Character((char) (i + 1));
288: String expected = c1.toString() + c2.toString();
289: String escapedC1 = "&#x"
290: + Integer.toHexString((c1.charValue())) + ";";
291: String escapedC2 = "&#x"
292: + Integer.toHexString((c2.charValue())) + ";";
293: assertEquals("hex number unescape index " + (int) i,
294: expected, StringEscapeUtils.unescapeHtml(escapedC1
295: + escapedC2));
296: }
297: }
298:
299: public void testUnescapeUnknownEntity() throws Exception {
300: assertEquals("&zzzz;", StringEscapeUtils.unescapeHtml("&zzzz;"));
301: }
302:
303: public void testEscapeHtmlVersions() throws Exception {
304: assertEquals("Β", StringEscapeUtils.escapeHtml("\u0392"));
305: assertEquals("\u0392", StringEscapeUtils.unescapeHtml("Β"));
306:
307: //todo: refine API for escaping/unescaping specific HTML versions
308:
309: }
310:
311: public void testEscapeXml() throws Exception {
312: assertEquals("<abc>", StringEscapeUtils
313: .escapeXml("<abc>"));
314: assertEquals("<abc>", StringEscapeUtils
315: .unescapeXml("<abc>"));
316:
317: assertEquals(
318: "XML should use numbers, not names for HTML entities",
319: "¡", StringEscapeUtils.escapeXml("\u00A1"));
320: assertEquals(
321: "XML should use numbers, not names for HTML entities",
322: "\u00A0", StringEscapeUtils.unescapeXml(" "));
323:
324: assertEquals("ain't", StringEscapeUtils
325: .unescapeXml("ain't"));
326: assertEquals("ain't", StringEscapeUtils.escapeXml("ain't"));
327: assertEquals("", StringEscapeUtils.escapeXml(""));
328: assertEquals(null, StringEscapeUtils.escapeXml(null));
329: assertEquals(null, StringEscapeUtils.unescapeXml(null));
330:
331: StringWriter sw = new StringWriter();
332: try {
333: StringEscapeUtils.escapeXml(sw, "<abc>");
334: } catch (IOException e) {
335: }
336: assertEquals("XML was escaped incorrectly", "<abc>", sw
337: .toString());
338:
339: sw = new StringWriter();
340: try {
341: StringEscapeUtils.unescapeXml(sw, "<abc>");
342: } catch (IOException e) {
343: }
344: assertEquals("XML was unescaped incorrectly", "<abc>", sw
345: .toString());
346: }
347:
348: // SQL
349: // see http://www.jguru.com/faq/view.jsp?EID=8881
350: //--------------------
351:
352: public void testEscapeSql() throws Exception {
353: assertEquals("don''t stop", StringEscapeUtils
354: .escapeSql("don't stop"));
355: assertEquals("", StringEscapeUtils.escapeSql(""));
356: assertEquals(null, StringEscapeUtils.escapeSql(null));
357: }
358:
359: // Tests issue #38569
360: // http://issues.apache.org/bugzilla/show_bug.cgi?id=38569
361: public void testStandaloneAmphersand() {
362: assertEquals("<P&O>", StringEscapeUtils
363: .unescapeHtml("<P&O>"));
364: assertEquals("test & <", StringEscapeUtils
365: .unescapeHtml("test & <"));
366: assertEquals("<P&O>", StringEscapeUtils
367: .unescapeXml("<P&O>"));
368: assertEquals("test & <", StringEscapeUtils
369: .unescapeXml("test & <"));
370: }
371:
372: public void testLang313() {
373: assertEquals("& &", StringEscapeUtils.unescapeHtml("& &"));
374: }
375:
376: }
|