# Copyright (c) 2012 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.

"""Contains functionality used to implement a partial mock."""

import collections
import logging
import os
import re
from unittest import mock

from chromite.lib import cros_build_lib
from chromite.lib import osutils


def _PredicateSplit(func, iterable):
  """Splits an iterable into two groups based on a predicate return value.

  Args:
    func: A functor that takes an item as its argument and returns a boolean
      value indicating which group the item belongs.
    iterable: The collection to split.

  Returns:
    A tuple containing two lists, the first containing items that func()
    returned True for, and the second containing items that func() returned
    False for.
  """
  trues, falses = [], []
  for x in iterable:
    (trues if func(x) else falses).append(x)
  return trues, falses


class Comparator(object):
  """Base class for all comparators."""

  def Match(self, arg):
    """Match the comparator against an argument."""
    raise NotImplementedError('method must be implemented by a subclass.')

  def Equals(self, rhs):
    """Returns whether rhs compares the same thing."""
    return isinstance(rhs, type(self)) and self.__dict__ == rhs.__dict__

  def __eq__(self, rhs):
    return self.Equals(rhs)

  def __ne__(self, rhs):
    return not self.Equals(rhs)


class In(Comparator):
  """Checks whether an item (or key) is in a list (or dict) parameter."""

  def __init__(self, key):
    """Initialize.

    Args:
      key: Any thing that could be in a list or a key in a dict
    """
    Comparator.__init__(self)
    self._key = key

  def Match(self, arg):
    try:
      return self._key in arg
    except TypeError:
      return False

  def __repr__(self):
    return '<sequence or map containing %r>' % str(self._key)


class InOrder(Comparator):
  """Checks whether every items of a list exists in a list/dict parameter."""

  def __init__(self, items):
    """Constructor.

    Args:
      items: A list of things that could be in a list or a key in a dict
    """
    super().__init__()
    self.items = items

  def Match(self, arg):
    """Checks if args' item matches all expected items in sequence.

    Args:
      arg: parameter list.

    Returns:
      True if all expected items are matched.
    """
    items = list(self.items)
    to_match = items.pop(0)
    for a in arg:
      if to_match == a:
        if len(items) < 1:
          return True
        to_match = items.pop(0)
    return False

  def __repr__(self):
    return '<sequence or map containing %r>' % str(self.items)


class Regex(Comparator):
  """Checks if a string matches a regular expression."""

  def __init__(self, pattern, flags=0):
    """Initialize.

    Args:
      pattern: is the regular expression to search for
      flags: passed to re.compile function as the second argument
    """
    Comparator.__init__(self)
    self.pattern = pattern
    self.flags = flags
    self.regex = re.compile(pattern, flags=flags)

  def Match(self, arg):
    try:
      return self.regex.search(arg) is not None
    except TypeError:
      return False

  def __repr__(self):
    s = '<regular expression %r' % self.regex.pattern
    if self.regex.flags:
      s += ', flags=%d' % self.regex.flags
    s += '>'
    return s


class ListRegex(Regex):
  """Checks if any string from an iterable matches a regular expression.

  This can be used to match on a list. For example, a regex of
  'dump_fmap -p .*bios.bin' will match ['dump_fmap', '-p', 'mainbios.bin'].
  """

  @staticmethod
  def _ProcessArg(arg):
    if not isinstance(arg, str):
      return ' '.join(arg)
    return arg

  def Match(self, arg):
    try:
      return self.regex.search(self._ProcessArg(arg)) is not None
    except TypeError:
      return False


class Ignore(Comparator):
  """Used when we don't care about an argument of a method call."""

  def Match(self, _arg):
    return True

  def __repr__(self):
    return '<IgnoreArg>'


class HasString(str):
  """A substring matcher for mock assertion.

  It overrides str's '==' operator so that
  HasString('substring') == 'A sentence with substring'

  It is used for mock.assert_called_with(). Note that it is not a Comparator.

  Examples:
    some_mock.assert_called_with(
        partial_mock.HasString('need_this_keyword'))
  """
  def __eq__(self, target):
    return self in target


def _RecursiveCompare(lhs, rhs):
  """Compare parameter specs recursively.

  Args:
    lhs: Left Hand Side parameter spec to compare.
    rhs: Right Hand Side parameter spec to compare.
    equality: In the case of comparing Comparator objects, True means we call
      the Equals() function.  We call Match() if set to False (default).
  """
  if isinstance(lhs, Comparator):
    return lhs.Match(rhs)
  elif isinstance(lhs, (tuple, list)):
    return (isinstance(rhs, type(lhs)) and
            len(lhs) == len(rhs) and
            all(_RecursiveCompare(i, j) for i, j in zip(lhs, rhs)))
  elif isinstance(lhs, dict):
    return _RecursiveCompare(sorted(lhs.items()), sorted(rhs.items()))
  else:
    return lhs == rhs


