test/jdk/jdk/nio/zipfs/ZipFSTester.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, 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.

@@ -26,10 +26,11 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
 import java.net.URLDecoder;
 import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
 import java.nio.channels.FileChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.FileSystem;

@@ -56,49 +57,55 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.zip.CRC32;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
 
 import static java.nio.file.StandardOpenOption.*;
 import static java.nio.file.StandardCopyOption.*;
 
 /*
  * Tests various zipfs operations.
  *
  * @test
  * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
  *      7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211
- *      8131067
+ *      8131067 8034802
  * @summary Test Zip filesystem provider
  * @modules jdk.zipfs
  * @run main ZipFSTester
  * @run main/othervm/java.security.policy=test.policy ZipFSTester
  */
 
 public class ZipFSTester {
 
     public static void main(String[] args) throws Exception {
-
         // create JAR file for test, actual contents don't matter
         Path jarFile = Utils.createJarFile("tester.jar",
                 "META-INF/MANIFEST.MF",
                 "dir1/foo",
-                "dir2/bar");
+                "dir2/bar",
+                "dir1/dir3/fooo");
 
         try (FileSystem fs = newZipFileSystem(jarFile, Collections.emptyMap())) {
             test0(fs);
             test1(fs);
             test2(fs);   // more tests
         }
+
+        testStreamChannel();
         testTime(jarFile);
         test8069211();
         test8131067();
     }
 
+    private static Random rdm = new Random();
+
     static void test0(FileSystem fs)
         throws Exception
     {
         List<String> list = new LinkedList<>();
         try (ZipFile zf = new ZipFile(fs.toString())) {

@@ -119,17 +126,32 @@
     }
 
     static void test1(FileSystem fs0)
         throws Exception
     {
-        Random rdm = new Random();
-        // clone a fs and test on it
+        // prepare a src for testing
+        Path src = getTempPath();
+        String tmpName = src.toString();
+        try (OutputStream os = Files.newOutputStream(src)) {
+            byte[] bits = new byte[12345];
+            rdm.nextBytes(bits);
+            os.write(bits);
+        }
+
+        // clone a fs from fs0 and test on it
         Path tmpfsPath = getTempPath();
         Map<String, Object> env = new HashMap<String, Object>();
         env.put("create", "true");
         try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) {
             z2zcopy(fs0, copy, "/", 0);
+
+            // copy the test jar itself in
+            Files.copy(Paths.get(fs0.toString()), copy.getPath("/foo.jar"));
+            Path zpath = copy.getPath("/foo.jar");
+            try (FileSystem zzfs = FileSystems.newFileSystem(zpath, null)) {
+                Files.copy(src, zzfs.getPath("/srcInjarjar"));
+            }
         }
 
         try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) {
 
             FileSystemProvider provider = fs.provider();

@@ -140,19 +162,10 @@
                      new HashMap<String, Object>()))
             {
                 throw new RuntimeException("newFileSystem(URI...) does not throw exception");
             } catch (FileSystemAlreadyExistsException fsaee) {}
 
-            // prepare a src
-            Path src = getTempPath();
-            String tmpName = src.toString();
-            OutputStream os = Files.newOutputStream(src);
-            byte[] bits = new byte[12345];
-            rdm.nextBytes(bits);
-            os.write(bits);
-            os.close();
-
             try {
                 provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(),
                                        new HashMap<String, Object>());
                 throw new RuntimeException("newFileSystem() opens a directory as zipfs");
             } catch (UnsupportedOperationException uoe) {}

@@ -160,10 +173,12 @@
             try {
                 provider.newFileSystem(src, new HashMap<String, Object>());
                 throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs");
             } catch (UnsupportedOperationException uoe) {}
 
+            // walk
+            walk(fs.getPath("/"));
 
             // copyin
             Path dst = getPathWithParents(fs, tmpName);
             Files.copy(src, dst);
             checkEqual(src, dst);

@@ -234,14 +249,33 @@
             Files.delete(tmp);
 
             // test channels
             channel(fs, dst);
             Files.delete(dst);
