package com.correx.infrastructure.tools.filesystem

import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.nio.file.Files

class PathJailTest {

    @Test
    fun `empty allow-list fails closed`() {
        val dir = Files.createTempDirectory("jail").toRealPath()
        assertFalse(PathJail.isContained(dir.resolve("f.txt"), emptySet()))
    }

    @Test
    fun `path inside an allowed root is contained`() {
        val root = Files.createTempDirectory("jail-in").toRealPath()
        assertTrue(PathJail.isContained(root.resolve("sub/f.txt"), setOf(root)))
    }

    @Test
    fun `path outside all allowed roots is rejected`() {
        val root = Files.createTempDirectory("jail-root").toRealPath()
        val other = Files.createTempDirectory("jail-other").toRealPath()
        assertFalse(PathJail.isContained(other.resolve("f.txt"), setOf(root)))
    }

    @Test
    fun `non-existent target under an allowed root is contained`() {
        val root = Files.createTempDirectory("jail-new").toRealPath()
        assertTrue(PathJail.isContained(root.resolve("does/not/exist/yet.txt"), setOf(root)))
    }

    @Test
    fun `symlink inside an allowed root that points outside is rejected`() {
        val root = Files.createTempDirectory("jail-link-root").toRealPath()
        val outside = Files.createTempDirectory("jail-link-escape").toRealPath()
        Files.writeString(outside.resolve("secret.txt"), "secret")
        val link = root.resolve("escape")
        Files.createSymbolicLink(link, outside)

        // Without toRealPath() this string-prefixes inside root and would be allowed;
        // symlink-resolved it lands in `outside`, so it must be rejected.
        assertFalse(PathJail.isContained(link.resolve("secret.txt"), setOf(root)))
    }
}
