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.input;
18  
19  import java.io.EOFException;
20  import java.io.IOException;
21  import java.io.InputStream;
22  
23  import junit.framework.TestCase;
24  
25  /**
26   * JUnit Test Case for {@link NullInputStream}.
27   *
28   * @version $Id: NullInputStreamTest.java 463529 2006-10-13 00:37:09Z niallp $
29   */
30  public class NullInputStreamTest extends TestCase {
31  
32      /** Constructor */
33      public NullInputStreamTest(String name) {
34          super(name);
35      }
36  
37      /** Set up */
38      protected void setUp() throws Exception {
39          super.setUp();
40      }
41  
42      /** Tear Down */
43      protected void tearDown() throws Exception {
44          super.tearDown();
45      }
46  
47      /**
48       * Test <code>available()</code> method.
49       */
50      public void testRead() throws Exception {
51          int size = 5;
52          InputStream input = new TestNullInputStream(size);
53          for (int i = 0; i < size; i++) {
54              assertEquals("Check Size [" + i + "]", (size - i), input.available());
55              assertEquals("Check Value [" + i + "]", i, input.read());
56          }
57          assertEquals("Available after contents all read", 0, input.available());
58  
59          // Check availbale is zero after End of file
60          assertEquals("End of File", -1, input.read());
61          assertEquals("Available after End of File", 0, input.available());
62  
63          // Test reading after the end of file
64          try {
65              int result = input.read();
66              fail("Should have thrown an IOException, byte=[" + result + "]");
67          } catch (IOException e) {
68              assertEquals("Read after end of file", e.getMessage());
69          }
70  
71          // Close - should reset
72          input.close();
73          assertEquals("Available after close", size, input.available());
74      }
75  
76      /**
77       * Test <code>read(byte[])</code> method.
78       */
79      public void testReadByteArray() throws Exception {
80          byte[] bytes = new byte[10];
81          InputStream input = new TestNullInputStream(15);
82  
83          // Read into array
84          int count1 = input.read(bytes);
85          assertEquals("Read 1", bytes.length, count1);
86          for (int i = 0; i < count1; i++) {
87              assertEquals("Check Bytes 1", i, bytes[i]);
88          }
89  
90          // Read into array
91          int count2 = input.read(bytes);
92          assertEquals("Read 2", 5, count2);
93          for (int i = 0; i < count2; i++) {
94              assertEquals("Check Bytes 2", count1 + i, bytes[i]);
95          }
96  
97          // End of File
98          int count3 = input.read(bytes);
99          assertEquals("Read 3 (EOF)", -1, count3);
100 
101         // Test reading after the end of file
102         try {
103             int count4 = input.read(bytes);
104             fail("Should have thrown an IOException, byte=[" + count4 + "]");
105         } catch (IOException e) {
106             assertEquals("Read after end of file", e.getMessage());
107         }
108 
109         // reset by closing
110         input.close();
111     
112         // Read into array using offset & length
113         int offset = 2;
114         int lth    = 4;
115         int count5 = input.read(bytes, offset, lth);
116         assertEquals("Read 5", lth, count5);
117         for (int i = offset; i < lth; i++) {
118             assertEquals("Check Bytes 2", i, bytes[i]);
119         }
120     }
121 
122     /**
123      * Test when configured to throw an EOFException at the end of file
124      * (rather than return -1).
125      */
126     public void testEOFException() throws Exception {
127         InputStream input = new TestNullInputStream(2, false, true);
128         assertEquals("Read 1",  0, input.read());
129         assertEquals("Read 2",  1, input.read());
130         try {
131             int result = input.read();
132             fail("Should have thrown an EOFException, byte=[" + result + "]");
133         } catch (EOFException e) {
134             // expected
135         }
136     }
137 
138     /**
139      * Test <code>mark()</code> and <code>reset()</code> methods.
140      */
141     public void testMarkAndReset() throws Exception {
142         int position = 0;
143         int readlimit = 10;
144         InputStream input = new TestNullInputStream(100, true, false);
145         
146         assertTrue("Mark Should be Supported", input.markSupported());
147 
148         // No Mark
149         try {
150             input.reset();
151             fail("Read limit exceeded, expected IOException ");
152         } catch (Exception e) {
153             assertEquals("No Mark IOException message",
154                          "No position has been marked",
155                          e.getMessage());
156         }
157 
158         for (; position < 3; position++) {
159             assertEquals("Read Before Mark [" + position +"]",  position, input.read());
160         }
161 
162         // Mark
163         input.mark(readlimit);
164 
165         // Read further
166         for (int i = 0; i < 3; i++) {
167             assertEquals("Read After Mark [" + i +"]",  (position + i), input.read());
168         }
169 
170         // Reset
171         input.reset();
172 
173         // Read From marked position
174         for (int i = 0; i < readlimit + 1; i++) {
175             assertEquals("Read After Reset [" + i +"]",  (position + i), input.read());
176         }
177 
178         // Reset after read limit passed
179         try {
180             input.reset();
181             fail("Read limit exceeded, expected IOException ");
182         } catch (Exception e) {
183             assertEquals("Read limit IOException message",
184                          "Marked position [" + position
185                          + "] is no longer valid - passed the read limit ["
186                          + readlimit + "]",
187                          e.getMessage());
188         }
189     }
190 
191     /**
192      * Test <code>mark()</code> not supported.
193      */
194     public void testMarkNotSupported() throws Exception {
195         InputStream input = new TestNullInputStream(100, false, true);
196         assertFalse("Mark Should NOT be Supported", input.markSupported());
197 
198         try {
199             input.mark(5);
200             fail("mark() should throw UnsupportedOperationException");
201         } catch (UnsupportedOperationException e) {
202             assertEquals("mark() error message",  "Mark not supported", e.getMessage());
203         }
204 
205         try {
206             input.reset();
207             fail("reset() should throw UnsupportedOperationException");
208         } catch (UnsupportedOperationException e) {
209             assertEquals("reset() error message",  "Mark not supported", e.getMessage());
210         }
211     }
212 
213     /**
214      * Test <code>skip()</code> method.
215      */
216    public void testSkip() throws Exception {
217         InputStream input = new TestNullInputStream(10, true, false);
218         assertEquals("Read 1", 0, input.read());
219         assertEquals("Read 2", 1, input.read());
220         assertEquals("Skip 1", 5, input.skip(5));
221         assertEquals("Read 3", 7, input.read());
222         assertEquals("Skip 2", 2, input.skip(5)); // only 2 left to skip
223         assertEquals("Skip 3 (EOF)", -1, input.skip(5)); // End of file
224         try {
225             input.skip(5); //
226             fail("Expected IOException for skipping after end of file");
227         } catch (Exception e) {
228             assertEquals("Skip after EOF IOException message",
229                     "Skip after end of file",
230                     e.getMessage());
231         }
232     }
233 
234 
235     // ------------- Test NullInputStream implementation -------------
236 
237     private static final class TestNullInputStream extends NullInputStream {
238         public TestNullInputStream(int size) {
239             super(size);
240         }
241         public TestNullInputStream(int size, boolean markSupported, boolean throwEofException) {
242             super(size, markSupported, throwEofException);
243         }
244         protected int processByte() {
245             return ((int)getPosition() - 1);
246         }
247         protected void processBytes(byte[] bytes, int offset, int length) {
248             int startPos = (int)getPosition() - length;
249             for (int i = offset; i < length; i++) {
250                 bytes[i] = (byte)(startPos + i);
251             }
252         }
253         
254     }
255 }