def ListContains(small, big, strict=False):
  """Looks for a sublist within a bigger list.

  Args:
    small: The sublist or string to search for.
    big: The list to search in.
    strict: If True, all items in list must be adjacent.
  """
  if strict:
    for i in range(len(big) - len(small) + 1):
      if _RecursiveCompare(small, big[i:i + len(small)]):
        return True
    return False
  else:
    j = 0
    for s in small:
      for j in range(j, len(big)):
        if _RecursiveCompare(s, big[j]):
          j += 1
          break
      else:
        return False
    return True


def DictContains(small, big):
  """Looks for a subset within a dictionary.

  Args:
    small: The sub-dict to search for.
    big: The dict to search in.
  """
  for k, v in small.items():
    if k not in big or not _RecursiveCompare(v, big[k]):
      return False
  return True


class MockedCallResults(object):
  """Implements internal result specification for partial mocks.

  Used with the PartialMock class.

  Internal results are different from external results (return values,
  side effects, exceptions, etc.) for functions.  Internal results are
  *used* by the partial mock to generate external results.  Often internal
  results represent the external results of the dependencies of the function
  being partially mocked.  Of course, the partial mock can just pass through
  the internal results to become external results.
  """

  Params = collections.namedtuple('Params', ['args', 'kwargs'])
  MockedCall = collections.namedtuple(
      'MockedCall', ['params', 'strict', 'result', 'side_effect'])

  def __init__(self, name):
    """Initialize.

    Args:
      name: The name given to the mock.  Will be used in debug output.
    """
    self.name = name
    self.mocked_calls = []
    self.default_result, self.default_side_effect = None, None

  @staticmethod
  def AssertArgs(args, kwargs):
    """Verify arguments are of expected type."""
    assert isinstance(args, (tuple))
    if kwargs:
      assert isinstance(kwargs, dict)

  def AddResultForParams(self, args, result, kwargs=None, side_effect=None,
                         strict=True):
    """Record the internal results of a given partial mock call.

    Args:
      args: A list containing the positional args an invocation must have for
        it to match the internal result.  The list can contain instances of
        meta-args (such as IgnoreArg, Regex, In, etc.).  Positional argument
        matching is always *strict*, meaning extra positional arguments in
        the invocation are not allowed.
      result: The internal result that will be matched for the command
        invocation specified.
      kwargs: A dictionary containing the keyword args an invocation must have
        for it to match the internal result.  The dictionary can contain
        instances of meta-args (such as IgnoreArg, Regex, In, etc.).  Keyword
        argument matching is by default *strict*, but can be modified by the
        |strict| argument.
      side_effect: A functor that gets called every time a partially mocked
        function is invoked.  The arguments the partial mock is invoked with are
        passed to the functor.  This is similar to how side effects work for
        mocks.
      strict: Specifies whether keyword are matched strictly.  With strict
        matching turned on, any keyword args a partial mock is invoked with that
        are not specified in |kwargs| will cause the match to fail.
    """
    self.AssertArgs(args, kwargs)
    if kwargs is None:
      kwargs = {}

    params = self.Params(args=args, kwargs=kwargs)
    dup, filtered = _PredicateSplit(
        lambda mc: mc.params == params, self.mocked_calls)

    new = self.MockedCall(params=params, strict=strict, result=result,
                          side_effect=side_effect)
    filtered.append(new)
    self.mocked_calls = filtered

    if dup:
      logging.debug('%s: replacing mock for arguments %r:\n%r -> %r',
                    self.name, params, dup, new)

  def SetDefaultResult(self, result, side_effect=None):
    """Set the default result for an unmatched partial mock call.

    Args:
      result: See AddResultsForParams.
      side_effect: See AddResultsForParams.
    """
    self.default_result, self.default_side_effect = result, side_effect

  def LookupResult(self, args, kwargs=None, hook_args=None, hook_kwargs=None):
    """For a given mocked function call lookup the recorded internal results.

    Args:
      args: A list containing positional args the function was called with.
      kwargs: A dict containing keyword args the function was called with.
      hook_args: A list of positional args to call the hook with.
      hook_kwargs: A dict of key/value args to call the hook with.

    Returns:
      The recorded result for the invocation.

    Raises:
      AssertionError when the call is not mocked, or when there is more
      than one mock that matches.
    """
    def filter_fn(mc):
      if mc.strict:
        return _RecursiveCompare(mc.params, params)

      return (DictContains(mc.params.kwargs, kwargs) and
              _RecursiveCompare(mc.params.args, args))

    def is_exception(obj):
      """Returns True if obj is an exception instance or class."""
      return (
          isinstance(obj, BaseException) or
          isinstance(obj, type) and issubclass(obj, BaseException))

    self.AssertArgs(args, kwargs)
    if kwargs is None:
      kwargs = {}

    params = self.Params(args, kwargs)
    matched, _ = _PredicateSplit(filter_fn, self.mocked_calls)
    if len(matched) > 1:
      raise AssertionError(
          '%s: args %r matches more than one mock:\n%s'
          % (self.name, params, '\n'.join([repr(c) for c in matched])))
    elif matched:
      side_effect, result = matched[0].side_effect, matched[0].result
    elif (self.default_result, self.default_side_effect) != (None, None):
      side_effect, result = self.default_side_effect, self.default_result
    else:
      raise AssertionError('%s: %r not mocked!' % (self.name, params))

    if is_exception(side_effect):
      # Pylint-2.2 can't handle this if guard.
      # pylint: disable=raising-bad-type
      raise side_effect
    if side_effect:
      assert hook_args is not None
      assert hook_kwargs is not None
      hook_result = side_effect(*hook_args, **hook_kwargs)
      if hook_result is not None:
        return hook_result
    return result


