View Javadoc
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 static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.util.concurrent.atomic.AtomicBoolean;
29  import java.util.zip.Adler32;
30  import java.util.zip.CRC32;
31  
32  import org.apache.commons.io.IOUtils;
33  import org.apache.commons.io.test.CustomIOException;
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Tests {@link ChecksumInputStream}.
38   */
39  public class ChecksumInputStreamTest {
40  
41      private ChecksumInputStream createInputStream() throws IOException {
42          return ChecksumInputStream.builder().setCharSequence("Hi").setChecksum(new CRC32()).get();
43      }
44  
45      @Test
46      public void testAfterReadConsumer() throws Exception {
47          final AtomicBoolean boolRef = new AtomicBoolean();
48          // @formatter:off
49          try (InputStream bounded = ChecksumInputStream.builder()
50                  .setCharSequence("Hi")
51                  .setChecksum(new CRC32())
52                  .setExpectedChecksumValue(1293356558)
53                  .setAfterRead(i -> boolRef.set(true))
54                  .get()) {
55              IOUtils.consume(bounded);
56          }
57          // @formatter:on
58          assertTrue(boolRef.get());
59          // Throwing
60          final String message = "test exception message";
61          // @formatter:off
62          try (InputStream bounded = ChecksumInputStream.builder()
63                  .setCharSequence("Hi")
64                  .setChecksum(new CRC32())
65                  .setExpectedChecksumValue(1293356558)
66                  .setAfterRead(i -> {
67                      throw new CustomIOException(message);
68                  })
69                  .get()) {
70              assertEquals(message, assertThrowsExactly(CustomIOException.class, () -> IOUtils.consume(bounded)).getMessage());
71          }
72          // @formatter:on
73      }
74  
75      @SuppressWarnings("resource")
76      @Test
77      public void testAvailableAfterClose() throws Exception {
78          final InputStream shadow;
79          try (InputStream in = createInputStream()) {
80              assertTrue(in.available() > 0);
81              shadow = in;
82          }
83          assertEquals(0, shadow.available());
84      }
85  
86      @Test
87      public void testAvailableAfterOpen() throws Exception {
88          try (InputStream in = createInputStream()) {
89              assertTrue(in.available() > 0);
90              assertEquals('H', in.read());
91              assertTrue(in.available() > 0);
92          }
93      }
94  
95      @Test
96      public void testDefaultThresholdFailure() throws IOException {
97          final byte[] byteArray = new byte[3];
98          final Adler32 adler32 = new Adler32();
99          try (ChecksumInputStream checksum = ChecksumInputStream.builder()
100         // @formatter:off
101                 .setByteArray(byteArray)
102                 .setChecksum(adler32)
103                 .setExpectedChecksumValue((byte) -68)
104                 .get()) {
105                 // @formatter:on
106             assertEquals(0, checksum.getByteCount());
107             assertEquals(-1, checksum.getRemaining());
108             // Ask to read one more byte than there is, we get the correct byte count.
109             assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
110             // Next read is at EOF
111             assertThrows(IOException.class, () -> checksum.read(new byte[1]));
112             assertEquals(byteArray.length, checksum.getByteCount());
113             assertEquals(-4, checksum.getRemaining());
114         }
115     }
116 
117     @Test
118     public void testDefaultThresholdSuccess() throws IOException {
119         // sanity-check
120         final Adler32 sanityCheck = new Adler32();
121         final byte[] byteArray = new byte[3];
122         sanityCheck.update(byteArray);
123         final long expectedChecksum = sanityCheck.getValue();
124         // actual
125         final Adler32 adler32 = new Adler32();
126         try (ChecksumInputStream checksum = ChecksumInputStream.builder()
127         // @formatter:off
128                 .setByteArray(byteArray)
129                 .setChecksum(adler32)
130                 .setExpectedChecksumValue(expectedChecksum)
131                 .get()) {
132                 // @formatter:on
133             assertEquals(0, checksum.getByteCount());
134             assertEquals(-1, checksum.getRemaining());
135             assertEquals(3, checksum.read(byteArray));
136             assertEquals(byteArray.length, checksum.getByteCount());
137             assertEquals(-4, checksum.getRemaining());
138             assertEquals(-1, checksum.read(byteArray));
139             assertEquals(byteArray.length, checksum.getByteCount());
140             assertEquals(-4, checksum.getRemaining());
141         }
142     }
143 
144     @SuppressWarnings("resource")
145     @Test
146     public void testReadAfterClose() throws Exception {
147         final InputStream shadow;
148         try (InputStream in = createInputStream()) {
149             assertTrue(in.available() > 0);
150             shadow = in;
151         }
152         assertEquals(IOUtils.EOF, shadow.read());
153     }
154 
155     @Test
156     public void testReadTakingByteArrayThrowsException() throws IOException {
157         final Adler32 adler32 = new Adler32();
158         final byte[] byteArray = new byte[3];
159         final long sizeThreshold = -1859L;
160         try (ChecksumInputStream checksum = ChecksumInputStream.builder()
161         // @formatter:off
162                 .setByteArray(byteArray)
163                 .setChecksum(adler32)
164                 .setExpectedChecksumValue((byte) -68)
165                 .setCountThreshold(sizeThreshold)
166                 .get()) {
167                 // @formatter:on
168             assertEquals(0, checksum.getByteCount());
169             assertEquals(sizeThreshold, checksum.getRemaining());
170             // Ask to read one more byte than there is.
171             assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
172             // Next read is at EOF
173             assertThrows(IOException.class, () -> checksum.read(new byte[1]));
174             assertEquals(byteArray.length, checksum.getByteCount());
175             assertEquals(sizeThreshold - byteArray.length, checksum.getRemaining());
176         }
177     }
178 
179     @Test
180     public void testReadTakingNoArgumentsThrowsException() throws IOException {
181         final CRC32 crc32 = new CRC32();
182         final byte[] byteArray = new byte[9];
183         try (ChecksumInputStream checksum = ChecksumInputStream.builder()
184         // @formatter:off
185                 .setByteArray(byteArray)
186                 .setChecksum(crc32)
187                 .setExpectedChecksumValue((byte) 1)
188                 .setCountThreshold(1)
189                 .get()) {
190                 // @formatter:on
191             assertEquals(0, checksum.getByteCount());
192             assertEquals(1, checksum.getRemaining());
193             assertThrows(IOException.class, () -> checksum.read());
194             assertEquals(1, checksum.getByteCount());
195             assertEquals(0, checksum.getRemaining());
196         }
197     }
198 
199     @Test
200     public void testSkip() throws IOException {
201         // sanity-check
202         final CRC32 sanityCheck = new CRC32();
203         final byte[] byteArray = new byte[4];
204         sanityCheck.update(byteArray);
205         final long expectedChecksum = sanityCheck.getValue();
206         // actual
207         final CRC32 crc32 = new CRC32();
208         final InputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
209         try (ChecksumInputStream checksum = ChecksumInputStream.builder()
210         // @formatter:off
211                 .setInputStream(byteArrayInputStream)
212                 .setChecksum(crc32)
213                 .setExpectedChecksumValue(expectedChecksum)
214                 .setCountThreshold(33)
215                 .get()) {
216                 // @formatter:on
217             assertEquals(0, checksum.getByteCount());
218             assertEquals(4, checksum.read(byteArray));
219             assertEquals(byteArray.length, checksum.getByteCount());
220             assertEquals(29, checksum.getRemaining());
221             final long skipReturnValue = checksum.skip((byte) 1);
222             assertEquals(byteArray.length, checksum.getByteCount());
223             assertEquals(29, checksum.getRemaining());
224             assertEquals(558161692L, crc32.getValue());
225             assertEquals(0, byteArrayInputStream.available());
226             assertArrayEquals(new byte[4], byteArray);
227             assertEquals(0L, skipReturnValue);
228             assertEquals(29, checksum.getRemaining());
229         }
230     }
231 
232 }