View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.codec.net;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertNull;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  
24  import java.nio.charset.StandardCharsets;
25  
26  import org.apache.commons.codec.CharEncoding;
27  import org.apache.commons.codec.DecoderException;
28  import org.apache.commons.codec.EncoderException;
29  import org.junit.jupiter.api.Test;
30  
31  /**
32   * URL codec test cases
33   */
34  public class URLCodecTest {
35  
36      static final int SWISS_GERMAN_STUFF_UNICODE[] = { 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4 };
37  
38      static final int RUSSIAN_STUFF_UNICODE[] = { 0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438, 0x432, 0x435, 0x442 };
39  
40      private String constructString(final int[] unicodeChars) {
41          final StringBuilder buffer = new StringBuilder();
42          if (unicodeChars != null) {
43              for (final int unicodeChar : unicodeChars) {
44                  buffer.append((char) unicodeChar);
45              }
46          }
47          return buffer.toString();
48      }
49  
50      @Test
51      public void testBasicEncodeDecode() throws Exception {
52          final URLCodec urlCodec = new URLCodec();
53          final String plain = "Hello there!";
54          final String encoded = urlCodec.encode(plain);
55          assertEquals("Hello+there%21", encoded, "Basic URL encoding test");
56          assertEquals(plain, urlCodec.decode(encoded), "Basic URL decoding test");
57          this.validateState(urlCodec);
58      }
59  
60      @Test
61      public void testDecodeInvalid() throws Exception {
62          final URLCodec urlCodec = new URLCodec();
63          assertThrows(DecoderException.class, () -> urlCodec.decode("%"));
64          assertThrows(DecoderException.class, () -> urlCodec.decode("%A"));
65          // Bad 1st char after %
66          assertThrows(DecoderException.class, () -> urlCodec.decode("%WW"));
67          // Bad 2nd char after %
68          assertThrows(DecoderException.class, () -> urlCodec.decode("%0W"));
69          this.validateState(urlCodec);
70      }
71  
72      @Test
73      public void testDecodeInvalidContent() throws DecoderException {
74          final String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE);
75          final URLCodec urlCodec = new URLCodec();
76          final byte[] input = ch_msg.getBytes(StandardCharsets.ISO_8859_1);
77          final byte[] output = urlCodec.decode(input);
78          assertEquals(input.length, output.length);
79          for (int i = 0; i < input.length; i++) {
80              assertEquals(input[i], output[i]);
81          }
82          this.validateState(urlCodec);
83      }
84  
85      @Test
86      public void testDecodeObjects() throws Exception {
87          final URLCodec urlCodec = new URLCodec();
88          final String plain = "Hello+there%21";
89          String decoded = (String) urlCodec.decode((Object) plain);
90          assertEquals("Hello there!", decoded, "Basic URL decoding test");
91          final byte[] plainBA = plain.getBytes(StandardCharsets.UTF_8);
92          final byte[] decodedBA = (byte[]) urlCodec.decode((Object) plainBA);
93          decoded = new String(decodedBA);
94          assertEquals("Hello there!", decoded, "Basic URL decoding test");
95          final Object result = urlCodec.decode((Object) null);
96  
97          assertNull(result, "Decoding a null Object should return null");
98  
99          assertThrows(DecoderException.class, () -> urlCodec.decode(Double.valueOf(3.0d)), "Trying to url encode a Double object should cause an exception.");
100         this.validateState(urlCodec);
101     }
102 
103     @Test
104     public void testDecodeStringWithNull() throws Exception {
105         final URLCodec urlCodec = new URLCodec();
106         final String test = null;
107         final String result = urlCodec.decode(test, "charset");
108         assertNull(result, "Result should be null");
109     }
110 
111     @Test
112     public void testDecodeWithNullArray() throws Exception {
113         final byte[] plain = null;
114         final byte[] result = URLCodec.decodeUrl(plain);
115         assertNull(result, "Result should be null");
116     }
117 
118     @Test
119     public void testDefaultEncoding() throws Exception {
120         final String plain = "Hello there!";
121         final URLCodec urlCodec = new URLCodec("UnicodeBig");
122         urlCodec.encode(plain); // To work around a weird quirk in Java 1.2.2
123         final String encoded1 = urlCodec.encode(plain, "UnicodeBig");
124         final String encoded2 = urlCodec.encode(plain);
125         assertEquals(encoded1, encoded2);
126         this.validateState(urlCodec);
127     }
128 
129     @Test
130     public void testEncodeDecodeNull() throws Exception {
131         final URLCodec urlCodec = new URLCodec();
132         assertNull(urlCodec.encode((String) null), "Null string URL encoding test");
133         assertNull(urlCodec.decode((String) null), "Null string URL decoding test");
134         this.validateState(urlCodec);
135     }
136 
137     @Test
138     public void testEncodeNull() throws Exception {
139         final URLCodec urlCodec = new URLCodec();
140         final byte[] plain = null;
141         final byte[] encoded = urlCodec.encode(plain);
142         assertNull(encoded, "Encoding a null string should return null");
143         this.validateState(urlCodec);
144     }
145 
146     @Test
147     public void testEncodeObjects() throws Exception {
148         final URLCodec urlCodec = new URLCodec();
149         final String plain = "Hello there!";
150         String encoded = (String) urlCodec.encode((Object) plain);
151         assertEquals("Hello+there%21", encoded, "Basic URL encoding test");
152 
153         final byte[] plainBA = plain.getBytes(StandardCharsets.UTF_8);
154         final byte[] encodedBA = (byte[]) urlCodec.encode((Object) plainBA);
155         encoded = new String(encodedBA);
156         assertEquals("Hello+there%21", encoded, "Basic URL encoding test");
157 
158         final Object result = urlCodec.encode((Object) null);
159         assertNull(result, "Encoding a null Object should return null");
160 
161         assertThrows(EncoderException.class, () -> urlCodec.encode(Double.valueOf(3.0d)), "Trying to url encode a Double object should cause an exception.");
162         this.validateState(urlCodec);
163     }
164 
165     @Test
166     public void testEncodeStringWithNull() throws Exception {
167         final URLCodec urlCodec = new URLCodec();
168         final String test = null;
169         final String result = urlCodec.encode(test, "charset");
170         assertNull(result, "Result should be null");
171     }
172 
173     @Test
174     public void testEncodeUrlWithNullBitSet() throws Exception {
175         final URLCodec urlCodec = new URLCodec();
176         final String plain = "Hello there!";
177         final String encoded = new String(URLCodec.encodeUrl(null, plain.getBytes(StandardCharsets.UTF_8)));
178         assertEquals("Hello+there%21", encoded, "Basic URL encoding test");
179         assertEquals(plain, urlCodec.decode(encoded), "Basic URL decoding test");
180         this.validateState(urlCodec);
181     }
182 
183     @Test
184     public void testInvalidEncoding() {
185         final URLCodec urlCodec = new URLCodec("NONSENSE");
186         final String plain = "Hello there!";
187         assertThrows(EncoderException.class, () -> urlCodec.encode(plain), "We set the encoding to a bogus NONSENSE value");
188         assertThrows(DecoderException.class, () -> urlCodec.decode(plain), "We set the encoding to a bogus NONSENSE value");
189         this.validateState(urlCodec);
190     }
191 
192     @Test
193     public void testSafeCharEncodeDecode() throws Exception {
194         final URLCodec urlCodec = new URLCodec();
195         final String plain = "abc123_-.*";
196         final String encoded = urlCodec.encode(plain);
197         assertEquals(plain, encoded, "Safe chars URL encoding test");
198         assertEquals(plain, urlCodec.decode(encoded), "Safe chars URL decoding test");
199         this.validateState(urlCodec);
200     }
201 
202     @Test
203     public void testUnsafeEncodeDecode() throws Exception {
204         final URLCodec urlCodec = new URLCodec();
205         final String plain = "~!@#$%^&()+{}\"\\;:`,/[]";
206         final String encoded = urlCodec.encode(plain);
207         assertEquals("%7E%21%40%23%24%25%5E%26%28%29%2B%7B%7D%22%5C%3B%3A%60%2C%2F%5B%5D", encoded, "Unsafe chars URL encoding test");
208         assertEquals(plain, urlCodec.decode(encoded), "Unsafe chars URL decoding test");
209         this.validateState(urlCodec);
210     }
211 
212     @Test
213     public void testUTF8RoundTrip() throws Exception {
214 
215         final String ru_msg = constructString(RUSSIAN_STUFF_UNICODE);
216         final String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE);
217 
218         final URLCodec urlCodec = new URLCodec();
219         this.validateState(urlCodec);
220 
221         assertEquals("%D0%92%D1%81%D0%B5%D0%BC_%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82", urlCodec.encode(ru_msg, CharEncoding.UTF_8));
222         assertEquals("Gr%C3%BCezi_z%C3%A4m%C3%A4", urlCodec.encode(ch_msg, CharEncoding.UTF_8));
223 
224         assertEquals(ru_msg, urlCodec.decode(urlCodec.encode(ru_msg, CharEncoding.UTF_8), CharEncoding.UTF_8));
225         assertEquals(ch_msg, urlCodec.decode(urlCodec.encode(ch_msg, CharEncoding.UTF_8), CharEncoding.UTF_8));
226         this.validateState(urlCodec);
227     }
228 
229     private void validateState(final URLCodec urlCodec) {
230         // no tests for now.
231     }
232 }