class PartialMock(object):
  """Provides functionality for partially mocking out a function or method.

  Partial mocking is useful in cases where the side effects of a function or
  method are complex, and so re-using the logic of the function with
  *dependencies* mocked out is preferred over mocking out the entire function
  and re-implementing the side effect (return value, state modification) logic
  in the test.  It is also useful for creating re-usable mocks.

  Methods mocked out will retain the same spec as their original, but will still
  be bound to this class rather than the mocked class.  In the example below,
  this is why the mocked print function has an extra |inst| argument after the
  first |self| argument.

  Examples:
    # Defined in chromite/lib/foo.py.
    class SomeClass(object):
      def print(self, msg):
        ...
      def write(self, fd, msg):
        ...

    # Defined in chromite/lib/foo_unittest.py.
    class SomeClassMock(partial_mock.PartialMock):
      TARGET = 'chromite.lib.foo.SomeClass'
      ATTRS = ('print',)

      # NB: |self| refers to the instance of |SomeClassMock| while |inst| refers
      # to the instance of |SomeClass|.  This allows access to state in either.
      def print(self, inst, msg):
        ...

  Attributes:
    TARGET: The import spec for the target object to be (partially) mocked.
        This is like the target argument to mock.patch().
    ATTRS: A tuple of attributes on |TARGET| to mock out.  Each attribute must
        be defined with a corresponding signature.  You may mock out as many or
        few attributes as needed (hence, "partial mock").
  """

  # The import spec for the object being mocked.
  TARGET = None
  # Tuples of attribute names on the target object to mock.
  ATTRS = None

  def __init__(self, create_tempdir=False):
    """Initialize.

    Args:
      create_tempdir: If set to True, the partial mock will create its own
        temporary directory when start() is called, and will set self.tempdir to
        the path of the directory.  The directory is deleted when stop() is
        called.
    """
    self.backup = {}
    self.patchers = {}
    self.patched = {}
    self.external_patchers = []
    self.create_tempdir = create_tempdir

    # Set when start() is called.
    self._tempdir_obj = None
    self.tempdir = None
    self.__saved_env__ = None
    self.started = False

    self._results = {}

    if not all([self.TARGET, self.ATTRS]) and any([self.TARGET, self.ATTRS]):
      raise AssertionError('TARGET=%r but ATTRS=%r!'
                           % (self.TARGET, self.ATTRS))

    if self.ATTRS is not None:
      # pylint: disable=not-an-iterable
      for attr in self.ATTRS:
        self._results[attr] = MockedCallResults(attr)

  def __enter__(self):
    return self.start()

  def __exit__(self, exc_type, exc_value, traceback):
    self.stop()

  def PreStart(self):
    """Called at the beginning of start(). Child classes can override this.

    If __init__ was called with |create_tempdir| set, then self.tempdir will
    point to an existing temporary directory when this function is called.
    """

  def PreStop(self):
    """Called at the beginning of stop().  Child classes can override this.

    If __init__ was called with |create_tempdir| set, then self.tempdir will
    not be deleted until after this function returns.
    """

  def StartPatcher(self, patcher):
    """PartialMock will stop the patcher when stop() is called."""
    self.external_patchers.append(patcher)
    return patcher.start()

  def PatchObject(self, *args, **kwargs):
    """Create and start a mock.patch.object().

    stop() will be called automatically during tearDown.
    """
    return self.StartPatcher(mock.patch.object(*args, **kwargs))

  def _start(self):
    if not all([self.TARGET, self.ATTRS]):
      return

    name, member = self.TARGET.rsplit('.', 1)
    module = __import__(name)
    # __import__('foo.bar') returns foo, so...
    for bit in name.split('.')[1:]:
      module = getattr(module, bit)

    cls = getattr(module, member)
    for attr in self.ATTRS:  # pylint: disable=not-an-iterable
      self.backup[attr] = getattr(cls, attr)
      src_attr = '_target%s' % attr if attr.startswith('__') else attr
      if hasattr(self.backup[attr], 'reset_mock'):
        raise AssertionError(
            'You are trying to nest mock contexts - this is currently '
            'unsupported by PartialMock.')
      if callable(self.backup[attr]):
        patcher = mock.patch.object(cls, attr, autospec=True,
                                    side_effect=getattr(self, src_attr))
      else:
        patcher = mock.patch.object(cls, attr, getattr(self, src_attr))
      self.patched[attr] = patcher.start()
      self.patchers[attr] = patcher

    return self

  def start(self):
    """Activates the mock context."""
    try:
      self.__saved_env__ = os.environ.copy()
      self.tempdir = None
      if self.create_tempdir:
        self._tempdir_obj = osutils.TempDir(set_global=True)
        self.tempdir = self._tempdir_obj.tempdir

      self.started = True
      self.PreStart()
      return self._start()
    except:
      self.stop()
      raise

  def stop(self):
    """Restores namespace to the unmocked state."""
    try:
      if self.__saved_env__ is not None:
        osutils.SetEnvironment(self.__saved_env__)

      tasks = ([self.PreStop] + [p.stop for p in self.patchers.values()] +
               [p.stop for p in self.external_patchers])
      if self._tempdir_obj is not None:
        tasks += [self._tempdir_obj.Cleanup]
      cros_build_lib.SafeRun(tasks)
    finally:
      self.started = False
      self.tempdir, self._tempdir_obj = None, None

  def UnMockAttr(self, attr):
    """Unsetting the mock of an attribute/function."""
    self.patchers.pop(attr).stop()


