import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class BadZipTest {
    File hugeZipFile;

    @BeforeEach
    void setUp() throws Exception {
        hugeZipFile = File.createTempFile("hugeZip", ".zip");
    }

    @AfterEach
    void tearDown() throws Exception {
        hugeZipFile.delete();
    }

    @Test
    void testParseBigZipCEN() throws Exception {
        long startTime = System.currentTimeMillis();
        try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(hugeZipFile))) {
            int dirCount = 25_000;
            long nextLog = System.currentTimeMillis();
            for (int dirN = 0; dirN < dirCount; dirN++) {
                String dirName = UUID.randomUUID() + "/";
                for (int fileN = 0; fileN < 1_000; fileN++) {
                    ZipEntry entry = new ZipEntry(dirName + UUID.randomUUID());
                    zip.putNextEntry(entry);
                    zip.closeEntry(); // all files are empty
                }
                if (System.currentTimeMillis() >= nextLog) {
                    nextLog = 30_000 + System.currentTimeMillis();
                    System.out.printf("Processed %s%% directories (%s), file size is %sMb (%ss)%n",
                            dirN * 100 / dirCount, dirN, hugeZipFile.length() / 1024 / 1024,
                            (System.currentTimeMillis() - startTime) / 1000);
                }
            }
        }
        System.out.printf("File generated in %ss, file size is %sMb%n",
                (System.currentTimeMillis() - startTime) / 1000, hugeZipFile.length() / 1024 / 1024);

// the exception thrown here
// java.lang.NegativeArraySizeException: -1319967274
// at java.base/java.util.zip.ZipFile$Source.initCEN(ZipFile.java:1487)
        try (ZipFile zip = new ZipFile(hugeZipFile)) {
            assertTrue(zip.entries().hasMoreElements());
        }
    }
}