/*
 * Copyright (c) 2020 Microsoft Corporation. All rights reserved.
 * Copyright (c) 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 java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

import static org.testng.Assert.*;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import org.testng.SkipException;

import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;

/* @test
 * @summary Test Files' public APIs with drives created using the subst command on Windows.
 * @requires (os.family == "windows")
 * @library /test/lib ..
 * @build SubstDrive
 * @run testng SubstDrive
 */
public class SubstDrive {

    private static Path SUBST_DRIVE;
    private static Path TEST_TEMP_DIRECTORY;

    /**
     * Setup for the test:
     *      + Create a temporary directory where all subsequently created temp
     *        directories will be in. This directory and all of its contents will be
     *        deleted when the test finishes.
     *      + Find a drive that is available for use with subst.
     */
    @BeforeClass
    public void setup() throws IOException {
        TEST_TEMP_DIRECTORY = Files.createTempDirectory("tmp");
        System.out.printf("Test directory is at %s\n", TEST_TEMP_DIRECTORY);

        Optional<Path> substDrive = findAvailableDrive(TEST_TEMP_DIRECTORY);
        if (!substDrive.isPresent()) {
            throw new SkipException(
                "Could not find any available drive to use with subst, skipping the tests");
        }
        SUBST_DRIVE = substDrive.get();
        System.out.printf("Using drive %s\n with subst", SUBST_DRIVE);
    }

    /**
     * Delete the root temporary directory together with all of its contents
     * when all tests finish.
     */
    @AfterClass
    public void removeRootTempDirectory() throws IOException {
        TestUtil.removeAll(TEST_TEMP_DIRECTORY);
    }

    /**
     * Each test method maps drive `SUBST_DRIVE` to a temporary directory,
     * unmap the drive after every test so that subsequent ones can reuse
     * the drive.
     */
    @AfterMethod
    public void deleteSubstDrive() throws IOException {
        Stream<String> substitutedDrives = substFindMappedDrives();
        // Only delete `SUBST_DRIVE` if it is currently being substituted
        if (substitutedDrives.anyMatch(e -> e.contains(SUBST_DRIVE.toString()))) {
            substDelete(SUBST_DRIVE);
        }
    }

    /**
     * Test whether files can be created in the substituted drive.
     */
    @Test
    public void testCreateAndDeleteFile() throws IOException {
        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        substCreate(SUBST_DRIVE, tempDirectory);

        String fileContents = "Hello world!";
        Path p = Path.of(SUBST_DRIVE.toString(), "testFile.txt");
        Files.createFile(p);

        assertTrue(Files.exists(p));

        Files.writeString(p, fileContents);
        assertEquals(Files.readString(p), fileContents);
    }

    /**
     * Test if we can delete the substituted drive (essentially just a directory).
     */
    @Test
    public void testDeleteSubstitutedDrive() throws IOException {
        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        substCreate(SUBST_DRIVE, tempDirectory);

        assertTrue(Files.exists(tempDirectory));
        Files.delete(SUBST_DRIVE);
        assertTrue(Files.notExists(tempDirectory));
    }

    /**
     * Test if the attributes returned by the Files' APIs are consistent when
     * using the actual path and the substituted path.
     */
    @Test
    public void testAttributes() throws IOException {
        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        substCreate(SUBST_DRIVE, tempDirectory);

        assertTrue(Files.isSameFile(tempDirectory, SUBST_DRIVE));

        assertEquals(
            Files.isExecutable(tempDirectory),
            Files.isExecutable(SUBST_DRIVE));

        assertEquals(
            Files.isReadable(tempDirectory),
            Files.isReadable(SUBST_DRIVE));

        assertEquals(
            Files.isDirectory(tempDirectory),
            Files.isDirectory(SUBST_DRIVE));

        assertEquals(
            Files.isHidden(tempDirectory),
            Files.isHidden(SUBST_DRIVE));

        assertEquals(
            Files.isRegularFile(tempDirectory),
            Files.isRegularFile(SUBST_DRIVE));

        assertEquals(
            Files.isSymbolicLink(tempDirectory),
            Files.isSymbolicLink(SUBST_DRIVE));

        assertEquals(
            Files.getOwner(tempDirectory),
            Files.getOwner(SUBST_DRIVE));

        assertEquals(
            Files.isWritable(tempDirectory),
            Files.isWritable(SUBST_DRIVE));
    }

