/*
 * Copyright (c) 2021, 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 jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;

/*
 * @test
 * @summary Tests that the Properties.store() APIs generate output that is reproducible
 * @bug 8231640 8282023 8316540
 * @comment The test launches several processes and in the presence of -Xcomp it's too slow
 *          and thus causes timeouts
 * @requires vm.compMode != "Xcomp"
 * @library /test/lib
 * @run driver StoreReproducibilityTest
 */
public class StoreReproducibilityTest {

    private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu";
    private static final String SYS_PROP_JAVA_PROPERTIES_DATE = "java.properties.date";
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN, Locale.ROOT)
            .withZone(ZoneOffset.UTC);

    public static void main(final String[] args) throws Exception {
        // test that store method uses the java.properties.date system property
        testStoreUsesPropValue();
        // free form non-date value for java.properties.date system property
        testNonDateSysPropValue();
        // blank value for java.properties.date system property
        testBlankSysPropValue();
        // empty value for java.properties.date system property
        testEmptySysPropValue();
        // value for java.properties.date system property contains line terminator characters
        testMultiLineSysPropValue();
        // value for java.properties.date system property contains backslash character
        testBackSlashInSysPropValue();
    }

    /**
     * Launches a Java program which is responsible for using Properties.store() to write out the
     * properties to a file. The launched Java program is passed a value for the
     * {@code java.properties.date} system property and the date comment written out
     * to the file is expected to use this value.
     * The program is launched multiple times with the same value for {@code java.properties.date}
     * and the output written by each run of this program is verified to be exactly the same.
     * Additionally, the date comment that's written out is verified to be the expected date that
     * corresponds to the passed {@code java.properties.date}.
     */
    private static void testStoreUsesPropValue() throws Exception {
        final List<Path> storedFiles = new ArrayList<>();
        final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(243535322));
        for (int i = 0; i < 5; i++) {
            final Path tmpFile = Files.createTempFile("8231640", ".props");
            storedFiles.add(tmpFile);
            final ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(
                    "-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
                    StoreTest.class.getName(),
                    tmpFile.toString(),
                    i % 2 == 0 ? "--use-outputstream" : "--use-writer");
            executeJavaProcess(processBuilder);
            assertExpectedComment(tmpFile, sysPropVal);
            if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
                throw new RuntimeException("Unexpected properties stored in " + tmpFile);
            }
        }
        assertAllFileContentsAreSame(storedFiles, sysPropVal);
    }

    /**
     * Launches a Java program which is responsible for using Properties.store() to write out the
     * properties to a file. The launched Java program is passed a {@link String#isBlank() blank} value
     * for the {@code java.properties.date} system property.
     * It is expected and verified in this test that such a value for the system property
     * will cause a comment line to be written out with only whitespaces.
     * The launched program is expected to complete without any errors.
     */
    private static void testBlankSysPropValue() throws Exception {
        final List<Path> storedFiles = new ArrayList<>();
        final String sysPropVal = "      \t";
        for (int i = 0; i < 2; i++) {
            final Path tmpFile = Files.createTempFile("8231640", ".props");
            storedFiles.add(tmpFile);
            final ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(
                    "-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
                    StoreTest.class.getName(),
                    tmpFile.toString(),
                    i % 2 == 0 ? "--use-outputstream" : "--use-writer");
            executeJavaProcess(processBuilder);
            if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
                throw new RuntimeException("Unexpected properties stored in " + tmpFile);
            }
            String blankCommentLine = findNthComment(tmpFile, 2);
            if (blankCommentLine == null) {
                throw new RuntimeException("Comment line representing the value of "
                        + SYS_PROP_JAVA_PROPERTIES_DATE + " system property is missing in file " + tmpFile);
            }
            if (!blankCommentLine.isBlank()) {
                throw new RuntimeException("Expected comment line to be blank but was " + blankCommentLine);
            }
        }
        assertAllFileContentsAreSame(storedFiles, sysPropVal);
    }

    /**
     * Launches a Java program which is responsible for using Properties.store() to write out the
     * properties to a file. The launched Java program is passed a {@link String#isEmpty() empty} value
     * for the {@code java.properties.date} system property.
     * It is expected and verified in this test that such a value for the system property
     * will cause the current date and time to be written out as a comment.
     * The launched program is expected to complete without any errors.
     */
    private static void testEmptySysPropValue() throws Exception {
        for (int i = 0; i < 2; i++) {
            final Path tmpFile = Files.createTempFile("8231640", ".props");
            final ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(
                    "-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=",
                    "-Duser.timezone=UTC",
                    StoreTest.class.getName(),
                    tmpFile.toString(),
                    i % 2 == 0 ? "--use-outputstream" : "--use-writer");
            Date launchedAt = new Date();
            // wait for a second before launching so that we can then expect
            // the date written out by the store() APIs to be "after" this launch date
            Thread.sleep(1000);
            executeJavaProcess(processBuilder);
            if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
                throw new RuntimeException("Unexpected properties stored in " + tmpFile);
            }
            assertCurrentDate(tmpFile, launchedAt);
        }
    }

    /**
     * Launches a Java program which is responsible for using Properties.store() to write out the
     * properties to a file. The launched Java program is passed the {@code java.properties.date}
     * system property with a value that doesn't represent a formatted date.
     * It is expected and verified in this test that such a value for the system property
     * will cause the comment to use that value verbatim. The launched program is expected to complete
     * without any errors.
     */
    private static void testNonDateSysPropValue() throws Exception {
        final String sysPropVal = "foo-bar";
        final List<Path> storedFiles = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            final Path tmpFile = Files.createTempFile("8231640", ".props");
            storedFiles.add(tmpFile);
            final ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(
                    "-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
                    StoreTest.class.getName(),
                    tmpFile.toString(),
                    i % 2 == 0 ? "--use-outputstream" : "--use-writer");
            executeJavaProcess(processBuilder);
            if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
                throw new RuntimeException("Unexpected properties stored in " + tmpFile);
            }
            assertExpectedComment(tmpFile, sysPropVal);
        }
        assertAllFileContentsAreSame(storedFiles, sysPropVal);
    }

    /**
     * Launches a Java program which is responsible for using Properties.store() to write out the
     * properties to a file. The launched Java program is passed the {@code java.properties.date}
     * system property with a value that has line terminator characters.
     * It is expected and verified in this test that such a value for the system property
     * will cause the comment written out to be multiple separate comments. The launched program is expected
     * to complete without any errors.
     */
    private static void testMultiLineSysPropValue() throws Exception {
        final String[] sysPropVals = {"hello-world\nc=d", "hello-world\rc=d", "hello-world\r\nc=d"};
        for (final String sysPropVal : sysPropVals) {
            final List<Path> storedFiles = new ArrayList<>();
            for (int i = 0; i < 2; i++) {
                final Path tmpFile = Files.createTempFile("8231640", ".props");
                storedFiles.add(tmpFile);
                final ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(
                        "-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
                        StoreTest.class.getName(),
                        tmpFile.toString(),
                        i % 2 == 0 ? "--use-outputstream" : "--use-writer");
                executeJavaProcess(processBuilder);
                if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
                    throw new RuntimeException("Unexpected properties stored in " + tmpFile);
                }
                // verify this results in 2 separate comment lines in the stored file
                String commentLine1 = findNthComment(tmpFile, 2);
                String commentLine2 = findNthComment(tmpFile, 3);
                if (commentLine1 == null || commentLine2 == null) {
                    throw new RuntimeException("Did not find the expected multi-line comments in " + tmpFile);
                }
                if (!commentLine1.equals("hello-world")) {
                    throw new RuntimeException("Unexpected comment line " + commentLine1 + " in " + tmpFile);
                }
                if (!commentLine2.equals("c=d")) {
                    throw new RuntimeException("Unexpected comment line " + commentLine2 + " in " + tmpFile);
                }
            }
            assertAllFileContentsAreSame(storedFiles, sysPropVal);
        }
    }

    /**
     * Launches a Java program which is responsible for using Properties.store() to write out the
     * properties to a file. The launched Java program is passed the {@code java.properties.date}
     * system property with a value that has backslash character.
     * It is expected and verified in this test that such a value for the system property
     * will not cause any malformed comments or introduce any new properties in the stored content.
     * The launched program is expected to complete without any errors.
     */
    private static void testBackSlashInSysPropValue() throws Exception {
        final String[] sysPropVals = {"\\hello-world", "hello-world\\", "hello-world\\c=d",
                "newline-plus-backslash\\\nc=d"};
        for (final String sysPropVal : sysPropVals) {
            final List<Path> storedFiles = new ArrayList<>();
            for (int i = 0; i < 2; i++) {
                final Path tmpFile = Files.createTempFile("8231640", ".props");
                storedFiles.add(tmpFile);
                final ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder(
                        "-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
                        StoreTest.class.getName(),
                        tmpFile.toString(),
                        i % 2 == 0 ? "--use-outputstream" : "--use-writer");
                executeJavaProcess(processBuilder);
                if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
                    throw new RuntimeException("Unexpected properties stored in " + tmpFile);
                }
                String commentLine1 = findNthComment(tmpFile, 2);
                if (commentLine1 == null) {
                    throw new RuntimeException("Did not find the expected comment line in " + tmpFile);
                }
                if (sysPropVal.contains("newline-plus-backslash")) {
                    if (!commentLine1.equals("newline-plus-backslash\\")) {
                        throw new RuntimeException("Unexpected comment line " + commentLine1 + " in " + tmpFile);
                    }
                    // we expect this specific system property value to be written out into 2 separate comment lines
                    String commentLine2 = findNthComment(tmpFile, 3);
                    if (commentLine2 == null) {
                        throw new RuntimeException(sysPropVal + " was expected to be split into 2 comment line, " +
                                "but wasn't, in " + tmpFile);
                    }
                    if (!commentLine2.equals("c=d")) {
                        throw new RuntimeException("Unexpected comment line " + commentLine2 + " in " + tmpFile);
                    }
                } else {
                    if (!commentLine1.equals(sysPropVal)) {
                        throw new RuntimeException("Unexpected comment line " + commentLine1 + " in " + tmpFile);
                    }
                }
            }
            assertAllFileContentsAreSame(storedFiles, sysPropVal);
        }
    }

    // launches the java process and waits for it to exit. throws an exception if exit value is non-zero
    private static void executeJavaProcess(ProcessBuilder pb) throws Exception {
        final OutputAnalyzer outputAnalyzer = ProcessTools.executeProcess(pb);
        try {
            outputAnalyzer.shouldHaveExitValue(0);
        } finally {
            // print out any stdout/err that was generated in the launched program
            outputAnalyzer.reportDiagnosticSummary();
        }
    }

    // Properties.load() from the passed file and return the loaded Properties instance
    private static Properties loadProperties(final Path file) throws IOException {
        final Properties props = new Properties();
        props.load(Files.newBufferedReader(file));
        return props;
    }

    /**
     * Verifies that the comment in the {@code destFile} is same as {@code expectedComment},
     * instead of the default date comment.
     */
    private static void assertExpectedComment(final Path destFile,
                                              final String expectedComment) throws Exception {
        final String actualComment = findNthComment(destFile, 2);
        if (actualComment == null) {
            throw new RuntimeException("Comment \"" + expectedComment + "\" not found in stored properties " + destFile);
        }
        if (!expectedComment.equals(actualComment)) {
            throw new RuntimeException("Expected comment \"" + expectedComment + "\" but found \"" + actualComment + "\" " +
                    "in stored properties " + destFile);
        }
    }

    /**
     * Verifies that the date comment in the {@code destFile} can be parsed using the
     * "EEE MMM dd HH:mm:ss zzz uuuu" format and the time represented by it is {@link Date#after(Date) after}
     * the passed {@code date}
     * The JVM runtime to invoke this method should set the time zone to UTC, i.e, specify
     * "-Duser.timezone=UTC" at the command line. Otherwise, it will fail with some time
     * zones that have ambiguous short names, such as "IST"
     */
    private static void assertCurrentDate(final Path destFile, final Date date) throws Exception {
        final String dateComment = findNthComment(destFile, 2);
        if (dateComment == null) {
            throw new RuntimeException("Date comment not found in stored properties " + destFile);
        }
        System.out.println("Found date comment " + dateComment + " in file " + destFile);
        final Date parsedDate;
        try {
            Instant instant = Instant.from(FORMATTER.parse(dateComment));
            parsedDate = new Date(instant.toEpochMilli());
        } catch (DateTimeParseException pe) {
            throw new RuntimeException("Unexpected date " + dateComment + " in stored properties " + destFile, pe);
        }
        if (!parsedDate.after(date)) {
            throw new RuntimeException("Expected date comment " + dateComment + " to be after " + date
                    + " but was " + parsedDate);
        }
    }

    // returns the "Nth" comment from the file. Comment index starts from 1.
    private static String findNthComment(Path file, int commentIndex) throws IOException {
        List<String> comments = new ArrayList<>();
        try (final BufferedReader reader = Files.newBufferedReader(file)) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("#")) {
                    comments.add(line.substring(1));
                    if (comments.size() == commentIndex) {
                        return comments.get(commentIndex - 1);
                    }
                }
            }
        }
        return null;
    }

    // verifies the byte equality of the contents in each of the files
    private static void assertAllFileContentsAreSame(final List<Path> files,
                                                     final String sysPropVal) throws Exception {
        final byte[] file1Contents = Files.readAllBytes(files.get(0));
        for (int i = 1; i < files.size(); i++) {
            final byte[] otherFileContents = Files.readAllBytes(files.get(i));
            if (!Arrays.equals(file1Contents, otherFileContents)) {
                throw new RuntimeException("Properties.store() did not generate reproducible content when " +
                        SYS_PROP_JAVA_PROPERTIES_DATE + " was set to " + sysPropVal);
            }
        }
    }

    static class StoreTest {
        private static final Properties propsToStore = new Properties();

        static {
            propsToStore.setProperty("a", "b");
        }

        /**
         * Uses Properties.store() APIs to store the properties into file
         */
        public static void main(final String[] args) throws Exception {
            final Path destFile = Path.of(args[0]);
            final String comment = "some user specified comment";
            System.out.println("Current default timezone is " + TimeZone.getDefault());
            if (args[1].equals("--use-outputstream")) {
                try (var os = Files.newOutputStream(destFile)) {
                    propsToStore.store(os, comment);
                }
            } else {
                try (var br = Files.newBufferedWriter(destFile)) {
                    propsToStore.store(br, comment);
                }
            }
        }
    }
}
