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 */ 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 */ 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 */ 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. */ 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 */ 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 */ 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 */ 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 */ 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