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

/* @test
 * @bug 8295753 8306882
 * @summary Verify correct operation of Path.toRealPath
 * @library .. /test/lib
 * @build ToRealPath jdk.test.lib.Platform
 * @run junit ToRealPath
 */

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;

import jdk.test.lib.Platform;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;

import static java.nio.file.LinkOption.*;
import static org.junit.jupiter.api.Assertions.*;

public class ToRealPath {
    static final boolean SUPPORTS_LINKS;
    static final Path DIR;
    static final Path SUBDIR;
    static final Path FILE;
    static final Path LINK;
    static final Set<Path> extraDeletions;

    static {
        try {
            DIR = TestUtil.createTemporaryDirectory();
            SUBDIR = Files.createDirectory(DIR.resolve("subdir"));
            FILE = Files.createFile(DIR.resolve("foo"));
            LINK = DIR.resolve("link");
            SUPPORTS_LINKS = TestUtil.supportsSymbolicLinks(DIR);
            extraDeletions = new HashSet<Path>();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    };

    public boolean supportsSymbolicLinks() {
        return SUPPORTS_LINKS;
    }

    @Test
    public void locateSameFile() throws IOException {
        assertTrue(Files.isSameFile(FILE.toRealPath(),
                                    FILE.toRealPath(NOFOLLOW_LINKS)));
    }

    @Test
    public void failNotExist() {
        Path doesNotExist = DIR.resolve("DoesNotExist");
        assertThrows(IOException.class, () -> doesNotExist.toRealPath());
    }

    @Test
    public void failNotExistNoFollow() {
        Path doesNotExist = DIR.resolve("DoesNotExist");
        assertThrows(IOException.class,
                     () -> doesNotExist.toRealPath(NOFOLLOW_LINKS));
    }

    @EnabledIf("supportsSymbolicLinks")
    @Test
    public void shouldResolveLinks() throws IOException {
        Path resolvedFile = FILE;
        if (Platform.isWindows()) {
            // Path::toRealPath does not work with environments using the
            // legacy subst mechanism. This is a workaround to keep the
            // test working if 'dir' points to a location on a subst drive.
            // See JDK-8213216.
            //
            Path tempLink = DIR.resolve("tempLink");
            Files.createSymbolicLink(tempLink, DIR.toAbsolutePath());
            Path resolvedDir = tempLink.toRealPath();
            Files.delete(tempLink);
            resolvedFile = resolvedDir.resolve(FILE.getFileName());
        }

        Files.createSymbolicLink(LINK, resolvedFile.toAbsolutePath());
        assertTrue(LINK.toRealPath().equals(resolvedFile.toRealPath()));
        Files.delete(LINK);
    }

    @Test
    @EnabledIf("supportsSymbolicLinks")
    public void shouldNotResolveLinks() throws IOException {
        Files.createSymbolicLink(LINK, FILE.toAbsolutePath());
        assertEquals(LINK.toRealPath(NOFOLLOW_LINKS).getFileName(),
                     LINK.getFileName());
        Files.delete(LINK);
    }

    @Test
    public void eliminateDot() throws IOException {
        assertEquals(DIR.resolve(".").toRealPath(),
                     DIR.toRealPath());
    }

    @Test
    public void eliminateDotNoFollow() throws IOException {
        assertEquals(DIR.resolve(".").toRealPath(NOFOLLOW_LINKS),
                     DIR.toRealPath(NOFOLLOW_LINKS));
    }

    @Test
    public void eliminateDots() throws IOException {
        assertEquals(SUBDIR.resolve("..").toRealPath(),
                     DIR.toRealPath());
    }

    @Test
    public void eliminateDotsNoFollow() throws IOException {
        assertEquals(SUBDIR.resolve("..").toRealPath(NOFOLLOW_LINKS),
                     DIR.toRealPath(NOFOLLOW_LINKS));
    }

    @Test
    @EnabledIf("supportsSymbolicLinks")
    public void noCollapseDots1() throws IOException {
        Path subPath = DIR.resolve(Path.of("dir", "subdir"));
        Path sub = Files.createDirectories(subPath);
        System.out.println("sub: " + sub);
        Files.createSymbolicLink(LINK, sub);
        System.out.println("LINK: " + LINK + " -> " + sub);
        Path p = Path.of("..", "..", FILE.getFileName().toString());
        System.out.println("p: " + p);
        Path path = LINK.resolve(p);
        System.out.println("path:      " + path);
        if (Platform.isWindows() && Files.notExists(path)) {
            Files.createFile(path);
            extraDeletions.add(path);
        }
        System.out.println("no follow: " + path.toRealPath(NOFOLLOW_LINKS));
        if (Platform.isWindows())
            assertTrue(Files.isSameFile(path.toRealPath(NOFOLLOW_LINKS), path));
        else
            assertEquals(path.toRealPath(NOFOLLOW_LINKS), path);

        Files.delete(sub);
        Files.delete(sub.getParent());
        Files.delete(LINK);
    }

    @Test
    @EnabledIf("supportsSymbolicLinks")
    public void noCollapseDots2() throws IOException {
        Path subPath = DIR.resolve(Path.of("dir", "subdir"));
        Path sub = Files.createDirectories(subPath);
        Path out = Files.createFile(DIR.resolve(Path.of("out.txt")));
        Path aaa = DIR.resolve(Path.of("aaa"));
        Files.createSymbolicLink(aaa, sub);
        System.out.println("aaa: " + aaa + " -> " + sub);
        Path bbb = DIR.resolve(Path.of("bbb"));
        Files.createSymbolicLink(bbb, sub);
        System.out.println("bbb: " + bbb + " -> " + sub);
        Path p = Path.of("aaa", "..", "..", "bbb", "..", "..", "out.txt");
        Path path = DIR.resolve(p);
        System.out.println("path:      " + path);
        if (Platform.isWindows() && Files.notExists(path)) {
            Files.createFile(path);
            extraDeletions.add(path);
        }
        System.out.println("no follow: " + path.toRealPath(NOFOLLOW_LINKS));
        if (Platform.isWindows())
            assertTrue(Files.isSameFile(path.toRealPath(NOFOLLOW_LINKS), path));
        else
            assertEquals(path.toRealPath(NOFOLLOW_LINKS), path);
        System.out.println(path.toRealPath());

        Files.delete(sub);
        Files.delete(sub.getParent());
        Files.delete(out);
        Files.delete(aaa);
        Files.delete(bbb);
    }

    @Test
    @EnabledOnOs(OS.MAC)
    public final void macOSTests() throws IOException {
        // theTarget = dir/subdir/theTarget
        Path theTarget = Path.of(SUBDIR.toString(), "theTarget");
        Files.createFile(theTarget);

        // dir/theLink -> dir/subdir
        Path theLink = Path.of(DIR.toString(), "theLink");
        Files.createSymbolicLink(theLink, SUBDIR);

        // thePath = dir/thelink/thetarget (all lower case)
        Path thePath = Path.of(DIR.toString(), "thelink", "thetarget");
        Path noFollow = thePath.toRealPath(NOFOLLOW_LINKS);
        int nc = noFollow.getNameCount();

        // Real path should retain case as dir/theLink/theTarget
        assertEquals(noFollow.getName(nc - 2), Path.of("theLink"));
        assertEquals(noFollow.getName(nc - 1), Path.of("theTarget"));
        assertEquals(noFollow.toString(),
                     Path.of(DIR.toString(), "theLink", "theTarget").toString());

        // Test where a link is preceded by ".." in the path
        Path superBeforeLink =
            Path.of(SUBDIR.toString(), "..", "thelink", "thetarget");
        noFollow = superBeforeLink.toRealPath(NOFOLLOW_LINKS);
        nc = noFollow.getNameCount();
        assertEquals(noFollow.getName(nc - 2), Path.of("theLink"));
        assertEquals(noFollow.getName(nc - 1), Path.of("theTarget"));

        // Test where a link is followed by ".." in the path
        Path linkBeforeSuper =
            Path.of(DIR.toString(), "thelink", "..", "subdir", "thetarget");
        noFollow = linkBeforeSuper.toRealPath(NOFOLLOW_LINKS);
        nc = noFollow.getNameCount();
        assertEquals(noFollow.getName(nc - 4), Path.of("theLink"));
        assertEquals(noFollow.getName(nc - 1), Path.of("theTarget"));

        Files.delete(theLink);
        Files.delete(theTarget);
    }

    @AfterAll
    public static void cleanup() throws IOException {
        Files.delete(FILE);
        Files.delete(SUBDIR);
        Files.delete(DIR);
        for (Path p : extraDeletions)
            Files.deleteIfExists(p);
    }
}
