blob: 86e4687ef8809ca37289ca0e621fb6c13c2fd893 [file] [log] [blame]
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.archivepatcher.applier;
import com.google.archivepatcher.shared.JreDeflateParameters;
import com.google.archivepatcher.shared.TypedRange;
import com.google.archivepatcher.shared.UnitTestZipArchive;
import com.google.archivepatcher.shared.UnitTestZipEntry;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
/**
* Tests for {@link PartiallyCompressingOutputStream}.
*/
@RunWith(JUnit4.class)
@SuppressWarnings("javadoc")
public class PartiallyCompressingOutputStreamTest {
private ByteArrayOutputStream outBuffer;
private PartiallyCompressingOutputStream stream;
// The preamble comes before any compressed bytes in the stream
private static byte[] PREAMBLE_BYTES = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// First range for compression
private static JreDeflateParameters PARAMS1 = JreDeflateParameters.of(1, 0, true);
private static UnitTestZipEntry ENTRY1 =
UnitTestZipArchive.makeUnitTestZipEntry(
"/foo", PARAMS1.level, PARAMS1.nowrap, "foo-level1", null);
private static long OFFSET1 = PREAMBLE_BYTES.length;
private static long LENGTH1 = ENTRY1.getUncompressedBinaryContent().length;
private static TypedRange<JreDeflateParameters> COMPRESS_RANGE_1 =
new TypedRange<JreDeflateParameters>(OFFSET1, LENGTH1, PARAMS1);
private static byte[] GAP1_BYTES = new byte[] {37};
// Second range for compression, with a gap in between. Note this changes nowrap and level
private static JreDeflateParameters PARAMS2 = JreDeflateParameters.of(6, 0, false);
private static UnitTestZipEntry ENTRY2 =
UnitTestZipArchive.makeUnitTestZipEntry(
"/bar", PARAMS2.level, PARAMS2.nowrap, "bar-level6", null);
private static long OFFSET2 = OFFSET1 + LENGTH1 + GAP1_BYTES.length;
private static long LENGTH2 = ENTRY2.getUncompressedBinaryContent().length;
private static TypedRange<JreDeflateParameters> COMPRESS_RANGE_2 =
new TypedRange<JreDeflateParameters>(OFFSET2, LENGTH2, PARAMS2);
private byte[] fuse(byte[]... arrays) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (byte[] array : arrays) {
buffer.write(array);
}
return buffer.toByteArray();
}
@Before
public void setup() {
outBuffer = new ByteArrayOutputStream();
}
@Test
public void testWrite_Nothing() throws IOException {
// Test the case where there are no compression ranges at all and nothing is written.
stream =
new PartiallyCompressingOutputStream(
Collections.<TypedRange<JreDeflateParameters>>emptyList(), outBuffer, 32768);
byte[] input = new byte[] {};
stream.write(input);
stream.flush();
stream.close();
Assert.assertArrayEquals(input, outBuffer.toByteArray());
}
@Test
public void testWrite_NoneCompressed() throws IOException {
// Test the case where there are no compression ranges at all.
stream =
new PartiallyCompressingOutputStream(
Collections.<TypedRange<JreDeflateParameters>>emptyList(), outBuffer, 32768);
byte[] input = new byte[] {1, 77, 66, 44, 22, 11};
byte[] expected = input.clone();
stream.write(input);
stream.flush();
Assert.assertArrayEquals(expected, outBuffer.toByteArray());
}
@Test
public void testWrite_AllCompressed() throws IOException {
// Test the case where a single compression range covers the entire input
TypedRange<JreDeflateParameters> range =
new TypedRange<JreDeflateParameters>(
0, ENTRY1.getUncompressedBinaryContent().length, PARAMS1);
stream =
new PartiallyCompressingOutputStream(Collections.singletonList(range), outBuffer, 32768);
stream.write(ENTRY1.getUncompressedBinaryContent());
stream.flush();
Assert.assertArrayEquals(ENTRY1.getCompressedBinaryContent(), outBuffer.toByteArray());
}
@Test
public void testWrite_GapAndCompression() throws IOException {
// Write uncompressed data followed by compressed data
stream =
new PartiallyCompressingOutputStream(
Collections.singletonList(COMPRESS_RANGE_1), outBuffer, 32768);
byte[] input = fuse(PREAMBLE_BYTES, ENTRY1.getUncompressedBinaryContent());
byte[] expected = fuse(PREAMBLE_BYTES, ENTRY1.getCompressedBinaryContent());
stream.write(input);
stream.flush();
Assert.assertArrayEquals(expected, outBuffer.toByteArray());
}
@Test
public void testWrite_GapAndCompressionAndGap() throws IOException {
// Write uncompressed data followed by compressed data and another bit of uncompressed data
stream =
new PartiallyCompressingOutputStream(
Collections.singletonList(COMPRESS_RANGE_1), outBuffer, 32768);
byte[] input = fuse(PREAMBLE_BYTES, ENTRY1.getUncompressedBinaryContent(), GAP1_BYTES);
byte[] expected = fuse(PREAMBLE_BYTES, ENTRY1.getCompressedBinaryContent(), GAP1_BYTES);
stream.write(input);
stream.flush();
Assert.assertArrayEquals(expected, outBuffer.toByteArray());
}
@Test
public void testWrite_MixedSequence_Thrash() throws IOException {
// Write uncompressed data, compressed data, uncompressed data, compressed data (new params)
// Thrash by writing one byte at a time to pound on edge-casey code
stream =
new PartiallyCompressingOutputStream(
Arrays.asList(COMPRESS_RANGE_1, COMPRESS_RANGE_2), outBuffer, 32768);
byte[] input =
fuse(
PREAMBLE_BYTES,
ENTRY1.getUncompressedBinaryContent(),
GAP1_BYTES,
ENTRY2.getUncompressedBinaryContent());
byte[] expected =
fuse(
PREAMBLE_BYTES,
ENTRY1.getCompressedBinaryContent(),
GAP1_BYTES,
ENTRY2.getCompressedBinaryContent());
for (int x = 0; x < input.length; x++) {
stream.write(input[x] & 0xff);
stream.flush();
}
stream.close();
Assert.assertArrayEquals(expected, outBuffer.toByteArray());
}
}