# pylint: disable=g-bad-file-header
# Copyright 2019 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import os
import subprocess
import textwrap
import unittest

from src.test.py.bazel import test_base


class MockPythonLines(object):

  NORMAL = textwrap.dedent(
      r"""\
      if [ "$1" = "-V" ]; then
          echo "Mock Python 3.xyz!"
      else
          echo "I am mock Python!"
      fi
      """
  ).split("\n")

  FAIL = textwrap.dedent(r"""\
      echo "Mock failure!"
      exit 1
      """).split("\n")

  VERSION_ERROR = textwrap.dedent(r"""\
      if [ "$1" = "-V" ]; then
          echo "Error!"
          exit 1
      else
          echo "I am mock Python!"
      fi
      """).split("\n")


# TODO(brandjon): Switch to shutil.which when the test is moved to PY3.
def which(cmd):
  """A poor man's approximation of `shutil.which()` or the `which` command.

  Args:
      cmd: The command (executable) name to lookup; should not contain path
        separators

  Returns:
      The absolute path to the first match in PATH, or None if not found.
  """
  for p in os.environ["PATH"].split(os.pathsep):
    fullpath = os.path.abspath(os.path.join(p, cmd))
    if os.path.exists(fullpath):
      return fullpath
  return None


# TODO(brandjon): Move this test to PY3. Blocked (ironically!) on the fix for
# #4815 being available in the host version of Bazel used to run this test.
class PywrapperTest(test_base.TestBase):
  """Unit tests for pywrapper_template.txt.

  These tests are based on the instantiation of the template for Python 2. They
  ensure that the wrapper can locate, validate, and launch a Python 2 executable
  on PATH. To ensure hermeticity, the tests launch the wrapper with PATH
  restricted to the scratch directory.

  Unix only.
  """

  def setup_tool(self, cmd):
    """Copies a command from its system location to the test directory."""
    path = which(cmd)
    self.assertIsNotNone(
        path, msg="Could not locate '%s' command on PATH" % cmd)
    self.CopyFile(path, os.path.join("dir", cmd), executable=True)

  def locate_runfile(self, runfile_path):
    resolved_path = self.Rlocation(runfile_path)
    self.assertIsNotNone(
        resolved_path, msg="Could not locate %s in runfiles" % runfile_path)
    return resolved_path

  def setUp(self):
    super(PywrapperTest, self).setUp()

    # Locate scripts under test.
    self.wrapper_path = self.locate_runfile(
        "io_bazel/tools/python/py3wrapper.sh"
    )
    self.nonstrict_wrapper_path = self.locate_runfile(
        "io_bazel/tools/python/py3wrapper_nonstrict.sh"
    )

    # Setup scratch directory with all executables the script depends on.
    #
    # This is brittle, but we need to make sure we can run the script when only
    # the scratch directory is on PATH, so that we can control whether or not
    # the python executables exist on PATH.
    self.setup_tool("which")
    self.setup_tool("echo")
    self.setup_tool("grep")

  def run_with_restricted_path(self, program, title_for_logging=None):
    new_env = dict(os.environ)
    new_env["PATH"] = self.Path("dir")
    proc = subprocess.Popen([program],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            universal_newlines=True,
                            cwd=self.Path("dir"),
                            env=new_env)
    # TODO(brandjon): Add a timeout arg here when upgraded to PY3.
    out, err = proc.communicate()
    if title_for_logging is not None:
      print(textwrap.dedent("""\
          ----------------
          %s
          Exit code: %d
          stdout:
          %s
          stderr:
          %s
          ----------------
          """) % (title_for_logging, proc.returncode, out, err))
    return proc.returncode, out, err

  def run_wrapper(self, title_for_logging):
    return self.run_with_restricted_path(self.wrapper_path, title_for_logging)

  def run_nonstrict_wrapper(self, title_for_logging):
    return self.run_with_restricted_path(self.nonstrict_wrapper_path,
                                         title_for_logging)

  def assert_wrapper_success(self, returncode, out, err):
    self.assertEqual(returncode, 0, msg="Expected to exit without error")
    self.assertEqual(
        out, "I am mock Python!\n", msg="stdout was not as expected")
    self.assertEqual(err, "", msg="Expected to produce no stderr output")

  def assert_wrapper_failure(self, returncode, out, err, message):
    self.assertEqual(returncode, 1, msg="Expected to exit with error code 1")
    self.assertRegexpMatches(
        err, message, msg="stderr did not contain expected string")

  def test_finds_python(self):
    self.ScratchFile("dir/python", MockPythonLines.NORMAL, executable=True)
    returncode, out, err = self.run_wrapper("test_finds_python")
    self.assert_wrapper_success(returncode, out, err)

  def test_no_interpreter_found(self):
    returncode, out, err = self.run_wrapper("test_no_interpreter_found")
    self.assert_wrapper_failure(
        returncode, out, err, "Neither 'python3' nor 'python' were found"
    )

  def test_error_getting_version(self):
    self.ScratchFile(
        "dir/python", MockPythonLines.VERSION_ERROR, executable=True
    )
    returncode, out, err = self.run_wrapper("test_error_getting_version")
    self.assert_wrapper_failure(returncode, out, err,
                                "Could not get interpreter version")

  def test_interpreter_not_executable(self):
    self.ScratchFile(
        "dir/python", MockPythonLines.VERSION_ERROR, executable=False
    )
    returncode, out, err = self.run_wrapper("test_interpreter_not_executable")
    self.assert_wrapper_failure(
        returncode, out, err, "Neither 'python3' nor 'python' were found"
    )


if __name__ == "__main__":
  unittest.main()
