diff options
Diffstat (limited to 'luni/src/test/java/libcore/java/util/zip/ZipFileTest.java')
-rw-r--r-- | luni/src/test/java/libcore/java/util/zip/ZipFileTest.java | 339 |
1 files changed, 285 insertions, 54 deletions
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java index afceaba..49dc050 100644 --- a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java +++ b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Random; +import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; @@ -35,7 +36,6 @@ import junit.framework.TestCase; import libcore.io.IoUtils; public final class ZipFileTest extends TestCase { - /** * Exercise Inflater's ability to refill the zlib's input buffer. As of this * writing, this buffer's max size is 64KiB compressed bytes. We'll write a @@ -45,7 +45,7 @@ public final class ZipFileTest extends TestCase { public void testInflatingFilesRequiringZipRefill() throws IOException { int originalSize = 1024 * 1024; byte[] readBuffer = new byte[8192]; - ZipFile zipFile = new ZipFile(createZipFile(originalSize)); + ZipFile zipFile = new ZipFile(createZipFile(1, originalSize)); for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) { ZipEntry zipEntry = e.nextElement(); assertTrue("This test needs >64 KiB of compressed data to exercise Inflater", @@ -121,72 +121,303 @@ public final class ZipFileTest extends TestCase { public void testInflatingStreamsRequiringZipRefill() throws IOException { int originalSize = 1024 * 1024; byte[] readBuffer = new byte[8192]; - ZipInputStream in = new ZipInputStream(new FileInputStream(createZipFile(originalSize))); + ZipInputStream in = new ZipInputStream(new FileInputStream(createZipFile(1, originalSize))); while (in.getNextEntry() != null) { while (in.read(readBuffer, 0, readBuffer.length) != -1) {} } in.close(); } + public void testZipFileWithLotsOfEntries() throws IOException { + int expectedEntryCount = 64*1024 - 1; + File f = createZipFile(expectedEntryCount, 0); + ZipFile zipFile = new ZipFile(f); + int entryCount = 0; + for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) { + ZipEntry zipEntry = e.nextElement(); + ++entryCount; + } + assertEquals(expectedEntryCount, entryCount); + zipFile.close(); + } + + // http://code.google.com/p/android/issues/detail?id=36187 + public void testZipFileLargerThan2GiB() throws IOException { + if (false) { // TODO: this test requires too much time and too much disk space! + File f = createZipFile(1024, 3*1024*1024); + ZipFile zipFile = new ZipFile(f); + int entryCount = 0; + for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) { + ZipEntry zipEntry = e.nextElement(); + ++entryCount; + } + assertEquals(1024, entryCount); + zipFile.close(); + } + } + + public void testZip64Support() throws IOException { + try { + createZipFile(64*1024, 0); + fail(); // Make this test more like testHugeZipFile when we have Zip64 support. + } catch (ZipException expected) { + } + } + /** - * Compresses a single random file into a .zip archive. + * Compresses the given number of files, each of the given size, into a .zip archive. */ - private File createZipFile(int uncompressedSize) throws IOException { + private File createZipFile(int entryCount, int entrySize) throws IOException { + File result = createTemporaryZipFile(); + + byte[] writeBuffer = new byte[8192]; + Random random = new Random(); + + ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(result))); + for (int entry = 0; entry < entryCount; ++entry) { + ZipEntry ze = new ZipEntry(Integer.toHexString(entry)); + out.putNextEntry(ze); + + for (int i = 0; i < entrySize; i += writeBuffer.length) { + random.nextBytes(writeBuffer); + int byteCount = Math.min(writeBuffer.length, entrySize - i); + out.write(writeBuffer, 0, byteCount); + } + + out.closeEntry(); + } + + out.close(); + return result; + } + + private File createTemporaryZipFile() throws IOException { File result = File.createTempFile("ZipFileTest", "zip"); result.deleteOnExit(); + return result; + } - ZipOutputStream out = new ZipOutputStream(new FileOutputStream(result)); - ZipEntry entry = new ZipEntry("random"); - out.putNextEntry(entry); + private ZipOutputStream createZipOutputStream(File f) throws IOException { + return new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(f))); + } - byte[] writeBuffer = new byte[8192]; - Random random = new Random(); - for (int i = 0; i < uncompressedSize; i += writeBuffer.length) { - random.nextBytes(writeBuffer); - out.write(writeBuffer, 0, Math.min(writeBuffer.length, uncompressedSize - i)); + public void testSTORED() throws IOException { + ZipOutputStream out = createZipOutputStream(createTemporaryZipFile()); + CRC32 crc = new CRC32(); + + // Missing CRC, size, and compressed size => failure. + try { + ZipEntry ze = new ZipEntry("a"); + ze.setMethod(ZipEntry.STORED); + out.putNextEntry(ze); + fail(); + } catch (ZipException expected) { + } + + // Missing CRC and compressed size => failure. + try { + ZipEntry ze = new ZipEntry("a"); + ze.setMethod(ZipEntry.STORED); + ze.setSize(0); + out.putNextEntry(ze); + fail(); + } catch (ZipException expected) { } + // Missing CRC and size => failure. + try { + ZipEntry ze = new ZipEntry("a"); + ze.setMethod(ZipEntry.STORED); + ze.setSize(0); + ze.setCompressedSize(0); + out.putNextEntry(ze); + fail(); + } catch (ZipException expected) { + } + + // Missing size and compressed size => failure. + try { + ZipEntry ze = new ZipEntry("a"); + ze.setMethod(ZipEntry.STORED); + ze.setCrc(crc.getValue()); + out.putNextEntry(ze); + fail(); + } catch (ZipException expected) { + } + + // Missing size is copied from compressed size. + { + ZipEntry ze = new ZipEntry("okay1"); + ze.setMethod(ZipEntry.STORED); + ze.setCrc(crc.getValue()); + + assertEquals(-1, ze.getSize()); + assertEquals(-1, ze.getCompressedSize()); + + ze.setCompressedSize(0); + + assertEquals(-1, ze.getSize()); + assertEquals(0, ze.getCompressedSize()); + + out.putNextEntry(ze); + + assertEquals(0, ze.getSize()); + assertEquals(0, ze.getCompressedSize()); + } + + // Missing compressed size is copied from size. + { + ZipEntry ze = new ZipEntry("okay2"); + ze.setMethod(ZipEntry.STORED); + ze.setCrc(crc.getValue()); + + assertEquals(-1, ze.getSize()); + assertEquals(-1, ze.getCompressedSize()); + + ze.setSize(0); + + assertEquals(0, ze.getSize()); + assertEquals(-1, ze.getCompressedSize()); + + out.putNextEntry(ze); + + assertEquals(0, ze.getSize()); + assertEquals(0, ze.getCompressedSize()); + } + + // Mismatched size and compressed size => failure. + try { + ZipEntry ze = new ZipEntry("a"); + ze.setMethod(ZipEntry.STORED); + ze.setCrc(crc.getValue()); + ze.setCompressedSize(1); + ze.setSize(0); + out.putNextEntry(ze); + fail(); + } catch (ZipException expected) { + } + + // Everything present => success. + ZipEntry ze = new ZipEntry("okay"); + ze.setMethod(ZipEntry.STORED); + ze.setCrc(crc.getValue()); + ze.setSize(0); + ze.setCompressedSize(0); + out.putNextEntry(ze); + + out.close(); + } + + private String makeString(int count, String ch) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; ++i) { + sb.append(ch); + } + return sb.toString(); + } + + public void testComment() throws Exception { + String expectedFileComment = "1 \u0666 2"; + String expectedEntryComment = "a \u0666 b"; + + File file = createTemporaryZipFile(); + ZipOutputStream out = createZipOutputStream(file); + + // Is file comment length checking done on bytes or characters? (Should be bytes.) + out.setComment(null); + out.setComment(makeString(0xffff, "a")); + try { + out.setComment(makeString(0xffff + 1, "a")); + fail(); + } catch (IllegalArgumentException expected) { + } + try { + out.setComment(makeString(0xffff, "\u0666")); + fail(); + } catch (IllegalArgumentException expected) { + } + + ZipEntry ze = new ZipEntry("a"); + + // Is entry comment length checking done on bytes or characters? (Should be bytes.) + ze.setComment(null); + ze.setComment(makeString(0xffff, "a")); + try { + ze.setComment(makeString(0xffff + 1, "a")); + fail(); + } catch (IllegalArgumentException expected) { + } + try { + ze.setComment(makeString(0xffff, "\u0666")); + fail(); + } catch (IllegalArgumentException expected) { + } + + ze.setComment(expectedEntryComment); + out.putNextEntry(ze); out.closeEntry(); + + out.setComment(expectedFileComment); out.close(); - return result; - } - - public void testHugeZipFile() throws IOException { - int expectedEntryCount = 64*1024 - 1; - File f = createHugeZipFile(expectedEntryCount); - ZipFile zipFile = new ZipFile(f); - int entryCount = 0; - for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) { - ZipEntry zipEntry = e.nextElement(); - ++entryCount; - } - assertEquals(expectedEntryCount, entryCount); - zipFile.close(); - } - - public void testZip64Support() throws IOException { - try { - createHugeZipFile(64*1024); - fail(); // Make this test more like testHugeZipFile when we have Zip64 support. - } catch (ZipException expected) { - } - } - - /** - * Compresses the given number of empty files into a .zip archive. - */ - private File createHugeZipFile(int count) throws IOException { - File result = File.createTempFile("ZipFileTest", "zip"); - result.deleteOnExit(); - - ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(result))); - for (int i = 0; i < count; ++i) { - ZipEntry entry = new ZipEntry(Integer.toHexString(i)); - out.putNextEntry(entry); - out.closeEntry(); - } - - out.close(); - return result; - } + + ZipFile zipFile = new ZipFile(file); + // TODO: there's currently no API for reading the file comment --- strings(1) the file? + assertEquals(expectedEntryComment, zipFile.getEntry("a").getComment()); + zipFile.close(); + } + + public void testNameLengthChecks() throws IOException { + // Is entry name length checking done on bytes or characters? + // Really it should be bytes, but the RI only checks characters at construction time. + // Android does the same, because it's cheap... + try { + new ZipEntry((String) null); + fail(); + } catch (NullPointerException expected) { + } + new ZipEntry(makeString(0xffff, "a")); + try { + new ZipEntry(makeString(0xffff + 1, "a")); + fail(); + } catch (IllegalArgumentException expected) { + } + + // ...but Android won't let you create a zip file with a truncated name. + ZipOutputStream out = createZipOutputStream(createTemporaryZipFile()); + ZipEntry ze = new ZipEntry(makeString(0xffff, "\u0666")); + try { + out.putNextEntry(ze); + fail(); // The RI fails this test; it just checks the character count at construction time. + } catch (IllegalArgumentException expected) { + } + out.closeEntry(); + out.putNextEntry(new ZipEntry("okay")); // ZipOutputStream.close throws if you add nothing! + out.close(); + } + + public void testCrc() throws IOException { + ZipEntry ze = new ZipEntry("test"); + ze.setMethod(ZipEntry.STORED); + ze.setSize(4); + + // setCrc takes a long, not an int, so -1 isn't a valid CRC32 (because it's 64 bits). + try { + ze.setCrc(-1); + } catch (IllegalArgumentException expected) { + } + + // You can set the CRC32 to 0xffffffff if you're slightly more careful though... + ze.setCrc(0xffffffffL); + assertEquals(0xffffffffL, ze.getCrc()); + + // And it actually works, even though we use -1L to mean "no CRC set"... + ZipOutputStream out = createZipOutputStream(createTemporaryZipFile()); + out.putNextEntry(ze); + out.write(-1); + out.write(-1); + out.write(-1); + out.write(-1); + out.closeEntry(); + out.close(); + } } |