1/* 2 * Copyright (C) 2010 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 17package libcore.java.util.zip; 18 19import java.io.BufferedOutputStream; 20import java.io.File; 21import java.io.FileInputStream; 22import java.io.FileOutputStream; 23import java.io.IOException; 24import java.util.Arrays; 25import java.util.List; 26import java.util.jar.JarEntry; 27import java.util.zip.ZipEntry; 28import java.util.zip.ZipException; 29import java.util.zip.ZipFile; 30import java.util.zip.ZipInputStream; 31import java.util.zip.ZipOutputStream; 32 33public class ZipEntryTest extends junit.framework.TestCase { 34 private static File createTemporaryZipFile() throws IOException { 35 File result = File.createTempFile("ZipFileTest", "zip"); 36 result.deleteOnExit(); 37 return result; 38 } 39 40 private static ZipOutputStream createZipOutputStream(File f) throws IOException { 41 return new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(f))); 42 } 43 44 private static String makeString(int count, String s) { 45 StringBuilder sb = new StringBuilder(); 46 for (int i = 0; i < count; ++i) { 47 sb.append(s); 48 } 49 return sb.toString(); 50 } 51 52 // http://code.google.com/p/android/issues/detail?id=4690 53 public void test_utf8FileNames() throws Exception { 54 // Create a zip file containing non-ASCII filenames. 55 File f = File.createTempFile("your", "mum"); 56 List<String> filenames = Arrays.asList("us-ascii", 57 "\u043c\u0430\u0440\u0442\u0430", // russian 58 "\u1f00\u03c0\u1f78", // greek 59 "\u30b3\u30f3\u30cb\u30c1\u30cf"); // japanese 60 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f)); 61 for (String filename : filenames) { 62 out.putNextEntry(new ZipEntry(filename)); 63 out.closeEntry(); // Empty files are fine. 64 } 65 out.close(); 66 // Read it back, and check we find all those names. 67 // This failed when we were mangling the encoding. 68 ZipFile zipFile = new ZipFile(f); 69 for (String filename : filenames) { 70 assertNotNull(filename, zipFile.getEntry(filename)); 71 } 72 // Check that ZipInputStream works too. 73 ZipInputStream in = new ZipInputStream(new FileInputStream(f)); 74 ZipEntry entry; 75 int entryCount = 0; 76 while ((entry = in.getNextEntry()) != null) { 77 assertTrue(entry.getName(), filenames.contains(entry.getName())); 78 ++entryCount; 79 } 80 assertEquals(filenames.size(), entryCount); 81 in.close(); 82 } 83 84 // http://b/2099615 85 public void testClone() { 86 byte[] extra = { 5, 7, 9 }; 87 JarEntry jarEntry = new JarEntry("foo"); 88 jarEntry.setExtra(extra); 89 assertSame("Expected no defensive copy of extra", extra, jarEntry.getExtra()); 90 91 ZipEntry clone = (ZipEntry) jarEntry.clone(); 92 assertEquals(JarEntry.class, clone.getClass()); 93 assertNotSame(extra, clone.getExtra()); 94 } 95 96 public void testTooLongName() throws Exception { 97 String tooLongName = makeString(65536, "z"); 98 try { 99 new ZipEntry(tooLongName); 100 fail(); 101 } catch (IllegalArgumentException expected) { 102 } 103 } 104 105 public void testMaxLengthName() throws Exception { 106 String maxLengthName = makeString(65535, "z"); 107 108 File f = createTemporaryZipFile(); 109 ZipOutputStream out = createZipOutputStream(f); 110 out.putNextEntry(new ZipEntry(maxLengthName)); 111 out.closeEntry(); 112 out.close(); 113 114 // Read it back, and check that we see the entry. 115 ZipFile zipFile = new ZipFile(f); 116 assertNotNull(zipFile.getEntry(maxLengthName)); 117 zipFile.close(); 118 } 119 120 public void testTooLongExtra() throws Exception { 121 byte[] tooLongExtra = new byte[65536]; 122 ZipEntry ze = new ZipEntry("x"); 123 try { 124 ze.setExtra(tooLongExtra); 125 fail(); 126 } catch (IllegalArgumentException expected) { 127 } 128 } 129 130 public void testMaxLengthExtra() throws Exception { 131 byte[] maxLengthExtra = new byte[65535]; 132 133 File f = createTemporaryZipFile(); 134 ZipOutputStream out = createZipOutputStream(f); 135 ZipEntry ze = new ZipEntry("x"); 136 ze.setSize(0); 137 ze.setExtra(maxLengthExtra); 138 out.putNextEntry(ze); 139 out.closeEntry(); 140 out.close(); 141 142 // Read it back, and check that we see the entry. 143 ZipFile zipFile = new ZipFile(f); 144 assertEquals(maxLengthExtra.length, zipFile.getEntry("x").getExtra().length); 145 zipFile.close(); 146 } 147 148 149 // TODO: This test does not compile because we need to add a ZipOutputStream constructor 150 // that forces zip64. This also needs followup changes in ZipInputStream et al. to assume zip64 151 // if the header says so, and to not depend purely on the entry length. 152 // 153 // public void testMaxLengthExtra_zip64() throws Exception { 154 // // Not quite the max length (65535), but large enough that there's no space 155 // // for the zip64 extended info header. 156 // byte[] maxLengthExtra = new byte[65530]; 157 // 158 // File f = createTemporaryZipFile(); 159 // ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(f)), 160 // true /* forceZip64 */); 161 // ZipEntry ze = new ZipEntry("x"); 162 // 163 // ze.setExtra(maxLengthExtra); 164 // try { 165 // out.putNextEntry(ze); 166 // fail(); 167 // } catch (ZipException expected) { 168 // } 169 // } 170 171 172 public void testTooLongComment() throws Exception { 173 String tooLongComment = makeString(65536, "z"); 174 ZipEntry ze = new ZipEntry("x"); 175 try { 176 ze.setComment(tooLongComment); 177 fail(); 178 } catch (IllegalArgumentException expected) { 179 } 180 } 181 182 public void testMaxLengthComment() throws Exception { 183 String maxLengthComment = makeString(65535, "z"); 184 185 File f = createTemporaryZipFile(); 186 ZipOutputStream out = createZipOutputStream(f); 187 ZipEntry ze = new ZipEntry("x"); 188 ze.setComment(maxLengthComment); 189 out.putNextEntry(ze); 190 out.closeEntry(); 191 out.close(); 192 193 // Read it back, and check that we see the entry. 194 ZipFile zipFile = new ZipFile(f); 195 assertEquals(maxLengthComment, zipFile.getEntry("x").getComment()); 196 zipFile.close(); 197 } 198 199 public void testCommentAndExtraInSameOrder() throws Exception { 200 String comment = makeString(17, "z"); 201 byte[] extra = makeString(11, "a").getBytes(); 202 203 File f = createTemporaryZipFile(); 204 ZipOutputStream out = createZipOutputStream(f); 205 206 // Regular (non zip64) format. 207 ZipEntry ze = new ZipEntry("x"); 208 ze.setSize(0); 209 ze.setExtra(extra); 210 ze.setComment(comment); 211 out.putNextEntry(ze); 212 out.closeEntry(); 213 214 // An entry without a length is assumed to be zip64. 215 ze = new ZipEntry("y"); 216 ze.setExtra(extra); 217 ze.setComment(comment); 218 out.putNextEntry(ze); 219 out.closeEntry(); 220 out.close(); 221 222 // Read it back and make sure comments and extra are in the right order 223 ZipFile zipFile = new ZipFile(f); 224 try { 225 assertEquals(comment, zipFile.getEntry("x").getComment()); 226 assertTrue(Arrays.equals(extra, zipFile.getEntry("x").getExtra())); 227 228 assertEquals(comment, zipFile.getEntry("y").getComment()); 229 assertTrue(Arrays.equals(extra, zipFile.getEntry("y").getExtra())); 230 } finally { 231 zipFile.close(); 232 } 233 } 234} 235