1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.text;
18
19 import org.junit.Test;
20
21 import java.io.IOException;
22 import java.io.StringWriter;
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.Modifier;
25 import java.nio.charset.Charset;
26 import java.nio.charset.StandardCharsets;
27 import java.nio.file.Files;
28 import java.nio.file.Paths;
29
30 import static org.apache.commons.text.StringEscapeUtils.escapeXSI;
31 import static org.apache.commons.text.StringEscapeUtils.unescapeXSI;
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertFalse;
34 import static org.junit.Assert.assertNotNull;
35 import static org.junit.Assert.assertNull;
36 import static org.junit.Assert.assertTrue;
37 import static org.junit.Assert.fail;
38
39
40
41
42
43
44
45
46
47 public class StringEscapeUtilsTest {
48 private final static String FOO = "foo";
49
50 @Test
51 public void testConstructor() {
52 assertNotNull(new StringEscapeUtils());
53 final Constructor<?>[] cons = StringEscapeUtils.class.getDeclaredConstructors();
54 assertEquals(1, cons.length);
55 assertTrue(Modifier.isPublic(cons[0].getModifiers()));
56 assertTrue(Modifier.isPublic(StringEscapeUtils.class.getModifiers()));
57 assertFalse(Modifier.isFinal(StringEscapeUtils.class.getModifiers()));
58 }
59
60 @Test
61 public void testEscapeJava() throws IOException {
62 assertEquals(null, StringEscapeUtils.escapeJava(null));
63 try {
64 StringEscapeUtils.ESCAPE_JAVA.translate(null, null);
65 fail();
66 } catch (final IOException ex) {
67 fail();
68 } catch (final IllegalArgumentException ex) {
69 }
70 try {
71 StringEscapeUtils.ESCAPE_JAVA.translate("", null);
72 fail();
73 } catch (final IOException ex) {
74 fail();
75 } catch (final IllegalArgumentException ex) {
76 }
77
78 assertEscapeJava("empty string", "", "");
79 assertEscapeJava(FOO, FOO);
80 assertEscapeJava("tab", "\\t", "\t");
81 assertEscapeJava("backslash", "\\\\", "\\");
82 assertEscapeJava("single quote should not be escaped", "'", "'");
83 assertEscapeJava("\\\\\\b\\t\\r", "\\\b\t\r");
84 assertEscapeJava("\\u1234", "\u1234");
85 assertEscapeJava("\\u0234", "\u0234");
86 assertEscapeJava("\\u00EF", "\u00ef");
87 assertEscapeJava("\\u0001", "\u0001");
88 assertEscapeJava("Should use capitalized Unicode hex", "\\uABCD", "\uabcd");
89
90 assertEscapeJava("He didn't say, \\\"stop!\\\"",
91 "He didn't say, \"stop!\"");
92 assertEscapeJava("non-breaking space", "This space is non-breaking:" + "\\u00A0",
93 "This space is non-breaking:\u00a0");
94 assertEscapeJava("\\uABCD\\u1234\\u012C",
95 "\uABCD\u1234\u012C");
96 }
97
98
99
100
101 @Test
102 public void testEscapeJavaWithSlash() {
103 final String input = "String with a slash (/) in it";
104
105 final String expected = input;
106 final String actual = StringEscapeUtils.escapeJava(input);
107
108
109
110
111
112 assertEquals(expected, actual);
113 }
114
115 private void assertEscapeJava(final String escaped, final String original) throws IOException {
116 assertEscapeJava(null, escaped, original);
117 }
118
119 private void assertEscapeJava(String message, final String expected, final String original) throws IOException {
120 final String converted = StringEscapeUtils.escapeJava(original);
121 message = "escapeJava(String) failed" + (message == null ? "" : (": " + message));
122 assertEquals(message, expected, converted);
123
124 final StringWriter writer = new StringWriter();
125 StringEscapeUtils.ESCAPE_JAVA.translate(original, writer);
126 assertEquals(expected, writer.toString());
127 }
128
129 @Test
130 public void testUnescapeJava() throws IOException {
131 assertEquals(null, StringEscapeUtils.unescapeJava(null));
132 try {
133 StringEscapeUtils.UNESCAPE_JAVA.translate(null, null);
134 fail();
135 } catch (final IOException ex) {
136 fail();
137 } catch (final IllegalArgumentException ex) {
138 }
139 try {
140 StringEscapeUtils.UNESCAPE_JAVA.translate("", null);
141 fail();
142 } catch (final IOException ex) {
143 fail();
144 } catch (final IllegalArgumentException ex) {
145 }
146 try {
147 StringEscapeUtils.unescapeJava("\\u02-3");
148 fail();
149 } catch (final RuntimeException ex) {
150 }
151
152 assertUnescapeJava("", "");
153 assertUnescapeJava("test", "test");
154 assertUnescapeJava("\ntest\b", "\\ntest\\b");
155 assertUnescapeJava("\u123425foo\ntest\b", "\\u123425foo\\ntest\\b");
156 assertUnescapeJava("'\foo\teste\r", "\\'\\foo\\teste\\r");
157 assertUnescapeJava("", "\\");
158
159 assertUnescapeJava("lowercase Unicode", "\uABCDx", "\\uabcdx");
160 assertUnescapeJava("uppercase Unicode", "\uABCDx", "\\uABCDx");
161 assertUnescapeJava("Unicode as final character", "\uABCD", "\\uabcd");
162 }
163
164 private void assertUnescapeJava(final String unescaped, final String original) throws IOException {
165 assertUnescapeJava(null, unescaped, original);
166 }
167
168 private void assertUnescapeJava(final String message, final String unescaped, final String original) throws IOException {
169 final String expected = unescaped;
170 final String actual = StringEscapeUtils.unescapeJava(original);
171
172 assertEquals("unescape(String) failed" +
173 (message == null ? "" : (": " + message)) +
174 ": expected '" + StringEscapeUtils.escapeJava(expected) +
175
176 "' actual '" + StringEscapeUtils.escapeJava(actual) + "'",
177 expected, actual);
178
179 final StringWriter writer = new StringWriter();
180 StringEscapeUtils.UNESCAPE_JAVA.translate(original, writer);
181 assertEquals(unescaped, writer.toString());
182
183 }
184
185 @Test
186 public void testEscapeEcmaScript() {
187 assertEquals(null, StringEscapeUtils.escapeEcmaScript(null));
188 try {
189 StringEscapeUtils.ESCAPE_ECMASCRIPT.translate(null, null);
190 fail();
191 } catch (final IOException ex) {
192 fail();
193 } catch (final IllegalArgumentException ex) {
194 }
195 try {
196 StringEscapeUtils.ESCAPE_ECMASCRIPT.translate("", null);
197 fail();
198 } catch (final IOException ex) {
199 fail();
200 } catch (final IllegalArgumentException ex) {
201 }
202
203 assertEquals("He didn\\'t say, \\\"stop!\\\"", StringEscapeUtils.escapeEcmaScript("He didn't say, \"stop!\""));
204 assertEquals("document.getElementById(\\\"test\\\").value = \\'<script>alert(\\'aaa\\');<\\/script>\\';",
205 StringEscapeUtils.escapeEcmaScript("document.getElementById(\"test\").value = '<script>alert('aaa');</script>';"));
206 }
207
208
209
210
211
212 private static final String[][] HTML_ESCAPES = {
213 {"no escaping", "plain text", "plain text"},
214 {"no escaping", "plain text", "plain text"},
215 {"empty string", "", ""},
216 {"null", null, null},
217 {"ampersand", "bread & butter", "bread & butter"},
218 {"quotes", ""bread" & butter", "\"bread\" & butter"},
219 {"final character only", "greater than >", "greater than >"},
220 {"first character only", "< less than", "< less than"},
221 {"apostrophe", "Huntington's chorea", "Huntington's chorea"},
222 {"languages", "English,Français,\u65E5\u672C\u8A9E (nihongo)", "English,Fran\u00E7ais,\u65E5\u672C\u8A9E (nihongo)"},
223 {"8-bit ascii shouldn't number-escape", "\u0080\u009F", "\u0080\u009F"},
224 };
225
226 @Test
227 public void testEscapeHtml() {
228 for (final String[] element : HTML_ESCAPES) {
229 final String message = element[0];
230 final String expected = element[1];
231 final String original = element[2];
232 assertEquals(message, expected, StringEscapeUtils.escapeHtml4(original));
233 final StringWriter sw = new StringWriter();
234 try {
235 StringEscapeUtils.ESCAPE_HTML4.translate(original, sw);
236 } catch (final IOException e) {
237 }
238 final String actual = original == null ? null : sw.toString();
239 assertEquals(message, expected, actual);
240 }
241 }
242
243 @Test
244 public void testEscapeHtml4Once() {
245 for (final String[] element : HTML_ESCAPES) {
246 final String message = element[0];
247 final String expected = element[1];
248 final String original = element[2];
249 assertEquals(message, expected, StringEscapeUtils.escapeHtml4Once(original));
250 assertEquals(message, expected, StringEscapeUtils.escapeHtml4Once(expected));
251 final StringWriter sw = new StringWriter();
252 try {
253 StringEscapeUtils.ESCAPE_HTML4_ONCE.translate(original, sw);
254 } catch (final IOException e) {
255 }
256 final String actual = original == null ? null : sw.toString();
257 assertEquals(message, expected, actual);
258 final StringWriter sw2 = new StringWriter();
259 try {
260 StringEscapeUtils.ESCAPE_HTML4_ONCE.translate(expected, sw2);
261 } catch (final IOException e) {
262 }
263 final String actual2 = original == null ? null : sw2.toString();
264 assertEquals(message, expected, actual2);
265 }
266 }
267
268 @Test
269 public void testEscapeHtml3Once() {
270 for (final String[] element : HTML_ESCAPES) {
271 final String message = element[0];
272 final String expected = element[1];
273 final String original = element[2];
274 assertEquals(message, expected, StringEscapeUtils.escapeHtml3Once(original));
275 assertEquals(message, expected, StringEscapeUtils.escapeHtml3Once(expected));
276 final StringWriter sw = new StringWriter();
277 try {
278 StringEscapeUtils.ESCAPE_HTML3_ONCE.translate(original, sw);
279 } catch (final IOException e) {
280 }
281 final String actual = original == null ? null : sw.toString();
282 assertEquals(message, expected, actual);
283 final StringWriter sw2 = new StringWriter();
284 try {
285 StringEscapeUtils.ESCAPE_HTML3_ONCE.translate(expected, sw2);
286 } catch (final IOException e) {
287 }
288 final String actual2 = original == null ? null : sw2.toString();
289 assertEquals(message, expected, actual2);
290 }
291 }
292
293 @Test
294 public void testUnescapeHtml4() {
295 for (final String[] element : HTML_ESCAPES) {
296 final String message = element[0];
297 final String expected = element[2];
298 final String original = element[1];
299 assertEquals(message, expected, StringEscapeUtils.unescapeHtml4(original));
300
301 final StringWriter sw = new StringWriter();
302 try {
303 StringEscapeUtils.UNESCAPE_HTML4.translate(original, sw);
304 } catch (final IOException e) {
305 }
306 final String actual = original == null ? null : sw.toString();
307 assertEquals(message, expected, actual);
308 }
309
310
311
312 assertEquals("funny chars pass through OK", "Fran\u00E7ais", StringEscapeUtils.unescapeHtml4("Fran\u00E7ais"));
313
314 assertEquals("Hello&;World", StringEscapeUtils.unescapeHtml4("Hello&;World"));
315 assertEquals("Hello&#;World", StringEscapeUtils.unescapeHtml4("Hello&#;World"));
316 assertEquals("Hello&# ;World", StringEscapeUtils.unescapeHtml4("Hello&# ;World"));
317 assertEquals("Hello&##;World", StringEscapeUtils.unescapeHtml4("Hello&##;World"));
318 }
319
320 @Test
321 public void testUnescapeHexCharsHtml() {
322
323 assertEquals("hex number unescape", "\u0080\u009F", StringEscapeUtils.unescapeHtml4("€Ÿ"));
324 assertEquals("hex number unescape", "\u0080\u009F", StringEscapeUtils.unescapeHtml4("€Ÿ"));
325
326 for (char i = Character.MIN_VALUE; i < Character.MAX_VALUE; i++) {
327 final Character c1 = new Character(i);
328 final Character c2 = new Character((char)(i+1));
329 final String expected = c1.toString() + c2.toString();
330 final String escapedC1 = "&#x" + Integer.toHexString((c1.charValue())) + ";";
331 final String escapedC2 = "&#x" + Integer.toHexString((c2.charValue())) + ";";
332 assertEquals("hex number unescape index " + (int)i, expected, StringEscapeUtils.unescapeHtml4(escapedC1 + escapedC2));
333 }
334 }
335
336 @Test
337 public void testUnescapeUnknownEntity() throws Exception {
338 assertEquals("&zzzz;", StringEscapeUtils.unescapeHtml4("&zzzz;"));
339 }
340
341 @Test
342 public void testEscapeHtmlVersions() throws Exception {
343 assertEquals("Β", StringEscapeUtils.escapeHtml4("\u0392"));
344 assertEquals("\u0392", StringEscapeUtils.unescapeHtml4("Β"));
345
346
347 }
348
349
350
351 @Test
352 public void testEscapeXml10() throws Exception {
353 assertEquals("a<b>c"d'e&f", StringEscapeUtils.escapeXml10("a<b>c\"d'e&f"));
354 assertEquals("XML 1.0 should not escape \t \n \r",
355 "a\tb\rc\nd", StringEscapeUtils.escapeXml10("a\tb\rc\nd"));
356 assertEquals("XML 1.0 should omit most #x0-x8 | #xb | #xc | #xe-#x19",
357 "ab", StringEscapeUtils.escapeXml10("a\u0000\u0001\u0008\u000b\u000c\u000e\u001fb"));
358 assertEquals("XML 1.0 should omit #xd800-#xdfff",
359 "a\ud7ff \ue000b", StringEscapeUtils.escapeXml10("a\ud7ff\ud800 \udfff \ue000b"));
360 assertEquals("XML 1.0 should omit #xfffe | #xffff",
361 "a\ufffdb", StringEscapeUtils.escapeXml10("a\ufffd\ufffe\uffffb"));
362 assertEquals("XML 1.0 should escape #x7f-#x84 | #x86 - #x9f, for XML 1.1 compatibility",
363 "a\u007e„\u0085†Ÿ\u00a0b", StringEscapeUtils.escapeXml10("a\u007e\u007f\u0084\u0085\u0086\u009f\u00a0b"));
364 }
365
366 @Test
367 public void testEscapeXml11() throws Exception {
368 assertEquals("a<b>c"d'e&f", StringEscapeUtils.escapeXml11("a<b>c\"d'e&f"));
369 assertEquals("XML 1.1 should not escape \t \n \r",
370 "a\tb\rc\nd", StringEscapeUtils.escapeXml11("a\tb\rc\nd"));
371 assertEquals("XML 1.1 should omit #x0",
372 "ab", StringEscapeUtils.escapeXml11("a\u0000b"));
373 assertEquals("XML 1.1 should escape #x1-x8 | #xb | #xc | #xe-#x19",
374 "ab", StringEscapeUtils.escapeXml11("a\u0001\u0008\u000b\u000c\u000e\u001fb"));
375 assertEquals("XML 1.1 should escape #x7F-#x84 | #x86-#x9F",
376 "a\u007e„\u0085†Ÿ\u00a0b", StringEscapeUtils.escapeXml11("a\u007e\u007f\u0084\u0085\u0086\u009f\u00a0b"));
377 assertEquals("XML 1.1 should omit #xd800-#xdfff",
378 "a\ud7ff \ue000b", StringEscapeUtils.escapeXml11("a\ud7ff\ud800 \udfff \ue000b"));
379 assertEquals("XML 1.1 should omit #xfffe | #xffff",
380 "a\ufffdb", StringEscapeUtils.escapeXml11("a\ufffd\ufffe\uffffb"));
381 }
382
383
384
385
386
387
388 @Test
389 public void testUnescapeXmlSupplementaryCharacters() {
390 assertEquals("Supplementary character must be represented using a single escape", "\uD84C\uDFB4",
391 StringEscapeUtils.unescapeXml("𣎴") );
392
393 assertEquals("Supplementary characters mixed with basic characters should be decoded correctly", "a b c \uD84C\uDFB4",
394 StringEscapeUtils.unescapeXml("a b c 𣎴") );
395 }
396
397
398
399 @Test
400 public void testStandaloneAmphersand() {
401 assertEquals("<P&O>", StringEscapeUtils.unescapeHtml4("<P&O>"));
402 assertEquals("test & <", StringEscapeUtils.unescapeHtml4("test & <"));
403 assertEquals("<P&O>", StringEscapeUtils.unescapeXml("<P&O>"));
404 assertEquals("test & <", StringEscapeUtils.unescapeXml("test & <"));
405 }
406
407 @Test
408 public void testLang313() {
409 assertEquals("& &", StringEscapeUtils.unescapeHtml4("& &"));
410 }
411
412 @Test
413 public void testEscapeCsvString() throws Exception {
414 assertEquals("foo.bar", StringEscapeUtils.escapeCsv("foo.bar"));
415 assertEquals("\"foo,bar\"", StringEscapeUtils.escapeCsv("foo,bar"));
416 assertEquals("\"foo\nbar\"", StringEscapeUtils.escapeCsv("foo\nbar"));
417 assertEquals("\"foo\rbar\"", StringEscapeUtils.escapeCsv("foo\rbar"));
418 assertEquals("\"foo\"\"bar\"", StringEscapeUtils.escapeCsv("foo\"bar"));
419 assertEquals("foo\uD84C\uDFB4bar", StringEscapeUtils.escapeCsv("foo\uD84C\uDFB4bar"));
420 assertEquals("", StringEscapeUtils.escapeCsv(""));
421 assertEquals(null, StringEscapeUtils.escapeCsv(null));
422 }
423
424 @Test
425 public void testEscapeCsvWriter() throws Exception {
426 checkCsvEscapeWriter("foo.bar", "foo.bar");
427 checkCsvEscapeWriter("\"foo,bar\"", "foo,bar");
428 checkCsvEscapeWriter("\"foo\nbar\"", "foo\nbar");
429 checkCsvEscapeWriter("\"foo\rbar\"", "foo\rbar");
430 checkCsvEscapeWriter("\"foo\"\"bar\"", "foo\"bar");
431 checkCsvEscapeWriter("foo\uD84C\uDFB4bar", "foo\uD84C\uDFB4bar");
432 checkCsvEscapeWriter("", null);
433 checkCsvEscapeWriter("", "");
434 }
435
436 private void checkCsvEscapeWriter(final String expected, final String value) {
437 try {
438 final StringWriter writer = new StringWriter();
439 StringEscapeUtils.ESCAPE_CSV.translate(value, writer);
440 assertEquals(expected, writer.toString());
441 } catch (final IOException e) {
442 fail("Threw: " + e);
443 }
444 }
445
446 @Test
447 public void testUnescapeCsvString() throws Exception {
448 assertEquals("foo.bar", StringEscapeUtils.unescapeCsv("foo.bar"));
449 assertEquals("foo,bar", StringEscapeUtils.unescapeCsv("\"foo,bar\""));
450 assertEquals("foo\nbar", StringEscapeUtils.unescapeCsv("\"foo\nbar\""));
451 assertEquals("foo\rbar", StringEscapeUtils.unescapeCsv("\"foo\rbar\""));
452 assertEquals("foo\"bar", StringEscapeUtils.unescapeCsv("\"foo\"\"bar\""));
453 assertEquals("foo\uD84C\uDFB4bar", StringEscapeUtils.unescapeCsv("foo\uD84C\uDFB4bar"));
454 assertEquals("", StringEscapeUtils.unescapeCsv(""));
455 assertEquals(null, StringEscapeUtils.unescapeCsv(null));
456
457 assertEquals("\"foo.bar\"", StringEscapeUtils.unescapeCsv("\"foo.bar\""));
458 }
459
460 @Test
461 public void testUnescapeCsvWriter() throws Exception {
462 checkCsvUnescapeWriter("foo.bar", "foo.bar");
463 checkCsvUnescapeWriter("foo,bar", "\"foo,bar\"");
464 checkCsvUnescapeWriter("foo\nbar", "\"foo\nbar\"");
465 checkCsvUnescapeWriter("foo\rbar", "\"foo\rbar\"");
466 checkCsvUnescapeWriter("foo\"bar", "\"foo\"\"bar\"");
467 checkCsvUnescapeWriter("foo\uD84C\uDFB4bar", "foo\uD84C\uDFB4bar");
468 checkCsvUnescapeWriter("", null);
469 checkCsvUnescapeWriter("", "");
470
471 checkCsvUnescapeWriter("\"foo.bar\"", "\"foo.bar\"");
472 }
473
474 private void checkCsvUnescapeWriter(final String expected, final String value) {
475 try {
476 final StringWriter writer = new StringWriter();
477 StringEscapeUtils.UNESCAPE_CSV.translate(value, writer);
478 assertEquals(expected, writer.toString());
479 } catch (final IOException e) {
480 fail("Threw: " + e);
481 }
482 }
483
484
485
486
487 @Test
488 public void testEscapeHtmlHighUnicode() {
489
490
491
492
493 final byte[] data = new byte[] { (byte)0xF0, (byte)0x9D, (byte)0x8D, (byte)0xA2 };
494
495 final String original = new String(data, Charset.forName("UTF8"));
496
497 final String escaped = StringEscapeUtils.escapeHtml4( original );
498 assertEquals( "High Unicode should not have been escaped", original, escaped);
499
500 final String unescaped = StringEscapeUtils.unescapeHtml4( escaped );
501 assertEquals( "High Unicode should have been unchanged", original, unescaped);
502
503
504
505
506 }
507
508
509
510
511 @Test
512 public void testEscapeHiragana() {
513
514 final String original = "\u304B\u304C\u3068";
515 final String escaped = StringEscapeUtils.escapeHtml4(original);
516 assertEquals( "Hiragana character Unicode behaviour should not be being escaped by escapeHtml4",
517 original, escaped);
518
519 final String unescaped = StringEscapeUtils.unescapeHtml4( escaped );
520
521 assertEquals( "Hiragana character Unicode behaviour has changed - expected no unescaping", escaped, unescaped);
522 }
523
524
525
526
527
528
529
530 @Test
531 public void testLang708() throws IOException {
532 byte[] inputBytes = Files.readAllBytes(Paths.get("src/test/resources/stringEscapeUtilsTestData.txt"));
533 final String input = new String(inputBytes, StandardCharsets.UTF_8);
534 final String escaped = StringEscapeUtils.escapeEcmaScript(input);
535
536 assertTrue(escaped, escaped.endsWith("}]"));
537
538 assertTrue(escaped, escaped.endsWith("\"valueCode\\\":\\\"\\\"}]"));
539 }
540
541
542
543
544 @Test
545 public void testLang911() {
546 final String bellsTest = "\ud83d\udc80\ud83d\udd14";
547 final String value = StringEscapeUtils.escapeJava(bellsTest);
548 final String valueTest = StringEscapeUtils.unescapeJava(value);
549 assertEquals(bellsTest, valueTest);
550 }
551
552 @Test
553 public void testEscapeJson() {
554 assertEquals(null, StringEscapeUtils.escapeJson(null));
555 try {
556 StringEscapeUtils.ESCAPE_JSON.translate(null, null);
557 fail();
558 } catch (final IOException ex) {
559 fail();
560 } catch (final IllegalArgumentException ex) {
561 }
562 try {
563 StringEscapeUtils.ESCAPE_JSON.translate("", null);
564 fail();
565 } catch (final IOException ex) {
566 fail();
567 } catch (final IllegalArgumentException ex) {
568 }
569
570 assertEquals("He didn't say, \\\"stop!\\\"", StringEscapeUtils.escapeJson("He didn't say, \"stop!\""));
571
572 final String expected = "\\\"foo\\\" isn't \\\"bar\\\". specials: \\b\\r\\n\\f\\t\\\\\\/";
573 final String input ="\"foo\" isn't \"bar\". specials: \b\r\n\f\t\\/";
574
575 assertEquals(expected, StringEscapeUtils.escapeJson(input));
576 }
577
578 @Test
579 public void testBuilder() {
580 String result = StringEscapeUtils.builder(StringEscapeUtils.ESCAPE_XML10).escape("<").append(">").toString();
581 assertEquals("<>", result);
582 }
583
584 @Test
585 public void testEscapeXSI() {
586 assertNull(null, escapeXSI(null));
587 assertEquals("He\\ didn\\'t\\ say,\\ \\\"Stop!\\\"", escapeXSI("He didn't say, \"Stop!\""));
588 assertEquals("\\\\", escapeXSI("\\"));
589 assertEquals("", escapeXSI("\n"));
590 }
591
592 @Test
593 public void testUnscapeXSI() {
594 assertNull(null, unescapeXSI(null));
595 assertEquals("\"", unescapeXSI("\\\""));
596 assertEquals("He didn't say, \"Stop!\"", unescapeXSI("He\\ didn\\'t\\ say,\\ \\\"Stop!\\\""));
597 assertEquals("\\", unescapeXSI("\\\\"));
598 assertEquals("", unescapeXSI("\\"));
599 }
600
601 }