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 
18 package org.apache.harmony.tests.java.util.zip;
19 
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.Arrays;
24 import java.util.zip.DataFormatException;
25 import java.util.zip.Deflater;
26 import java.util.zip.DeflaterInputStream;
27 import libcore.io.Streams;
28 import libcore.junit.junit3.TestCaseWithRules;
29 import libcore.junit.util.ResourceLeakageDetector;
30 import libcore.junit.util.ResourceLeakageDetector.DisableResourceLeakageDetection;
31 import org.junit.Rule;
32 import org.junit.rules.TestRule;
33 
34 public class DeflaterInputStreamTest extends TestCaseWithRules {
35     @Rule
36     public TestRule guardRule = ResourceLeakageDetector.getRule();
37 
38     private static final String TEST_STR = "Hi,this is a test";
39 
40     private static final byte[] TEST_STRING_DEFLATED_BYTES = {
41             120, -100, -13, -56, -44, 41, -55, -56, 44, 86,
42             0, -94, 68, -123, -110, -44, -30, 18, 0, 52,
43             34, 5, -13 };
44 
45     private InputStream is;
46 
47     @Override
setUp()48     protected void setUp() throws Exception {
49         super.setUp();
50         is = new ByteArrayInputStream(TEST_STR.getBytes("UTF-8"));
51     }
52 
53     @Override
tearDown()54     protected void tearDown() throws Exception {
55         is.close();
56         super.tearDown();
57     }
58 
59     /**
60      * DeflaterInputStream#available()
61      */
testAvailable()62     public void testAvailable() throws IOException {
63         byte[] buf = new byte[1024];
64         DeflaterInputStream dis = new DeflaterInputStream(is);
65         assertEquals(1, dis.available());
66         assertEquals(120, dis.read());
67         assertEquals(1, dis.available());
68         assertEquals(22, dis.read(buf, 0, 1024));
69         assertEquals(0, dis.available());
70         assertEquals(-1, dis.read());
71         assertEquals(0, dis.available());
72         dis.close();
73         try {
74             dis.available();
75             fail("should throw IOException");
76         } catch (IOException e) {
77             // expected
78         }
79     }
80 
81     /**
82      * DeflaterInputStream#close()
83      */
testClose()84     public void testClose() throws IOException {
85         byte[] buf = new byte[1024];
86         DeflaterInputStream dis = new DeflaterInputStream(is);
87         assertEquals(1, dis.available());
88         dis.close();
89         try {
90             dis.available();
91             fail("should throw IOException");
92         } catch (IOException e) {
93             // expected
94         }
95         try {
96             dis.read(buf, 0, 1024);
97             fail("should throw IOException");
98         } catch (IOException e) {
99             // expected
100         }
101         // can close after close
102         dis.close();
103     }
104 
105     /**
106      * DeflaterInputStream#mark()
107      */
testMark()108     public void testMark() throws IOException {
109         // mark do nothing
110         DeflaterInputStream dis = new DeflaterInputStream(is);
111         dis.mark(-1);
112         dis.mark(0);
113         dis.mark(1);
114         dis.close();
115         dis.mark(1);
116     }
117 
118     /**
119      * DeflaterInputStream#markSupported()
120      */
testMarkSupported()121     public void testMarkSupported() throws IOException {
122         DeflaterInputStream dis = new DeflaterInputStream(is);
123         assertFalse(dis.markSupported());
124         dis.close();
125         assertFalse(dis.markSupported());
126     }
127 
128     /**
129      * DeflaterInputStream#read()
130      */
testRead()131     public void testRead() throws IOException {
132         DeflaterInputStream dis = new DeflaterInputStream(is);
133         assertEquals(1, dis.available());
134         assertEquals(120, dis.read());
135         assertEquals(1, dis.available());
136         assertEquals(156, dis.read());
137         assertEquals(1, dis.available());
138         assertEquals(243, dis.read());
139         assertEquals(1, dis.available());
140         dis.close();
141         try {
142             dis.read();
143             fail("should throw IOException");
144         } catch (IOException e) {
145             // expected
146         }
147     }
148 
testRead_golden()149     public void testRead_golden() throws Exception {
150         try (DeflaterInputStream dis = new DeflaterInputStream(is)) {
151             byte[] contents = Streams.readFully(dis);
152             assertTrue(Arrays.equals(TEST_STRING_DEFLATED_BYTES, contents));
153         }
154 
155         try (DeflaterInputStream dis = new DeflaterInputStream(
156                 new ByteArrayInputStream(TEST_STR.getBytes("UTF-8")))) {
157             byte[] result = new byte[32];
158             int count = 0;
159             int bytesRead;
160             while ((bytesRead = dis.read(result, count, 4)) != -1) {
161                 count += bytesRead;
162             }
163             assertEquals(23, count);
164             byte[] splicedResult = new byte[23];
165             System.arraycopy(result, 0, splicedResult, 0, 23);
166             assertTrue(Arrays.equals(TEST_STRING_DEFLATED_BYTES, splicedResult));
167         }
168     }
169 
testRead_leavesBufUnmodified()170     public void testRead_leavesBufUnmodified() throws Exception {
171         DeflaterInputStreamWithPublicBuffer dis = new DeflaterInputStreamWithPublicBuffer(is);
172         byte[] contents = Streams.readFully(dis);
173         assertTrue(Arrays.equals(TEST_STRING_DEFLATED_BYTES, contents));
174 
175         // protected field buf is a part of the public API of this class.
176         // we guarantee that it's only used as an input buffer, and not for
177         // anything else.
178         byte[] buf = dis.getBuffer();
179         byte[] expected = TEST_STR.getBytes("UTF-8");
180 
181         byte[] splicedBuf = new byte[expected.length];
182         System.arraycopy(buf, 0, splicedBuf, 0, splicedBuf.length);
183         assertTrue(Arrays.equals(expected, splicedBuf));
184     }
185 
186     /**
187      * DeflaterInputStream#read(byte[], int, int)
188      */
testReadByteArrayIntInt()189     public void testReadByteArrayIntInt() throws IOException {
190         byte[] buf1 = new byte[256];
191         byte[] buf2 = new byte[256];
192         try (DeflaterInputStream dis = new DeflaterInputStream(is)) {
193             assertEquals(23, dis.read(buf1, 0, 256));
194         }
195 
196         try (DeflaterInputStream dis = new DeflaterInputStream(is)) {
197             assertEquals(8, dis.read(buf2, 0, 256));
198         }
199 
200         is = new ByteArrayInputStream(TEST_STR.getBytes("UTF-8"));
201         DeflaterInputStream dis = new DeflaterInputStream(is);
202         assertEquals(1, dis.available());
203         assertEquals(120, dis.read());
204         assertEquals(1, dis.available());
205         assertEquals(22, dis.read(buf2, 0, 256));
206         assertEquals(0, dis.available());
207         assertEquals(-1, dis.read());
208         assertEquals(0, dis.available());
209         try {
210             dis.read(buf1, 0, 512);
211             fail("should throw IndexOutOfBoundsException");
212         } catch (IndexOutOfBoundsException e) {
213             // expected
214         }
215         try {
216             dis.read(null, 0, 0);
217             fail("should throw NullPointerException");
218         } catch (NullPointerException e) {
219             // expected
220         }
221         try {
222             dis.read(null, -1, 0);
223             fail("should throw NullPointerException");
224         } catch (NullPointerException e) {
225             // expected
226         }
227         try {
228             dis.read(null, -1, -1);
229             fail("should throw NullPointerException");
230         } catch (NullPointerException e) {
231             // expected
232         }
233         try {
234             dis.read(buf1, -1, -1);
235             fail("should throw IndexOutOfBoundsException");
236         } catch (IndexOutOfBoundsException e) {
237             // expected
238         }
239         try {
240             dis.read(buf1, 0, -1);
241             fail("should throw IndexOutOfBoundsException");
242         } catch (IndexOutOfBoundsException e) {
243             // expected
244         }
245         dis.close();
246         try {
247             dis.read(buf1, 0, 512);
248             fail("should throw IOException");
249         } catch (IOException e) {
250             // expected
251         }
252         try {
253             dis.read(buf1, 0, 1);
254             fail("should throw IOException");
255         } catch (IOException e) {
256             // expected
257         }
258         try {
259             dis.read(null, 0, 0);
260             fail("should throw IOException");
261         } catch (IOException e) {
262             // expected
263         }
264         try {
265             dis.read(null, -1, 0);
266             fail("should throw IOException");
267         } catch (IOException e) {
268             // expected
269         }
270         try {
271             dis.read(null, -1, -1);
272             fail("should throw IOException");
273         } catch (IOException e) {
274             // expected
275         }
276         try {
277             dis.read(buf1, -1, -1);
278             fail("should throw IOException");
279         } catch (IOException e) {
280             // expected
281         }
282         try {
283             dis.read(buf1, 0, -1);
284             fail("should throw IOException");
285         } catch (IOException e) {
286             // expected
287         }
288     }
289 
290     /**
291      * DeflaterInputStream#reset()
292      */
testReset()293     public void testReset() throws IOException {
294         DeflaterInputStream dis = new DeflaterInputStream(is);
295         try {
296             dis.reset();
297             fail("should throw IOException");
298         } catch (IOException e) {
299             // expected
300         }
301         dis.close();
302         try {
303             dis.reset();
304             fail("should throw IOException");
305         } catch (IOException e) {
306             // expected
307         }
308     }
309 
310     /**
311      * DeflaterInputStream#skip()
312      */
testSkip()313     public void testSkip() throws IOException {
314         byte[] buf = new byte[1024];
315         try (DeflaterInputStream dis = new DeflaterInputStream(is)) {
316             assertEquals(1, dis.available());
317             dis.skip(1);
318             assertEquals(1, dis.available());
319             assertEquals(22, dis.read(buf, 0, 1024));
320             assertEquals(0, dis.available());
321             assertEquals(0, dis.available());
322             is = new ByteArrayInputStream(TEST_STR.getBytes("UTF-8"));
323         }
324 
325         is = new ByteArrayInputStream(TEST_STR.getBytes("UTF-8"));
326         try (DeflaterInputStream dis = new DeflaterInputStream(is)) {
327             assertEquals(23, dis.skip(Long.MAX_VALUE));
328             assertEquals(0, dis.available());
329         }
330 
331         DeflaterInputStream dis = new DeflaterInputStream(is);
332         assertEquals(1, dis.available());
333         dis.skip(56);
334         assertEquals(0, dis.available());
335         assertEquals(-1, dis.read(buf, 0, 1024));
336 
337         assertEquals(0, dis.available());
338         // can still skip
339         dis.skip(1);
340         dis.close();
341         try {
342             dis.skip(1);
343             fail("should throw IOException");
344         } catch (IOException e) {
345             // expected
346         }
347     }
348 
349     /**
350      * DeflaterInputStream#DeflaterInputStream(InputStream)
351      */
352     @DisableResourceLeakageDetection(
353             why = "DeflaterInputStream does not clean up the default Deflater created in the"
354                     + " constructor if the constructor fails; i.e. constructor calls"
355                     + " this(..., new Deflater(), ...) and that constructor fails but does not know"
356                     + " that it needs to call Deflater.end() as the caller has no access to it",
357             bug = "31798154")
testDeflaterInputStreamInputStream()358     public void testDeflaterInputStreamInputStream() throws IOException {
359         // ok
360         new DeflaterInputStream(is).close();
361         // fail
362         try {
363             new DeflaterInputStream(null);
364             fail("should throw NullPointerException");
365         } catch (NullPointerException e) {
366             // expected
367         }
368     }
369 
370     /**
371      * DataFormatException#DataFormatException()
372      */
testDataFormatException()373     public void testDataFormatException() {
374         new DataFormatException();
375     }
376 
377     /**
378      * DeflaterInputStream#DeflaterInputStream(InputStream, Deflater)
379      */
testDeflaterInputStreamInputStreamDeflater()380     public void testDeflaterInputStreamInputStreamDeflater() throws IOException {
381         // ok
382         Deflater deflater = new Deflater();
383         try {
384             new DeflaterInputStream(is, deflater).close();
385             // fail
386             try {
387                 new DeflaterInputStream(is, null);
388                 fail("should throw NullPointerException");
389             } catch (NullPointerException e) {
390                 // expected
391             }
392             try {
393                 new DeflaterInputStream(null, deflater);
394                 fail("should throw NullPointerException");
395             } catch (NullPointerException e) {
396                 // expected
397             }
398         } finally {
399             deflater.end();
400         }
401     }
402 
403     /**
404      * DeflaterInputStream#DeflaterInputStream(InputStream, Deflater, int)
405      */
testDeflaterInputStreamInputStreamDeflaterInt()406     public void testDeflaterInputStreamInputStreamDeflaterInt() {
407         // ok
408         Deflater deflater = new Deflater();
409         try {
410             new DeflaterInputStream(is, deflater, 1024);
411             // fail
412             try {
413                 new DeflaterInputStream(is, null, 1024);
414                 fail("should throw NullPointerException");
415             } catch (NullPointerException e) {
416                 // expected
417             }
418             try {
419                 new DeflaterInputStream(null, deflater, 1024);
420                 fail("should throw NullPointerException");
421             } catch (NullPointerException e) {
422                 // expected
423             }
424             try {
425                 new DeflaterInputStream(is, deflater, -1);
426                 fail("should throw IllegalArgumentException");
427             } catch (IllegalArgumentException e) {
428                 // expected
429             }
430             try {
431                 new DeflaterInputStream(null, deflater, -1);
432                 fail("should throw NullPointerException");
433             } catch (NullPointerException e) {
434                 // expected
435             }
436             try {
437                 new DeflaterInputStream(is, null, -1);
438                 fail("should throw NullPointerException");
439             } catch (NullPointerException e) {
440                 // expected
441             }
442         } finally {
443             deflater.end();
444         }
445     }
446 
447     public static final class DeflaterInputStreamWithPublicBuffer extends DeflaterInputStream {
448 
DeflaterInputStreamWithPublicBuffer(InputStream in)449         public DeflaterInputStreamWithPublicBuffer(InputStream in) {
450             super(in);
451         }
452 
getBuffer()453         public byte[] getBuffer() {
454             return buf;
455         }
456     }
457 }
458