import os
import os.path
import subprocess
import sys
import unittest

if os.path.isfile("share/lutris/bin/lutris-wrapper"):
    lutris_wrapper_bin = "share/lutris/bin/lutris-wrapper"
else:
    lutris_wrapper_bin = "lutris-wrapper"


class LutrisWrapperTestCase(unittest.TestCase):
    def test_excluded_initial_process(self):
        "Test that an excluded process that starts a monitored process works"
        env = os.environ.copy()
        env["PYTHONPATH"] = ":".join(sys.path)
        # run the lutris-wrapper with a bash subshell. bash is "excluded"
        wrapper_proc = subprocess.Popen(
            [
                sys.executable,
                lutris_wrapper_bin,
                "title",
                "0",
                "1",
                "bash",
                "bash",
                "-c",
                "echo Hello World; exec 1>&-; while sleep infinity; do true; done",
            ],
            stdin=subprocess.DEVNULL,
            stdout=subprocess.PIPE,
            env=env,
        )
        try:
            # Wait for the "Hello World" message that indicates that the process
            # tree has started. This message arrives on stdout.
            for line in wrapper_proc.stdout:
                if line.strip() == b"Hello World":
                    # We found the output we're looking for.
                    break
            else:
                self.fail("stdout EOF unexpectedly")

            # Wait a short while to see if lutris-wrapper will exit (it shouldn't)
            try:
                wrapper_proc.wait(0.5)
            except subprocess.TimeoutExpired:
                # as expected, the process is still alive.
                pass
            else:
                # the test failed because the process exited for some reason.
                self.fail("Process exited unexpectedly")
        finally:
            if wrapper_proc.returncode is None:
                wrapper_proc.terminate()
                wrapper_proc.wait(30)
            wrapper_proc.stdout.close()

    def test_cleanup_children(self):
        "Test that nonresponsive child processes can be killed with 2x sigterm"
        env = os.environ.copy()
        env["PYTHONPATH"] = ":".join(sys.path)
        # First, we run the lutris-wrapper with a bash subshell which ignores
        # SIGTERMs, emits a message to indicate readiness, and then closes
        # stdout.
        wrapper_proc = subprocess.Popen(
            [
                sys.executable,
                lutris_wrapper_bin,
                "title",
                "0",
                "0",
                "bash",
                "-c",
                "trap '' SIGTERM; echo Hello World; exec 1>&-; while sleep infinity; do true; done",
            ],
            stdin=subprocess.DEVNULL,
            stdout=subprocess.PIPE,
            env=env,
        )
        try:
            # Wait for the "Hello World" message that indicates that the process
            # tree has started. This message arrives on stdout.
            for line in wrapper_proc.stdout:
                if line.strip() == b"Hello World":
                    # We found the output we're looking for.
                    break
            else:
                self.fail("stdout EOF unexpectedly")

            # Send first SIGTERM
            wrapper_proc.terminate()

            # Wait for confirmation that lutris-wrapper got our signal.
            for line in wrapper_proc.stdout:
                if line.strip() == b"--terminated processes--":
                    break
            else:
                self.fail("stdout EOF unexpectedly")

            wrapper_proc.stdout.close()  # don't need this anymore.

            # Wait a short while to see if lutris-wrapper will exit (it shouldn't)
            try:
                wrapper_proc.wait(0.5)
            except subprocess.TimeoutExpired:
                # as expected, the process is still alive.
                pass
            else:
                # the test failed because the process exited for some reason.
                self.fail("Process exited unexpectedly")

            # Send second SIGTERM
            wrapper_proc.terminate()

            # verify that lutris-wrapper closes.
            wrapper_proc.wait(30)
        finally:
            if wrapper_proc.returncode is None:
                wrapper_proc.kill()
                wrapper_proc.wait(30)
            wrapper_proc.stdout.close()
