#!/usr/bin/python

# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se>
# Licensed to PSF under a Contributor Agreement.
# See http://www.python.org/2.4/license for licensing details.

"""Subprocress execution

This module holds a subclass of subprocess.Popen with our own required
features.
"""

import errno
import os
import pty
import select
import subprocess
import sys
import unittest


# Import these here so the caller does not need to import subprocess also.
PIPE = subprocess.PIPE
STDOUT = subprocess.STDOUT
PIPE_PTY = -3   # Pipe output through a pty


class Popen(subprocess.Popen):
  """Like subprocess.Popen with ptys and incremental output

  This class deals with running a child process and filtering its output on
  both stdout and stderr while it is running. We do this so we can monitor
  progress, and possibly relay the output to the user if requested.

  The class is similar to subprocess.Popen, the equivalent is something like:

    Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

  But this class has many fewer features, and two enhancement:

  1. Rather than getting the output data only at the end, this class sends it
     to a provided operation as it arrives.
  2. We use pseudo terminals so that the child will hopefully flush its output
     to us as soon as it is produced, rather than waiting for the end of a
     line.

  Use CommunicateFilter() to handle output from the subprocess.

  """

  def __init__(self, args, stdin=None, stdout=PIPE_PTY, stderr=PIPE_PTY,
               shell=False, cwd=None, env=None, close_fds=False, **kwargs):
    """Cut-down constructor

    Args:
      args: Program and arguments for subprocess to execute.
      stdin: See subprocess.Popen()
      stdout: See subprocess.Popen(), except that we support the sentinel
          value of cros_subprocess.PIPE_PTY.
      stderr: See subprocess.Popen(), except that we support the sentinel
          value of cros_subprocess.PIPE_PTY.
      shell: See subprocess.Popen()
      cwd: Working directory to change to for subprocess, or None if none.
      env: Environment to use for this subprocess, or None to inherit parent.
      kwargs: No other arguments are supported at the moment.  Passing other
          arguments will cause a ValueError to be raised.
    """
    stdout_pty = None
    stderr_pty = None

    if stdout == PIPE_PTY:
      stdout_pty = pty.openpty()
      stdout = os.fdopen(stdout_pty[1])
    if stderr == PIPE_PTY:
      stderr_pty = pty.openpty()
      stderr = os.fdopen(stderr_pty[1])

    super(Popen, self).__init__(args, stdin=stdin,
        stdout=stdout, stderr=stderr, shell=shell, cwd=cwd, env=env,
        close_fds=close_fds, **kwargs)

    # If we're on a PTY, we passed the slave half of the PTY to the subprocess.
    # We want to use the master half on our end from now on.  Setting this here
    # does make some assumptions about the implementation of subprocess, but
    # those assumptions are pretty minor.

    # Note that if stderr is STDOUT, then self.stderr will be set to None by
    # this constructor.
    if stdout_pty is not None:
      self.stdout = os.fdopen(stdout_pty[0])
    if stderr_pty is not None:
      self.stderr = os.fdopen(stderr_pty[0])

    # Insist that unit tests exist for other arguments we don't support.
    if kwargs:
      raise ValueError("Unit tests do not test extra args - please add tests")

  def CommunicateFilter(self, output, input_str=''):
    """Interact with process: Read data from stdout and stderr.

    This method runs until end-of-file is reached, then waits for the
    subprocess to terminate.

    The output function is sent all output from the subprocess and must be
    defined like this:

      def Output([self,] stream, data)
      Args:
        stream: the stream the output was received on, which will be
            sys.stdout or sys.stderr.
        data: a string containing the data

    Note: The data read is buffered in memory, so do not use this
    method if the data size is large or unlimited.

    Args:
      output: Function to call with each fragment of output.
      input_str: Input string to feed into process's stdin

    Returns:
      A tuple (stdout, stderr, combined) which is the data received on
      stdout, stderr and the combined data (interleaved stdout and stderr).

      Note that the interleaved output will only be sensible if you have
      set both stdout and stderr to PIPE or PIPE_PTY. Even then it depends on
      the timing of the output in the subprocess. If a subprocess flips
      between stdout and stderr quickly in succession, by the time we come to
      read the output from each we may see several lines in each, and will read
      all the stdout lines, then all the stderr lines. So the interleaving
      may not be correct. In this case you might want to pass
      stderr=cros_subprocess.STDOUT to the constructor.

      This feature is still useful for subprocesses where stderr is
      rarely used and indicates an error.

      Note also that if you set stderr to STDOUT, then stderr will be empty
      and the combined output will just be the same as stdout.
    """

    read_set = []
    write_set = []
    stdout = None # Return
    stderr = None # Return

    if self.stdin:
      # Flush stdio buffer.  This might block, if the user has
      # been writing to .stdin in an uncontrolled fashion.
      self.stdin.flush()
      if input_str:
        write_set.append(self.stdin)
      else:
        self.stdin.close()
    if self.stdout:
      read_set.append(self.stdout)
      stdout = []
    if self.stderr and self.stderr != self.stdout:
      read_set.append(self.stderr)
      stderr = []
    combined = []

    input_offset = 0
    while read_set or write_set:
      try:
        rlist, wlist, _ = select.select(read_set, write_set, [])
      except select.error, e:
        if e.args[0] == errno.EINTR:
          continue
        raise

      if self.stdin in wlist:
        # When select has indicated that the file is writable,
        # we can write up to PIPE_BUF bytes without risk
        # blocking.  POSIX defines PIPE_BUF >= 512
        chunk = input_str[input_offset : input_offset + 512]
        bytes_written = os.write(self.stdin.fileno(), chunk)
        input_offset += bytes_written
        if input_offset >= len(input_str):
          self.stdin.close()
          write_set.remove(self.stdin)

      if self.stdout in rlist:
        data = ""
        # We will get an error on read if the pty is closed
        try:
          data = os.read(self.stdout.fileno(), 1024)
        except OSError:
          pass
        if data == "":
          self.stdout.close()
          read_set.remove(self.stdout)
        else:
          stdout.append(data)
          combined.append(data)
          output(sys.stdout, data)
      if self.stderr in rlist:
        data = ""
        # We will get an error on read if the pty is closed
        try:
          data = os.read(self.stderr.fileno(), 1024)
        except OSError:
          pass
        if data == "":
          self.stderr.close()
          read_set.remove(self.stderr)
        else:
          stderr.append(data)
          combined.append(data)
          output(sys.stderr, data)

    # All data exchanged.  Translate lists into strings.
    if stdout is not None:
      stdout = ''.join(stdout)
    if stderr is not None:
      stderr = ''.join(stderr)
    combined = ''.join(combined)

    # Translate newlines, if requested.  We cannot let the file
    # object do the translation: It is based on stdio, which is
    # impossible to combine with select (unless forcing no
    # buffering).
    if self.universal_newlines and hasattr(file, 'newlines'):
      if stdout:
        stdout = self._translate_newlines(stdout)
      if stderr:
        stderr = self._translate_newlines(stderr)

    self.wait()
    return (stdout, stderr, combined)