    /**
     * Test if setting attributes for a substituted path works the same way
     * as it would for a real path.
     */
    @Test
    public void testGetSetAttributes() throws IOException {
        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        substCreate(SUBST_DRIVE, tempDirectory);

        Files.setAttribute(SUBST_DRIVE, "dos:hidden", true);
        assertTrue(Files.isHidden(SUBST_DRIVE));
        assertTrue(Files.isHidden(tempDirectory));

        Files.setAttribute(tempDirectory, "dos:hidden", false);
        assertFalse(Files.isHidden(SUBST_DRIVE));
        assertFalse(Files.isHidden(tempDirectory));

        Map<String, Object> attr1 = Files.readAttributes(SUBST_DRIVE, "*");
        Map<String, Object> attr2 = Files.readAttributes(tempDirectory, "*");
        assertEquals(attr1, attr2);
    }

    /**
     * Test if the FileStores returned from using substituted path and real path
     * are the same.
     */
    @Test
    public void testFileStore() throws IOException {
        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        substCreate(SUBST_DRIVE, tempDirectory);

        FileStore fileStore1 = Files.getFileStore(tempDirectory);
        FileStore fileStore2 = Files.getFileStore(SUBST_DRIVE);

        assertEquals(
            fileStore1.getTotalSpace(),
            fileStore2.getTotalSpace());

        assertEquals(
            fileStore1.getBlockSize(),
            fileStore2.getBlockSize());

        assertEquals(
            fileStore1.name(),
            fileStore2.name());

        assertEquals(
            fileStore1.type(),
            fileStore2.type());

        assertEquals(
            SUBST_DRIVE.getFileSystem().getRootDirectories(),
            tempDirectory.getFileSystem().getRootDirectories());
    }

    /**
     * Test if Files.copy works correctly on a substituted drive, and that
     * all of the attributes are the same.
     */
    @Test
    public void testMoveAndCopySubstDrive() throws IOException {
        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        Path tempDirectoryCopy = Path.of(tempDirectory.toString() + "_copy");

        substCreate(SUBST_DRIVE, tempDirectory);

        Files.copy(SUBST_DRIVE, tempDirectoryCopy);

        assertEquals(
            Files.isExecutable(SUBST_DRIVE),
            Files.isExecutable(tempDirectoryCopy));

        assertEquals(
            Files.isReadable(SUBST_DRIVE),
            Files.isReadable(tempDirectoryCopy));

        assertEquals(
            Files.isDirectory(SUBST_DRIVE),
            Files.isDirectory(tempDirectoryCopy));

        assertEquals(
            Files.isHidden(SUBST_DRIVE),
            Files.isHidden(tempDirectoryCopy));

        assertEquals(
            Files.isRegularFile(SUBST_DRIVE),
            Files.isRegularFile(tempDirectoryCopy));

        assertEquals(
            Files.isWritable(SUBST_DRIVE),
            Files.isWritable(tempDirectoryCopy));

        assertEquals(
            Files.getOwner(SUBST_DRIVE),
            Files.getOwner(tempDirectoryCopy));
    }

    /**
     * Test if the attributes of a resolved symlink are the same as its target's
     * Note: requires administrator privileges.
     */
    @Test
    public void testGetResolvedSymlinkAttribute() throws IOException {
        if (!TestUtil.supportsSymbolicLinks(TEST_TEMP_DIRECTORY)) {
            return;
        }

        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        substCreate(SUBST_DRIVE, tempDirectory);

        Path tempFile = Path.of(SUBST_DRIVE.toString(), "test.txt");
        String contents = "Hello world!";
        Files.writeString(tempFile, contents);
        assertEquals(Files.readString(tempFile), contents);

        Path link = Path.of(SUBST_DRIVE.toString(), "link");
        Files.createSymbolicLink(link, tempFile);

        assertEquals(Files.readString(link), contents);
        assertEquals(Files.isExecutable(link), Files.isExecutable(tempFile));
        assertEquals(Files.isReadable(link), Files.isReadable(tempFile));
        assertEquals(Files.isDirectory(link), Files.isDirectory(tempFile));
        assertEquals(Files.isHidden(link), Files.isHidden(tempFile));
        assertEquals(Files.isRegularFile(link), Files.isRegularFile(tempFile));
        assertEquals(Files.isWritable(link), Files.isWritable(tempFile));
        assertEquals(Files.getOwner(link), Files.getOwner(tempFile));
    }

