View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.util;
29  
30  import java.io.ByteArrayInputStream;
31  import java.io.ByteArrayOutputStream;
32  import java.io.ObjectInputStream;
33  import java.io.ObjectOutputStream;
34  
35  import org.apache.http.Consts;
36  import org.junit.Assert;
37  import org.junit.Test;
38  
39  /**
40   * Unit tests for {@link ByteArrayBuffer}.
41   *
42   */
43  public class TestByteArrayBuffer {
44  
45      @Test
46      public void testConstructor() throws Exception {
47          final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
48          Assert.assertEquals(16, buffer.capacity());
49          Assert.assertEquals(0, buffer.length());
50          Assert.assertNotNull(buffer.buffer());
51          Assert.assertEquals(16, buffer.buffer().length);
52          try {
53              new ByteArrayBuffer(-1);
54              Assert.fail("IllegalArgumentException should have been thrown");
55          } catch (final IllegalArgumentException ex) {
56              // expected
57          }
58      }
59  
60      @Test
61      public void testSimpleAppend() throws Exception {
62          final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
63          Assert.assertEquals(16, buffer.capacity());
64          Assert.assertEquals(0, buffer.length());
65          final byte[] b1 = buffer.toByteArray();
66          Assert.assertNotNull(b1);
67          Assert.assertEquals(0, b1.length);
68          Assert.assertTrue(buffer.isEmpty());
69          Assert.assertFalse(buffer.isFull());
70  
71          final byte[] tmp = new byte[] { 1, 2, 3, 4};
72          buffer.append(tmp, 0, tmp.length);
73          Assert.assertEquals(16, buffer.capacity());
74          Assert.assertEquals(4, buffer.length());
75          Assert.assertFalse(buffer.isEmpty());
76          Assert.assertFalse(buffer.isFull());
77  
78          final byte[] b2 = buffer.toByteArray();
79          Assert.assertNotNull(b2);
80          Assert.assertEquals(4, b2.length);
81          for (int i = 0; i < tmp.length; i++) {
82              Assert.assertEquals(tmp[i], b2[i]);
83              Assert.assertEquals(tmp[i], buffer.byteAt(i));
84          }
85          buffer.clear();
86          Assert.assertEquals(16, buffer.capacity());
87          Assert.assertEquals(0, buffer.length());
88          Assert.assertTrue(buffer.isEmpty());
89          Assert.assertFalse(buffer.isFull());
90      }
91  
92      @Test
93      public void testExpandAppend() throws Exception {
94          final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
95          Assert.assertEquals(4, buffer.capacity());
96  
97          final byte[] tmp = new byte[] { 1, 2, 3, 4};
98          buffer.append(tmp, 0, 2);
99          buffer.append(tmp, 0, 4);
100         buffer.append(tmp, 0, 0);
101 
102         Assert.assertEquals(8, buffer.capacity());
103         Assert.assertEquals(6, buffer.length());
104 
105         buffer.append(tmp, 0, 4);
106 
107         Assert.assertEquals(16, buffer.capacity());
108         Assert.assertEquals(10, buffer.length());
109     }
110 
111     @Test
112     public void testInvalidAppend() throws Exception {
113         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
114         buffer.append((byte[])null, 0, 0);
115 
116         final byte[] tmp = new byte[] { 1, 2, 3, 4};
117         try {
118             buffer.append(tmp, -1, 0);
119             Assert.fail("IndexOutOfBoundsException should have been thrown");
120         } catch (final IndexOutOfBoundsException ex) {
121             // expected
122         }
123         try {
124             buffer.append(tmp, 0, -1);
125             Assert.fail("IndexOutOfBoundsException should have been thrown");
126         } catch (final IndexOutOfBoundsException ex) {
127             // expected
128         }
129         try {
130             buffer.append(tmp, 0, 8);
131             Assert.fail("IndexOutOfBoundsException should have been thrown");
132         } catch (final IndexOutOfBoundsException ex) {
133             // expected
134         }
135         try {
136             buffer.append(tmp, 10, Integer.MAX_VALUE);
137             Assert.fail("IndexOutOfBoundsException should have been thrown");
138         } catch (final IndexOutOfBoundsException ex) {
139             // expected
140         }
141         try {
142             buffer.append(tmp, 2, 4);
143             Assert.fail("IndexOutOfBoundsException should have been thrown");
144         } catch (final IndexOutOfBoundsException ex) {
145             // expected
146         }
147     }
148 
149     @Test
150     public void testAppendOneByte() throws Exception {
151         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
152         Assert.assertEquals(4, buffer.capacity());
153 
154         final byte[] tmp = new byte[] { 1, 127, -1, -128, 1, -2};
155         for (final byte element : tmp) {
156             buffer.append(element);
157         }
158         Assert.assertEquals(8, buffer.capacity());
159         Assert.assertEquals(6, buffer.length());
160 
161         for (int i = 0; i < tmp.length; i++) {
162             Assert.assertEquals(tmp[i], buffer.byteAt(i));
163         }
164     }
165 
166     @Test
167     public void testSetLength() throws Exception {
168         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
169         buffer.setLength(2);
170         Assert.assertEquals(2, buffer.length());
171     }
172 
173     @Test
174     public void testSetInvalidLength() throws Exception {
175         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
176         try {
177             buffer.setLength(-2);
178             Assert.fail("IndexOutOfBoundsException should have been thrown");
179         } catch (final IndexOutOfBoundsException ex) {
180             // expected
181         }
182         try {
183             buffer.setLength(200);
184             Assert.fail("IndexOutOfBoundsException should have been thrown");
185         } catch (final IndexOutOfBoundsException ex) {
186             // expected
187         }
188     }
189 
190     @Test
191     public void testEnsureCapacity() throws Exception {
192         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
193         buffer.ensureCapacity(2);
194         Assert.assertEquals(4, buffer.capacity());
195         buffer.ensureCapacity(8);
196         Assert.assertEquals(8, buffer.capacity());
197     }
198 
199     @Test
200     public void testIndexOf() throws Exception {
201         final byte COLON = (byte) ':';
202         final byte COMMA = (byte) ',';
203         final byte[] bytes = "name1: value1; name2: value2".getBytes(Consts.ASCII);
204         final int index1 = 5;
205         final int index2 = 20;
206 
207         final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
208         buffer.append(bytes, 0, bytes.length);
209 
210         Assert.assertEquals(index1, buffer.indexOf(COLON));
211         Assert.assertEquals(-1, buffer.indexOf(COMMA));
212         Assert.assertEquals(index1, buffer.indexOf(COLON, -1, 11));
213         Assert.assertEquals(index1, buffer.indexOf(COLON, 0, 1000));
214         Assert.assertEquals(-1, buffer.indexOf(COLON, 2, 1));
215         Assert.assertEquals(index2, buffer.indexOf(COLON, index1 + 1, buffer.length()));
216     }
217 
218     @Test
219     public void testAppendCharArrayAsAscii() throws Exception {
220         final String s1 = "stuff";
221         final String s2 = " and more stuff";
222         final char[] b1 = s1.toCharArray();
223         final char[] b2 = s2.toCharArray();
224 
225         final ByteArrayBuffer buffer = new ByteArrayBuffer(8);
226         buffer.append(b1, 0, b1.length);
227         buffer.append(b2, 0, b2.length);
228 
229         Assert.assertEquals(s1 + s2, new String(buffer.toByteArray(), "US-ASCII"));
230     }
231 
232     @Test
233     public void testAppendNullCharArray() throws Exception {
234         final ByteArrayBuffer buffer = new ByteArrayBuffer(8);
235         buffer.append((char[])null, 0, 0);
236         Assert.assertEquals(0, buffer.length());
237     }
238 
239     @Test
240     public void testAppendEmptyCharArray() throws Exception {
241         final ByteArrayBuffer buffer = new ByteArrayBuffer(8);
242         buffer.append(new char[] {}, 0, 0);
243         Assert.assertEquals(0, buffer.length());
244     }
245 
246     @Test
247     public void testAppendNullCharArrayBuffer() throws Exception {
248         final ByteArrayBuffer buffer = new ByteArrayBuffer(8);
249         buffer.append((CharArrayBuffer)null, 0, 0);
250         Assert.assertEquals(0, buffer.length());
251     }
252 
253     @Test
254     public void testInvalidAppendCharArrayAsAscii() throws Exception {
255         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
256         buffer.append((char[])null, 0, 0);
257 
258         final char[] tmp = new char[] { '1', '2', '3', '4'};
259         try {
260             buffer.append(tmp, -1, 0);
261             Assert.fail("IndexOutOfBoundsException should have been thrown");
262         } catch (final IndexOutOfBoundsException ex) {
263             // expected
264         }
265         try {
266             buffer.append(tmp, 0, -1);
267             Assert.fail("IndexOutOfBoundsException should have been thrown");
268         } catch (final IndexOutOfBoundsException ex) {
269             // expected
270         }
271         try {
272             buffer.append(tmp, 0, 8);
273             Assert.fail("IndexOutOfBoundsException should have been thrown");
274         } catch (final IndexOutOfBoundsException ex) {
275             // expected
276         }
277         try {
278             buffer.append(tmp, 10, Integer.MAX_VALUE);
279             Assert.fail("IndexOutOfBoundsException should have been thrown");
280         } catch (final IndexOutOfBoundsException ex) {
281             // expected
282         }
283         try {
284             buffer.append(tmp, 2, 4);
285             Assert.fail("IndexOutOfBoundsException should have been thrown");
286         } catch (final IndexOutOfBoundsException ex) {
287             // expected
288         }
289     }
290 
291     @Test
292     public void testSerialization() throws Exception {
293         final ByteArrayBuffer orig = new ByteArrayBuffer(32);
294         orig.append(1);
295         orig.append(2);
296         orig.append(3);
297         final ByteArrayOutputStream outbuffer = new ByteArrayOutputStream();
298         final ObjectOutputStream outStream = new ObjectOutputStream(outbuffer);
299         outStream.writeObject(orig);
300         outStream.close();
301         final byte[] raw = outbuffer.toByteArray();
302         final ByteArrayInputStream inBuffer = new ByteArrayInputStream(raw);
303         final ObjectInputStream inStream = new ObjectInputStream(inBuffer);
304         final ByteArrayBuffer clone = (ByteArrayBuffer) inStream.readObject();
305         Assert.assertEquals(orig.capacity(), clone.capacity());
306         Assert.assertEquals(orig.length(), clone.length());
307         final byte[] data = clone.toByteArray();
308         Assert.assertNotNull(data);
309         Assert.assertEquals(3, data.length);
310         Assert.assertEquals(1, data[0]);
311         Assert.assertEquals(2, data[1]);
312         Assert.assertEquals(3, data[2]);
313     }
314 
315     @Test
316     public void testControlCharFiltering() throws Exception {
317         final char[] chars = new char[256];
318         for (char i = 0; i < 256; i++) {
319             chars[i] = i;
320         }
321 
322         final byte[] bytes = asByteArray(chars);
323 
324         Assert.assertEquals(
325             "?????????\t??????????????????????"
326                 + " !\"#$%&'()*+,-./0123456789:;<=>?"
327                 + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
328                 + "`abcdefghijklmnopqrstuvwxyz"
329                 + "{|}~???????????????????????"
330                 + "??????????\u00A0¡¢£¤¥¦§¨©ª«¬\u00AD®¯"
331                 + "°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ"
332                 + "ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîï"
333                 + "ðñòóôõö÷øùúûüýþÿ",
334             new String(bytes, "ISO-8859-1"));
335     }
336 
337     @Test
338     public void testUnicodeFiltering() throws Exception {
339         // Various languages
340         Assert.assertEquals("?????", new String(asByteArray("буквы".toCharArray()), "ISO-8859-1"));
341         Assert.assertEquals("????", new String(asByteArray("四字熟語".toCharArray()), "ISO-8859-1"));
342 
343         // Unicode snowman
344         Assert.assertEquals("?", new String(asByteArray("☃".toCharArray()), "ISO-8859-1"));
345 
346         // Emoji (surrogate pair)
347         Assert.assertEquals("??", new String(asByteArray("\uD83D\uDE00".toCharArray()), "ISO-8859-1"));
348     }
349 
350     private static byte[] asByteArray(final char[] chars) {
351         final ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(chars.length);
352         byteArrayBuffer.append(chars, 0, chars.length);
353         return byteArrayBuffer.toByteArray();
354     }
355 }