# Just being a unittest.TestCase gives us 14 public methods.  Unless we
# disable this, we can only have 6 tests in a TestCase.  That's not enough.
#
# pylint: disable=R0904

class TestSubprocess(unittest.TestCase):
  """Our simple unit test for this module"""

  class MyOperation:
    """Provides a operation that we can pass to Popen"""
    def __init__(self, input_to_send=None):
      """Constructor to set up the operation and possible input.

      Args:
        input_to_send: a text string to send when we first get input. We will
          add \r\n to the string.
      """
      self.stdout_data = ''
      self.stderr_data = ''
      self.combined_data = ''
      self.stdin_pipe = None
      self._input_to_send = input_to_send
      if input_to_send:
        pipe = os.pipe()
        self.stdin_read_pipe = pipe[0]
        self._stdin_write_pipe = os.fdopen(pipe[1], 'w')

    def Output(self, stream, data):
      """Output handler for Popen. Stores the data for later comparison"""
      if stream == sys.stdout:
        self.stdout_data += data
      if stream == sys.stderr:
        self.stderr_data += data
      self.combined_data += data

      # Output the input string if we have one.
      if self._input_to_send:
        self._stdin_write_pipe.write(self._input_to_send + '\r\n')
        self._stdin_write_pipe.flush()

  def _BasicCheck(self, plist, oper):
    """Basic checks that the output looks sane."""
    self.assertEqual(plist[0], oper.stdout_data)
    self.assertEqual(plist[1], oper.stderr_data)
    self.assertEqual(plist[2], oper.combined_data)

    # The total length of stdout and stderr should equal the combined length
    self.assertEqual(len(plist[0]) + len(plist[1]), len(plist[2]))

  def test_simple(self):
    """Simple redirection: Get process list"""
    oper = TestSubprocess.MyOperation()
    plist = Popen(['ps']).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)

  def test_stderr(self):
    """Check stdout and stderr"""
    oper = TestSubprocess.MyOperation()
    cmd = 'echo fred >/dev/stderr && false || echo bad'
    plist = Popen([cmd], shell=True).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(plist [0], 'bad\r\n')
    self.assertEqual(plist [1], 'fred\r\n')

  def test_shell(self):
    """Check with and without shell works"""
    oper = TestSubprocess.MyOperation()
    cmd = 'echo test >/dev/stderr'
    self.assertRaises(OSError, Popen, [cmd], shell=False)
    plist = Popen([cmd], shell=True).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(len(plist [0]), 0)
    self.assertEqual(plist [1], 'test\r\n')

  def test_list_args(self):
    """Check with and without shell works using list arguments"""
    oper = TestSubprocess.MyOperation()
    cmd = ['echo', 'test', '>/dev/stderr']
    plist = Popen(cmd, shell=False).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(plist [0], ' '.join(cmd[1:]) + '\r\n')
    self.assertEqual(len(plist [1]), 0)

    oper = TestSubprocess.MyOperation()

    # this should be interpreted as 'echo' with the other args dropped
    cmd = ['echo', 'test', '>/dev/stderr']
    plist = Popen(cmd, shell=True).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(plist [0], '\r\n')

  def test_cwd(self):
    """Check we can change directory"""
    for shell in (False, True):
      oper = TestSubprocess.MyOperation()
      plist = Popen('pwd', shell=shell, cwd='/tmp').CommunicateFilter(oper.Output)
      self._BasicCheck(plist, oper)
      self.assertEqual(plist [0], '/tmp\r\n')

  def test_env(self):
    """Check we can change environment"""
    for add in (False, True):
      oper = TestSubprocess.MyOperation()
      env = os.environ
      if add:
        env ['FRED'] = 'fred'
      cmd = 'echo $FRED'
      plist = Popen(cmd, shell=True, env=env).CommunicateFilter(oper.Output)
      self._BasicCheck(plist, oper)
      self.assertEqual(plist [0], add and 'fred\r\n' or '\r\n')

  def test_extra_args(self):
    """Check we can't add extra arguments"""
    self.assertRaises(ValueError, Popen, 'true', startupinfo=False)

  def test_basic_input(self):
    """Check that incremental input works

    We set up a subprocess which will prompt for name. When we see this prompt
    we send the name as input to the process. It should then print the name
    properly to stdout.
    """
    oper = TestSubprocess.MyOperation('Flash')
    prompt = 'What is your name?: '
    cmd = 'echo -n "%s"; read name; echo Hello $name' % prompt
    plist = Popen([cmd], stdin=oper.stdin_read_pipe,
        shell=True).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(len(plist [1]), 0)
    self.assertEqual(plist [0], prompt + 'Hello Flash\r\r\n')

  #TODO(sjg): Add test for passing PIPE in case underlying subprocess breaks.
  #TODO(sjg): Add test for passing a file handle also.

  def test_isatty(self):
    """Check that ptys appear as terminals to the subprocess"""
    oper = TestSubprocess.MyOperation()
    cmd = ('if [ -t %d ]; then echo "terminal %d" >&%d; '
        'else echo "not %d" >&%d; fi;')
    both_cmds = ''
    for fd in (1, 2):
      both_cmds += cmd % (fd, fd, fd, fd, fd)
    plist = Popen(both_cmds, shell=True).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(plist [0], 'terminal 1\r\n')
    self.assertEqual(plist [1], 'terminal 2\r\n')

    # Now try with PIPE and make sure it is not a terminal
    oper = TestSubprocess.MyOperation()
    plist = Popen(both_cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        shell=True).CommunicateFilter(oper.Output)
    self._BasicCheck(plist, oper)
    self.assertEqual(plist [0], 'not 1\n')
    self.assertEqual(plist [1], 'not 2\n')

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