test/jdk/java/util/zip/ZipFile/Assortment.java
changeset 47216 71c04702a3d5
parent 30046 cf2c86e1819e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/zip/ZipFile/Assortment.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 4770745 6234507 6303183 8048990
+ * @summary test a variety of zip file entries
+ * @author Martin Buchholz
+ * @key randomness
+ */
+
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+import java.io.*;
+
+public class Assortment {
+    static int passed = 0, failed = 0;
+
+    static void fail(String msg) {
+        failed++;
+        new Exception(msg).printStackTrace();
+    }
+
+    static void unexpected(Throwable t) {
+        failed++;
+        t.printStackTrace();
+    }
+
+    static void check(boolean condition, String msg) {
+        if (! condition)
+            fail(msg);
+    }
+
+    static void check(boolean condition) {
+        check(condition, "Something's wrong");
+    }
+
+    static final int get16(byte b[], int off) {
+        return Byte.toUnsignedInt(b[off]) | (Byte.toUnsignedInt(b[off+1]) << 8);
+    }
+
+    // check if all "expected" extra fields equal to their
+    // corresponding fields in "extra". The "extra" might have
+    // timestamp fields added by ZOS.
+    static boolean equalsExtraData(byte[] expected, byte[] extra) {
+        if (expected == null)
+            return true;
+        int off = 0;
+        int len = expected.length;
+        while (off + 4 < len) {
+            int tag = get16(expected, off);
+            int sz = get16(expected, off + 2);
+            int off0 = 0;
+            int len0 = extra.length;
+            boolean matched = false;
+            while (off0 + 4 < len0) {
+                int tag0 = get16(extra, off0);
+                int sz0 = get16(extra, off0 + 2);
+                if (tag == tag0 && sz == sz0) {
+                    matched = true;
+                    for (int i = 0; i < sz; i++) {
+                        if (expected[off + i] != extra[off0 +i])
+                            matched = false;
+                    }
+                    break;
+                }
+                off0 += (4 + sz0);
+            }
+            if (!matched)
+                return false;
+            off += (4 + sz);
+        }
+        return true;
+    }
+
+    private static class Entry {
+        private String name;
+        private int    method;
+        private byte[] data;
+        private byte[] extra;
+        private String comment;
+
+        Entry(String name,
+              int    method,
+              byte[] data,
+              byte[] extra,
+              String comment) {
+            this.name    = name;
+            this.method  = method;
+            this.data    = data;
+            this.extra   = extra;
+            this.comment = comment;
+        }
+
+        void write(ZipOutputStream s) throws Exception {
+            ZipEntry e = new ZipEntry(name);
+            CRC32 crc32 = new CRC32();
+            e.setMethod(method);
+            if (method == ZipEntry.STORED) {
+                e.setSize(data == null ? 0 : data.length);
+                crc32.reset();
+                if (data != null) crc32.update(data);
+                e.setCrc(crc32.getValue());
+            } else {
+                e.setSize(0);
+                e.setCrc(0);
+            }
+            if (comment != null) e.setComment(comment);
+            if (extra   != null) e.setExtra(extra);
+            s.putNextEntry(e);
+            if (data != null) s.write(data);
+        }
+
+        byte[] getData(ZipFile f, ZipEntry e) throws Exception {
+            byte[] fdata = new byte[(int)e.getSize()];
+            InputStream is = f.getInputStream(e);
+            is.read(fdata);
+            return fdata;
+        }
+
+        void verify(ZipFile f, ZipEntry e) throws Exception {
+            verify(e, getData(f, e));
+        }
+
+        void verify(ZipEntry e, byte[] eData) throws Exception {
+            byte[] data  = (this.data == null) ? new byte[]{} : this.data;
+            byte[] extra = (this.extra != null && this.extra.length == 0) ?
+                null : this.extra;
+            check(name.equals(e.getName()));
+            check(method == e.getMethod());
+            check((((comment == null) || comment.equals(""))
+                   && (e.getComment() == null))
+                  || comment.equals(e.getComment()));
+            check(equalsExtraData(extra, e.getExtra()));
+            check(Arrays.equals(data, eData));
+            check(e.getSize() == data.length);
+            check((method == ZipEntry.DEFLATED) ||
+                  (e.getCompressedSize() == data.length));
+        }
+
+        void verify(ZipFile f) throws Exception {
+            ZipEntry e = f.getEntry(name);
+            verify(e, getData(f, e));
+        }
+
+        void verifyZipInputStream(ZipInputStream s) throws Exception {
+            ZipEntry e = s.getNextEntry();
+
+            byte[] data = (this.data == null) ? new byte[]{} : this.data;
+            byte[] otherData = new byte[data.length];
+            s.read(otherData);
+            check(Arrays.equals(data, otherData));
+
+            byte[] extra = (this.extra != null && this.extra.length == 0) ?
+                null : this.extra;
+            check(equalsExtraData(extra, e.getExtra()));
+            check(name.equals(e.getName()));
+            check(method == e.getMethod());
+            check(e.getSize() == -1 || e.getSize() == data.length);
+            check((method == ZipEntry.DEFLATED) ||
+                  (e.getCompressedSize() == data.length));
+        }
+
+        void verifyJarInputStream(JarInputStream s) throws Exception {
+            // JarInputStream "automatically" reads the manifest
+            if (name.equals("meta-iNf/ManIfEst.Mf"))
+                return;
+
+            verifyZipInputStream(s);
+        }
+    }
+
+    private static int uniquifier = 86;
+    private static String uniquify(String name) {
+        return name + (uniquifier++);
+    }
+
+    private static byte[] toBytes(String s) throws Exception {
+        return s.getBytes("UTF-8");
+    }
+
+    private static byte[] toExtra(byte[] bytes) throws Exception {
+        if (bytes == null) return null;
+        // Construct a fake extra field with valid header length
+        byte[] v = new byte[bytes.length + 4];
+        v[0] = (byte) 0x47;
+        v[1] = (byte) 0xff;
+        v[2] = (byte) bytes.length;
+        v[3] = (byte) (bytes.length << 8);
+        System.arraycopy(bytes, 0, v, 4, bytes.length);
+        return v;
+    }
+
+    private static Random random = new Random();
+
+    private static String makeName(int length) {
+        StringBuilder sb = new StringBuilder(length);
+        for (int i = 0; i < length; i++)
+            sb.append((char)(random.nextInt(10000)+1));
+        return sb.toString();
+    }
+
+    public static void main(String[] args) throws Exception {
+        File zipName = new File("x.zip");
+        int[]    methods  = {ZipEntry.STORED, ZipEntry.DEFLATED};
+        String[] names    = {makeName(1), makeName(160), makeName(9000)};
+        byte[][] datas    = {null, new byte[]{}, new byte[]{'d'}};
+        byte[][] extras   = {null, new byte[]{}, new byte[]{'e'}};
+        String[] comments = {null, "", "c"};
+
+        List<Entry> entries = new ArrayList<Entry>();
+
+        // Highly unusual manifest
+        entries.add(new Entry("meta-iNf/ManIfEst.Mf",
+                              ZipEntry.STORED,
+                              toBytes("maNiFest-VeRsIon: 1.0\n"),
+                              toExtra(toBytes("Can manifests have extra??")),
+                              "Can manifests have comments??"));
+
+        // The emptiest possible entry
+        entries.add(new Entry("", ZipEntry.STORED, null, null, ""));
+
+        for (String name : names)
+            for (int method : methods)
+                for (byte[] data : datas) // datae??
+                    for (byte[] extra : extras)
+                        for (String comment : comments)
+                            entries.add(new Entry(uniquify(name), method, data,
+                                                  toExtra(extra), comment));
+
+        //----------------------------------------------------------------
+        // Write zip file using ZipOutputStream
+        //----------------------------------------------------------------
+        try (FileOutputStream fos = new FileOutputStream(zipName);
+             ZipOutputStream zos = new ZipOutputStream(fos))
+        {
+            for (Entry e : entries)
+                e.write(zos);
+        }
+
+        //----------------------------------------------------------------
+        // Verify zip file contents using ZipFile.getEntry()
+        //----------------------------------------------------------------
+        try (ZipFile f = new ZipFile(zipName)) {
+            for (Entry e : entries)
+                e.verify(f);
+        }
+
+        //----------------------------------------------------------------
+        // Verify zip file contents using JarFile.getEntry()
+        //----------------------------------------------------------------
+        try (JarFile f = new JarFile(zipName)) {
+            check(f.getManifest() != null);
+            for (Entry e : entries)
+                e.verify(f);
+        }
+
+        //----------------------------------------------------------------
+        // Verify zip file contents using ZipFile.entries()
+        //----------------------------------------------------------------
+        try (ZipFile f = new ZipFile(zipName)) {
+            Enumeration<? extends ZipEntry> en = f.entries();
+            for (Entry e : entries)
+                e.verify(f, en.nextElement());
+
+            check(!en.hasMoreElements());
+        }
+
+        //----------------------------------------------------------------
+        // Verify zip file contents using JarFile.entries()
+        //----------------------------------------------------------------
+        try (JarFile f = new JarFile(zipName)) {
+            Enumeration<? extends ZipEntry> en = f.entries();
+            for (Entry e : entries)
+                e.verify(f, en.nextElement());
+
+            check(!en.hasMoreElements());
+        }
+
+        //----------------------------------------------------------------
+        // Verify zip file contents using ZipInputStream class
+        //----------------------------------------------------------------
+        try (FileInputStream fis = new FileInputStream(zipName);
+             ZipInputStream s = new ZipInputStream(fis)) {
+
+            for (Entry e : entries)
+                e.verifyZipInputStream(s);
+        }
+
+        //----------------------------------------------------------------
+        // Verify zip file contents using JarInputStream class
+        //----------------------------------------------------------------
+        try (FileInputStream fis = new FileInputStream(zipName);
+             JarInputStream s = new JarInputStream(fis)) {
+
+            // JarInputStream "automatically" reads the manifest
+            check(s.getManifest() != null);
+
+            for (Entry e : entries)
+                e.verifyJarInputStream(s);
+        }
+
+//      String cmd = "unzip -t " + zipName.getPath() + " >/dev/tty";
+//      new ProcessBuilder(new String[]{"/bin/sh", "-c", cmd}).start().waitFor();
+
+        zipName.deleteOnExit();
+
+        System.out.printf("passed = %d, failed = %d%n", passed, failed);
+        if (failed > 0) throw new Exception("Some tests failed");
+    }
+}