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