    /**
     * Test if files and directories can be created, moved, and cut when the
     * substituted drive is a symlink.
     * Note: requires administrator privileges.
     */
    @Test
    public void testSubstWithSymlinkedDirectory() throws IOException {
        if (!TestUtil.supportsSymbolicLinks(TEST_TEMP_DIRECTORY)) {
            return;
        }

        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        Path tempLink = Path.of(tempDirectory.toString() + "_link");
        Files.createSymbolicLink(tempLink, tempDirectory);

        substCreate(SUBST_DRIVE, tempLink);

        assertEquals(
            Files.readAttributes(SUBST_DRIVE, "*"),
            Files.readAttributes(tempDirectory, "*"));

        assertTrue(Files.isWritable(SUBST_DRIVE));

        Path tempFile = Files.createTempFile(SUBST_DRIVE, "prefix", "suffix");
        String contents = "Hello world!";
        Files.writeString(tempFile, contents);
        assertEquals(Files.readString(tempFile), contents);

        Path tempDirectory2 = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        Path copy = Path.of(tempDirectory2.toString(), "copied");
        Files.copy(tempFile, copy);

        assertTrue(Files.exists(copy));
        assertEquals(Files.readString(copy), contents);

        Path cut = Path.of(tempDirectory2.toString(), "cut");
        Files.move(tempFile, cut);
        assertTrue(Files.notExists(tempFile));
        assertTrue(Files.exists(cut));
        assertEquals(Files.readString(cut), contents);
    }

    /**
     * When the substituted drive is a symlink, test if it has the same
     * attributes as its target.
     * Note: requires administrator privileges.
     */
    @Test
    public void testMoveAndCopyFilesToSymlinkedDrive() throws IOException {
        if (!TestUtil.supportsSymbolicLinks(TEST_TEMP_DIRECTORY)) {
            return;
        }

        Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
        Path tempLink = Path.of(tempDirectory.toString() + "_link");
        Files.createSymbolicLink(tempLink, tempDirectory);

        substCreate(SUBST_DRIVE, tempLink);

        assertEquals(
            Files.readAttributes(SUBST_DRIVE, "*"),
            Files.readAttributes(tempDirectory, "*"));

        assertTrue(Files.isWritable(SUBST_DRIVE));
    }

    /**
     * Run a command and optionally prints stdout contents to
     * `customOutputStream`.
     */
    private void runCmd(ProcessBuilder pb, PrintStream customOutputStream) {
        try {
            PrintStream ps = customOutputStream != null ?
                                    customOutputStream :
                                    System.out;
            OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(pb)
                                            .outputTo(ps)
                                            .errorTo(System.err);

            int exitCode = outputAnalyzer.getExitValue();
            assertEquals(
                exitCode /* actual value */,
                0        /* expected value */,
                String.format(
                    "Command `%s` failed with exit code %d",
                    pb.command(),
                    exitCode
                )
            );

        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    /**
     * Helper to map a path to a drive letter using subst.
     * For reference, see:
     * https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst
     */
    private void substCreate(Path drive, Path path) {
        runCmd(
            new ProcessBuilder(
                "cmd", "/c", "subst", drive.toString(), path.toString()),
            null /* customOutputStream */);
    }

    /**
     * Delete a drive mapping using subst.
     * For reference, see:
     * https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst
     */
    private void substDelete(Path drive) throws IOException {
        runCmd(
            new ProcessBuilder(
                "cmd", "/c", "subst", drive.toString(), "/D"),
            null /* customOutputStream */);
    }

    /**
     * Return a list of strings that represents all the currently mapped drives.
     * For instance, with the following output of subst:
     *      A:\: => path1
     *      B:\: => path2
     *      T:\: => path3
     *      X:\: => path4
     * The function returns: ["A:\", "B:\", "T:\", "X:\"]
     * For reference, see:
     * https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst
     */
    private Stream<String> substFindMappedDrives() throws UnsupportedEncodingException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        String utf8 = StandardCharsets.UTF_8.name();
        try (PrintStream ps = new PrintStream(baos, true, utf8)) {
            // subst without any arguments returns a list of drives that
            // are being substituted
            runCmd(new ProcessBuilder("cmd", "/c", "subst"), ps);
            String stdout = baos.toString(utf8);
            return stdout
                    // split lines
                    .lines()
                    // only examine lines with "=>"
                    .filter(line -> line.contains("=>"))
                    // split each line into 2 components and take the first one
                    .map(line -> line.split("=>")[0].trim());
        }
    }

    /**
     * subst can fail if the drive to be mapped already exists. The method returns
     * a drive that is available.
     */
    private Optional<Path> findAvailableDrive(Path tempDirectory) {
        for (char letter = 'Z'; letter >= 'A'; letter--) {
            try {
                Path p = Path.of(letter + ":");
                substCreate(p, tempDirectory);
                substDelete(p);
                return Optional.of(p);
            } catch (Throwable t) {
                // fall through
            }
        }
        return Optional.empty();
    }
}
