import subprocess
import tempfile
import shutil
import errno
import os

import pexpect
from . import PexpectTestCase

import pytest


class TestCaseWhich(PexpectTestCase.PexpectTestCase):
    " Tests for pexpect.which(). "

    def test_which_finds_ls(self):
        " which() can find ls(1). "
        exercise = pexpect.which("ls")
        assert exercise is not None
        assert exercise.startswith('/')

    def test_os_defpath_which(self):
        " which() finds an executable in $PATH and returns its abspath. "
        fname = 'cc'
        bin_dir = tempfile.mkdtemp()
        bin_path = os.path.join(bin_dir, fname)
        save_path = os.environ['PATH']
        save_defpath = os.defpath

        try:
            # setup
            os.environ['PATH'] = ''
            os.defpath = bin_dir
            with open(bin_path, 'w') as fp:
                pass

            # given non-executable,
            os.chmod(bin_path, 0o400)

            # exercise absolute and relative,
            assert pexpect.which(bin_path) is None
            assert pexpect.which(fname) is None

            # given executable,
            os.chmod(bin_path, 0o700)

            # exercise absolute and relative,
            assert pexpect.which(bin_path) == bin_path
            assert pexpect.which(fname) == bin_path

        finally:
            # restore,
            os.environ['PATH'] = save_path
            os.defpath = save_defpath

            # destroy scratch files and folders,
            if os.path.exists(bin_path):
                os.unlink(bin_path)
            if os.path.exists(bin_dir):
                os.rmdir(bin_dir)

    def test_path_search_which(self):
        " which() finds an executable in $PATH and returns its abspath. "
        fname = 'gcc'
        bin_dir = tempfile.mkdtemp()
        bin_path = os.path.join(bin_dir, fname)
        save_path = os.environ['PATH']
        try:
            # setup
            os.environ['PATH'] = bin_dir
            with open(bin_path, 'w') as fp:
                pass

            # given non-executable,
            os.chmod(bin_path, 0o400)

            # exercise absolute and relative,
            assert pexpect.which(bin_path) is None
            assert pexpect.which(fname) is None

            # given executable,
            os.chmod(bin_path, 0o700)

            # exercise absolute and relative,
            assert pexpect.which(bin_path) == bin_path
            assert pexpect.which(fname) == bin_path

        finally:
            # restore,
            os.environ['PATH'] = save_path

            # destroy scratch files and folders,
            if os.path.exists(bin_path):
                os.unlink(bin_path)
            if os.path.exists(bin_dir):
                os.rmdir(bin_dir)

    def test_which_follows_symlink(self):
        " which() follows symlinks and returns its path. "
        fname = 'original'
        symname = 'extra-crispy'
        bin_dir = tempfile.mkdtemp()
        bin_path = os.path.join(bin_dir, fname)
        sym_path = os.path.join(bin_dir, symname)
        save_path = os.environ['PATH']
        try:
            # setup
            os.environ['PATH'] = bin_dir
            with open(bin_path, 'w') as fp:
                pass