#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc.  All rights reserved.
# https://developers.google.com/protocol-buffers/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Adds support for parameterized tests to Python's unittest TestCase class.

A parameterized test is a method in a test case that is invoked with different
argument tuples.

A simple example:

  class AdditionExample(parameterized.TestCase):
    @parameterized.parameters(
       (1, 2, 3),
       (4, 5, 9),
       (1, 1, 3))
    def testAddition(self, op1, op2, result):
      self.assertEqual(result, op1 + op2)


Each invocation is a separate test case and properly isolated just
like a normal test method, with its own setUp/tearDown cycle. In the
example above, there are three separate testcases, one of which will
fail due to an assertion error (1 + 1 != 3).

Parameters for individual test cases can be tuples (with positional parameters)
or dictionaries (with named parameters):

  class AdditionExample(parameterized.TestCase):
    @parameterized.parameters(
       {'op1': 1, 'op2': 2, 'result': 3},
       {'op1': 4, 'op2': 5, 'result': 9},
    )
    def testAddition(self, op1, op2, result):
      self.assertEqual(result, op1 + op2)

If a parameterized test fails, the error message will show the
original test name (which is modified internally) and the arguments
for the specific invocation, which are part of the string returned by
the shortDescription() method on test cases.

The id method of the test, used internally by the unittest framework,
is also modified to show the arguments. To make sure that test names
stay the same across several invocations, object representations like

  >>> class Foo(object):
  ...  pass
  >>> repr(Foo())
  '<__main__.Foo object at 0x23d8610>'

are turned into '<__main__.Foo>'. For even more descriptive names,
especially in test logs, you can use the named_parameters decorator. In
this case, only tuples are supported, and the first parameters has to
be a string (or an object that returns an apt name when converted via
str()):

  class NamedExample(parameterized.TestCase):
    @parameterized.named_parameters(
       ('Normal', 'aa', 'aaa', True),
       ('EmptyPrefix', '', 'abc', True),
       ('BothEmpty', '', '', True))
    def testStartsWith(self, prefix, string, result):
      self.assertEqual(result, strings.startswith(prefix))

Named tests also have the benefit that they can be run individually
from the command line:

  $ testmodule.py NamedExample.testStartsWithNormal
  .
  --------------------------------------------------------------------
  Ran 1 test in 0.000s

  OK

Parameterized Classes
=====================
If invocation arguments are shared across test methods in a single
TestCase class, instead of decorating all test methods
individually, the class itself can be decorated:

  @parameterized.parameters(
    (1, 2, 3)
    (4, 5, 9))
  class ArithmeticTest(parameterized.TestCase):
    def testAdd(self, arg1, arg2, result):
      self.assertEqual(arg1 + arg2, result)

    def testSubtract(self, arg2, arg2, result):
      self.assertEqual(result - arg1, arg2)

Inputs from Iterables
=====================
If parameters should be shared across several test cases, or are dynamically
created from other sources, a single non-tuple iterable can be passed into
the decorator. This iterable will be used to obtain the test cases:

  class AdditionExample(parameterized.TestCase):
    @parameterized.parameters(
      c.op1, c.op2, c.result for c in testcases
    )
    def testAddition(self, op1, op2, result):
      self.assertEqual(result, op1 + op2)


Single-Argument Test Methods
============================
If a test method takes only one argument, the single argument does not need to
be wrapped into a tuple:

  class NegativeNumberExample(parameterized.TestCase):
    @parameterized.parameters(
       -1, -3, -4, -5
    )
    def testIsNegative(self, arg):
      self.assertTrue(IsNegative(arg))
