EMMA Coverage Report (generated Mon Nov 01 16:48:29 PDT 2010)
[all classes][com.google.caja.lexer.escaping]

COVERAGE SUMMARY FOR SOURCE FILE [EscapingTest.java]

nameclass, %method, %block, %line, %
EscapingTest.java100% (1/1)95%  (19/20)79%  (513/653)87%  (137/158)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EscapingTest100% (1/1)95%  (19/20)79%  (513/653)87%  (137/158)
<static initializer> 100% (1/1)100% (86/86)100% (16/16)
EscapingTest (): void 100% (1/1)100% (3/3)100% (1/1)
assertJsEscaped (String, String): void 100% (1/1)100% (14/14)100% (4/4)
assertStringsEqual (String, String): void 100% (1/1)6%   (5/87)8%   (1/13)
diagnosticString (String, int, int): String 0%   (0/1)0%   (0/58)0%   (0/9)
testAsciiOnlyEscapeJsString (): void 100% (1/1)100% (14/14)100% (4/4)
testEscapeCssIdent (): void 100% (1/1)100% (67/67)100% (19/19)
testEscapeCssString (): void 100% (1/1)100% (45/45)100% (13/13)
testEscapeJsonString (): void 100% (1/1)100% (13/13)100% (4/4)
testEscapeUri (): void 100% (1/1)100% (56/56)100% (16/16)
testEscapeXml (): void 100% (1/1)100% (13/13)100% (4/4)
testEscapeXmlAsciiOnly (): void 100% (1/1)100% (13/13)100% (4/4)
testIdentifierEscaping (): void 100% (1/1)100% (13/13)100% (4/4)
testMinimalEscapeJsString (): void 100% (1/1)100% (35/35)100% (11/11)
testMinimalEscapeRegex (): void 100% (1/1)100% (14/14)100% (4/4)
testParanoidAsciiOnlyEscapeJsString (): void 100% (1/1)100% (14/14)100% (4/4)
testParanoidEscapeJsString (): void 100% (1/1)100% (14/14)100% (4/4)
testParanoidEscapeRegex (): void 100% (1/1)100% (14/14)100% (4/4)
testRegexNormalization (): void 100% (1/1)100% (14/14)100% (4/4)
testRegexNormalizationBalancesCharGroups (): void 100% (1/1)100% (66/66)100% (16/16)

