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