/*
 * Copyright (c) 2020, 2024, 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.
 */

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.testng.Assert.assertThrows;

/**
 * @test
 * @bug 8252739
 * @summary Verify Deflater.setDictionary(dictionary, offset, length) uses the offset
 * @run testng/othervm DeflaterDictionaryTests
 */
public class DeflaterDictionaryTests {
    // Output buffer size
    private static final int RESULT_SIZE = 1024;
    // Data to compress
    private static final String SRC_DATA = "Welcome to the US Open;".repeat(6);
    // Dictionary to be used
    private static final String DICTIONARY = "US Open";
    private static final int DICTIONARY_OFFSET = 1;
    private static final int DICTIONARY_LENGTH = 3;

    /**
     * DataProvider with offsets which should be valid for setDictionary
     *
     * @return valid offset values
     */
    @DataProvider(name = "validDictionaryOffsets")
    protected Object[][] validDictionaryOffsets() {
        return new Object[][]{
                {0},
                {DICTIONARY_OFFSET},
                {DICTIONARY_LENGTH}
        };
    }

    /**
     * DataProvider with  invalid offsets for setDictionary
     *
     * @return invalid offset values
     */
    @DataProvider(name = "invalidDictionaryOffsets")
    protected Object[][] invalidDictionaryOffsets() {
        return new Object[][]{
                {-1},
                {DICTIONARY_LENGTH + 2},
                {DICTIONARY.length()}
        };
    }

    /**
     * Validate that an offset can be used with Deflater::setDictionary
     *
     * @param dictionary_offset offset value to be used
     * @throws Exception if an error occurs
     */
    @Test(dataProvider = "validDictionaryOffsets")
    public void testByteArray(int dictionary_offset) throws Exception {
        byte[] input = SRC_DATA.getBytes(UTF_8);
        byte[] output = new byte[RESULT_SIZE];
        Deflater deflater = new Deflater();
        Inflater inflater = new Inflater();
        try {
            // Compress the bytes
            deflater.setDictionary(DICTIONARY.getBytes(UTF_8), dictionary_offset, DICTIONARY_LENGTH);
            deflater.setInput(input);
            deflater.finish();
            int compressedDataLength = deflater.deflate(output, 0, output.length, Deflater.NO_FLUSH);
            System.out.printf("Deflater::getBytesWritten:%d, Deflater::getAdler: %d," +
                            " compressed length: %d%n", deflater.getBytesWritten(),
                    deflater.getAdler(), compressedDataLength);
            deflater.finished();

            // Decompress the bytes
            inflater.setInput(output, 0, compressedDataLength);
            byte[] result = new byte[RESULT_SIZE];
            int resultLength = inflater.inflate(result);
            if (inflater.needsDictionary()) {
                System.out.println("Specifying Dictionary");
                inflater.setDictionary(DICTIONARY.getBytes(UTF_8), dictionary_offset, DICTIONARY_LENGTH);
                resultLength = inflater.inflate(result);
            } else {
                System.out.println("Did not need to use a Dictionary");
            }
            inflater.finished();
            System.out.printf("Inflater::getAdler:%d, length: %d%n",
                    inflater.getAdler(), resultLength);

            Assert.assertEquals(SRC_DATA.length(), resultLength);
            Assert.assertEquals(input, Arrays.copyOf(result, resultLength));
        } finally {
            // Release Resources
            deflater.end();
            inflater.end();
        }
    }

