/*
 * Copyright (c) 2015, 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 8142508 8146431
 * @modules java.base/java.util.zip:open
 * @summary Tests various ZipFile apis
 * @run main/manual TestZipFile
 */

import java.io.*;
import java.lang.reflect.Method;
import java.nio.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.zip.*;

public class TestZipFile {

    private static Random r = new Random();
    private static int    N = 50;
    private static int    NN = 10;
    private static int    ENUM = 10000;
    private static int    ESZ = 10000;
    private static ExecutorService executor = Executors.newFixedThreadPool(20);
    private static Set<Path> paths = new HashSet<>();

    static void realMain (String[] args) throws Throwable {

        try {
            for (int i = 0; i < N; i++) {
                test(r.nextInt(ENUM), r.nextInt(ESZ), false, true);
                test(r.nextInt(ENUM), r.nextInt(ESZ), true, true);
            }

            for (int i = 0; i < NN; i++) {
                test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), false, true);
                test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), true, true);
                testCachedDelete();
                testCachedOverwrite();
                //test(r.nextInt(ENUM), r.nextInt(ESZ), false, true);
            }

            test(70000, 1000, false, true);   // > 65536 entry number;
            testDelete();                     // OPEN_DELETE

            executor.shutdown();
            executor.awaitTermination(10, TimeUnit.MINUTES);
        } finally {
            for (Path path : paths) {
                Files.deleteIfExists(path);
            }
        }
    }

    static void test(int numEntry, int szMax, boolean addPrefix, boolean cleanOld) {
        String name = "zftest" + r.nextInt() + ".zip";
        Zip zip = new Zip(name, numEntry, szMax, addPrefix, cleanOld);
        for (int i = 0; i < NN; i++) {
            executor.submit(() -> doTest(zip));
        }
     }

    // test scenario:
    // (1) open the ZipFile(zip) with OPEN_READ | OPEN_DELETE
    // (2) test the ZipFile works correctly
    // (3) check the zip is deleted after ZipFile gets closed
    static void testDelete() throws Throwable {
        String name = "zftest" + r.nextInt() + ".zip";
        Zip zip = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
        try (ZipFile zf = new ZipFile(new File(zip.name),
                                      ZipFile.OPEN_READ | ZipFile.OPEN_DELETE ))
        {
            doTest0(zip, zf);
        }
        Path p = Paths.get(name);
        if (Files.exists(p)) {
            fail("Failed to delete " + name + " with OPEN_DELETE");
        }
    }

    // test scenario:
    // (1) keep a ZipFile(zip1) alive (in ZipFile's cache), dont close it
    // (2) delete zip1 and create zip2 with the same name the zip1 with zip2
    // (3) zip1 tests should fail, but no crash
    // (4) zip2 tasks should all get zip2, then pass normal testing.
    static void testCachedDelete() throws Throwable {
        String name = "zftest" + r.nextInt() + ".zip";
        Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);

        try (ZipFile zf = new ZipFile(zip1.name)) {
            for (int i = 0; i < NN; i++) {
                executor.submit(() -> verifyNoCrash(zip1));
            }
            // delete the "zip1"  and create a new one to test
            Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
            /*
                System.out.println("========================================");
                System.out.printf("    zip1=%s, mt=%d, enum=%d%n    ->attrs=[key=%s, sz=%d, mt=%d]%n",
                    zip1.name, zip1.lastModified, zip1.entries.size(),
                    zip1.attrs.fileKey(), zip1.attrs.size(), zip1.attrs.lastModifiedTime().toMillis());
                System.out.printf("    zip2=%s, mt=%d, enum=%d%n    ->attrs=[key=%s, sz=%d, mt=%d]%n",
                    zip2.name, zip2.lastModified, zip2.entries.size(),
                    zip2.attrs.fileKey(), zip2.attrs.size(), zip2.attrs.lastModifiedTime().toMillis());
            */
            for (int i = 0; i < NN; i++) {
                executor.submit(() -> doTest(zip2));
            }
        }
    }

   // overwrite the "zip1"  and create a new one to test. So the two zip files
   // have the same fileKey, but probably different lastModified()
    static void testCachedOverwrite() throws Throwable {
        String name = "zftest" + r.nextInt() + ".zip";
        Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
        try (ZipFile zf = new ZipFile(zip1.name)) {
            for (int i = 0; i < NN; i++) {
                executor.submit(() -> verifyNoCrash(zip1));
            }
            // overwrite the "zip1"  with new contents
            Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, false);
            for (int i = 0; i < NN; i++) {
                executor.submit(() -> doTest(zip2));
            }
        }
    }

    // just check the entries and contents. since the file has been either overwritten
    // or deleted/rewritten, we only care if it crahes or not.
    static void verifyNoCrash(Zip zip) throws RuntimeException {
        try (ZipFile zf = new ZipFile(zip.name)) {
            List<ZipEntry> zlist = new ArrayList(zip.entries.keySet());
            String[] elist = zf.stream().map( e -> e.getName()).toArray(String[]::new);
            if (!Arrays.equals(elist,
                               zlist.stream().map( e -> e.getName()).toArray(String[]::new)))
            {
                //System.out.printf("++++++ LIST NG [%s] entries.len=%d, expected=%d+++++++%n",
                //                  zf.getName(), elist.length, zlist.size());
                return;
            }
            for (ZipEntry ze : zlist) {
                byte[] zdata = zip.entries.get(ze);
                ZipEntry e = zf.getEntry(ze.getName());
                if (e != null) {
                    checkEqual(e, ze);
                    if (!e.isDirectory()) {
                        // check with readAllBytes
                        try (InputStream is = zf.getInputStream(e)) {
                            if (!Arrays.equals(zdata, is.readAllBytes())) {
                                //System.out.printf("++++++ BYTES NG  [%s]/[%s] ++++++++%n",
                                //                  zf.getName(), ze.getName());
                            }
                        }
                    }
                }
            }
        } catch (Throwable t) {
            // t.printStackTrace();
            // fail(t.toString());
        }
    }

    static void checkEqual(ZipEntry x, ZipEntry y) {
        if (x.getName().equals(y.getName()) &&
            x.isDirectory() == y.isDirectory() &&
            x.getMethod() == y.getMethod() &&
            (x.getTime() / 2000) == y.getTime() / 2000 &&
            x.getSize() == y.getSize() &&
            x.getCompressedSize() == y.getCompressedSize() &&
            x.getCrc() == y.getCrc() &&
            x.getComment().equals(y.getComment())
        ) {
            pass();
        } else {
            fail(x + " not equal to " + y);
            System.out.printf("      %s       %s%n", x.getName(), y.getName());
            System.out.printf("      %d       %d%n", x.getMethod(), y.getMethod());
            System.out.printf("      %d       %d%n", x.getTime(), y.getTime());
            System.out.printf("      %d       %d%n", x.getSize(), y.getSize());
            System.out.printf("      %d       %d%n", x.getCompressedSize(), y.getCompressedSize());
            System.out.printf("      %d       %d%n", x.getCrc(), y.getCrc());
            System.out.println("-----------------");
        }
    }

    static void doTest(Zip zip) throws RuntimeException {
        //Thread me = Thread.currentThread();
        try (ZipFile zf = new ZipFile(zip.name)) {
            doTest0(zip, zf);
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    static void doTest0(Zip zip, ZipFile zf) throws Throwable {
        // (0) check zero-length entry name, no AIOOBE
        try {
            check(zf.getEntry("") == null);;
        } catch (Throwable t) {
            unexpected(t);
        }

        List<ZipEntry> list = new ArrayList(zip.entries.keySet());
        // (1) check entry list, in expected order
        if (!check(Arrays.equals(
                list.stream().map( e -> e.getName()).toArray(String[]::new),
                zf.stream().map( e -> e.getName()).toArray(String[]::new)))) {
            return;
        }
        // (2) shuffle, and check each entry and its bytes
        Collections.shuffle(list);
        for (ZipEntry ze : list) {
            byte[] data = zip.entries.get(ze);
            ZipEntry e = zf.getEntry(ze.getName());
            checkEqual(e, ze);
            if (!e.isDirectory()) {
                // check with readAllBytes
                try (InputStream is = zf.getInputStream(e)) {
                    check(Arrays.equals(data, is.readAllBytes()));
                }
                // check with smaller sized buf
                try (InputStream is = zf.getInputStream(e)) {
                    byte[] buf = new byte[(int)e.getSize()];
                    int sz = r.nextInt((int)e.getSize()/4 + 1) + 1;
                    int off = 0;
                    int n;
                    while ((n = is.read(buf, off, buf.length - off)) > 0) {
                        off += n;
                    }
                    check(is.read() == -1);
                    check(Arrays.equals(data, buf));
                }
            }
        }
        // (3) check getMetaInfEntryNames
        String[] metas = list.stream()
                             .map( e -> e.getName())
                             .filter( s -> s.startsWith("META-INF/"))
                             .sorted()
                             .toArray(String[]::new);
        if (metas.length > 0) {
            // meta-inf entries
            Method getMetas = ZipFile.class.getDeclaredMethod("getMetaInfEntryNames");
            getMetas.setAccessible(true);
            String[] names = (String[])getMetas.invoke(zf);
            if (names == null) {
                fail("Failed to get metanames from " + zf);
            } else {
                Arrays.sort(names);
                check(Arrays.equals(names, metas));
            }
        }
    }

    private static class Zip {
        String name;
        Map<ZipEntry, byte[]> entries;
        BasicFileAttributes attrs;
        long lastModified;

        Zip(String name, int num, int szMax, boolean prefix, boolean clean) {
            this.name = name;
            entries = new LinkedHashMap<>(num);
            try {
                Path p = Paths.get(name);
                if (clean) {
                    Files.deleteIfExists(p);
                }
                paths.add(p);
            } catch (Exception x) {
                throw (RuntimeException)x;
            }

            try (FileOutputStream fos = new FileOutputStream(name);
                 BufferedOutputStream bos = new BufferedOutputStream(fos);
                 ZipOutputStream zos = new ZipOutputStream(bos))
            {
                if (prefix) {
                    byte[] bytes = new byte[r.nextInt(1000)];
                    r.nextBytes(bytes);
                    bos.write(bytes);
                }
                CRC32 crc = new CRC32();
                for (int i = 0; i < num; i++) {
                    String ename = "entry-" + i + "-name-" + r.nextLong();
                    ZipEntry ze = new ZipEntry(ename);
                    int method = r.nextBoolean() ? ZipEntry.STORED : ZipEntry.DEFLATED;
                    writeEntry(zos, crc, ze, ZipEntry.STORED, szMax);
                }
                // add some manifest entries
                for (int i = 0; i < r.nextInt(20); i++) {
                    String meta = "META-INF/" + "entry-" + i + "-metainf-" + r.nextLong();
                    ZipEntry ze = new ZipEntry(meta);
                    writeEntry(zos, crc, ze, ZipEntry.STORED, szMax);
                }
            } catch (Exception x) {
                throw (RuntimeException)x;
            }
            try {
                this.attrs = Files.readAttributes(Paths.get(name), BasicFileAttributes.class);
                this.lastModified = new File(name).lastModified();
            } catch (Exception x) {
                throw (RuntimeException)x;
            }
        }

        private void writeEntry(ZipOutputStream zos, CRC32 crc,
                                ZipEntry ze, int method, int szMax)
            throws IOException
        {
            ze.setMethod(method);
            byte[] data = new byte[r.nextInt(szMax + 1)];
            r.nextBytes(data);
            if (method == ZipEntry.STORED) {  // must set size/csize/crc
                ze.setSize(data.length);
                ze.setCompressedSize(data.length);
                crc.reset();
                crc.update(data);
                ze.setCrc(crc.getValue());
            }
            ze.setTime(System.currentTimeMillis());
            ze.setComment(ze.getName());
            zos.putNextEntry(ze);
            zos.write(data);
            zos.closeEntry();
            entries.put(ze, data);
        }
    }

    //--------------------- Infrastructure ---------------------------
    static volatile int passed = 0, failed = 0;
    static void pass() {passed++;}
    static void pass(String msg) {System.out.println(msg); passed++;}
    static void fail() {failed++; Thread.dumpStack();}
    static void fail(String msg) {System.out.println(msg); fail();}
    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
    static void unexpected(Throwable t, String msg) {
        System.out.println(msg); failed++; t.printStackTrace();}
    static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}

    public static void main(String[] args) throws Throwable {
        try {realMain(args);} catch (Throwable t) {unexpected(t);}
        System.out.println("\nPassed = " + passed + " failed = " + failed);
        if (failed > 0) throw new AssertionError("Some tests failed");}
}
