1602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel/*
2602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Copyright (C) 2014 The Android Open Source Project
3602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel *
4602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Licensed under the Apache License, Version 2.0 (the "License");
5602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * you may not use this file except in compliance with the License.
6602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * You may obtain a copy of the License at
7602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel *
8602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel *      http://www.apache.org/licenses/LICENSE-2.0
9602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel *
10602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Unless required by applicable law or agreed to in writing, software
11602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * distributed under the License is distributed on an "AS IS" BASIS,
12602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * See the License for the specific language governing permissions and
14602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * limitations under the License.
15602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel */
16602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
17602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselpackage android.support.multidex;
18602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
19602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport android.support.multidex.ZipUtil.CentralDirectory;
20602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
21602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport org.junit.Assert;
22602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport org.junit.BeforeClass;
23602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport org.junit.Test;
24602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
25602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.EOFException;
26602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.File;
27602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.FileOutputStream;
28602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.IOException;
29602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.InputStream;
30602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.OutputStream;
31602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.io.RandomAccessFile;
32602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.nio.ByteBuffer;
33602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.nio.ByteOrder;
34602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.Enumeration;
35602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.HashMap;
36602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.Map;
37602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.zip.ZipEntry;
38602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.zip.ZipException;
39602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselimport java.util.zip.ZipFile;
40602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
41602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel/**
42602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * Tests of ZipUtil class.
43602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel *
44602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * The test assumes that ANDROID_BUILD_TOP environment variable is defined and point to the top of a
45602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * built android tree. This is the case when the console used for running the tests is setup for
46602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel * android tree compilation.
47602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel */
48602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Rousselpublic class ZipUtilTest {
49602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    private static final File zipFile = new File(System.getenv("ANDROID_BUILD_TOP"),
50602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        "out/target/common/obj/JAVA_LIBRARIES/android-support-multidex_intermediates/javalib.jar");
51602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    @BeforeClass
52602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    public static void setupClass() throws ZipException, IOException {
53602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        // just verify the zip is valid
54602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        new ZipFile(zipFile).close();
55602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    }
56602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
57602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    @Test
58602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    public void testCrcDoNotCrash() throws IOException {
59602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
60602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        long crc =
61602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                ZipUtil.getZipCrc(zipFile);
62602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        System.out.println("crc is " + crc);
63602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
64602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    }
65602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
66602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    @Test
67602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    public void testCrcRange() throws IOException {
68602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        RandomAccessFile raf = new RandomAccessFile(zipFile, "r");
69602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        CentralDirectory dir = ZipUtil.findCentralDirectory(raf);
70602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        byte[] dirData = new byte[(int) dir.size];
71602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        int length = dirData.length;
72602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        int off = 0;
73602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        raf.seek(dir.offset);
74602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        while (length > 0) {
75602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            int read = raf.read(dirData, off, length);
76602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            if (length == -1) {
77602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                throw new EOFException();
78602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            }
79602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            length -= read;
80602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            off += read;
81602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        }
82602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        raf.close();
83602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        ByteBuffer buffer = ByteBuffer.wrap(dirData);
84602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        Map<String, ZipEntry> toCheck = new HashMap<String, ZipEntry>();
85602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        while (buffer.hasRemaining()) {
86602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            buffer = buffer.slice();
87602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            buffer.order(ByteOrder.LITTLE_ENDIAN);
88602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            ZipEntry entry = ZipEntryReader.readEntry(buffer);
89602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            toCheck.put(entry.getName(), entry);
90602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        }
91602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
92602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        ZipFile zip = new ZipFile(zipFile);
93602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        Assert.assertEquals(zip.size(), toCheck.size());
94602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        Enumeration<? extends ZipEntry> ref = zip.entries();
95602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        while (ref.hasMoreElements()) {
96602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            ZipEntry refEntry = ref.nextElement();
97602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            ZipEntry checkEntry = toCheck.get(refEntry.getName());
98602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertNotNull(checkEntry);
99602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getName(), checkEntry.getName());
100602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getComment(), checkEntry.getComment());
101602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getTime(), checkEntry.getTime());
102602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getCrc(), checkEntry.getCrc());
103602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getCompressedSize(), checkEntry.getCompressedSize());
104602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getSize(), checkEntry.getSize());
105602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertEquals(refEntry.getMethod(), checkEntry.getMethod());
106602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            Assert.assertArrayEquals(refEntry.getExtra(), checkEntry.getExtra());
107602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        }
108602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        zip.close();
109602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    }
110602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
111602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    @Test
112602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    public void testCrcValue() throws IOException {
113602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        ZipFile zip = new ZipFile(zipFile);
114602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        Enumeration<? extends ZipEntry> ref = zip.entries();
115602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        byte[] buffer = new byte[0x2000];
116602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        while (ref.hasMoreElements()) {
117602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            ZipEntry refEntry = ref.nextElement();
118602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            if (refEntry.getSize() > 0) {
119602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                File tmp = File.createTempFile("ZipUtilTest", ".fakezip");
120602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                InputStream in = zip.getInputStream(refEntry);
121602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                OutputStream out = new FileOutputStream(tmp);
122602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                int read = in.read(buffer);
123602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                while (read != -1) {
124602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                    out.write(buffer, 0, read);
125602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                    read = in.read(buffer);
126602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                }
127602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                in.close();
128602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                out.close();
129602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                RandomAccessFile raf = new RandomAccessFile(tmp, "r");
130602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                CentralDirectory dir = new CentralDirectory();
131602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                dir.offset = 0;
132602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                dir.size = raf.length();
133602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                long crc = ZipUtil.computeCrcOfCentralDir(raf, dir);
134602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                Assert.assertEquals(refEntry.getCrc(), crc);
135602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                raf.close();
136602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                tmp.delete();
137602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            }
138602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        }
139602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        zip.close();
140602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    }
141602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    @Test
142602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    public void testInvalidCrcValue() throws IOException {
143602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        ZipFile zip = new ZipFile(zipFile);
144602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        Enumeration<? extends ZipEntry> ref = zip.entries();
145602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        byte[] buffer = new byte[0x2000];
146602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        while (ref.hasMoreElements()) {
147602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            ZipEntry refEntry = ref.nextElement();
148602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            if (refEntry.getSize() > 0) {
149602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                File tmp = File.createTempFile("ZipUtilTest", ".fakezip");
150602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                InputStream in = zip.getInputStream(refEntry);
151602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                OutputStream out = new FileOutputStream(tmp);
152602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                int read = in.read(buffer);
153602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                while (read != -1) {
154602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                    out.write(buffer, 0, read);
155602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                    read = in.read(buffer);
156602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                }
157602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                in.close();
158602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                out.close();
159602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                RandomAccessFile raf = new RandomAccessFile(tmp, "r");
160602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                CentralDirectory dir = new CentralDirectory();
161602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                dir.offset = 0;
162602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                dir.size = raf.length() - 1;
163602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                long crc = ZipUtil.computeCrcOfCentralDir(raf, dir);
164602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                Assert.assertNotEquals(refEntry.getCrc(), crc);
165602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                raf.close();
166602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel                tmp.delete();
167602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel            }
168602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        }
169602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel        zip.close();
170602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel    }
171602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel
172602c6ca8cae4718ba8ff9f65e53305d002479359Yohann Roussel}
173