Home | History | Annotate | Download | only in zip
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tools.build.apkzlib.zip;
     18 
     19 import static org.junit.Assert.assertArrayEquals;
     20 import static org.junit.Assert.assertEquals;
     21 import static org.junit.Assert.assertFalse;
     22 import static org.junit.Assert.assertNotNull;
     23 import static org.junit.Assert.assertSame;
     24 import static org.junit.Assert.assertTrue;
     25 
     26 import com.android.tools.build.apkzlib.utils.CachedFileContents;
     27 import com.google.common.base.Charsets;
     28 import com.google.common.hash.Hashing;
     29 import com.google.common.io.ByteStreams;
     30 import com.google.common.io.Closer;
     31 import java.io.ByteArrayOutputStream;
     32 import java.io.File;
     33 import java.io.FileOutputStream;
     34 import java.util.zip.ZipEntry;
     35 import java.util.zip.ZipOutputStream;
     36 import org.junit.Rule;
     37 import org.junit.Test;
     38 import org.junit.rules.TemporaryFolder;
     39 
     40 public class ZipMergeTest {
     41     @Rule
     42     public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
     43 
     44     @Test
     45     public void mergeZip() throws Exception {
     46         File aZip = ZipTestUtils.cloneRsrc("simple-zip.zip", mTemporaryFolder, "a.zip");
     47 
     48         CachedFileContents<Object> changeDetector;
     49         File merged = new File(mTemporaryFolder.getRoot(), "r.zip");
     50         try (ZFile mergedZf = new ZFile(merged)) {
     51             mergedZf.mergeFrom(new ZFile(aZip), f -> false);
     52             mergedZf.close();
     53 
     54             assertEquals(3, mergedZf.entries().size());
     55 
     56             StoredEntry e0 = mergedZf.get("dir/");
     57             assertNotNull(e0);
     58             assertSame(StoredEntryType.DIRECTORY, e0.getType());
     59 
     60             StoredEntry e1 = mergedZf.get("dir/inside");
     61             assertNotNull(e1);
     62             assertSame(StoredEntryType.FILE, e1.getType());
     63             ByteArrayOutputStream e1BytesOut = new ByteArrayOutputStream();
     64             ByteStreams.copy(e1.open(), e1BytesOut);
     65             byte e1Bytes[] = e1BytesOut.toByteArray();
     66             String e1Txt = new String(e1Bytes, Charsets.US_ASCII);
     67             assertEquals("inside", e1Txt);
     68 
     69             StoredEntry e2 = mergedZf.get("file.txt");
     70             assertNotNull(e2);
     71             assertSame(StoredEntryType.FILE, e2.getType());
     72             ByteArrayOutputStream e2BytesOut = new ByteArrayOutputStream();
     73             ByteStreams.copy(e2.open(), e2BytesOut);
     74             byte e2Bytes[] = e2BytesOut.toByteArray();
     75             String e2Txt = new String(e2Bytes, Charsets.US_ASCII);
     76             assertEquals("file with more text to allow deflating to be useful", e2Txt);
     77 
     78             changeDetector = new CachedFileContents<>(merged);
     79             changeDetector.closed(null);
     80 
     81             /*
     82              * Clone aZip into bZip and merge. Should have no effect on the final zip file.
     83              */
     84             File bZip = ZipTestUtils.cloneRsrc("simple-zip.zip", mTemporaryFolder, "b.zip");
     85 
     86             mergedZf.mergeFrom(new ZFile(bZip), f -> false);
     87         }
     88 
     89         assertTrue(changeDetector.isValid());
     90     }
     91 
     92     @Test
     93     public void mergeZipWithDeferredCrc() throws Exception {
     94         File foo = mTemporaryFolder.newFile("foo");
     95 
     96         byte[] wBytes = ZipTestUtils.rsrcBytes("text-files/wikipedia.html");
     97 
     98         try (ZipOutputStream fooOut = new ZipOutputStream(new FileOutputStream(foo))) {
     99             fooOut.putNextEntry(new ZipEntry("w"));
    100             fooOut.write(wBytes);
    101         }
    102 
    103         try (Closer closer = Closer.create()) {
    104             ZFile fooZf = closer.register(new ZFile(foo));
    105             StoredEntry wStored = fooZf.get("w");
    106             assertNotNull(wStored);
    107             assertTrue(wStored.getCentralDirectoryHeader().getGpBit().isDeferredCrc());
    108             assertEquals(CompressionMethod.DEFLATE,
    109                     wStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
    110 
    111             ZFile merged = closer.register(new ZFile(new File(mTemporaryFolder.getRoot(), "bar")));
    112             merged.mergeFrom(fooZf, f -> false);
    113             merged.update();
    114 
    115             StoredEntry wmStored = merged.get("w");
    116             assertNotNull(wmStored);
    117             assertFalse(wmStored.getCentralDirectoryHeader().getGpBit().isDeferredCrc());
    118             assertEquals(CompressionMethod.DEFLATE,
    119                     wmStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
    120         }
    121     }
    122 
    123     @Test
    124     public void mergeZipKeepsDeflatedAndStored() throws Exception {
    125         File foo = mTemporaryFolder.newFile("foo");
    126 
    127         byte[] wBytes = ZipTestUtils.rsrcBytes("text-files/wikipedia.html");
    128         byte[] lBytes = ZipTestUtils.rsrcBytes("images/lena.png");
    129 
    130         try (ZipOutputStream fooOut = new ZipOutputStream(new FileOutputStream(foo))) {
    131             fooOut.putNextEntry(new ZipEntry("w"));
    132             fooOut.write(wBytes);
    133             ZipEntry le = new ZipEntry("l");
    134             le.setMethod(ZipEntry.STORED);
    135             le.setSize(lBytes.length);
    136             le.setCrc(Hashing.crc32().hashBytes(lBytes).padToLong());
    137             fooOut.putNextEntry(le);
    138             fooOut.write(lBytes);
    139         }
    140 
    141         try (Closer closer = Closer.create()) {
    142             ZFile fooZf = closer.register(new ZFile(foo));
    143             StoredEntry wStored = fooZf.get("w");
    144             assertNotNull(wStored);
    145             assertEquals(CompressionMethod.DEFLATE,
    146                     wStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
    147             StoredEntry lStored = fooZf.get("l");
    148             assertNotNull(lStored);
    149             assertEquals(CompressionMethod.STORE,
    150                     lStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
    151 
    152             ZFile merged = closer.register(new ZFile(new File(mTemporaryFolder.getRoot(), "bar")));
    153             merged.mergeFrom(fooZf, f -> false);
    154             merged.update();
    155 
    156             StoredEntry wmStored = merged.get("w");
    157             assertNotNull(wmStored);
    158             assertFalse(wmStored.getCentralDirectoryHeader().getGpBit().isDeferredCrc());
    159             assertEquals(CompressionMethod.DEFLATE,
    160                     wmStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
    161             assertArrayEquals(wBytes, wmStored.read());
    162 
    163             StoredEntry lmStored = merged.get("l");
    164             assertNotNull(lmStored);
    165             assertEquals(CompressionMethod.STORE,
    166                     lmStored.getCentralDirectoryHeader().getCompressionInfoWithWait().getMethod());
    167             assertArrayEquals(lBytes, lmStored.read());
    168         }
    169     }
    170 
    171     @Test
    172     public void mergeZipWithSorting() throws Exception {
    173         File foo = mTemporaryFolder.newFile("foo");
    174 
    175         byte[] wBytes = ZipTestUtils.rsrcBytes("text-files/wikipedia.html");
    176         byte[] lBytes = ZipTestUtils.rsrcBytes("images/lena.png");
    177 
    178         try (ZipOutputStream fooOut = new ZipOutputStream(new FileOutputStream(foo))) {
    179             fooOut.putNextEntry(new ZipEntry("w"));
    180             fooOut.write(wBytes);
    181             ZipEntry le = new ZipEntry("l");
    182             le.setMethod(ZipEntry.STORED);
    183             le.setSize(lBytes.length);
    184             le.setCrc(Hashing.crc32().hashBytes(lBytes).padToLong());
    185             fooOut.putNextEntry(le);
    186             fooOut.write(lBytes);
    187         }
    188 
    189         try (
    190                 ZFile fooZf = new ZFile(foo);
    191                 ZFile merged = new ZFile(new File(mTemporaryFolder.getRoot(), "bar"))) {
    192             merged.mergeFrom(fooZf, f -> false);
    193             merged.sortZipContents();
    194             merged.update();
    195 
    196             StoredEntry wmStored = merged.get("w");
    197             assertNotNull(wmStored);
    198             assertArrayEquals(wBytes, wmStored.read());
    199 
    200             StoredEntry lmStored = merged.get("l");
    201             assertNotNull(lmStored);
    202             assertArrayEquals(lBytes, lmStored.read());
    203         }
    204     }
    205 }
    206