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