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.binary;
19  
20  import static org.junit.Assert.assertTrue;
21  import static org.junit.Assert.fail;
22  
23  import java.io.ByteArrayOutputStream;
24  import java.io.OutputStream;
25  import java.util.Arrays;
26  
27  import org.junit.Test;
28  
29  public class Base32OutputStreamTest {
30  
31      private final static byte[] CRLF = {(byte) '\r', (byte) '\n'};
32  
33      private final static byte[] LF = {(byte) '\n'};
34  
35  
36  
37  //    /**
38  //     * Test the Base32OutputStream implementation against the special NPE inducing input
39  //     * identified in the CODEC-98 bug.
40  //     *
41  //     * @throws Exception for some failure scenarios.
42  //     */
43  //    @Test
44  //    public void testCodec98NPE() throws Exception {
45  //        byte[] codec98 = StringUtils.getBytesUtf8(Base32TestData.CODEC_98_NPE);
46  //        byte[] codec98_1024 = new byte[1024];
47  //        System.arraycopy(codec98, 0, codec98_1024, 0, codec98.length);
48  //        ByteArrayOutputStream data = new ByteArrayOutputStream(1024);
49  //        Base32OutputStream stream = new Base32OutputStream(data, false);
50  //        stream.write(codec98_1024, 0, 1024);
51  //        stream.close();
52  //
53  //        byte[] decodedBytes = data.toByteArray();
54  //        String decoded = StringUtils.newStringUtf8(decodedBytes);
55  //        assertEquals(
56  //            "codec-98 NPE Base32OutputStream", Base32TestData.CODEC_98_NPE_DECODED, decoded
57  //        );
58  //    }
59  
60  
61      /**
62       * Test the Base32OutputStream implementation against empty input.
63       *
64       * @throws Exception
65       *             for some failure scenarios.
66       */
67      @Test
68      public void testBase32EmptyOutputStreamMimeChunkSize() throws Exception {
69          testBase32EmptyOutputStream(BaseNCodec.MIME_CHUNK_SIZE);
70      }
71  
72      /**
73       * Test the Base32OutputStream implementation against empty input.
74       *
75       * @throws Exception
76       *             for some failure scenarios.
77       */
78      @Test
79      public void testBase32EmptyOutputStreamPemChunkSize() throws Exception {
80          testBase32EmptyOutputStream(BaseNCodec.PEM_CHUNK_SIZE);
81      }
82  
83      private void testBase32EmptyOutputStream(int chunkSize) throws Exception {
84          byte[] emptyEncoded = new byte[0];
85          byte[] emptyDecoded = new byte[0];
86          testByteByByte(emptyEncoded, emptyDecoded, chunkSize, CRLF);
87          testByChunk(emptyEncoded, emptyDecoded, chunkSize, CRLF);
88      }
89  
90      /**
91       * Test the Base32OutputStream implementation
92       *
93       * @throws Exception
94       *             for some failure scenarios.
95       */
96      @Test
97      public void testBase32OutputStreamByChunk() throws Exception {
98          // Hello World test.
99          byte[] encoded = StringUtils.getBytesUtf8(Base32TestData.BASE32_FIXTURE);
100         byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
101         testByChunk(encoded, decoded, BaseNCodec.MIME_CHUNK_SIZE, CRLF);
102 
103 //        // Single Byte test.
104 //        encoded = StringUtils.getBytesUtf8("AA==\r\n");
105 //        decoded = new byte[]{(byte) 0};
106 //        testByChunk(encoded, decoded, Base32.MIME_CHUNK_SIZE, CRLF);
107 
108 
109 //        // Single Line test.
110 //        String singleLine = Base32TestData.ENCODED_64_CHARS_PER_LINE.replaceAll("\n", "");
111 //        encoded = StringUtils.getBytesUtf8(singleLine);
112 //        decoded = Base32TestData.DECODED;
113 //        testByChunk(encoded, decoded, 0, LF);
114 
115         // test random data of sizes 0 thru 150
116         BaseNCodec codec = new Base32();
117         for (int i = 0; i <= 150; i++) {
118             byte[][] randomData = Base32TestData.randomData(codec, i);
119             encoded = randomData[1];
120             decoded = randomData[0];
121             testByChunk(encoded, decoded, 0, LF);
122         }
123     }
124 
125     /**
126      * Test the Base32OutputStream implementation
127      *
128      * @throws Exception
129      *             for some failure scenarios.
130      */
131     @Test
132     public void testBase32OutputStreamByteByByte() throws Exception {
133         // Hello World test.
134         byte[] encoded = StringUtils.getBytesUtf8(Base32TestData.BASE32_FIXTURE);
135         byte[] decoded = StringUtils.getBytesUtf8(Base32TestData.STRING_FIXTURE);
136         testByteByByte(encoded, decoded, 76, CRLF);
137 
138 //        // Single Byte test.
139 //        encoded = StringUtils.getBytesUtf8("AA==\r\n");
140 //        decoded = new byte[]{(byte) 0};
141 //        testByteByByte(encoded, decoded, 76, CRLF);
142 
143 
144 //        // Single Line test.
145 //        String singleLine = Base32TestData.ENCODED_64_CHARS_PER_LINE.replaceAll("\n", "");
146 //        encoded = StringUtils.getBytesUtf8(singleLine);
147 //        decoded = Base32TestData.DECODED;
148 //        testByteByByte(encoded, decoded, 0, LF);
149 
150         // test random data of sizes 0 thru 150
151         BaseNCodec codec = new Base32();
152         for (int i = 0; i <= 150; i++) {
153             byte[][] randomData = Base32TestData.randomData(codec, i);
154             encoded = randomData[1];
155             decoded = randomData[0];
156             testByteByByte(encoded, decoded, 0, LF);
157         }
158     }
159 
160     /**
161      * Test method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]-->
162      * encoded 3. decoded ---[WRAP-WRAP-WRAP-etc...] --> decoded
163      * <p/>
164      * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base32OutputStream wraps itself in encode and decode
165      * mode over and over again.
166      *
167      * @param encoded
168      *            Base32 encoded data
169      * @param decoded
170      *            the data from above, but decoded
171      * @param chunkSize
172      *            chunk size (line-length) of the Base32 encoded data.
173      * @param seperator
174      *            Line separator in the Base32 encoded data.
175      * @throws Exception
176      *             Usually signifies a bug in the Base32 commons-codec implementation.
177      */
178     private void testByChunk(byte[] encoded, byte[] decoded, int chunkSize, byte[] seperator) throws Exception {
179 
180         // Start with encode.
181         ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
182         OutputStream out = new Base32OutputStream(byteOut, true, chunkSize, seperator);
183         out.write(decoded);
184         out.close();
185         byte[] output = byteOut.toByteArray();
186         assertTrue("Streaming chunked Base32 encode", Arrays.equals(output, encoded));
187 
188         // Now let's try decode.
189         byteOut = new ByteArrayOutputStream();
190         out = new Base32OutputStream(byteOut, false);
191         out.write(encoded);
192         out.close();
193         output = byteOut.toByteArray();
194         assertTrue("Streaming chunked Base32 decode", Arrays.equals(output, decoded));
195 
196         // I always wanted to do this! (wrap encoder with decoder etc etc).
197         byteOut = new ByteArrayOutputStream();
198         out = byteOut;
199         for (int i = 0; i < 10; i++) {
200             out = new Base32OutputStream(out, false);
201             out = new Base32OutputStream(out, true, chunkSize, seperator);
202         }
203         out.write(decoded);
204         out.close();
205         output = byteOut.toByteArray();
206 
207         assertTrue("Streaming chunked Base32 wrap-wrap-wrap!", Arrays.equals(output, decoded));
208     }
209 
210     /**
211      * Test method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]-->
212      * encoded 3. decoded ---[WRAP-WRAP-WRAP-etc...] --> decoded
213      * <p/>
214      * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base32OutputStream wraps itself in encode and decode
215      * mode over and over again.
216      *
217      * @param encoded
218      *            Base32 encoded data
219      * @param decoded
220      *            the data from above, but decoded
221      * @param chunkSize
222      *            chunk size (line-length) of the Base32 encoded data.
223      * @param seperator
224      *            Line separator in the Base32 encoded data.
225      * @throws Exception
226      *             Usually signifies a bug in the Base32 commons-codec implementation.
227      */
228     private void testByteByByte(byte[] encoded, byte[] decoded, int chunkSize, byte[] seperator) throws Exception {
229 
230         // Start with encode.
231         ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
232         OutputStream out = new Base32OutputStream(byteOut, true, chunkSize, seperator);
233         for (byte element : decoded) {
234             out.write(element);
235         }
236         out.close();
237         byte[] output = byteOut.toByteArray();
238         assertTrue("Streaming byte-by-byte Base32 encode", Arrays.equals(output, encoded));
239 
240         // Now let's try decode.
241         byteOut = new ByteArrayOutputStream();
242         out = new Base32OutputStream(byteOut, false);
243         for (byte element : encoded) {
244             out.write(element);
245         }
246         out.close();
247         output = byteOut.toByteArray();
248         assertTrue("Streaming byte-by-byte Base32 decode", Arrays.equals(output, decoded));
249 
250         // Now let's try decode with tonnes of flushes.
251         byteOut = new ByteArrayOutputStream();
252         out = new Base32OutputStream(byteOut, false);
253         for (byte element : encoded) {
254             out.write(element);
255             out.flush();
256         }
257         out.close();
258         output = byteOut.toByteArray();
259         assertTrue("Streaming byte-by-byte flush() Base32 decode", Arrays.equals(output, decoded));
260 
261         // I always wanted to do this! (wrap encoder with decoder etc etc).
262         byteOut = new ByteArrayOutputStream();
263         out = byteOut;
264         for (int i = 0; i < 10; i++) {
265             out = new Base32OutputStream(out, false);
266             out = new Base32OutputStream(out, true, chunkSize, seperator);
267         }
268         for (byte element : decoded) {
269             out.write(element);
270         }
271         out.close();
272         output = byteOut.toByteArray();
273 
274         assertTrue("Streaming byte-by-byte Base32 wrap-wrap-wrap!", Arrays.equals(output, decoded));
275     }
276 
277     /**
278      * Tests Base32OutputStream.write for expected IndexOutOfBoundsException conditions.
279      *
280      * @throws Exception
281      *             for some failure scenarios.
282      */
283     @Test
284     public void testWriteOutOfBounds() throws Exception {
285         byte[] buf = new byte[1024];
286         ByteArrayOutputStream bout = new ByteArrayOutputStream();
287         Base32OutputStream out = new Base32OutputStream(bout);
288 
289         try {
290             out.write(buf, -1, 1);
291             fail("Expected Base32OutputStream.write(buf, -1, 1) to throw a IndexOutOfBoundsException");
292         } catch (IndexOutOfBoundsException ioobe) {
293             // Expected
294         }
295 
296         try {
297             out.write(buf, 1, -1);
298             fail("Expected Base32OutputStream.write(buf, 1, -1) to throw a IndexOutOfBoundsException");
299         } catch (IndexOutOfBoundsException ioobe) {
300             // Expected
301         }
302 
303         try {
304             out.write(buf, buf.length + 1, 0);
305             fail("Expected Base32OutputStream.write(buf, buf.length + 1, 0) to throw a IndexOutOfBoundsException");
306         } catch (IndexOutOfBoundsException ioobe) {
307             // Expected
308         }
309 
310         try {
311             out.write(buf, buf.length - 1, 2);
312             fail("Expected Base32OutputStream.write(buf, buf.length - 1, 2) to throw a IndexOutOfBoundsException");
313         } catch (IndexOutOfBoundsException ioobe) {
314             // Expected
315         }
316         out.close();
317     }
318 
319     /**
320      * Tests Base32OutputStream.write(null).
321      *
322      * @throws Exception
323      *             for some failure scenarios.
324      */
325     @Test
326     public void testWriteToNullCoverage() throws Exception {
327         ByteArrayOutputStream bout = new ByteArrayOutputStream();
328         Base32OutputStream out = new Base32OutputStream(bout);
329         try {
330             out.write(null, 0, 0);
331             fail("Expcted Base32OutputStream.write(null) to throw a NullPointerException");
332         } catch (NullPointerException e) {
333             // Expected
334         }
335         out.close();
336     }
337 
338 }