def CheckAttr(f):
  """Automatically set mock_attr based on class default.

  This function decorator automatically sets the mock_attr keyword argument
  based on the class default. The mock_attr specifies which mocked attribute
  a given function is referring to.

  Raises an AssertionError if mock_attr is left unspecified.
  """

  def new_f(self, *args, **kwargs):
    mock_attr = kwargs.pop('mock_attr', None)
    if mock_attr is None:
      mock_attr = self.DEFAULT_ATTR
      if self.DEFAULT_ATTR is None:
        raise AssertionError(
            'mock_attr not specified, and no default configured.')
    return f(self, *args, mock_attr=mock_attr, **kwargs)
  return new_f


class PartialCmdMock(PartialMock):
  """Base class for mocking functions that wrap command line functionality.

  Implements mocking for functions that shell out.  The internal results are
  'returncode', 'output', 'error'.
  """

  DEFAULT_ATTR = None

  # TODO(crbug.com/1006587): Drop redundant arguments & backwards compat APIs.
  @CheckAttr
  def SetDefaultCmdResult(self, returncode=0, output=None, error=None,
                          stdout=None, stderr=None,
                          side_effect=None, mock_attr=None):
    """Specify the default command result if no command is matched.

    Args:
      returncode: See AddCmdResult.
      output: (Deprecated) Alias to stdout.
      error: (Deprecated) Alias to stderr.
      stdout: See AddCmdResult.
      stderr: See AddCmdResult.
      side_effect: See MockedCallResults.AddResultForParams
      mock_attr: Which attributes's mock is being referenced.
    """
    if stdout is None:
      stdout = output
    elif output is not None:
      raise ValueError('Only specify |stdout|, not |output|')
    if stdout is None:
      stdout = ''
    if stderr is None:
      stderr = error
    elif error is not None:
      raise ValueError('Only specify |stderr|, not |error|')
    if stderr is None:
      stderr = ''
    result = cros_build_lib.CommandResult(
        returncode=returncode, stdout=stdout, stderr=stderr)
    self._results[mock_attr].SetDefaultResult(result, side_effect)

  # TODO(crbug.com/1006587): Drop redundant arguments & backwards compat APIs.
  @CheckAttr
  def AddCmdResult(self, cmd, returncode=0, output=None, error=None,
                   stdout=None, stderr=None, kwargs=None, strict=False,
                   side_effect=None, mock_attr=None):
    """Specify the result to simulate for a given command.

    Args:
      cmd: The command string or list to record a result for.
      returncode: The returncode of the command (on the command line).
      output: (Deprecated) Alias to stdout.
      error: (Deprecated) Alias to stderr.
      stdout: The stdout output of the command.
      stderr: The stderr output of the command.
      kwargs: Keyword arguments that the function needs to be invoked with.
      strict: Defaults to False.  See MockedCallResults.AddResultForParams.
      side_effect: See MockedCallResults.AddResultForParams
      mock_attr: Which attributes's mock is being referenced.
    """
    if stdout is None:
      stdout = output
    elif output is not None:
      raise ValueError('Only specify |stdout|, not |output|')
    if stdout is None:
      stdout = ''
    if stderr is None:
      stderr = error
    elif error is not None:
      raise ValueError('Only specify |stderr|, not |error|')
    if stderr is None:
      stderr = ''
    result = cros_build_lib.CommandResult(
        returncode=returncode, stdout=stdout, stderr=stderr)
    self._results[mock_attr].AddResultForParams(
        (cmd,), result, kwargs=kwargs, side_effect=side_effect, strict=strict)

  @CheckAttr
  def CommandContains(self, args, cmd_arg_index=-1, mock_attr=None, **kwargs):
    """Verify that at least one command contains the specified args.

    Args:
      args: Set of expected command-line arguments.
      cmd_arg_index: The index of the command list in the positional call_args.
        Defaults to the last positional argument.
      kwargs: Set of expected keyword arguments.
      mock_attr: Which attributes's mock is being referenced.
    """
    for call_args, call_kwargs in self.patched[mock_attr].call_args_list:
      if (ListContains(args, call_args[cmd_arg_index],
                       strict=isinstance(args, str)) and
          DictContains(kwargs, call_kwargs)):
        return True
    return False

  @CheckAttr
  def assertCommandContains(self, args=(), expected=True, mock_attr=None,
                            **kwargs):
    """Assert that run was called with the specified args.

    This verifies that at least one of the run calls contains the
    specified arguments on the command line.

    Args:
      args: Set of expected command-line arguments.
      expected: If False, instead verify that none of the run calls
          contained the specified arguments.
      **kwargs: Set of expected keyword arguments.
      mock_attr: Which attributes's mock is being referenced.
    """
    if bool(expected) != self.CommandContains(args, **kwargs):
      if expected:
        msg = 'Expected to find %r in any of:\n%s'
      else:
        msg = 'Expected to not find %r in any of:\n%s'
      patched = self.patched[mock_attr]
      cmds = '\n'.join(repr(x) for x in patched.call_args_list)
      raise AssertionError(msg % (mock.call(args, **kwargs), cmds))

  @CheckAttr
  def assertCommandCalled(self, args=(), mock_attr=None, **kwargs):
    """Assert that run was called with the specified args.

    This verifies that at least one of the run calls exactly
    matches the specified command line and misc-arguments.

    Args:
      args: Set of expected command-line arguments.
      mock_attr: Which attributes's mock is being referenced.
      **kwargs: Set of expected keyword arguments.
    """
    call = mock.call(args, **kwargs)
    patched = self.patched[mock_attr]

    for icall in patched.call_args_list:
      if call == icall:
        return

    cmds = '\n'.join(repr(x) for x in patched.call_args_list)
    raise AssertionError('Expected to find %r in any of:\n%s' % (call, cmds))

  @property
  @CheckAttr
  def call_count(self, mock_attr=None):  # pylint: disable=property-with-parameters
    """Return the number of times we've been called."""
    return self.patched[mock_attr].call_count

  @property
  @CheckAttr
  def call_args_list(self, mock_attr=None):  # pylint: disable=property-with-parameters
    """Return the list of args we've been called with."""
    return self.patched[mock_attr].call_args_list