-            Files.delete(src);
+
+            // test foo.jar in jar/zipfs #8034802
+            Path jpath = fs.getPath("/foo.jar");
+            System.out.println("walking: " + jpath);
+            try (FileSystem zzfs = FileSystems.newFileSystem(jpath, null)) {
+                walk(zzfs.getPath("/"));
+                // foojar:/srcInjarjar
+                checkEqual(src, zzfs.getPath("/srcInjarjar"));
+
+                dst = getPathWithParents(zzfs, tmpName);
+                fchCopy(src, dst);
+                checkEqual(src, dst);
+                tmp = Paths.get(tmpName + "_Tmp");
+                fchCopy(dst, tmp);   //  out
+                checkEqual(src, tmp);
+                Files.delete(tmp);
+
+                channel(zzfs, dst);
+                Files.delete(dst);
+            }
         } finally {
-            if (Files.exists(tmpfsPath))
-                Files.delete(tmpfsPath);
+            Files.deleteIfExists(tmpfsPath);
+            Files.deleteIfExists(src);
         }
     }
 
     static void test2(FileSystem fs) throws Exception {
 

@@ -381,21 +415,172 @@
         Files.delete(fs1Path);
         Files.delete(fs2Path);
         Files.delete(fs3Path);
     }
 
+    static final int METHOD_STORED     = 0;
+    static final int METHOD_DEFLATED   = 8;
+
+    static Object[][] getEntries() {
+        Object[][] entries = new Object[10 + rdm.nextInt(20)][3];
+        for (int i = 0; i < entries.length; i++) {
+            entries[i][0] = "entries" + i;
+            entries[i][1] = rdm.nextInt(10) % 2 == 0 ?
+                METHOD_STORED : METHOD_DEFLATED;
+            entries[i][2] = new byte[rdm.nextInt(8192)];
+            rdm.nextBytes((byte[])entries[i][2]);
+        }
+        return entries;
+    }
+
+    // check the content of read from zipfs is equal to the "bytes"
+    private static void checkRead(Path path, byte[] expected) throws IOException {
+        //streams
+        try (InputStream is = Files.newInputStream(path)) {
+            if (!Arrays.equals(is.readAllBytes(), expected)) {
+                System.out.printf(" newInputStream <%s> failed...%n", path.toString());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+        }
+
+        // channels -- via sun.nio.ch.ChannelInputStream
+        try (SeekableByteChannel sbc = Files.newByteChannel(path);
+            InputStream is = Channels.newInputStream(sbc)) {
+
+            // check all bytes match
+            if (!Arrays.equals(is.readAllBytes(), expected)) {
+                System.out.printf(" newByteChannel <%s> failed...%n", path.toString());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+
+            // Check if read position is at the end
+            if (sbc.position() != expected.length) {
+                System.out.printf("pos [%s]: size=%d, position=%d%n",
+                                  path.toString(), expected.length, sbc.position());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+
+            // Check position(x) + read() at the random/specific pos/len
+            byte[] buf = new byte[1024];
+            ByteBuffer bb = ByteBuffer.wrap(buf);
+            for (int i = 0; i < 10; i++) {
+                int pos = rdm.nextInt((int)sbc.size());
+                int len = rdm.nextInt(Math.min(buf.length, expected.length - pos));
+                // System.out.printf("  --> %d, %d%n", pos, len);
+                bb.position(0).limit(len);    // bb.flip().limit(len);
+                if (sbc.position(pos).position() != pos ||
+                    sbc.read(bb) != len ||
+                    !Arrays.equals(buf, 0, bb.position(), expected, pos, pos + len)) {
+                    System.out.printf("read()/position() failed%n");
+                }
+            }
+        } catch (IOException x) {
+            x.printStackTrace();
+            throw new RuntimeException("CHECK FAILED!");
+        }
+    }
+
+    // test entry stream/channel reading
+    static void testStreamChannel() throws Exception {
+        Path zpath = getTempPath();
+        try {
+            var crc = new CRC32();
+            Object[][] entries = getEntries();
+
+            // [1] create zip via ZipOutputStream
+            try (var os = Files.newOutputStream(zpath);
+                 var zos = new ZipOutputStream(os)) {
+                for (Object[] entry : entries) {
+                   var ze = new ZipEntry((String)entry[0]);
+                   int method = (int)entry[1];
+                   byte[] bytes = (byte[])entry[2];
+                   if (method == METHOD_STORED) {
+                       ze.setSize(bytes.length);
+                       crc.reset();
+                       crc.update(bytes);
+                       ze.setCrc(crc.getValue());
+                   }
+                   ze.setMethod(method);
+                   zos.putNextEntry(ze);
+                   zos.write(bytes);
+                   zos.closeEntry();
+                }
+            }
+            try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) {
+                for (Object[] e : entries) {
+                    Path path = zfs.getPath((String)e[0]);
+                    int method = (int)e[1];
+                    byte[] bytes = (byte[])e[2];
+                    // System.out.printf("checking read [%s, %d, %d]%n",
+                    //                   path.toString(), bytes.length, method);
+                    checkRead(path, bytes);
+                }
+            }
+            Files.deleteIfExists(zpath);
+
+            // [2] create zip via zfs.newByteChannel
+            try (var zfs = newZipFileSystem(zpath, Map.of("create", "true"))) {
+                for (Object[] e : entries) {
+                    //  tbd: method is not used
+                    try (var sbc = Files.newByteChannel(zfs.getPath((String)e[0]),
+                                                        CREATE_NEW, WRITE)) {
+                        sbc.write(ByteBuffer.wrap((byte[])e[2]));
+                    }
+                }
+            }
+            try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) {
+                for (Object[] e : entries) {
+                    checkRead(zfs.getPath((String)e[0]), (byte[])e[2]);
+                }
+            }
+            Files.deleteIfExists(zpath);
+
+            // [3] create zip via Files.write()/newoutputStream/
+            try (var zfs = newZipFileSystem(zpath, Map.of("create", "true"))) {
+                for (Object[] e : entries) {
+                    Files.write(zfs.getPath((String)e[0]), (byte[])e[2]);
+                }
+            }
+            try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) {
+                for (Object[] e : entries) {
+                    checkRead(zfs.getPath((String)e[0]), (byte[])e[2]);
+                }
+            }
+            Files.deleteIfExists(zpath);
+
+            // [4] create zip via zfs.newByteChannel, with "method_stored"
+            try (var zfs = newZipFileSystem(zpath,
+                    Map.of("create", true, "noCompression", true))) {
+                for (Object[] e : entries) {
+                    try (var sbc = Files.newByteChannel(zfs.getPath((String)e[0]),
+                                                        CREATE_NEW, WRITE)) {
+                        sbc.write(ByteBuffer.wrap((byte[])e[2]));
+                    }
+                }
+            }
+            try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) {
+                for (Object[] e : entries) {
+                    checkRead(zfs.getPath((String)e[0]), (byte[])e[2]);
+                }
+            }
+            Files.deleteIfExists(zpath);
+
+        } finally {
+            Files.deleteIfExists(zpath);
+        }
+    }
+
     // test file stamp
     static void testTime(Path src) throws Exception {
         BasicFileAttributes attrs = Files
                         .getFileAttributeView(src, BasicFileAttributeView.class)
                         .readAttributes();
         // create a new filesystem, copy this file into it
         Map<String, Object> env = new HashMap<String, Object>();
         env.put("create", "true");
         Path fsPath = getTempPath();
-        FileSystem fs = newZipFileSystem(fsPath, env);
-
+        try (FileSystem fs = newZipFileSystem(fsPath, env)) {
         System.out.println("test copy with timestamps...");
         // copyin
         Path dst = getPathWithParents(fs, "me");
         Files.copy(src, dst, COPY_ATTRIBUTES);
         checkEqual(src, dst);

@@ -417,12 +602,14 @@
             dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) ||
             attrs.creationTime().to(TimeUnit.SECONDS) !=
             dstAttrs.creationTime().to(TimeUnit.SECONDS)) {
             throw new RuntimeException("Timestamp Copy Failed!");
         }
