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.output;
18  
19  import junit.framework.TestCase;
20  //import org.apache.commons.fileupload.DeferredFileOutputStream;
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileNotFoundException;
25  import java.io.IOException;
26  import java.util.Arrays;
27  
28  /**
29   * Unit tests for the <code>DeferredFileOutputStream</code> class.
30   *
31   * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
32   *
33   * @version $Id: DeferredFileOutputStreamTest.java 437680 2006-08-28 11:57:00Z scolebourne $
34   */
35  public class DeferredFileOutputStreamTest extends TestCase
36   {
37  
38      /**
39       * The test data as a string (which is the simplest form).
40       */
41      private String testString = "0123456789";
42  
43      /**
44       * The test data as a byte array, derived from the string.
45       */
46      private byte[] testBytes = testString.getBytes();
47  
48      /**
49       * Standard JUnit test case constructor.
50       *
51       * @param name The name of the test case.
52       */
53      public DeferredFileOutputStreamTest(String name)
54      {
55          super(name);
56      }
57  
58      /**
59       * Tests the case where the amount of data falls below the threshold, and
60       * is therefore confined to memory.
61       */
62      public void testBelowThreshold()
63      {
64          DeferredFileOutputStream dfos =
65                  new DeferredFileOutputStream(testBytes.length + 42, null);
66          try
67          {
68              dfos.write(testBytes, 0, testBytes.length);
69              dfos.close();
70          }
71          catch (IOException e) {
72              fail("Unexpected IOException");
73          }
74          assertTrue(dfos.isInMemory());
75  
76          byte[] resultBytes = dfos.getData();
77          assertTrue(resultBytes.length == testBytes.length);
78          assertTrue(Arrays.equals(resultBytes, testBytes));
79      }
80  
81      /**
82       * Tests the case where the amount of data is exactly the same as the
83       * threshold. The behavior should be the same as that for the amount of
84       * data being below (i.e. not exceeding) the threshold.
85       */
86      public void testAtThreshold() {
87          DeferredFileOutputStream dfos =
88                  new DeferredFileOutputStream(testBytes.length, null);
89          try
90          {
91              dfos.write(testBytes, 0, testBytes.length);
92              dfos.close();
93          }
94          catch (IOException e) {
95              fail("Unexpected IOException");
96          }
97          assertTrue(dfos.isInMemory());
98  
99          byte[] resultBytes = dfos.getData();
100         assertTrue(resultBytes.length == testBytes.length);
101         assertTrue(Arrays.equals(resultBytes, testBytes));
102     }
103 
104     /**
105      * Tests the case where the amount of data exceeds the threshold, and is
106      * therefore written to disk. The actual data written to disk is verified,
107      * as is the file itself.
108      */
109     public void testAboveThreshold() {
110         File testFile = new File("testAboveThreshold.dat");
111 
112         // Ensure that the test starts from a clean base.
113         testFile.delete();
114 
115         DeferredFileOutputStream dfos =
116                 new DeferredFileOutputStream(testBytes.length - 5, testFile);
117         try
118         {
119             dfos.write(testBytes, 0, testBytes.length);
120             dfos.close();
121         }
122         catch (IOException e) {
123             fail("Unexpected IOException");
124         }
125         assertFalse(dfos.isInMemory());
126         assertNull(dfos.getData());
127 
128         verifyResultFile(testFile);
129 
130         // Ensure that the test starts from a clean base.
131         testFile.delete();
132     }
133 
134     /**
135      * Tests the case where there are multiple writes beyond the threshold, to
136      * ensure that the <code>thresholdReached()</code> method is only called
137      * once, as the threshold is crossed for the first time.
138      */
139     public void testThresholdReached() {
140         File testFile = new File("testThresholdReached.dat");
141 
142         // Ensure that the test starts from a clean base.
143         testFile.delete();
144 
145         DeferredFileOutputStream dfos =
146                 new DeferredFileOutputStream(testBytes.length / 2, testFile);
147         int chunkSize = testBytes.length / 3;
148 
149         try
150         {
151             dfos.write(testBytes, 0, chunkSize);
152             dfos.write(testBytes, chunkSize, chunkSize);
153             dfos.write(testBytes, chunkSize * 2,
154                     testBytes.length - chunkSize * 2);
155             dfos.close();
156         }
157         catch (IOException e) {
158             fail("Unexpected IOException");
159         }
160         assertFalse(dfos.isInMemory());
161         assertNull(dfos.getData());
162 
163         verifyResultFile(testFile);
164 
165         // Ensure that the test starts from a clean base.
166         testFile.delete();
167     }
168     
169 
170     /**
171      * Test wether writeTo() properly writes small content.
172      */
173     public void testWriteToSmall(){
174         File testFile = new File("testWriteToMem.dat");
175         ByteArrayOutputStream baos = new ByteArrayOutputStream();
176         // Ensure that the test starts from a clean base.
177         testFile.delete();
178 
179         DeferredFileOutputStream dfos =
180                 new DeferredFileOutputStream(testBytes.length *2, testFile);
181         try{
182             dfos.write(testBytes);
183 
184             assertFalse(testFile.exists());
185             assertTrue(dfos.isInMemory());
186             
187             try {
188                 dfos.writeTo(baos);
189                 fail("Should not have been able to write before closing");
190             } catch (IOException ioe) {
191                 // ok, as expected
192             }
193         
194             dfos.close();
195             dfos.writeTo(baos);
196         } catch (IOException ioe) {
197             fail("Unexpected IOException");
198         }
199         byte[] copiedBytes  = baos.toByteArray();
200         assertTrue(Arrays.equals(testBytes, copiedBytes));
201 
202         testFile.delete();
203     }
204 
205     /**
206      * Test wether writeTo() properly writes large content.
207      */
208     public void testWriteToLarge(){
209         File testFile = new File("testWriteToFile.dat");
210         ByteArrayOutputStream baos = new ByteArrayOutputStream();
211         // Ensure that the test starts from a clean base.
212         testFile.delete();
213 
214         DeferredFileOutputStream dfos =
215                 new DeferredFileOutputStream(testBytes.length /2, testFile);
216         try{
217             dfos.write(testBytes);
218 
219             assertTrue(testFile.exists());
220             assertFalse(dfos.isInMemory());
221             
222             try {
223                 dfos.writeTo(baos);
224                 fail("Should not have been able to write before closeing");
225             } catch (IOException ioe) {
226                 // ok, as expected
227             }
228         
229             dfos.close();
230             dfos.writeTo(baos);
231         } catch (IOException ioe) {
232             fail("Unexpected IOException");
233         }
234         byte[] copiedBytes  = baos.toByteArray();
235         assertTrue(Arrays.equals(testBytes, copiedBytes));
236         verifyResultFile(testFile);
237         testFile.delete();
238     }
239 
240     /**
241      * Verifies that the specified file contains the same data as the original
242      * test data.
243      *
244      * @param testFile The file containing the test output.
245      */
246     private void verifyResultFile(File testFile) {
247         try
248         {
249             FileInputStream fis = new FileInputStream(testFile);
250             assertTrue(fis.available() == testBytes.length);
251 
252             byte[] resultBytes = new byte[testBytes.length];
253             assertTrue(fis.read(resultBytes) == testBytes.length);
254 
255             assertTrue(Arrays.equals(resultBytes, testBytes));
256             assertTrue(fis.read(resultBytes) == -1);
257 
258             try
259             {
260                 fis.close();
261             }
262             catch (IOException e) {
263                 // Ignore an exception on close
264             }
265         }
266         catch (FileNotFoundException e) {
267             fail("Unexpected FileNotFoundException");
268         }
269         catch (IOException e) {
270             fail("Unexpected IOException");
271         }
272     }
273 }