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  package org.apache.commons.io;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.InputStream;
21  import java.io.InputStreamReader;
22  import java.io.OutputStream;
23  import java.io.OutputStreamWriter;
24  import java.io.IOException;
25  import java.io.Reader;
26  import java.io.Writer;
27  import java.util.Arrays;
28  
29  import junit.framework.Test;
30  import junit.framework.TestSuite;
31  import junit.textui.TestRunner;
32  
33  import org.apache.commons.io.input.NullInputStream;
34  import org.apache.commons.io.input.NullReader;
35  import org.apache.commons.io.output.ByteArrayOutputStream;
36  import org.apache.commons.io.output.NullOutputStream;
37  import org.apache.commons.io.output.NullWriter;
38  import org.apache.commons.io.testtools.FileBasedTestCase;
39  import org.apache.commons.io.testtools.YellOnCloseInputStream;
40  import org.apache.commons.io.testtools.YellOnFlushAndCloseOutputStream;
41  
42  /**
43   * JUnit tests for IOUtils copy methods.
44   * 
45   * @author Jeff Turner
46   * @author Matthew Hawthorne
47   * @author Jeremias Maerki
48   * @author Stephen Colebourne
49   * @version $Id: IOUtilsCopyTestCase.java 481854 2006-12-03 18:30:07Z scolebourne $
50   * @see IOUtils
51   */
52  public class IOUtilsCopyTestCase extends FileBasedTestCase {
53  
54      /*
55       * NOTE this is not particularly beautiful code. A better way to check for
56       * flush and close status would be to implement "trojan horse" wrapper
57       * implementations of the various stream classes, which set a flag when
58       * relevant methods are called. (JT)
59       */
60  
61      private static final int FILE_SIZE = 1024 * 4 + 1;
62  
63  
64      private byte[] inData = generateTestData(FILE_SIZE);
65  
66      public static void main(String[] args) {
67          TestRunner.run(suite());
68      }
69  
70      public static Test suite() {
71          return new TestSuite(IOUtilsCopyTestCase.class);
72      }
73  
74      public IOUtilsCopyTestCase(String testName) {
75          super(testName);
76      }
77  
78      // ----------------------------------------------------------------
79      // Setup
80      // ----------------------------------------------------------------
81  
82      public void setUp() throws Exception {
83      }
84  
85      public void tearDown() throws Exception {
86      }
87  
88      //-----------------------------------------------------------------------
89      public void testCopy_inputStreamToOutputStream() throws Exception {
90          InputStream in = new ByteArrayInputStream(inData);
91          in = new YellOnCloseInputStream(in);
92  
93          ByteArrayOutputStream baout = new ByteArrayOutputStream();
94          OutputStream out = new YellOnFlushAndCloseOutputStream(baout, false, true);
95  
96          int count = IOUtils.copy(in, out);
97          
98          assertTrue("Not all bytes were read", in.available() == 0);
99          assertEquals("Sizes differ", inData.length, baout.size());
100         assertTrue("Content differs", Arrays.equals(inData, baout.toByteArray()));
101     }
102 
103     public void testCopy_inputStreamToOutputStream_nullIn() throws Exception {
104         OutputStream out = new ByteArrayOutputStream();
105         try {
106             IOUtils.copy((InputStream) null, out);
107             fail();
108         } catch (NullPointerException ex) {}
109     }
110 
111     public void testCopy_inputStreamToOutputStream_nullOut() throws Exception {
112         InputStream in = new ByteArrayInputStream(inData);
113         try {
114             IOUtils.copy(in, (OutputStream) null);
115             fail();
116         } catch (NullPointerException ex) {}
117     }
118 
119     /**
120      * Test Copying file > 2GB  - see issue# IO-84
121      */
122     public void testCopy_inputStreamToOutputStream_IO84() throws Exception {
123         long size = (long)Integer.MAX_VALUE + (long)1;
124         InputStream  in  = new NullInputStream(size);
125         OutputStream out = new NullOutputStream();
126 
127         // Test copy() method
128         assertEquals(-1, IOUtils.copy(in, out));
129 
130         // reset the input
131         in.close();
132 
133         // Test copyLarge() method
134         assertEquals("copyLarge()", size, IOUtils.copyLarge(in, out));
135     }
136 
137     //-----------------------------------------------------------------------
138     public void testCopy_inputStreamToWriter() throws Exception {
139         InputStream in = new ByteArrayInputStream(inData);
140         in = new YellOnCloseInputStream(in);
141 
142         ByteArrayOutputStream baout = new ByteArrayOutputStream();
143         YellOnFlushAndCloseOutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
144         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
145         
146         IOUtils.copy(in, writer);
147         out.off();
148         writer.flush();
149 
150         assertTrue("Not all bytes were read", in.available() == 0);
151         assertEquals("Sizes differ", inData.length, baout.size());
152         assertTrue("Content differs", Arrays.equals(inData, baout.toByteArray()));
153     }
154 
155     public void testCopy_inputStreamToWriter_nullIn() throws Exception {
156         ByteArrayOutputStream baout = new ByteArrayOutputStream();
157         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
158         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
159         try {
160             IOUtils.copy((InputStream) null, writer);
161             fail();
162         } catch (NullPointerException ex) {}
163     }
164 
165     public void testCopy_inputStreamToWriter_nullOut() throws Exception {
166         InputStream in = new ByteArrayInputStream(inData);
167         try {
168             IOUtils.copy(in, (Writer) null);
169             fail();
170         } catch (NullPointerException ex) {}
171     }
172 
173     //-----------------------------------------------------------------------
174     public void testCopy_inputStreamToWriter_Encoding() throws Exception {
175         InputStream in = new ByteArrayInputStream(inData);
176         in = new YellOnCloseInputStream(in);
177 
178         ByteArrayOutputStream baout = new ByteArrayOutputStream();
179         YellOnFlushAndCloseOutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
180         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
181         
182         IOUtils.copy(in, writer, "UTF8");
183         out.off();
184         writer.flush();
185 
186         assertTrue("Not all bytes were read", in.available() == 0);
187         byte[] bytes = baout.toByteArray();
188         bytes = new String(bytes, "UTF8").getBytes("US-ASCII");
189         assertTrue("Content differs", Arrays.equals(inData, bytes));
190     }
191 
192     public void testCopy_inputStreamToWriter_Encoding_nullIn() throws Exception {
193         ByteArrayOutputStream baout = new ByteArrayOutputStream();
194         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
195         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
196         try {
197             IOUtils.copy((InputStream) null, writer, "UTF8");
198             fail();
199         } catch (NullPointerException ex) {}
200     }
201 
202     public void testCopy_inputStreamToWriter_Encoding_nullOut() throws Exception {
203         InputStream in = new ByteArrayInputStream(inData);
204         try {
205             IOUtils.copy(in, (Writer) null, "UTF8");
206             fail();
207         } catch (NullPointerException ex) {}
208     }
209 
210     public void testCopy_inputStreamToWriter_Encoding_nullEncoding() throws Exception {
211         InputStream in = new ByteArrayInputStream(inData);
212         in = new YellOnCloseInputStream(in);
213 
214         ByteArrayOutputStream baout = new ByteArrayOutputStream();
215         YellOnFlushAndCloseOutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
216         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
217         
218         IOUtils.copy(in, writer, null);
219         out.off();
220         writer.flush();
221 
222         assertTrue("Not all bytes were read", in.available() == 0);
223         assertEquals("Sizes differ", inData.length, baout.size());
224         assertTrue("Content differs", Arrays.equals(inData, baout.toByteArray()));
225     }
226 
227     //-----------------------------------------------------------------------
228     public void testCopy_readerToOutputStream() throws Exception {
229         InputStream in = new ByteArrayInputStream(inData);
230         in = new YellOnCloseInputStream(in);
231         Reader reader = new InputStreamReader(in, "US-ASCII");
232         
233         ByteArrayOutputStream baout = new ByteArrayOutputStream();
234         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, false, true);
235         
236         IOUtils.copy(reader, out);
237         //Note: this method *does* flush. It is equivalent to:
238         //  OutputStreamWriter _out = new OutputStreamWriter(fout);
239         //  IOUtils.copy( fin, _out, 4096 ); // copy( Reader, Writer, int );
240         //  _out.flush();
241         //  out = fout;
242 
243         // Note: rely on the method to flush
244         assertEquals("Sizes differ", inData.length, baout.size());
245         assertTrue("Content differs", Arrays.equals(inData, baout.toByteArray()));
246     }
247 
248     public void testCopy_readerToOutputStream_nullIn() throws Exception {
249         ByteArrayOutputStream baout = new ByteArrayOutputStream();
250         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
251         try {
252             IOUtils.copy((Reader) null, out);
253             fail();
254         } catch (NullPointerException ex) {}
255     }
256 
257     public void testCopy_readerToOutputStream_nullOut() throws Exception {
258         InputStream in = new ByteArrayInputStream(inData);
259         in = new YellOnCloseInputStream(in);
260         Reader reader = new InputStreamReader(in, "US-ASCII");
261         try {
262             IOUtils.copy(reader, (OutputStream) null);
263             fail();
264         } catch (NullPointerException ex) {}
265     }
266 
267     //-----------------------------------------------------------------------
268     public void testCopy_readerToOutputStream_Encoding() throws Exception {
269         InputStream in = new ByteArrayInputStream(inData);
270         in = new YellOnCloseInputStream(in);
271         Reader reader = new InputStreamReader(in, "US-ASCII");
272         
273         ByteArrayOutputStream baout = new ByteArrayOutputStream();
274         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, false, true);
275 
276         IOUtils.copy(reader, out, "UTF16");
277         // note: this method *does* flush.
278         // note: we don't flush here; this IOUtils method does it for us
279         
280         byte[] bytes = baout.toByteArray();
281         bytes = new String(bytes, "UTF16").getBytes("US-ASCII");
282         assertTrue("Content differs", Arrays.equals(inData, bytes));
283     }
284 
285     public void testCopy_readerToOutputStream_Encoding_nullIn() throws Exception {
286         ByteArrayOutputStream baout = new ByteArrayOutputStream();
287         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
288         try {
289             IOUtils.copy((Reader) null, out, "UTF16");
290             fail();
291         } catch (NullPointerException ex) {}
292     }
293 
294     public void testCopy_readerToOutputStream_Encoding_nullOut() throws Exception {
295         InputStream in = new ByteArrayInputStream(inData);
296         in = new YellOnCloseInputStream(in);
297         Reader reader = new InputStreamReader(in, "US-ASCII");
298         try {
299             IOUtils.copy(reader, (OutputStream) null, "UTF16");
300             fail();
301         } catch (NullPointerException ex) {}
302     }
303 
304     public void testCopy_readerToOutputStream_Encoding_nullEncoding() throws Exception {
305         InputStream in = new ByteArrayInputStream(inData);
306         in = new YellOnCloseInputStream(in);
307         Reader reader = new InputStreamReader(in, "US-ASCII");
308         
309         ByteArrayOutputStream baout = new ByteArrayOutputStream();
310         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, false, true);
311 
312         IOUtils.copy(reader, out, null);
313         // note: this method *does* flush.
314         // note: we don't flush here; this IOUtils method does it for us
315 
316         assertEquals("Sizes differ", inData.length, baout.size());
317         assertTrue("Content differs", Arrays.equals(inData, baout.toByteArray()));
318     }
319 
320     //-----------------------------------------------------------------------
321     public void testCopy_readerToWriter() throws Exception {
322         InputStream in = new ByteArrayInputStream(inData);
323         in = new YellOnCloseInputStream(in);
324         Reader reader = new InputStreamReader(in, "US-ASCII");
325 
326         ByteArrayOutputStream baout = new ByteArrayOutputStream();
327         YellOnFlushAndCloseOutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
328         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
329 
330         int count = IOUtils.copy(reader, writer);
331         out.off();
332         writer.flush();
333         assertEquals("The number of characters returned by copy is wrong", inData.length, count);
334         assertEquals("Sizes differ", inData.length, baout.size());
335         assertTrue("Content differs", Arrays.equals(inData, baout.toByteArray()));
336     }
337 
338     public void testCopy_readerToWriter_nullIn() throws Exception {
339         ByteArrayOutputStream baout = new ByteArrayOutputStream();
340         OutputStream out = new YellOnFlushAndCloseOutputStream(baout, true, true);
341         Writer writer = new OutputStreamWriter(baout, "US-ASCII");
342         try {
343             IOUtils.copy((Reader) null, writer);
344             fail();
345         } catch (NullPointerException ex) {}
346     }
347 
348     public void testCopy_readerToWriter_nullOut() throws Exception {
349         InputStream in = new ByteArrayInputStream(inData);
350         in = new YellOnCloseInputStream(in);
351         Reader reader = new InputStreamReader(in, "US-ASCII");
352         try {
353             IOUtils.copy(reader, (Writer) null);
354             fail();
355         } catch (NullPointerException ex) {}
356     }
357 
358     /**
359      * Test Copying file > 2GB  - see issue# IO-84
360      */
361     public void testCopy_readerToWriter_IO84() throws Exception {
362         long size = (long)Integer.MAX_VALUE + (long)1;
363         Reader reader = new NullReader(size);
364         Writer writer = new NullWriter();
365 
366         // Test copy() method
367         assertEquals(-1, IOUtils.copy(reader, writer));
368 
369         // reset the input
370         reader.close();
371 
372         // Test copyLarge() method
373         assertEquals("copyLarge()", size, IOUtils.copyLarge(reader, writer));
374 
375     }
376 
377 }