1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.binary;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25
26 import java.io.ByteArrayInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29
30 import org.apache.commons.io.IOUtils;
31 import org.junit.jupiter.api.Test;
32
33
34
35
36 class Base16InputStreamTest {
37
38
39
40
41 private static final String ENCODED_B16 = "CAFEBABEFFFF";
42
43 private static final String STRING_FIXTURE = "Hello World";
44
45
46
47
48
49
50 @Test
51 void testAvailable() throws IOException {
52 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
53 try (Base16InputStream b16Stream = new Base16InputStream(ins)) {
54 assertEquals(1, b16Stream.available());
55 assertEquals(6, b16Stream.skip(10));
56
57 assertEquals(0, b16Stream.available());
58 assertEquals(-1, b16Stream.read());
59 assertEquals(-1, b16Stream.read());
60 assertEquals(0, b16Stream.available());
61 }
62 }
63
64
65
66
67
68
69 @Test
70 void testBase16EmptyInputStream() throws IOException {
71 final byte[] emptyEncoded = {};
72 final byte[] emptyDecoded = {};
73 testByteByByte(emptyEncoded, emptyDecoded);
74 testByChunk(emptyEncoded, emptyDecoded);
75 }
76
77
78
79
80
81
82 @Test
83 void testBase16InputStreamByChunk() throws IOException {
84
85 byte[] encoded = StringUtils.getBytesUtf8("48656C6C6F20576F726C64");
86 byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
87 testByChunk(encoded, decoded);
88
89 encoded = StringUtils.getBytesUtf8("41");
90 decoded = new byte[] { (byte) 0x41 };
91 testByChunk(encoded, decoded);
92
93 encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_UPPERCASE);
94 decoded = BaseNTestData.DECODED;
95 testByChunk(encoded, decoded);
96
97 final BaseNCodec codec = Base16.builder().setLowerCase(true).get();
98 for (int i = 0; i <= 150; i++) {
99 final byte[][] randomData = BaseNTestData.randomData(codec, i);
100 encoded = randomData[1];
101 decoded = randomData[0];
102 testByChunk(encoded, decoded, true);
103 }
104 }
105
106
107
108
109
110
111 @Test
112 void testBase16InputStreamByteByByte() throws IOException {
113
114 byte[] encoded = StringUtils.getBytesUtf8("48656C6C6F20576F726C64");
115 byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
116 testByteByByte(encoded, decoded);
117
118 encoded = StringUtils.getBytesUtf8("41");
119 decoded = new byte[] { (byte) 0x41 };
120 testByteByByte(encoded, decoded);
121
122 encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_UPPERCASE);
123 decoded = BaseNTestData.DECODED;
124 testByteByByte(encoded, decoded);
125
126 final BaseNCodec codec = Base16.builder().setLowerCase(true).get();
127 for (int i = 0; i <= 150; i++) {
128 final byte[][] randomData = BaseNTestData.randomData(codec, i);
129 encoded = randomData[1];
130 decoded = randomData[0];
131 testByteByByte(encoded, decoded, true);
132 }
133 }
134
135 @Test
136 void testBuilder() {
137 assertNotNull(Base16InputStream.builder().getBaseNCodec());
138 }
139
140
141
142
143
144
145
146
147
148
149
150 private void testByChunk(final byte[] encoded, final byte[] decoded) throws IOException {
151 testByChunk(encoded, decoded, false);
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165 private void testByChunk(final byte[] encoded, final byte[] decoded, final boolean lowerCase) throws IOException {
166
167 try (InputStream in = new Base16InputStream(new ByteArrayInputStream(decoded), true, lowerCase)) {
168 final byte[] output = IOUtils.toByteArray(in);
169 assertEquals(-1, in.read(), "EOF");
170 assertEquals(-1, in.read(), "Still EOF");
171 assertArrayEquals(encoded, output, "Streaming Base16 encode");
172 }
173
174 try (InputStream in = new Base16InputStream(new ByteArrayInputStream(encoded), false, lowerCase)) {
175 final byte[] output = IOUtils.toByteArray(in);
176 assertEquals(-1, in.read(), "EOF");
177 assertEquals(-1, in.read(), "Still EOF");
178 assertArrayEquals(decoded, output, "Streaming Base16 decode");
179 }
180
181 try (InputStream in = new ByteArrayInputStream(decoded);
182 InputStream inEncode = new Base16InputStream(in, true, lowerCase);
183 InputStream inDecode = new Base16InputStream(inEncode, false, lowerCase)) {
184 final byte[] output = IOUtils.toByteArray(inDecode);
185 assertEquals(-1, inDecode.read(), "EOF");
186 assertEquals(-1, inDecode.read(), "Still EOF");
187 assertArrayEquals(decoded, output, "Streaming Base16 wrap-wrap!");
188 }
189 }
190
191
192
193
194
195
196
197
198
199
200
201 private void testByteByByte(final byte[] encoded, final byte[] decoded) throws IOException {
202 testByteByByte(encoded, decoded, false);
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216 private void testByteByByte(final byte[] encoded, final byte[] decoded, final boolean lowerCase) throws IOException {
217
218 try (InputStream in = new Base16InputStream(new ByteArrayInputStream(decoded), true, lowerCase)) {
219 final byte[] output = new byte[encoded.length];
220 for (int i = 0; i < output.length; i++) {
221 output[i] = (byte) in.read();
222 }
223 assertEquals(-1, in.read(), "EOF");
224 assertEquals(-1, in.read(), "Still EOF");
225 assertArrayEquals(encoded, output, "Streaming Base16 encode");
226 }
227 try (InputStream in = Base16InputStream.builder()
228 .setByteArray(decoded)
229 .setEncode(true).setBaseNCodec(Base16.builder().setLowerCase(lowerCase).get())
230 .get()) {
231 final byte[] output = new byte[encoded.length];
232 for (int i = 0; i < output.length; i++) {
233 output[i] = (byte) in.read();
234 }
235 assertEquals(-1, in.read(), "EOF");
236 assertEquals(-1, in.read(), "Still EOF");
237 assertArrayEquals(encoded, output, "Streaming Base16 encode");
238 }
239
240 try (InputStream in = new Base16InputStream(new ByteArrayInputStream(encoded), false, lowerCase)) {
241 final byte[] output = new byte[decoded.length];
242 for (int i = 0; i < output.length; i++) {
243 output[i] = (byte) in.read();
244 }
245 assertEquals(-1, in.read(), "EOF");
246 assertEquals(-1, in.read(), "Still EOF");
247 assertArrayEquals(decoded, output, "Streaming Base16 decode");
248 }
249
250 try (InputStream in = new ByteArrayInputStream(decoded);
251 InputStream inEncode = new Base16InputStream(in, true, lowerCase);
252 InputStream inDecode = new Base16InputStream(inEncode, false, lowerCase)) {
253 final byte[] output = new byte[decoded.length];
254 for (int i = 0; i < output.length; i++) {
255 output[i] = (byte) inDecode.read();
256 }
257 assertEquals(-1, inDecode.read(), "EOF");
258 assertEquals(-1, inDecode.read(), "Still EOF");
259 assertArrayEquals(decoded, output, "Streaming Base16 wrap-wrap!");
260 }
261 }
262
263
264
265
266
267
268 @Test
269 void testMarkSupported() throws IOException {
270 final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
271 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
272 try (Base16InputStream in = new Base16InputStream(bin, true)) {
273
274 assertFalse(in.markSupported(), "Base16InputStream.markSupported() is false");
275 }
276 }
277
278
279
280
281
282
283 @Test
284 void testRead0() throws IOException {
285 final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
286 final byte[] buf = new byte[1024];
287 int bytesRead = 0;
288 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
289 try (Base16InputStream in = new Base16InputStream(bin, true)) {
290 bytesRead = in.read(buf, 0, 0);
291 assertEquals(0, bytesRead, "Base16InputStream.read(buf, 0, 0) returns 0");
292 }
293 }
294
295
296
297
298
299
300 @Test
301 void testReadNull() throws IOException {
302 final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
303 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
304 try (Base16InputStream in = new Base16InputStream(bin, true)) {
305 assertThrows(NullPointerException.class, () -> in.read(null, 0, 0), "Base16InputStream.read(null, 0, 0)");
306 }
307 }
308
309
310
311
312
313
314 @Test
315 void testReadOutOfBounds() throws IOException {
316 final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
317 final byte[] buf = new byte[1024];
318 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
319 try (Base16InputStream in = new Base16InputStream(bin, true)) {
320 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, -1, 0), "Base16InputStream.read(buf, -1, 0)");
321 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, 0, -1), "Base16InputStream.read(buf, 0, -1)");
322 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, buf.length + 1, 0), "Base16InputStream.read(buf, buf.length + 1, 0)");
323 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, buf.length - 1, 2), "Base16InputStream.read(buf, buf.length - 1, 2)");
324 }
325 }
326
327
328
329
330
331
332 @Test
333 void testSkipBig() throws IOException {
334 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
335 try (Base16InputStream b16Stream = new Base16InputStream(ins)) {
336 assertEquals(6, b16Stream.skip(Integer.MAX_VALUE));
337
338 assertEquals(-1, b16Stream.read());
339 assertEquals(-1, b16Stream.read());
340 }
341 }
342
343
344
345
346
347
348 @Test
349 void testSkipNone() throws IOException {
350 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
351 try (Base16InputStream b16Stream = new Base16InputStream(ins)) {
352 final byte[] actualBytes = new byte[6];
353 assertEquals(0, b16Stream.skip(0));
354 b16Stream.read(actualBytes, 0, actualBytes.length);
355 assertArrayEquals(actualBytes, new byte[] { (byte) 202, (byte) 254, (byte) 186, (byte) 190, (byte) 255, (byte) 255 });
356
357 assertEquals(-1, b16Stream.read());
358 }
359 }
360
361
362
363
364
365
366 @Test
367 void testSkipPastEnd() throws IOException {
368 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
369 try (Base16InputStream b16Stream = new Base16InputStream(ins)) {
370
371 assertEquals(6, b16Stream.skip(10));
372
373 assertEquals(-1, b16Stream.read());
374 assertEquals(-1, b16Stream.read());
375 }
376 }
377
378
379
380
381
382
383 @Test
384 void testSkipToEnd() throws IOException {
385 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
386 try (Base16InputStream b16Stream = new Base16InputStream(ins)) {
387
388 assertEquals(6, b16Stream.skip(6));
389
390 assertEquals(-1, b16Stream.read());
391 assertEquals(-1, b16Stream.read());
392 }
393 }
394
395
396
397
398
399
400 @Test
401 void testSkipWrongArgument() throws IOException {
402 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
403 try (Base16InputStream b16Stream = new Base16InputStream(ins)) {
404 assertThrows(IllegalArgumentException.class, () -> b16Stream.skip(-10));
405 }
406
407 try (Base16InputStream b16Stream = Base16InputStream.builder().setByteArray(StringUtils.getBytesIso8859_1(ENCODED_B16)).get()) {
408 assertThrows(IllegalArgumentException.class, () -> b16Stream.skip(-10));
409 }
410 }
411 }