package jnr.posix;

import jnr.constants.platform.windows.OpenFlags;
import jnr.ffi.Library;
import jnr.ffi.Platform;
import jnr.ffi.annotations.Out;
import org.junit.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.junit.Assert.*;
import static jnr.posix.SpawnFileAction.*;

public class SpawnTest {
    private static POSIX posix;
    private static LibC libc;
    private static final List<String> emptyEnv = Arrays.asList(new String[0]);
    private static final List<SpawnFileAction> emptyActions = Arrays.asList(new SpawnFileAction[0]);

    public static interface LibC {
        int pipe(@Out int[] fds);
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
        if (Platform.getNativePlatform().isUnix()) {
            posix = POSIXFactory.getPOSIX(new DummyPOSIXHandler(), true);
            libc = Library.loadLibrary(LibC.class, jnr.ffi.Platform.getNativePlatform().getStandardCLibraryName());
        }
    }

    @Test public void validPid() {
        if (Platform.getNativePlatform().isUnix()) {
            long pid = -1;
            try {
                pid = posix.posix_spawnp("true", emptyActions, Arrays.asList("true"), emptyEnv);
                assertTrue(pid != -1);
            } finally {
                if (pid != -1) posix.libc().waitpid((int) pid, null, 0);
            }
        }
    }

    private static void closePipe(int[] fds) {
        posix.libc().close(fds[0]);
        posix.libc().close(fds[1]);
    }

    private static void killChild(long pid) {
        if (pid > 0) {
            posix.libc().kill((int) pid, 9); posix.libc().waitpid((int) pid, null, 0);
        }
    }

    @Test public void outputPipe() {
        if (Platform.getNativePlatform().isUnix()) {
            int[] outputPipe = { -1, -1 };
            long pid = -1;
            try {
                assertFalse(libc.pipe(outputPipe) < 0);
                assertNotSame(-1, outputPipe[0]);
                assertNotSame(-1, outputPipe[1]);

                List<SpawnFileAction> actions = Arrays.asList(dup(outputPipe[1], 1));
                pid = posix.posix_spawnp("echo", actions, Arrays.asList("echo", "bar"), emptyEnv);
                assertTrue(pid != -1);

                // close the write side of the output pipe, so read() will return immediately once the process has exited
                posix.libc().close(outputPipe[1]);

                ByteBuffer output = ByteBuffer.allocate(100);
                long nbytes = posix.libc().read(outputPipe[0], output, output.remaining());
                assertEquals(4L, nbytes);
                output.position((int) nbytes).flip();
                byte[] bytes = new byte[output.remaining()];
                output.get(bytes);
                assertEquals("bar", new String(bytes).trim());
            } finally {
                closePipe(outputPipe);
                killChild(pid);
            }
        }
    }

    @Test public void inputPipe() {
        if (Platform.getNativePlatform().isUnix()) {
            int[] outputPipe = { -1, -1 };
            int[] inputPipe = { -1, -1 };
            long pid = -1;
            try {
            assertFalse(libc.pipe(outputPipe) < 0);
                assertFalse(libc.pipe(inputPipe) < 0);
                assertNotSame(-1, outputPipe[0]);
                assertNotSame(-1, outputPipe[1]);
                assertNotSame(-1, inputPipe[0]);
                assertNotSame(-1, inputPipe[1]);

                List<SpawnFileAction> actions = Arrays.asList(dup(inputPipe[0], 0), dup(outputPipe[1], 1));
                pid = posix.posix_spawnp("cat", actions, Arrays.asList("cat", "-"), emptyEnv);
                assertTrue(pid != -1);
                posix.libc().close(inputPipe[0]);
                assertEquals(3, posix.libc().write(inputPipe[1], ByteBuffer.wrap("foo".getBytes(Charset.forName("US-ASCII"))), 3));
                posix.libc().close(inputPipe[1]); // send EOF to process

                // close the write side of the output pipe, so read() will return immediately once the process has exited
                posix.libc().close(outputPipe[1]);

                ByteBuffer output = ByteBuffer.allocate(100);
                long nbytes = posix.libc().read(outputPipe[0], output, output.remaining());
                assertEquals(3L, nbytes);
                output.position((int) nbytes).flip();
                byte[] bytes = new byte[output.remaining()];
                output.get(bytes);
                assertEquals("foo", new String(bytes).trim());
            } finally {
                closePipe(outputPipe);
                closePipe(inputPipe);
                killChild(pid);
            }
        }
    }

    @Test public void inputFile() throws IOException {
        if (Platform.getNativePlatform().isUnix()) {
            File inputFile = File.createTempFile("foo", null);
            FileOutputStream inputStream = new FileOutputStream(inputFile);
            inputStream.write("foo".getBytes("US-ASCII"));
            inputStream.close();
            int[] outputPipe = { -1, -1 };
            long pid = -1;
            try {
                assertFalse(libc.pipe(outputPipe) < 0);
                assertNotSame(-1, outputPipe[0]);
                assertNotSame(-1, outputPipe[1]);

                List<SpawnFileAction> actions = Arrays.asList(open(inputFile.getAbsolutePath(), 0, OpenFlags.O_RDONLY.intValue(), 0444),
                        dup(outputPipe[1], 1), close(outputPipe[0]));
                pid = posix.posix_spawnp("cat", actions, Arrays.asList("cat", "-"), emptyEnv);
                assertTrue(pid != -1);

                // close the write side of the output pipe, so read() will return immediately once the process has exited
                posix.libc().close(outputPipe[1]);

                ByteBuffer output = ByteBuffer.allocate(100);
                long nbytes = posix.libc().read(outputPipe[0], output, output.remaining());
                assertEquals(3L, nbytes);
                output.position((int) nbytes).flip();
                byte[] bytes = new byte[output.remaining()];
                output.get(bytes);
                assertEquals("foo", new String(bytes).trim());
            } finally {
                closePipe(outputPipe);
                killChild(pid);
            }
        }
    }

    @Test public void closeInput() throws IOException {
        if (Platform.getNativePlatform().isUnix()) {
            int[] outputPipe = { -1, -1 };
            int[] inputPipe = { -1, -1 };
            long pid = -1;
            try {
                assertFalse(libc.pipe(outputPipe) < 0);
                assertFalse(libc.pipe(inputPipe) < 0);
                assertNotSame(-1, outputPipe[0]);
                assertNotSame(-1, outputPipe[1]);
                assertNotSame(-1, inputPipe[0]);
                assertNotSame(-1, inputPipe[1]);

                List<SpawnFileAction> actions = Arrays.asList(dup(outputPipe[1], 1),
                        open("/dev/null", 2, OpenFlags.O_WRONLY.intValue(), 0444),
                        close(inputPipe[0]), close(inputPipe[1]));
                pid = posix.posix_spawnp("cat", actions, Arrays.asList("cat", "/dev/fd/" + inputPipe[0]), emptyEnv);
                assertTrue(pid != -1);
                assertEquals(3, posix.libc().write(inputPipe[1], ByteBuffer.wrap("foo".getBytes(Charset.forName("US-ASCII"))), 3));
                posix.libc().close(inputPipe[1]); // send EOF to process

                // close the write side of the output pipe, so read() will return immediately once the process has exited
                posix.libc().close(outputPipe[1]);

                // Output from the process on stdout should be empty
                ByteBuffer output = ByteBuffer.allocate(100);
                long nbytes = posix.libc().read(outputPipe[0], output, output.remaining());
                assertEquals(0L, nbytes);
            } finally {
                closePipe(inputPipe);
                closePipe(outputPipe);
                killChild(pid);
            }
        }
    }
}
