• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.net;
18 
19 import static com.google.common.escape.testing.EscaperAsserts.assertEscaping;
20 import static com.google.common.escape.testing.EscaperAsserts.assertUnescaped;
21 import static com.google.common.escape.testing.EscaperAsserts.assertUnicodeEscaping;
22 
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.base.Preconditions;
25 import com.google.common.escape.UnicodeEscaper;
26 
27 import junit.framework.TestCase;
28 
29 /**
30  * Tests for {@link PercentEscaper}.
31  *
32  * @author David Beaumont
33  */
34 @GwtCompatible
35 public class PercentEscaperTest extends TestCase {
36 
37   /** Tests that the simple escaper treats 0-9, a-z and A-Z as safe */
testSimpleEscaper()38   public void testSimpleEscaper() {
39     UnicodeEscaper e = new PercentEscaper("", false);
40     for (char c = 0; c < 128; c++) {
41       if ((c >= '0' && c <= '9') ||
42           (c >= 'a' && c <= 'z') ||
43           (c >= 'A' && c <= 'Z')) {
44         assertUnescaped(e, c);
45       } else {
46         assertEscaping(e, escapeAscii(c), c);
47       }
48     }
49 
50     // Testing mutlibyte escape sequences
51     assertEscaping(e, "%00", '\u0000');       // nul
52     assertEscaping(e, "%7F", '\u007f');       // del
53     assertEscaping(e, "%C2%80", '\u0080');    // xx-00010,x-000000
54     assertEscaping(e, "%DF%BF", '\u07ff');    // xx-11111,x-111111
55     assertEscaping(e, "%E0%A0%80", '\u0800'); // xxx-0000,x-100000,x-00,0000
56     assertEscaping(e, "%EF%BF%BF", '\uffff'); // xxx-1111,x-111111,x-11,1111
57     assertUnicodeEscaping(e, "%F0%90%80%80", '\uD800', '\uDC00');
58     assertUnicodeEscaping(e, "%F4%8F%BF%BF", '\uDBFF', '\uDFFF');
59 
60     // simple string tests
61     assertEquals("", e.escape(""));
62     assertEquals("safestring", e.escape("safestring"));
63     assertEquals("embedded%00null", e.escape("embedded\0null"));
64     assertEquals("max%EF%BF%BFchar", e.escape("max\uffffchar"));
65   }
66 
67   /** Tests the various ways that the space character can be handled */
testPlusForSpace()68   public void testPlusForSpace() {
69     UnicodeEscaper basicEscaper = new PercentEscaper("", false);
70     UnicodeEscaper plusForSpaceEscaper = new PercentEscaper("", true);
71     UnicodeEscaper spaceEscaper = new PercentEscaper(" ", false);
72 
73     assertEquals("string%20with%20spaces",
74         basicEscaper.escape("string with spaces"));
75     assertEquals("string+with+spaces",
76         plusForSpaceEscaper.escape("string with spaces"));
77     assertEquals("string with spaces",
78         spaceEscaper.escape("string with spaces"));
79   }
80 
81   /** Tests that if we add extra 'safe' characters they remain unescaped */
testCustomEscaper()82   public void testCustomEscaper() {
83     UnicodeEscaper e = new PercentEscaper("+*/-", false);
84     for (char c = 0; c < 128; c++) {
85       if ((c >= '0' && c <= '9') ||
86           (c >= 'a' && c <= 'z') ||
87           (c >= 'A' && c <= 'Z') ||
88           "+*/-".indexOf(c) >= 0) {
89         assertUnescaped(e, c);
90       } else {
91         assertEscaping(e, escapeAscii(c), c);
92       }
93     }
94   }
95 
96   /** Tests that if specify '%' as safe the result is an idempotent escaper. */
testCustomEscaper_withpercent()97   public void testCustomEscaper_withpercent() {
98     UnicodeEscaper e = new PercentEscaper("%", false);
99     assertEquals("foo%7Cbar", e.escape("foo|bar"));
100     assertEquals("foo%7Cbar", e.escape("foo%7Cbar"));  // idempotent
101   }
102 
103   /**
104    * Test that giving a null 'safeChars' string causes a
105    * {@link NullPointerException}.
106    */
testBadArguments_null()107   public void testBadArguments_null() {
108     try {
109       new PercentEscaper(null, false);
110       fail("Expected null pointer exception for null parameter");
111     } catch (NullPointerException expected) {
112       // pass
113     }
114   }
115 
116   /**
117    * Tests that specifying any alphanumeric characters as 'safe' causes an
118    * {@link IllegalArgumentException}.
119    */
testBadArguments_badchars()120   public void testBadArguments_badchars() {
121     String msg = "Alphanumeric characters are always 'safe' " +
122         "and should not be explicitly specified";
123     try {
124       new PercentEscaper("-+#abc.!", false);
125       fail(msg);
126     } catch (IllegalArgumentException expected) {
127       assertEquals(msg, expected.getMessage());
128     }
129   }
130 
131   /**
132    * Tests that if space is a safe character you cannot also specify
133    * 'plusForSpace' (throws {@link IllegalArgumentException}).
134    */
testBadArguments_plusforspace()135   public void testBadArguments_plusforspace() {
136     try {
137       new PercentEscaper(" ", false);
138     } catch (IllegalArgumentException e) {
139       fail("Space can be a 'safe' character if plusForSpace is false");
140     }
141     String msg =
142         "plusForSpace cannot be specified when space is a 'safe' character";
143     try {
144       new PercentEscaper(" ", true);
145       fail(msg);
146     } catch (IllegalArgumentException expected) {
147       assertEquals(msg, expected.getMessage());
148     }
149   }
150 
151   /** Helper to manually escape a 7-bit ascii character */
escapeAscii(char c)152   private String escapeAscii(char c) {
153     Preconditions.checkArgument(c < 128);
154     String hex = "0123456789ABCDEF";
155     return "%" + hex.charAt((c >> 4) & 0xf) + hex.charAt(c & 0xf);
156   }
157 }
158