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