+        } finally {
         Files.delete(fsPath);
     }
+    }
 
     static void test8069211() throws Exception {
         // create a new filesystem, copy this file into it
         Map<String, Object> env = new HashMap<String, Object>();
         env.put("create", "true");

@@ -622,12 +809,12 @@
     }
 
     // check the content of two paths are equal
     private static void checkEqual(Path src, Path dst) throws IOException
     {
-        //System.out.printf("checking <%s> vs <%s>...%n",
-        //                  src.toString(), dst.toString());
+        System.out.printf("checking <%s> vs <%s>...%n",
+                          src.toString(), dst.toString());
 
         //streams
         byte[] bufSrc = new byte[8192];
         byte[] bufDst = new byte[8192];
         try (InputStream isSrc = Files.newInputStream(src);

@@ -700,10 +887,25 @@
             if (chDst.position() != chDst.size()) {
                 System.out.printf("dst[%s]: size=%d, position=%d%n",
                                   chDst.toString(), chDst.size(), chDst.position());
                 throw new RuntimeException("CHECK FAILED!");
             }
+
+            // Check position(x) + read() at the specific pos/len
+            for (int i = 0; i < 10; i++) {
+                int pos = rdm.nextInt((int)chSrc.size());
+                int limit = rdm.nextInt(1024);
+                if (chSrc.position(pos).position() != chDst.position(pos).position()) {
+                    System.out.printf("dst/src.position(pos failed%n");
+                }
+                bbSrc.clear().limit(limit);
+                bbDst.clear().limit(limit);
+                if (chSrc.read(bbSrc) != chDst.read(bbDst) ||
+                    !bbSrc.flip().equals(bbDst.flip())) {
+                    System.out.printf("dst/src.read() failed%n");
+                }
+            }
         } catch (IOException x) {
             x.printStackTrace();
         }
     }