1d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// Copyright 2015 Google Inc. All rights reserved.
2d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden//
3d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// Licensed under the Apache License, Version 2.0 (the "License");
4d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// you may not use this file except in compliance with the License.
5d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// You may obtain a copy of the License at
6d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden//
7d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden//     http://www.apache.org/licenses/LICENSE-2.0
8d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden//
9d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// Unless required by applicable law or agreed to in writing, software
10d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// distributed under the License is distributed on an "AS IS" BASIS,
11d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// See the License for the specific language governing permissions and
13d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden// limitations under the License.
14d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
15d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenpackage com.google.archivepatcher.shared;
16d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
17d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport static org.junit.Assert.assertTrue;
18d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
19d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport com.google.archivepatcher.shared.DeflateUncompressor;
20d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
21d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.io.ByteArrayInputStream;
22d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.io.ByteArrayOutputStream;
23d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.io.IOException;
24d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.util.Arrays;
25d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.util.zip.Deflater;
26d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.util.zip.DeflaterOutputStream;
27d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport java.util.zip.Inflater;
28d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
29d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport org.junit.Assert;
30d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport org.junit.Before;
31d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport org.junit.Test;
32d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport org.junit.runner.RunWith;
33d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenimport org.junit.runners.JUnit4;
34d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
35d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden/**
36d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden * Tests for {@link DeflateUncompressor}.
37d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden */
38d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden@RunWith(JUnit4.class)
39d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden@SuppressWarnings("javadoc")
40d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Haydenpublic class DeflateUncompressorTest {
41d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
42d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  /**
43d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden   * Test data for compression. Uses the {@link DefaultDeflateCompatibilityWindow}'s corpus because
44d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden   * it is already set up to produce different outputs for each compression level.
45d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden   */
46d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  private final static byte[] CONTENT = new DefaultDeflateCompatibilityWindow().getCorpus();
47d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
48d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  private byte[] compressedContent;
49d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  private ByteArrayInputStream compressedContentIn;
50d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  private DeflateUncompressor uncompressor;
51d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  private ByteArrayOutputStream uncompressedContentOut;
52d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
53d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Before
54d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void setUp() throws IOException {
55d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    ByteArrayOutputStream compressedContentBuffer = new ByteArrayOutputStream();
56d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
57d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    DeflaterOutputStream deflateOut = new DeflaterOutputStream(compressedContentBuffer, deflater);
58d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.write(CONTENT);
59d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.finish();
60d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.close();
61d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflater.end();
62d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContent = compressedContentBuffer.toByteArray();
63d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor = new DeflateUncompressor();
64d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContentIn = new ByteArrayInputStream(compressedContent);
65d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressedContentOut = new ByteArrayOutputStream();
66d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
67d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
68d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
69d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testUncompress() throws IOException {
70d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
71d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    assertTrue(Arrays.equals(CONTENT, uncompressedContentOut.toByteArray()));
72d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
73d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
74d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
75d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testCorrectDefaults() {
76d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Sanity check to ensure that defaults are as we want them to be. Arguably crufty but nobody
77d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // should change these without some thought, particularly the wrapping choice should not be
78d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // changed in the compressor without also changing it in the *un*compressor.
79d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertTrue(uncompressor.isNowrap());
80d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
81d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
82d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
83d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testNowrap() throws IOException {
84d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Recompress with nowrap set to false.
85d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, false /* nowrap */);
86d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    ByteArrayOutputStream compressedContentBuffer = new ByteArrayOutputStream();
87d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    DeflaterOutputStream deflateOut = new DeflaterOutputStream(compressedContentBuffer, deflater);
88d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.write(CONTENT);
89d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.finish();
90d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.close();
91d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflater.end();
92d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContent = compressedContentBuffer.toByteArray();
93d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContentIn = new ByteArrayInputStream(compressedContent);
94d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
95d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Now expect wrapped content in the uncompressor, and uncompressing should "just work".
96d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setNowrap(false);
97d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
98d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    assertTrue(Arrays.equals(CONTENT, uncompressedContentOut.toByteArray()));
99d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
100d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
101d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
102d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testSetInputBufferSize() throws IOException {
103d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertNotEquals(17, uncompressor.getInputBufferSize()); // Ensure test is valid
104d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setInputBufferSize(17); // Arbitrary non-default value
105d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertEquals(17, uncompressor.getInputBufferSize());
106d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
107d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertArrayEquals(CONTENT, uncompressedContentOut.toByteArray());
108d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
109d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
110d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
111d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testSetOutputBufferSize() throws IOException {
112d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertNotEquals(17, uncompressor.getOutputBufferSize()); // Ensure test is valid
113d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setOutputBufferSize(17); // Arbitrary non-default value
114d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertEquals(17, uncompressor.getOutputBufferSize());
115d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
116d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertArrayEquals(CONTENT, uncompressedContentOut.toByteArray());
117d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
118d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
119d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
120d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testCreateOrResetInflater_Uncached() {
121d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setCaching(false);
122d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Inflater inflater1 = uncompressor.createOrResetInflater();
123d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Inflater inflater2 = uncompressor.createOrResetInflater();
124d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertNotSame(inflater1, inflater2);
125d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
126d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
127d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
128d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testCreateOrResetInflater_Cached() {
129d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setCaching(true);
130d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Inflater inflater1 = uncompressor.createOrResetInflater();
131d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Inflater inflater2 = uncompressor.createOrResetInflater();
132d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertSame(inflater1, inflater2);
133d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
134d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
135d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
136d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testRelease() {
137d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setCaching(true);
138d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Inflater inflater1 = uncompressor.createOrResetInflater();
139d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.release();
140d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Inflater inflater2 = uncompressor.createOrResetInflater();
141d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertNotSame(inflater1, inflater2);
142d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
143d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
144d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  @Test
145d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  public void testReusability() throws IOException {
146d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Checks that the uncompressor produces correct output when cached, i.e. that it is being
147d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // properly reset between runs.
148d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setCaching(true);
149d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
150d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertArrayEquals(CONTENT, uncompressedContentOut.toByteArray());
151d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
152d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Caching is on, try to reuse it without any changes.
153d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContentIn = new ByteArrayInputStream(compressedContent);
154d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressedContentOut = new ByteArrayOutputStream();
155d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
156d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Assert.assertArrayEquals(CONTENT, uncompressedContentOut.toByteArray());
157d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
158d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Caching is still on, reverse the wrapping style and try again. Changing the wrapping style
159d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // invalidates the cached uncompressor because the wrapping style cannot be changed, this is a
160d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // special code path we need to exercise.
161d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, false /* nowrap */);
162d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    ByteArrayOutputStream compressedContentBuffer = new ByteArrayOutputStream();
163d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    DeflaterOutputStream deflateOut = new DeflaterOutputStream(compressedContentBuffer, deflater);
164d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.write(CONTENT);
165d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.finish();
166d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflateOut.close();
167d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    deflater.end();
168d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContent = compressedContentBuffer.toByteArray();
169d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    compressedContentIn = new ByteArrayInputStream(compressedContent);
170d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden
171d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    // Now expect wrapped content in the uncompressor, and uncompressing should "just work".
172d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.setNowrap(false);
173d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressedContentOut = new ByteArrayOutputStream();
174d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    uncompressor.uncompress(compressedContentIn, uncompressedContentOut);
175d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden    assertTrue(Arrays.equals(CONTENT, uncompressedContentOut.toByteArray()));
176d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden  }
177d84e46c30d0ea027d047ee4c75c040a173ec9ffcAndrew Hayden}
178