1// Copyright (C) 2007 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14 
15package com.google.caja.lexer.escaping;
16 
17import java.util.regex.Matcher;
18import java.util.regex.Pattern;
19import junit.framework.TestCase;
20 
21/**
22 * @author mikesamuel@gmail.com (Mike Samuel)
23 */
24public class EscapingTest extends TestCase {
25 
26  private static final String CHARS;
27  static {
28    StringBuilder sb = new StringBuilder(150);
29    for (int i = 0; i < 133; ++i) {
30      sb.append((char) i);
31    }
32    sb.append('\u200E')  // [:Cf:] LRM
33        .append('\u200F')  // [:Cf:] RLM
34        .append('\u2010')  // Regular non-ascii codepoint
35        .append('\u2028')  // newline
36        .append('\u2029')  // newline
37        .appendCodePoint(0x1D120)  // Regular supplemental
38        .appendCodePoint(0x1D177);  // [:Cf:]
39    CHARS = sb.toString();
40  }
41  private static final String WORD_CHARS;
42  static {
43    StringBuilder firstAndLastCodepage = new StringBuilder();
44    for (int i = 0; i < 256; ++i) {
45      firstAndLastCodepage.append((char) i);
46    }
47    for (int i = 0xff00; i < 0xffff; ++i) {
48      firstAndLastCodepage.append((char) i);
49    }
50 
51    StringBuilder sb = new StringBuilder();
52    Matcher m = Pattern.compile("[\\p{javaLetterOrDigit}_$]+")
53        .matcher(firstAndLastCodepage);
54    while (m.find()) {
55      sb.append(m.group());
56    }
57    WORD_CHARS = sb.toString();
58  }
59 
60  public final void testMinimalEscapeJsString() {
61    StringBuilder sb = new StringBuilder();
62    Escaping.escapeJsString(CHARS, false, false, sb);
63    assertStringsEqual(
64        ("\\x00\001\002\003\004\005\006\007\\b\t\\n\013\014\\r\016\017"
65         + "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
66         + " !\\\"#$%&\\'()*+,-./"
67         + "0123456789:;<=>?"
68         + "@ABCDEFGHIJKLMNO"
69         + "PQRSTUVWXYZ[\\\\]^_"
70         + "`abcdefghijklmno"
71         + "pqrstuvwxyz{|}~\177"
72         + "\u0080\u0081\u0082\u0083\u0084"
73         + "\\u200e\\u200f\u2010\\u2028\\u2029"
74         + "\ud834\udd20"
75         + "\\ud834\\udd77"
76         ),
77        sb.toString());
78    // Disallowed in strings in Firefox2
79    assertJsEscaped("\\u200c\\u200d\\u200e\\u200f", "\u200C\u200D\u200E\u200F");
80    assertJsEscaped(
81        "\\u202a\\u202b\\u202c\\u202d\\u202e",
82        "\u202A\u202B\u202C\u202D\u202E");
83    assertJsEscaped(
84        "\\u206b\\u206c\\u206d\\u206e\\u206f",
85        "\u206B\u206C\u206D\u206E\u206F");
86    assertJsEscaped("\\ufeff", "\uFEFF");
87    // Disallowed in strings in IE6
88    assertJsEscaped(
89        "\\ufdd0\\ufdd1\\ufdd2\\ufdd3\\ufdd4\\ufdd5\\ufdd6\\ufdd7"
90        + "\\ufdd8\\ufdd9\\ufdda\\ufddb\\ufddc\\ufddd\\ufdde\\ufddf",
91        "\uFDD0\uFDD1\uFDD2\uFDD3\uFDD4\uFDD5\uFDD6\uFDD7"
92        + "\uFDD8\uFDD9\uFDDA\uFDDB\uFDDC\uFDDD\uFDDE\uFDDF");
93    assertJsEscaped(
94        "\\ufde0\\ufde1\\ufde2\\ufde3\\ufde4\\ufde5\\ufde6\\ufde7"
95        + "\\ufde8\\ufde9\\ufdea\\ufdeb\\ufdec\\ufded\\ufdee\\ufdef",
96        "\uFDE0\uFDE1\uFDE2\uFDE3\uFDE4\uFDE5\uFDE6\uFDE7"
97        + "\uFDE8\uFDE9\uFDEA\uFDEB\uFDEC\uFDED\uFDEE\uFDEF");
98    assertJsEscaped(
99        "\\ufff0\\ufff1\\ufff2\\ufff3\\ufff4\\ufff5\\ufff6\\ufff7"
100        + "\\ufff8\\ufffe\\uffff",
101        "\uFFF0\uFFF1\uFFF2\uFFF3\uFFF4\uFFF5\uFFF6\uFFF7"
102        + "\uFFF8\uFFFE\uFFFF");
103  }
104  private static void assertJsEscaped(String golden, String raw) {
105    StringBuilder sb = new StringBuilder();
106    Escaping.escapeJsString(raw, false, false, sb);
107    assertStringsEqual(golden, sb.toString());
108  }
109 
110  public final void testParanoidEscapeJsString() {
111    StringBuilder sb = new StringBuilder();
112    Escaping.escapeJsString(CHARS, false, true, sb);
113    assertStringsEqual(
114        (// all ctrl chars escaped
115         "\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07"
116         + "\\b\\t\\n\\x0b\\f\\r\\x0e\\x0f"
117         + "\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17"
118         + "\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"
119         + " !\\\"#$%\\x26\\'()*+,-./"  // & escaped
120         + "0123456789:;\\x3c=\\x3e?"  // < and > escaped
121         + "@ABCDEFGHIJKLMNO"
122         + "PQRSTUVWXYZ[\\\\]^_"
123         + "`abcdefghijklmno"
124         + "pqrstuvwxyz{|}~\177"
125         + "\u0080\u0081\u0082\u0083\u0084"
126         + "\\u200e\\u200f\u2010\\u2028\\u2029"
127         + "\ud834\udd20"
128         + "\\ud834\\udd77"
129         ),
130        sb.toString());
131  }
132 
133  public final void testEscapeJsonString() {
134    StringBuilder sb = new StringBuilder();
135    Escaping.escapeJsonString(CHARS, false, sb);
136    // JSON doesn't allow \x escapes, or \' as an escape sequence.
137    assertStringsEqual(
138        (// all ctrl chars escaped
139         "\\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007"
140         + "\\b\\t\\n\u000b\\f\\r\u000e\u000f"
141         + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"
142         + "\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"
143         + " !\\\"#$%\u0026\\u0027()*+,-./"  // & escaped
144         + "0123456789:;\u003c=\u003e?"  // < and > escaped
145         + "@ABCDEFGHIJKLMNO"
146         + "PQRSTUVWXYZ[\\\\]^_"
147         + "`abcdefghijklmno"
148         + "pqrstuvwxyz{|}~\177"
149         + "\u0080\u0081\u0082\u0083\u0084"
150         + "\\u200e\\u200f\u2010\\u2028\\u2029"
151         + "\ud834\udd20"
152         + "\\ud834\\udd77"
153         ),
154        sb.toString());
155  }
156 
157  public final void testAsciiOnlyEscapeJsString() {
158    StringBuilder sb = new StringBuilder();
159    Escaping.escapeJsString(CHARS, true, false, sb);
160    assertStringsEqual(
161        ("\\x00\001\002\003\004\005\006\007\\b\t\\n\013\014\\r\016\017"
162         + "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
163         + " !\\\"#$%&\\'()*+,-./"
164         + "0123456789:;<=>?"
165         + "@ABCDEFGHIJKLMNO"
166         + "PQRSTUVWXYZ[\\\\]^_"
167         + "`abcdefghijklmno"
168         + "pqrstuvwxyz{|}~\\x7f"  // All chars >= 0x7f escaped
169         + "\\x80\\x81\\x82\\x83\\x84"
170         + "\\u200e\\u200f\\u2010\\u2028\\u2029"
171         + "\\ud834\\udd20"
172         + "\\ud834\\udd77"
173         ),
174        sb.toString());
175  }
176 
177  public final void testParanoidAsciiOnlyEscapeJsString() {
178    StringBuilder sb = new StringBuilder();
179    Escaping.escapeJsString(CHARS, true, true, sb);
180    assertStringsEqual(
181        ("\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07"
182         + "\\b\\t\\n\\x0b\\f\\r\\x0e\\x0f"
183         + "\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17"
184         + "\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"
185         + " !\\\"#$%\\x26\\'()*+,-./"
186         + "0123456789:;\\x3c=\\x3e?"
187         + "@ABCDEFGHIJKLMNO"
188         + "PQRSTUVWXYZ[\\\\]^_"
189         + "`abcdefghijklmno"
190         + "pqrstuvwxyz{|}~\\x7f"
191         + "\\x80\\x81\\x82\\x83\\x84"
192         + "\\u200e\\u200f\\u2010\\u2028\\u2029"
193         + "\\ud834\\udd20"
194         + "\\ud834\\udd77"
195         ),
196        sb.toString());
197  }
198 
199  public final void testIdentifierEscaping() {
200    StringBuilder sb = new StringBuilder();
201    Escaping.escapeJsIdentifier(WORD_CHARS, true, sb);
202    assertStringsEqual(
203        (// all ctrl chars escaped
204         "$0123456789"
205         + "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
206         + "abcdefghijklmnopqrstuvwxyz"
207         + "\\u00aa\\u00b5\\u00ba"
208         + "\\u00c0\\u00c1\\u00c2\\u00c3\\u00c4\\u00c5\\u00c6\\u00c7"
209         + "\\u00c8\\u00c9\\u00ca\\u00cb\\u00cc\\u00cd\\u00ce\\u00cf"
210         + "\\u00d0\\u00d1\\u00d2\\u00d3\\u00d4\\u00d5\\u00d6"
211         + "\\u00d8\\u00d9\\u00da\\u00db\\u00dc\\u00dd\\u00de\\u00df"
212         + "\\u00e0\\u00e1\\u00e2\\u00e3\\u00e4\\u00e5\\u00e6\\u00e7"
213         + "\\u00e8\\u00e9\\u00ea\\u00eb\\u00ec\\u00ed\\u00ee\\u00ef"
214         + "\\u00f0\\u00f1\\u00f2\\u00f3\\u00f4\\u00f5\\u00f6"
215         + "\\u00f8\\u00f9\\u00fa\\u00fb\\u00fc\\u00fd\\u00fe\\u00ff"
216         + "\\uff10\\uff11\\uff12\\uff13\\uff14\\uff15\\uff16\\uff17"
217         + "\\uff18\\uff19"
218         + "\\uff21\\uff22\\uff23\\uff24\\uff25\\uff26\\uff27"
219         + "\\uff28\\uff29\\uff2a\\uff2b\\uff2c\\uff2d\\uff2e\\uff2f"
220         + "\\uff30\\uff31\\uff32\\uff33\\uff34\\uff35\\uff36\\uff37"
221         + "\\uff38\\uff39\\uff3a"
222         + "\\uff41\\uff42\\uff43\\uff44\\uff45\\uff46\\uff47"
223         + "\\uff48\\uff49\\uff4a\\uff4b\\uff4c\\uff4d\\uff4e\\uff4f"
224         + "\\uff50\\uff51\\uff52\\uff53\\uff54\\uff55\\uff56\\uff57"
225         + "\\uff58\\uff59\\uff5a"
226         + "\\uff66\\uff67"
227         + "\\uff68\\uff69\\uff6a\\uff6b\\uff6c\\uff6d\\uff6e\\uff6f"
228         + "\\uff70\\uff71\\uff72\\uff73\\uff74\\uff75\\uff76\\uff77"
229         + "\\uff78\\uff79\\uff7a\\uff7b\\uff7c\\uff7d\\uff7e\\uff7f"
230         + "\\uff80\\uff81\\uff82\\uff83\\uff84\\uff85\\uff86\\uff87"
231         + "\\uff88\\uff89\\uff8a\\uff8b\\uff8c\\uff8d\\uff8e\\uff8f"
232         + "\\uff90\\uff91\\uff92\\uff93\\uff94\\uff95\\uff96\\uff97"
233         + "\\uff98\\uff99\\uff9a\\uff9b\\uff9c\\uff9d\\uff9e\\uff9f"
234         + "\\uffa0\\uffa1\\uffa2\\uffa3\\uffa4\\uffa5\\uffa6\\uffa7"
235         + "\\uffa8\\uffa9\\uffaa\\uffab\\uffac\\uffad\\uffae\\uffaf"
236         + "\\uffb0\\uffb1\\uffb2\\uffb3\\uffb4\\uffb5\\uffb6\\uffb7"
237         + "\\uffb8\\uffb9\\uffba\\uffbb\\uffbc\\uffbd\\uffbe"
238         + "\\uffc2\\uffc3\\uffc4\\uffc5\\uffc6\\uffc7"
239         + "\\uffca\\uffcb\\uffcc\\uffcd\\uffce\\uffcf"
240         + "\\uffd2\\uffd3\\uffd4\\uffd5\\uffd6\\uffd7"
241         + "\\uffda\\uffdb\\uffdc"
242         ),
243        sb.toString());
244  }
245 
246 
247  public final void testMinimalEscapeRegex() {
248    StringBuilder sb = new StringBuilder();
249    Escaping.escapeRegex(CHARS, false, false, sb);
250    assertStringsEqual(
251        ("\\x00\001\002\003\004\005\006\007\\b\t\\n\013\014\\r\016\017"
252         + "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
253         // quotes unescaped.  regex specials escaped
254         + " !\"#\\$%&'\\(\\)\\*\\+,-\\.\\/"
255         + "0123456789:;<=>\\?"
256         + "@ABCDEFGHIJKLMNO"
257         + "PQRSTUVWXYZ\\[\\\\\\]\\^_"
258         + "`abcdefghijklmno"
259         + "pqrstuvwxyz\\{\\|\\}~\177"
260         + "\u0080\u0081\u0082\u0083\u0084"
261         + "\\u200e\\u200f\u2010\\u2028\\u2029"
262         + "\ud834\udd20"
263         + "\\ud834\\udd77"
264         ),
265        sb.toString());
266  }
267 
268  public final void testParanoidEscapeRegex() {
269    StringBuilder sb = new StringBuilder();
270    Escaping.escapeRegex(CHARS, false, true, sb);
271    assertStringsEqual(
272        (// all ctrl chars escaped
273         "\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07"
274         + "\\b\\t\\n\\x0b\\f\\r\\x0e\\x0f"
275         + "\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17"
276         + "\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"
277         + " !\"#\\$%\\x26'\\(\\)\\*\\+,-\\.\\/"
278         + "0123456789:;\\x3c=\\x3e\\?"
279         + "@ABCDEFGHIJKLMNO"
280         + "PQRSTUVWXYZ\\[\\\\\\]\\^_"
281         + "`abcdefghijklmno"
282         + "pqrstuvwxyz\\{\\|\\}~\177"
283         + "\u0080\u0081\u0082\u0083\u0084"
284         + "\\u200e\\u200f\u2010\\u2028\\u2029"
285         + "\ud834\udd20"
286         + "\\ud834\\udd77"
287         ),
288        sb.toString());
289  }
290 
291  public final void testRegexNormalization() {
292    StringBuilder sb = new StringBuilder();
293    Escaping.normalizeRegex(
294        "<Foo+\\> \u2028 \\\\Ba*r \r Baz\\+\\+", false, true, sb);
295    assertStringsEqual(
296        "\\x3cFoo+\\x3e \\u2028 \\\\Ba*r \\r Baz\\+\\+", sb.toString());
297  }
298 
299  public final void testRegexNormalizationBalancesCharGroups() {
300    // Make sure that the normalized regex always has balanced [...] blocks
301    // since / in those are not considered as closing the token.
302    {
303      StringBuilder sb = new StringBuilder();
304      Escaping.normalizeRegex("[", false, true, sb);
305      assertStringsEqual("\\[", sb.toString());
306    }
307 
308    {
309      StringBuilder sb = new StringBuilder();
310      Escaping.normalizeRegex("[a-z][foo", false, true, sb);
311      assertStringsEqual("[a-z]\\[foo", sb.toString());
312    }
313 
314    {
315      StringBuilder sb = new StringBuilder();
316      Escaping.normalizeRegex("[a-z][[foo]", false, true, sb);
317      assertStringsEqual("[a-z][\\[foo]", sb.toString());
318    }
319 
320    {
321      StringBuilder sb = new StringBuilder();
322      Escaping.normalizeRegex("[a-z][[foo", false, true, sb);
323      assertStringsEqual("[a-z]\\[\\[foo", sb.toString());
324    }
325 
326    {
327      StringBuilder sb = new StringBuilder();
328      Escaping.normalizeRegex("[a-z][[foo[", false, true, sb);
329      assertStringsEqual("[a-z]\\[\\[foo\\[", sb.toString());
330    }
331  }
332 
333  public final void testEscapeXml() {
334    StringBuilder sb = new StringBuilder();
335    Escaping.escapeXml(CHARS, false, sb);
336    assertStringsEqual(
337        (// all ctrl chars escaped
338         "&#0;&#1;&#2;&#3;&#4;&#5;&#6;&#7;"
339         + "&#8;\t\n&#11;&#12;\r&#14;&#15;"
340         + "&#16;&#17;&#18;&#19;&#20;&#21;&#22;&#23;"
341         + "&#24;&#25;&#26;&#27;&#28;&#29;&#30;&#31;"
342         + " !&#34;#$%&amp;&#39;()*+,-./"
343         + "0123456789:;&lt;=&gt;?"
344         + "@ABCDEFGHIJKLMNO"
345         + "PQRSTUVWXYZ[\\]^_"
346         + "&#96;abcdefghijklmno"
347         + "pqrstuvwxyz{|}~&#127;"
348         + "&#128;&#129;&#130;&#131;&#132;"
349         + "\u200e\u200f\u2010\u2028\u2029"
350         + "\ud834\udd20"
351         + "\ud834\udd77"
352         ),
353        sb.toString());
354  }
355 
356  public final void testEscapeXmlAsciiOnly() {
357    StringBuilder sb = new StringBuilder();
358    Escaping.escapeXml(CHARS, true, sb);
359    assertStringsEqual(
360        (// all ctrl chars escaped
361         "&#0;&#1;&#2;&#3;&#4;&#5;&#6;&#7;"
362         + "&#8;\t\n&#11;&#12;\r&#14;&#15;"
363         + "&#16;&#17;&#18;&#19;&#20;&#21;&#22;&#23;"
364         + "&#24;&#25;&#26;&#27;&#28;&#29;&#30;&#31;"
365         + " !&#34;#$%&amp;&#39;()*+,-./"
366         + "0123456789:;&lt;=&gt;?"
367         + "@ABCDEFGHIJKLMNO"
368         + "PQRSTUVWXYZ[\\]^_"
369         + "&#96;abcdefghijklmno"
370         + "pqrstuvwxyz{|}~&#127;"
371         + "&#128;&#129;&#130;&#131;&#132;"
372         + "&#8206;&#8207;&#8208;&#8232;&#8233;"
373         // Surrogate pairs are escaped by code-point, not code-unit.
374         + "&#119072;"
375         + "&#119159;"
376         ),
377        sb.toString());
378  }
379 
380  public final void testEscapeCssString() {
381    StringBuilder sb;
382 
383    sb = new StringBuilder();
384    Escaping.escapeCssString(CHARS, sb);
385    assertStringsEqual(
386        ("\\0\\1\\2\\3\\4\\5\\6\\7"
387         + "\\8 \\9 \\A\\B \\C \\D\\E\\F"
388         + "\\10\\11\\12\\13\\14\\15\\16\\17"
389         + "\\18\\19\\1A\\1B\\1C\\1D\\1E\\1F "
390         + " !\\22#$%&\\27\\28\\29\\2A\\2B\\2C-./"
391         + "0123456789:\\3B\\3C=\\3E?"
392         + "\\40 ABCDEFGHIJKLMNO"
393         + "PQRSTUVWXYZ\\5B\\5C\\5D^_"
394         + "`abcdefghijklmno"
395         + "pqrstuvwxyz\\7B\\7C\\7D~\\7F"
396         + "\\80\\81\\82\\83\\84"
397         + "\\200E\\200F\\2010\\2028\\2029"
398         + "\\D834\\DD20"
399         + "\\D834\\DD77 "
400         ),
401        sb.toString());
402 
403    sb = new StringBuilder();
404    Escaping.escapeCssString("<foo>", sb);
405    assertStringsEqual("\\3C foo\\3E ", sb.toString());
406 
407    sb = new StringBuilder();
408    Escaping.escapeCssString("<Bar>", sb);
409    assertStringsEqual("\\3C Bar\\3E ", sb.toString());
410 
411    sb = new StringBuilder();
412    Escaping.escapeCssString("<ZZZ>", sb);
413    assertStringsEqual("\\3CZZZ\\3E ", sb.toString());
414  }
415 
416  public final void testEscapeCssIdent() {
417    StringBuilder sb;
418 
419    sb = new StringBuilder();
420    Escaping.escapeCssIdent(CHARS, sb);
421    assertStringsEqual(
422        ("\\0\\1\\2\\3\\4\\5\\6\\7"
423         + "\\8 \\9 \\A\\B \\C \\D\\E\\F"
424         + "\\10\\11\\12\\13\\14\\15\\16\\17"
425         + "\\18\\19\\1A\\1B\\1C\\1D\\1E\\1F "
426         + "\\20\\21\\22\\23\\24\\25\\26\\27"
427         + "\\28\\29\\2A\\2B\\2C-\\2E\\2F "
428         + "0123456789\\3A\\3B\\3C\\3D\\3E\\3F"
429         + "\\40 ABCDEFGHIJKLMNO"
430         + "PQRSTUVWXYZ\\5B\\5C\\5D\\5E_"
431         + "\\60 abcdefghijklmno"
432         + "pqrstuvwxyz\\7B\\7C\\7D\\7E\\7F"
433         + "\\80\\81\\82\\83\\84"
434         + "\\200E\\200F\\2010\\2028\\2029"
435         + "\\D834\\DD20"
436         + "\\D834\\DD77 "
437         ),
438        sb.toString());
439 
440    sb = new StringBuilder();
441    Escaping.escapeCssIdent("foo-bar", sb);
442    assertStringsEqual("foo-bar", sb.toString());
443 
444    sb = new StringBuilder();
445    Escaping.escapeCssIdent("fo o", sb);
446    assertStringsEqual("fo\\20o", sb.toString());
447 
448    sb = new StringBuilder();
449    Escaping.escapeCssIdent("0foo", sb);
450    assertStringsEqual("\\30 foo", sb.toString());
451 
452    sb = new StringBuilder();
453    Escaping.escapeCssIdent("0zoicks", sb);
454    assertStringsEqual("\\30zoicks", sb.toString());
455 
456    sb = new StringBuilder();
457    Escaping.escapeCssIdent("4", sb);
458    assertStringsEqual("\\34 ", sb.toString());
459  }
460 
461  public static void testEscapeUri() {
462    StringBuilder sb;
463 
464    sb = new StringBuilder();
465    Escaping.escapeUri("", sb);
466    assertEquals("", sb.toString());
467 
468    sb = new StringBuilder();
469    Escaping.escapeUri("foo", sb);
470    assertEquals("foo", sb.toString());
471 
472    sb = new StringBuilder();
473    Escaping.escapeUri("FOO", sb);
474    assertEquals("FOO", sb.toString());
475 
476    // All of the reserved characters must be encoded.
477    sb = new StringBuilder();
478    Escaping.escapeUri(":/?#[]@!$&'()*+,;=", sb);
479    assertEquals(
480        "%3a%2f%3f%23%5b%5d%40%21%24%26%27%28%29%2a%2b%2c%3b%3d",
481        sb.toString());
482 
483    sb = new StringBuilder();
484    Escaping.escapeUri(CHARS, sb);
485    assertEquals(
486        ""
487        + "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f"
488        + "%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f"
489        // %20, not + since that is not valid in non-hierarchical URIs.
490        + "%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f"
491        + "0123456789%3a%3b%3c%3d%3e%3f"
492        + "%40ABCDEFGHIJKLMNO"
493        + "PQRSTUVWXYZ%5b%5c%5d%5e_"
494        + "%60abcdefghijklmno"
495        + "pqrstuvwxyz%7b%7c%7d~%7f"
496        + "%c2%80%c2%81%c2%82%c2%83%c2%84"
497        + "%e2%80%8e%e2%80%8f%e2%80%90%e2%80%a8%e2%80%a9"
498        + "%ed%a0%b4%ed%b4%a0%ed%a0%b4%ed%b5%b7",
499        sb.toString());
500  }
501 
502  private static void assertStringsEqual(String a, String b) {
503    if (a.equals(b)) { return; }
504    int m = a.length(), n = b.length();
505    int min = Math.min(m, n);
506 
507    int commonPrefix = 0;
508    while (commonPrefix < min
509           && a.charAt(commonPrefix) == b.charAt(commonPrefix)) {
510      ++commonPrefix;
511    }
512 
513    int commonSuffix = 0;
514    while (commonSuffix < (min - commonPrefix)
515           && a.charAt(m - commonSuffix - 1) == b.charAt(n - commonSuffix - 1)
516           ) {
517      ++commonSuffix;
518    }
519 
520    int msgPrefix = Math.max(0, commonPrefix - 2);
521    int msgSuffix = Math.max(0, commonSuffix - 2);
522    fail(diagnosticString(a, msgPrefix, m - msgSuffix) + " != " +
523         diagnosticString(b, msgPrefix, n - msgSuffix));
524  }
525 
526  private static String diagnosticString(String s, int start, int end) {
527    StringBuilder sb = new StringBuilder(end - start + 16);
528    if (start != 0) { sb.append("..."); }
529    for (int i = start; i < end; ++i) {
530      char ch = s.charAt(i);
531      if (ch >= 0x20 && ch < 0x7f) {
532        sb.append(ch);
533      } else {
534        sb.append('{').append(Integer.toString(ch, 16)).append('}');
535      }
536    }
537    if (end < s.length()) { sb.append("..."); }
538    return sb.toString();
539  }
540}

[all classes][com.google.caja.lexer.escaping]
EMMA 2.0.5312 (C) Vladimir Roubtsov