blob: cd1b246b387335eb36d9004ccdffd2ef02d57556 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.android.tools.build.apkzlib.zip;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import com.android.tools.build.apkzlib.utils.CachedFileContents;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class ZipMergeTest {
@Rule
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@Test
public void mergeZip() throws Exception {
File aZip = ZipTestUtils.cloneRsrc("simple-zip.zip", mTemporaryFolder, "a.zip");
CachedFileContents<Object> changeDetector;
File merged = new File(mTemporaryFolder.getRoot(), "r.zip");
try (ZFile mergedZf = new ZFile(merged)) {
mergedZf.mergeFrom(new ZFile(aZip), f -> false);
mergedZf.close();
assertEquals(3, mergedZf.entries().size());
StoredEntry e0 = mergedZf.get("dir/");
assertNotNull(e0);
assertSame(StoredEntryType.DIRECTORY, e0.getType());
StoredEntry e1 = mergedZf.get("dir/inside");
assertNotNull(e1);
assertSame(StoredEntryType.FILE, e1.getType());
ByteArrayOutputStream e1BytesOut = new ByteArrayOutputStream();
ByteStreams.copy(e1.open(), e1BytesOut);
byte e1Bytes[] = e1BytesOut.toByteArray();
String e1Txt = new String(e1Bytes, Charsets.US_ASCII);
assertEquals("inside", e1Txt);
StoredEntry e2 = mergedZf.get("file.txt");
assertNotNull(e2);
assertSame(StoredEntryType.FILE, e2.getType());
ByteArrayOutputStream e2BytesOut = new ByteArrayOutputStream();
ByteStreams.copy(e2.open(), e2BytesOut);
byte e2Bytes[] = e2BytesOut.toByteArray();
String e2Txt = new String(e2Bytes, Charsets.US_ASCII);
assertEquals("file with more text to allow deflating to be useful", e2Txt);
changeDetector = new CachedFileContents<>(merged);
changeDetector.closed(null);
/*
* Clone aZip into bZip and merge. Should have no effect on the final zip file.
*/
File bZip = ZipTestUtils.cloneRsrc("simple-zip.zip", mTemporaryFolder, "b.zip");
mergedZf.mergeFrom(new ZFile(bZip), f -> false);
}
assertTrue(changeDetector.isValid());
}
@Test
public void mergeZipWithDeferredCrc() throws Exception {
File foo = mTemporaryFolder.newFile("foo");
byte[] wBytes = ZipTestUtils.rsrcBytes("text-files/wikipedia.html");
try (ZipOutputStream fooOut = new ZipOutputStream(new FileOutputStream(foo))) {
fooOut.putNextEntry(new ZipEntry("w"));
fooOut.write(wBytes);
}
try (Closer closer = Closer.create()) {
ZFile fooZf = closer.register(new ZFile(foo));
StoredEntry wStored = fooZf.get("w");
assertNotNull(wStored);
assertTrue(wStored.getCentralDirectoryHeader().getGpBit().isDeferredCrc());
assertEquals(CompressionMethod.DEFLATE,
wStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
ZFile merged = closer.register(new ZFile(new File(mTemporaryFolder.getRoot(), "bar")));
merged.mergeFrom(fooZf, f -> false);
merged.update();
StoredEntry wmStored = merged.get("w");
assertNotNull(wmStored);
assertFalse(wmStored.getCentralDirectoryHeader().getGpBit().isDeferredCrc());
assertEquals(CompressionMethod.DEFLATE,
wmStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
}
}
@Test
public void mergeZipKeepsDeflatedAndStored() throws Exception {
File foo = mTemporaryFolder.newFile("foo");
byte[] wBytes = ZipTestUtils.rsrcBytes("text-files/wikipedia.html");
byte[] lBytes = ZipTestUtils.rsrcBytes("images/lena.png");
try (ZipOutputStream fooOut = new ZipOutputStream(new FileOutputStream(foo))) {
fooOut.putNextEntry(new ZipEntry("w"));
fooOut.write(wBytes);
ZipEntry le = new ZipEntry("l");
le.setMethod(ZipEntry.STORED);
le.setSize(lBytes.length);
le.setCrc(Hashing.crc32().hashBytes(lBytes).padToLong());
fooOut.putNextEntry(le);
fooOut.write(lBytes);
}
try (Closer closer = Closer.create()) {
ZFile fooZf = closer.register(new ZFile(foo));
StoredEntry wStored = fooZf.get("w");
assertNotNull(wStored);
assertEquals(CompressionMethod.DEFLATE,
wStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
StoredEntry lStored = fooZf.get("l");
assertNotNull(lStored);
assertEquals(CompressionMethod.STORE,
lStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
ZFile merged = closer.register(new ZFile(new File(mTemporaryFolder.getRoot(), "bar")));
merged.mergeFrom(fooZf, f -> false);
merged.update();
StoredEntry wmStored = merged.get("w");
assertNotNull(wmStored);
assertFalse(wmStored.getCentralDirectoryHeader().getGpBit().isDeferredCrc());
assertEquals(CompressionMethod.DEFLATE,
wmStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
assertArrayEquals(wBytes, wmStored.read());
StoredEntry lmStored = merged.get("l");
assertNotNull(lmStored);
assertEquals(CompressionMethod.STORE,
lmStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
assertArrayEquals(lBytes, lmStored.read());
}
}
@Test
public void mergeZipWithSorting() throws Exception {
File foo = mTemporaryFolder.newFile("foo");
byte[] wBytes = ZipTestUtils.rsrcBytes("text-files/wikipedia.html");
byte[] lBytes = ZipTestUtils.rsrcBytes("images/lena.png");
try (ZipOutputStream fooOut = new ZipOutputStream(new FileOutputStream(foo))) {
fooOut.putNextEntry(new ZipEntry("w"));
fooOut.write(wBytes);
ZipEntry le = new ZipEntry("l");
le.setMethod(ZipEntry.STORED);
le.setSize(lBytes.length);
le.setCrc(Hashing.crc32().hashBytes(lBytes).padToLong());
fooOut.putNextEntry(le);
fooOut.write(lBytes);
}
try (
ZFile fooZf = new ZFile(foo);
ZFile merged = new ZFile(new File(mTemporaryFolder.getRoot(), "bar"))) {
merged.mergeFrom(fooZf, f -> false);
merged.sortZipContents();
merged.update();
StoredEntry wmStored = merged.get("w");
assertNotNull(wmStored);
assertArrayEquals(wBytes, wmStored.read());
StoredEntry lmStored = merged.get("l");
assertNotNull(lmStored);
assertArrayEquals(lBytes, lmStored.read());
}
}
}