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 import static org.junit.jupiter.api.Assertions.assertTrue;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31
32 import org.apache.commons.codec.CodecPolicy;
33 import org.apache.commons.io.IOUtils;
34 import org.junit.jupiter.api.Test;
35
36
37
38
39 class Base32InputStreamTest {
40
41 private static final String ENCODED_FOO = "MZXW6===";
42
43 private static final byte[] CRLF = { (byte) '\r', (byte) '\n' };
44
45 private static final byte[] LF = { (byte) '\n' };
46
47 private static final String STRING_FIXTURE = "Hello World";
48
49
50
51
52
53
54
55 @Test
56 void testAvailable() throws Throwable {
57 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
58 try (Base32InputStream b32stream = new Base32InputStream(ins)) {
59 assertEquals(1, b32stream.available());
60 assertEquals(3, b32stream.skip(10));
61
62 assertEquals(0, b32stream.available());
63 assertEquals(-1, b32stream.read());
64 assertEquals(-1, b32stream.read());
65 assertEquals(0, b32stream.available());
66 }
67 }
68
69 private void testBase32EmptyInputStream(final int chuckSize) throws Exception {
70 final byte[] emptyEncoded = {};
71 final byte[] emptyDecoded = {};
72 testByteByByte(emptyEncoded, emptyDecoded, chuckSize, CRLF);
73 testByChunk(emptyEncoded, emptyDecoded, chuckSize, CRLF);
74 }
75
76
77
78
79
80
81
82 @Test
83 void testBase32EmptyInputStreamMimeChuckSize() throws Exception {
84 testBase32EmptyInputStream(BaseNCodec.MIME_CHUNK_SIZE);
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 @Test
160 void testBase32EmptyInputStreamPemChuckSize() throws Exception {
161 testBase32EmptyInputStream(BaseNCodec.PEM_CHUNK_SIZE);
162 }
163
164
165
166
167
168
169
170 @Test
171 void testBase32InputStreamByChunk() throws Exception {
172
173 byte[] encoded = StringUtils.getBytesUtf8(Base32TestData.BASE32_FIXTURE);
174 byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
175 testByChunk(encoded, decoded, BaseNCodec.MIME_CHUNK_SIZE, CRLF);
176
177
178 encoded = StringUtils.getBytesUtf8("AA======\r\n");
179 decoded = new byte[] { (byte) 0 };
180 testByChunk(encoded, decoded, BaseNCodec.MIME_CHUNK_SIZE, CRLF);
181
182
183
184
185
186
187
188
189
190
191
192
193
194 final BaseNCodec codec = new Base32();
195 for (int i = 0; i <= 150; i++) {
196 final byte[][] randomData = BaseNTestData.randomData(codec, i);
197 encoded = randomData[1];
198 decoded = randomData[0];
199 testByChunk(encoded, decoded, 0, LF);
200 }
201 }
202
203
204
205
206
207
208
209 @Test
210 void testBase32InputStreamByteByByte() throws Exception {
211
212 byte[] encoded = StringUtils.getBytesUtf8(Base32TestData.BASE32_FIXTURE);
213 byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
214 testByteByByte(encoded, decoded, BaseNCodec.MIME_CHUNK_SIZE, CRLF);
215
216
217 encoded = StringUtils.getBytesUtf8("AA======\r\n");
218 decoded = new byte[] { (byte) 0 };
219 testByteByByte(encoded, decoded, BaseNCodec.MIME_CHUNK_SIZE, CRLF);
220
221
222
223
224
225
226
227
228 final BaseNCodec codec = new Base32();
229 for (int i = 0; i <= 150; i++) {
230 final byte[][] randomData = BaseNTestData.randomData(codec, i);
231 encoded = randomData[1];
232 decoded = randomData[0];
233 testByteByByte(encoded, decoded, 0, LF);
234 }
235 }
236
237 @Test
238 void testBuilder() {
239 assertNotNull(Base32InputStream.builder().getBaseNCodec());
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 private void testByChunk(final byte[] encoded, final byte[] decoded, final int chunkSize, final byte[] separator) throws Exception {
261
262 try (InputStream in = new Base32InputStream(new ByteArrayInputStream(decoded), true, chunkSize, separator)) {
263 final byte[] output = IOUtils.toByteArray(in);
264 assertEquals(-1, in.read(), "EOF");
265 assertEquals(-1, in.read(), "Still EOF");
266 assertArrayEquals(encoded, output, "Streaming base32 encode");
267 }
268
269 try (InputStream in = new Base32InputStream(new ByteArrayInputStream(encoded))) {
270 final byte[] output = IOUtils.toByteArray(in);
271
272 assertEquals(-1, in.read(), "EOF");
273 assertEquals(-1, in.read(), "Still EOF");
274 assertArrayEquals(decoded, output, "Streaming base32 decode");
275 }
276
277 InputStream in = new ByteArrayInputStream(decoded);
278 for (int i = 0; i < 10; i++) {
279 in = new Base32InputStream(in, true, chunkSize, separator);
280 in = new Base32InputStream(in, false);
281 }
282 final InputStream in1 = in;
283 final byte[] output = IOUtils.toByteArray(in1);
284 assertEquals(-1, in.read(), "EOF");
285 assertEquals(-1, in.read(), "Still EOF");
286 assertArrayEquals(decoded, output, "Streaming base32 wrap-wrap-wrap!");
287 in.close();
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 private void testByteByByte(final byte[] encoded, final byte[] decoded, final int chunkSize, final byte[] separator) throws Exception {
309
310
311 InputStream in;
312 in = new Base32InputStream(new ByteArrayInputStream(decoded), true, chunkSize, separator);
313 byte[] output = new byte[encoded.length];
314 for (int i = 0; i < output.length; i++) {
315 output[i] = (byte) in.read();
316 }
317
318 assertEquals(-1, in.read(), "EOF");
319 assertEquals(-1, in.read(), "Still EOF");
320 assertArrayEquals(encoded, output, "Streaming base32 encode");
321
322 in.close();
323
324
325 in = new Base32InputStream(new ByteArrayInputStream(encoded));
326 output = new byte[decoded.length];
327 for (int i = 0; i < output.length; i++) {
328 output[i] = (byte) in.read();
329 }
330
331 assertEquals(-1, in.read(), "EOF");
332 assertEquals(-1, in.read(), "Still EOF");
333 assertArrayEquals(decoded, output, "Streaming base32 decode");
334
335 in.close();
336
337
338 in = new ByteArrayInputStream(decoded);
339 for (int i = 0; i < 10; i++) {
340 in = new Base32InputStream(in, true, chunkSize, separator);
341 in = new Base32InputStream(in, false);
342 }
343 output = new byte[decoded.length];
344 for (int i = 0; i < output.length; i++) {
345 output[i] = (byte) in.read();
346 }
347
348 assertEquals(-1, in.read(), "EOF");
349 assertEquals(-1, in.read(), "Still EOF");
350 assertArrayEquals(decoded, output, "Streaming base32 wrap-wrap-wrap!");
351 }
352
353
354
355
356 @Test
357 void testCodec105() throws IOException {
358 try (Base32InputStream in = new Base32InputStream(new Codec105ErrorInputStream(), true, 0, null)) {
359 for (int i = 0; i < 5; i++) {
360 in.read();
361 }
362 }
363 }
364
365
366
367
368 @Test
369 void testCodec130() throws IOException {
370 final ByteArrayOutputStream bos = new ByteArrayOutputStream();
371 try (Base32OutputStream base32os = new Base32OutputStream(bos)) {
372 base32os.write(StringUtils.getBytesUtf8(STRING_FIXTURE));
373 }
374
375 final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
376 final Base32InputStream ins = new Base32InputStream(bis);
377
378
379 assertEquals(1, ins.skip(1));
380 final byte[] decodedBytes = IOUtils.toByteArray(ins);
381 final String str = StringUtils.newStringUtf8(decodedBytes);
382
383 assertEquals(STRING_FIXTURE.substring(1), str);
384 }
385
386
387
388
389
390
391
392 @Test
393 void testMarkSupported() throws Exception {
394 final byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
395 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
396 try (Base32InputStream in = new Base32InputStream(bin, true, 4, new byte[] { 0, 0, 0 })) {
397
398 assertFalse(in.markSupported(), "Base32InputStream.markSupported() is false");
399 }
400 }
401
402
403
404
405
406
407
408 @Test
409 void testRead0() throws Exception {
410 final byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
411 final byte[] buf = new byte[1024];
412 int bytesRead = 0;
413 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
414 try (Base32InputStream in = new Base32InputStream(bin, true, 4, new byte[] { 0, 0, 0 })) {
415 bytesRead = in.read(buf, 0, 0);
416 assertEquals(0, bytesRead, "Base32InputStream.read(buf, 0, 0) returns 0");
417 }
418 }
419
420
421
422
423
424
425
426 @Test
427 void testReadNull() throws Exception {
428 final byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
429 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
430 try (Base32InputStream in = new Base32InputStream(bin, true, 4, new byte[] {0, 0, 0})) {
431 assertThrows(NullPointerException.class, () -> in.read(null, 0, 0));
432 }
433 }
434
435
436
437
438
439
440
441 @Test
442 void testReadOutOfBounds() throws Exception {
443 final byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
444 final byte[] buf = new byte[1024];
445 final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
446 try (Base32InputStream in = new Base32InputStream(bin, true, 4, new byte[] { 0, 0, 0 })) {
447 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, -1, 0), "Base32InputStream.read(buf, -1, 0)");
448 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, 0, -1), "Base32InputStream.read(buf, 0, -1)");
449 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, buf.length + 1, 0), "Base32InputStream.read(buf, buf.length + 1, 0)");
450 assertThrows(IndexOutOfBoundsException.class, () -> in.read(buf, buf.length - 1, 2), "Base32InputStream.read(buf, buf.length - 1, 2)");
451 }
452 }
453
454
455
456
457
458
459
460 @Test
461 void testSkipBig() throws Throwable {
462 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
463 try (Base32InputStream b32stream = new Base32InputStream(ins)) {
464 assertEquals(3, b32stream.skip(1024));
465
466 assertEquals(-1, b32stream.read());
467 assertEquals(-1, b32stream.read());
468 }
469 }
470
471
472
473
474
475
476
477 @Test
478 void testSkipNone() throws Throwable {
479 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
480 try (Base32InputStream b32stream = new Base32InputStream(ins)) {
481 final byte[] actualBytes = new byte[6];
482 assertEquals(0, b32stream.skip(0));
483 b32stream.read(actualBytes, 0, actualBytes.length);
484 assertArrayEquals(actualBytes, new byte[] { 102, 111, 111, 0, 0, 0 });
485
486 assertEquals(-1, b32stream.read());
487 }
488 }
489
490
491
492
493
494
495
496 @Test
497 void testSkipPastEnd() throws Throwable {
498 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
499 try (Base32InputStream b32stream = new Base32InputStream(ins)) {
500
501 assertEquals(3, b32stream.skip(10));
502
503 assertEquals(-1, b32stream.read());
504 assertEquals(-1, b32stream.read());
505 }
506 }
507
508
509
510
511
512
513
514 @Test
515 void testSkipToEnd() throws Throwable {
516 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
517 try (Base32InputStream b32stream = new Base32InputStream(ins)) {
518
519 assertEquals(3, b32stream.skip(3));
520
521 assertEquals(-1, b32stream.read());
522 assertEquals(-1, b32stream.read());
523 }
524 }
525
526
527
528
529
530
531
532 @Test
533 void testSkipWrongArgument() throws Throwable {
534 final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
535 try (Base32InputStream b32stream = new Base32InputStream(ins)) {
536 assertThrows(IllegalArgumentException.class, () -> b32stream.skip(-10));
537 }
538 }
539
540
541
542
543
544
545
546 @Test
547 void testStrictDecoding() throws Exception {
548 for (final String s : Base32Test.BASE32_IMPOSSIBLE_CASES) {
549 final byte[] encoded = StringUtils.getBytesUtf8(s);
550 final Base32InputStream in = new Base32InputStream(new ByteArrayInputStream(encoded), false);
551
552 assertFalse(in.isStrictDecoding());
553 IOUtils.toByteArray(in);
554
555 final Base32InputStream in2 = new Base32InputStream(new ByteArrayInputStream(encoded), false, 0, null, CodecPolicy.STRICT);
556 assertTrue(in2.isStrictDecoding());
557 assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(in2));
558
559 try (Base32InputStream in3 = Base32InputStream.builder()
560 .setByteArray(encoded)
561 .setEncode(false)
562 .setBaseNCodec(Base32.builder().setLineLength(0).setLineSeparator(null).setDecodingPolicy(CodecPolicy.STRICT).get())
563 .get()) {
564 assertTrue(in3.isStrictDecoding());
565 assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(in3));
566 }
567 }
568 }
569 }