"""

__author__ = 'tmarek@google.com (Torsten Marek)'

import functools
import re
import types
import unittest
import uuid

try:
  # Since python 3
  import collections.abc as collections_abc
except ImportError:
  # Won't work after python 3.8
  import collections as collections_abc

ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
_SEPARATOR = uuid.uuid1().hex
_FIRST_ARG = object()
_ARGUMENT_REPR = object()


def _CleanRepr(obj):
  return ADDR_RE.sub(r'<\1>', repr(obj))


# Helper function formerly from the unittest module, removed from it in
# Python 2.7.
def _StrClass(cls):
  return '%s.%s' % (cls.__module__, cls.__name__)


def _NonStringIterable(obj):
  return (isinstance(obj, collections_abc.Iterable) and
          not isinstance(obj, str))


def _FormatParameterList(testcase_params):
  if isinstance(testcase_params, collections_abc.Mapping):
    return ', '.join('%s=%s' % (argname, _CleanRepr(value))
                     for argname, value in testcase_params.items())
  elif _NonStringIterable(testcase_params):
    return ', '.join(map(_CleanRepr, testcase_params))
  else:
    return _FormatParameterList((testcase_params,))


class _ParameterizedTestIter(object):
  """Callable and iterable class for producing new test cases."""

  def __init__(self, test_method, testcases, naming_type):
    """Returns concrete test functions for a test and a list of parameters.

    The naming_type is used to determine the name of the concrete
    functions as reported by the unittest framework. If naming_type is
    _FIRST_ARG, the testcases must be tuples, and the first element must
    have a string representation that is a valid Python identifier.

    Args:
      test_method: The decorated test method.
      testcases: (list of tuple/dict) A list of parameter
                 tuples/dicts for individual test invocations.
      naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR.
    """
    self._test_method = test_method
    self.testcases = testcases
    self._naming_type = naming_type

  def __call__(self, *args, **kwargs):
    raise RuntimeError('You appear to be running a parameterized test case '
                       'without having inherited from parameterized.'
                       'TestCase. This is bad because none of '
                       'your test cases are actually being run.')

  def __iter__(self):
    test_method = self._test_method
    naming_type = self._naming_type

    def MakeBoundParamTest(testcase_params):
      @functools.wraps(test_method)
      def BoundParamTest(self):
        if isinstance(testcase_params, collections_abc.Mapping):
          test_method(self, **testcase_params)
        elif _NonStringIterable(testcase_params):
          test_method(self, *testcase_params)
        else:
          test_method(self, testcase_params)

      if naming_type is _FIRST_ARG:
        # Signal the metaclass that the name of the test function is unique
        # and descriptive.
        BoundParamTest.__x_use_name__ = True
        BoundParamTest.__name__ += str(testcase_params[0])
        testcase_params = testcase_params[1:]
      elif naming_type is _ARGUMENT_REPR:
        # __x_extra_id__ is used to pass naming information to the __new__
        # method of TestGeneratorMetaclass.
        # The metaclass will make sure to create a unique, but nondescriptive
        # name for this test.
        BoundParamTest.__x_extra_id__ = '(%s)' % (
            _FormatParameterList(testcase_params),)
      else:
        raise RuntimeError('%s is not a valid naming type.' % (naming_type,))

      BoundParamTest.__doc__ = '%s(%s)' % (
          BoundParamTest.__name__, _FormatParameterList(testcase_params))
      if test_method.__doc__:
        BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,)
      return BoundParamTest
    return (MakeBoundParamTest(c) for c in self.testcases)


def _IsSingletonList(testcases):
  """True iff testcases contains only a single non-tuple element."""
  return len(testcases) == 1 and not isinstance(testcases[0], tuple)


def _ModifyClass(class_object, testcases, naming_type):
  assert not getattr(class_object, '_id_suffix', None), (
      'Cannot add parameters to %s,'
      ' which already has parameterized methods.' % (class_object,))
  class_object._id_suffix = id_suffix = {}
  # We change the size of __dict__ while we iterate over it,
  # which Python 3.x will complain about, so use copy().
  for name, obj in class_object.__dict__.copy().items():
    if (name.startswith(unittest.TestLoader.testMethodPrefix)
        and isinstance(obj, types.FunctionType)):
      delattr(class_object, name)
      methods = {}
      _UpdateClassDictForParamTestCase(
          methods, id_suffix, name,
          _ParameterizedTestIter(obj, testcases, naming_type))
      for name, meth in methods.items():
        setattr(class_object, name, meth)


def _ParameterDecorator(naming_type, testcases):
  """Implementation of the parameterization decorators.

  Args:
    naming_type: The naming type.
    testcases: Testcase parameters.

  Returns:
    A function for modifying the decorated object.
  """
  def _Apply(obj):
    if isinstance(obj, type):
      _ModifyClass(
          obj,
          list(testcases) if not isinstance(testcases, collections_abc.Sequence)
          else testcases,
          naming_type)
      return obj
    else:
      return _ParameterizedTestIter(obj, testcases, naming_type)

  if _IsSingletonList(testcases):
    assert _NonStringIterable(testcases[0]), (
        'Single parameter argument must be a non-string iterable')
    testcases = testcases[0]

  return _Apply


def parameters(*testcases):  # pylint: disable=invalid-name
  """A decorator for creating parameterized tests.

  See the module docstring for a usage example.
  Args:
    *testcases: Parameters for the decorated method, either a single
                iterable, or a list of tuples/dicts/objects (for tests
                with only one argument).

  Returns:
     A test generator to be handled by TestGeneratorMetaclass.
  """
  return _ParameterDecorator(_ARGUMENT_REPR, testcases)


def named_parameters(*testcases):  # pylint: disable=invalid-name
  """A decorator for creating parameterized tests.

  See the module docstring for a usage example. The first element of
  each parameter tuple should be a string and will be appended to the
  name of the test method.

  Args:
    *testcases: Parameters for the decorated method, either a single
                iterable, or a list of tuples.

  Returns:
     A test generator to be handled by TestGeneratorMetaclass.
  """
  return _ParameterDecorator(_FIRST_ARG, testcases)


class TestGeneratorMetaclass(type):
  """Metaclass for test cases with test generators.

  A test generator is an iterable in a testcase that produces callables. These
  callables must be single-argument methods. These methods are injected into
  the class namespace and the original iterable is removed. If the name of the
  iterable conforms to the test pattern, the injected methods will be picked
  up as tests by the unittest framework.

  In general, it is supposed to be used in conjunction with the
  parameters decorator.
  """

  def __new__(mcs, class_name, bases, dct):
    dct['_id_suffix'] = id_suffix = {}
    for name, obj in dct.copy().items():
      if (name.startswith(unittest.TestLoader.testMethodPrefix) and
          _NonStringIterable(obj)):
        iterator = iter(obj)
        dct.pop(name)
        _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator)

    return type.__new__(mcs, class_name, bases, dct)


def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator):
  """Adds individual test cases to a dictionary.

  Args:
    dct: The target dictionary.
    id_suffix: The dictionary for mapping names to test IDs.
    name: The original name of the test case.
    iterator: The iterator generating the individual test cases.
  """
  for idx, func in enumerate(iterator):
    assert callable(func), 'Test generators must yield callables, got %r' % (
        func,)
    if getattr(func, '__x_use_name__', False):
      new_name = func.__name__
    else:
      new_name = '%s%s%d' % (name, _SEPARATOR, idx)
    assert new_name not in dct, (
        'Name of parameterized test case "%s" not unique' % (new_name,))
    dct[new_name] = func
    id_suffix[new_name] = getattr(func, '__x_extra_id__', '')


class TestCase(unittest.TestCase, metaclass=TestGeneratorMetaclass):
  """Base class for test cases using the parameters decorator."""

  def _OriginalName(self):
    return self._testMethodName.split(_SEPARATOR)[0]

  def __str__(self):
    return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__))

  def id(self):  # pylint: disable=invalid-name
    """Returns the descriptive ID of the test.

    This is used internally by the unittesting framework to get a name
    for the test to be used in reports.

    Returns:
      The test id.
    """
    return '%s.%s%s' % (_StrClass(self.__class__),
                        self._OriginalName(),
                        self._id_suffix.get(self._testMethodName, ''))


def CoopTestCase(other_base_class):
  """Returns a new base class with a cooperative metaclass base.

  This enables the TestCase to be used in combination
  with other base classes that have custom metaclasses, such as
  mox.MoxTestBase.

  Only works with metaclasses that do not override type.__new__.

  Example:

    import google3
    import mox

    from google3.testing.pybase import parameterized

    class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)):
      ...

  Args:
    other_base_class: (class) A test case base class.

  Returns:
    A new class object.
  """
  metaclass = type(
      'CoopMetaclass',
      (other_base_class.__metaclass__,
       TestGeneratorMetaclass), {})
  return metaclass(
      'CoopTestCase',
      (other_base_class, TestCase), {})
