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.tika;
18  
19  import java.io.BufferedInputStream;
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  
26  import org.apache.tika.utils.RereadableInputStream;
27  
28  import junit.framework.TestCase;
29  
30  public class TestRereadableInputStream extends TestCase {
31  
32      private final int TEST_SIZE = 3;
33  
34      private final int MEMORY_THRESHOLD = 1;
35  
36      private final int NUM_PASSES = 4;
37  
38      public void test() throws IOException {
39  
40          InputStream is = createTestInputStream();
41          RereadableInputStream ris = new RereadableInputStream(is,
42                  MEMORY_THRESHOLD, true, true);
43          try {
44              for (int pass = 0; pass < NUM_PASSES; pass++) {
45                  for (int byteNum = 0; byteNum < TEST_SIZE; byteNum++) {
46                      int byteRead = ris.read();
47                      assertEquals("Pass = " + pass + ", byte num should be "
48                              + byteNum + " but is " + byteRead + ".", byteNum,
49                              byteRead);
50                  }
51                  ris.rewind();
52              }
53          } finally {
54              // The RereadableInputStream should close the original input
55              // stream (if it hasn't already).
56              ris.close();
57          }
58      }
59  
60      /**
61       * Test that the constructor's readToEndOfStreamOnFirstRewind parameter
62       * correctly determines the behavior.
63       * 
64       * @throws IOException
65       */
66      public void testRewind() throws IOException {
67          doTestRewind(true);
68          doTestRewind(false);
69      }
70  
71      private void doTestRewind(boolean readToEndOnRewind) throws IOException {
72  
73          RereadableInputStream ris = null;
74  
75          try {
76              InputStream s1 = createTestInputStream();
77              ris = new RereadableInputStream(s1, 5, readToEndOnRewind, true);
78              ris.read();
79              assertEquals(1, ris.getSize());
80              ris.rewind();
81              boolean moreBytesWereRead = (ris.getSize() > 1);
82              assertEquals(readToEndOnRewind, moreBytesWereRead);
83          } finally {
84              if (ris != null) {
85                  ris.close();
86              }
87          }
88  
89      }
90  
91      private TestInputStream createTestInputStream() throws IOException {
92          return new TestInputStream(
93                  new BufferedInputStream(
94                          new FileInputStream(createTestFile())));
95      }
96  
97      private File createTestFile() throws IOException {
98          File testfile = File.createTempFile("TIKA_ris_test", ".tmp");
99          testfile.deleteOnExit();
100         FileOutputStream fos = new FileOutputStream(testfile);
101         for (int i = 0; i < TEST_SIZE; i++) {
102             fos.write(i);
103         }
104         fos.close();
105         return testfile;
106     }
107 
108 
109     public void testCloseBehavior() throws IOException {
110         doACloseBehaviorTest(true);
111         doACloseBehaviorTest(false);
112     }
113 
114     private void doACloseBehaviorTest(boolean wantToClose) throws IOException {
115 
116         TestInputStream tis = createTestInputStream();
117         RereadableInputStream ris =
118                 new RereadableInputStream(tis, 5, true, wantToClose);
119         ris.close();
120         assertEquals(wantToClose, tis.isClosed());
121 
122         if (! tis.isClosed()) {
123             tis.close();
124         }
125     }
126 
127 
128     /**
129      * Adds isClosed() to a BufferedInputStream.
130      */
131     class TestInputStream extends BufferedInputStream {
132 
133         private boolean closed;
134 
135         public TestInputStream(InputStream inputStream) {
136             super(inputStream);
137         }
138 
139         public void close() throws IOException {
140             super.close();
141             closed = true;
142         }
143 
144         public boolean isClosed() {
145             return closed;
146         }
147     }
148 
149 }