    /**
     * Validate that a ByteBuffer can be used with Deflater::setDictionary
     *
     * @throws Exception if an error occurs
     */
    @Test
    public void testHeapByteBuffer() throws Exception {
        byte[] input = SRC_DATA.getBytes(UTF_8);
        byte[] output = new byte[RESULT_SIZE];
        ByteBuffer dictDef = ByteBuffer.wrap(DICTIONARY.getBytes(UTF_8), DICTIONARY_OFFSET, DICTIONARY_LENGTH);
        ByteBuffer dictInf = ByteBuffer.wrap(DICTIONARY.getBytes(UTF_8), DICTIONARY_OFFSET, DICTIONARY_LENGTH);
        Deflater deflater = new Deflater();
        Inflater inflater = new Inflater();
        try {
            // Compress the bytes
            deflater.setDictionary(dictDef);
            deflater.setInput(input);
            deflater.finish();
            int compressedDataLength = deflater.deflate(output, 0, output.length, Deflater.NO_FLUSH);
            System.out.printf("Deflater::getBytesWritten:%d, Deflater::getAdler: %d," +
                            " compressed length: %d%n", deflater.getBytesWritten(),
                    deflater.getAdler(), compressedDataLength);
            deflater.finished();

            // Decompress the bytes
            inflater.setInput(output, 0, compressedDataLength);
            byte[] result = new byte[RESULT_SIZE];
            int resultLength = inflater.inflate(result);
            if (inflater.needsDictionary()) {
                System.out.println("Specifying Dictionary");
                inflater.setDictionary(dictInf);
                resultLength = inflater.inflate(result);
            } else {
                System.out.println("Did not need to use a Dictionary");
            }
            inflater.finished();
            System.out.printf("Inflater::getAdler:%d, length: %d%n",
                    inflater.getAdler(), resultLength);

            Assert.assertEquals(SRC_DATA.length(), resultLength);
            Assert.assertEquals(input, Arrays.copyOf(result, resultLength));
        } finally {
            // Release Resources
            deflater.end();
            inflater.end();
        }
    }

    /**
     * Validate that ByteBuffer::allocateDirect can be used with Deflater::setDictionary
     *
     * @throws Exception if an error occurs
     */
    @Test
    public void testByteBufferDirect() throws Exception {
        byte[] input = SRC_DATA.getBytes(UTF_8);
        byte[] output = new byte[RESULT_SIZE];
        ByteBuffer dictDef = ByteBuffer.allocateDirect(DICTIONARY.length());
        ByteBuffer dictInf = ByteBuffer.allocateDirect(DICTIONARY.length());
        dictDef.put(DICTIONARY.getBytes(UTF_8));
        dictInf.put(DICTIONARY.getBytes(UTF_8));
        dictDef.position(DICTIONARY_OFFSET);
        dictDef.limit(DICTIONARY_LENGTH);
        dictInf.position(DICTIONARY_OFFSET);
        dictInf.limit(DICTIONARY_LENGTH);
        Deflater deflater = new Deflater();
        Inflater inflater = new Inflater();
        try {
            // Compress the bytes
            deflater.setDictionary(dictDef.slice());
            deflater.setInput(input);
            deflater.finish();
            int compressedDataLength = deflater.deflate(output, 0, output.length, Deflater.NO_FLUSH);
            System.out.printf("Deflater::getBytesWritten:%d, Deflater::getAdler: %d," +
                            " compressed length: %d%n", deflater.getBytesWritten(),
                    deflater.getAdler(), compressedDataLength);
            deflater.finished();

            // Decompress the bytes
            inflater.setInput(output, 0, compressedDataLength);
            byte[] result = new byte[RESULT_SIZE];
            int resultLength = inflater.inflate(result);
            if (inflater.needsDictionary()) {
                System.out.println("Specifying Dictionary");
                inflater.setDictionary(dictInf.slice());
                resultLength = inflater.inflate(result);
            } else {
                System.out.println("Did not need to use a Dictionary");
            }
            inflater.finished();
            System.out.printf("Inflater::getAdler:%d, length: %d%n",
                    inflater.getAdler(), resultLength);

            Assert.assertEquals(SRC_DATA.length(), resultLength);
            Assert.assertEquals(input, Arrays.copyOf(result, resultLength));
        } finally {
            // Release Resources
            deflater.end();
            inflater.end();
        }
    }

    /**
     * Validate that an invalid offset used with setDictionary will
     * throw an Exception
     *
     * @param dictionary_offset offset value to be used
     */
    @Test(dataProvider = "invalidDictionaryOffsets")
    public void testInvalidOffsets(int dictionary_offset) {
        byte[] dictionary = DICTIONARY.getBytes(UTF_8);

        Deflater deflater = new Deflater();
        Inflater inflater = new Inflater();
        try {
            assertThrows(ArrayIndexOutOfBoundsException.class, () ->
                    deflater.setDictionary(dictionary, dictionary_offset, DICTIONARY_LENGTH));
            assertThrows(ArrayIndexOutOfBoundsException.class, () ->
                    inflater.setDictionary(dictionary, dictionary_offset, DICTIONARY_LENGTH));
        } finally {
            // Release Resources
            deflater.end();
            inflater.end();
        }
    }
}