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