#!/usr/bin/python

# 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.

import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                '..', '..'))
from chromite.lib import cros_test_lib
from chromite.lib import partial_mock

# pylint: disable=W0212

class ComparatorTest(cros_test_lib.MoxTestCase):
  """Test Comparitor functionality."""
  TEST_KEY1 = 'monkey'
  TEST_KEY2 = 'foon'

  def testEquals(self):
    """__eq__, __ne__ functionality of Comparator classes."""
    for cls_name in ['In', 'Regex', 'ListRegex']:
      cls = getattr(partial_mock, cls_name)
      obj1 = cls(self.TEST_KEY1)
      obj2 = cls(self.TEST_KEY1)
      obj3 = cls(self.TEST_KEY2)
      self.assertEquals(obj1, obj2)
      self.assertFalse(obj1 == obj3)
      self.assertNotEquals(obj1, obj3)

  def testIgnoreEquals(self):
    """Verify __eq__ functionality for Ignore."""
    obj1 = partial_mock.Ignore()
    obj2 = partial_mock.Ignore()
    self.assertEquals(obj1, obj2)
    self.assertFalse(obj1 != obj2)

  def testListRegex(self):
    """Verify ListRegex match functionality."""
    obj = partial_mock.ListRegex('.*monkey.*')
    self.assertTrue(obj.Match(['the', 'small monkeys', 'jumped']))
    self.assertFalse(obj.Match(['the', 'jumped']))
    self.assertFalse(obj.Match(None))
    self.assertFalse(obj.Match(1))


class RecursiveCompareTest(cros_test_lib.MoxTestCase):
  """Test recursive compare functionality."""

  LHS_DICT = {3: 1, 1: 2}
  RHS_DICT = {1: 2, 3: 1}
  LIST = [1, 2, 3, 4]
  TUPLE = (1, 2, 3, 4)

  def TrueHelper(self, lhs, rhs):
    self.assertTrue(partial_mock._RecursiveCompare(lhs, rhs))

  def FalseHelper(self, lhs, rhs):
    self.assertFalse(partial_mock._RecursiveCompare(lhs, rhs))

  def testIt(self):
    """Test basic equality cases."""
    self.TrueHelper(self.LHS_DICT, self.RHS_DICT)
    self.TrueHelper({3: self.LIST, 1: self.LHS_DICT},
                    {1: self.LHS_DICT, 3: self.LIST})
    self.FalseHelper({1: self.LHS_DICT, 3: self.LIST},
                     {1: self.LHS_DICT, 3: self.LIST + [5]})
    self.FalseHelper(self.LIST, self.TUPLE)

  def testUnicode(self):
    """Test recursively comparing unicode and non-unicode strings."""
    self.assertTrue(partial_mock._RecursiveCompare(['foo'], [u'foo']))


class ListContainsTest(cros_test_lib.MoxTestCase):

  L = range(10) + range(10) + [9]
  STRICTLY_TRUE_LISTS = [range(10), range(9, 10), range(3, 6), range(1), [],
                         [9, 9]]
  LOOSELY_TRUE_LISTS = [range(0, 10, 2), range(3, 6, 2), [1, 1]]
  FALSE_LISTS = [[1.5], [-1], [1, 1, 1], [10], [22], range(6, 11), range(-1, 5)]

  def testStrictContains(self):
    """Test ListContains with strict=True."""
    for x in self.STRICTLY_TRUE_LISTS:
      self.assertTrue(partial_mock.ListContains(x, self.L, strict=True))
    for x in self.LOOSELY_TRUE_LISTS + self.FALSE_LISTS:
      self.assertFalse(partial_mock.ListContains(x, self.L, strict=True))

  def testLooseContains(self):
    """Test ListContains with strict=False."""
    for x in self.STRICTLY_TRUE_LISTS + self.LOOSELY_TRUE_LISTS:
      self.assertTrue(partial_mock.ListContains(x, self.L))
    for x in self.FALSE_LISTS:
      self.assertFalse(partial_mock.ListContains(x, self.L))

  def testUnicode(self):
    """Test ListContains with unicode and non-unicode strings."""
    self.assertTrue(partial_mock.ListContains(['foo'], [u'foo']))


class MockedCallResultsTest(cros_test_lib.MoxTestCase):
  """Test MockedCallResults functionality."""

  ARGS = ('abc',)
  LIST_ARGS = ([1, 2, 3, 4],)
  KWARGS = {'test': 'ing'}
  NEW_ENTRY = {'new': 'entry'}

  def KwargsHelper(self, result, kwargs, strict=True):
    self.mr.AddResultForParams(self.ARGS, result, kwargs=kwargs,
                               strict=strict)

  def setUp(self):
    self.mr = partial_mock.MockedCallResults('SomeFunction')

  def testNoMock(self):
    """The call is not mocked."""
    self.assertRaises(AssertionError, self.mr.LookupResult, self.ARGS)

  def testArgReplacement(self):
    """Replacing mocks for args-only calls."""
    self.mr.AddResultForParams(self.ARGS, 1)
    self.mr.AddResultForParams(self.ARGS, 2)
    self.assertEquals(2, self.mr.LookupResult(self.ARGS))

  def testKwargsStrictReplacement(self):
    """Replacing strict kwargs mock with another strict mock."""
    self.KwargsHelper(1, self.KWARGS)
    self.KwargsHelper(2, self.KWARGS)
    self.assertEquals(2, self.mr.LookupResult(self.ARGS, kwargs=self.KWARGS))

  def testKwargsNonStrictReplacement(self):
    """Replacing strict kwargs mock with nonstrict mock."""
    self.KwargsHelper(1, self.KWARGS)
    self.KwargsHelper(2, self.KWARGS, strict=False)
    self.assertEquals(2, self.mr.LookupResult(self.ARGS, kwargs=self.KWARGS))

  def testListArgLookup(self):
    """Matching of arguments containing lists."""
    self.mr.AddResultForParams(self.LIST_ARGS, 1)
    self.mr.AddResultForParams(self.ARGS, 1)
    self.assertEquals(1, self.mr.LookupResult(self.LIST_ARGS))

  def testKwargsStrictLookup(self):
    """Strict lookup fails due to extra kwarg."""
    self.KwargsHelper(1, self.KWARGS)
    kwargs = self.NEW_ENTRY
    kwargs.update(self.KWARGS)
    self.assertRaises(AssertionError, self.mr.LookupResult, self.ARGS,
                      kwargs=kwargs)

  def testKwargsNonStrictLookup(self):
    """"Nonstrict lookup passes with extra kwarg."""
    self.KwargsHelper(1, self.KWARGS, strict=False)
    kwargs = self.NEW_ENTRY
    kwargs.update(self.KWARGS)
    self.assertEquals(1, self.mr.LookupResult(self.ARGS, kwargs=kwargs))

  def testIgnoreMatching(self):
    """Deep matching of Ignore objects."""
    ignore = partial_mock.Ignore()
    self.mr.AddResultForParams((ignore, ignore), 1, kwargs={'test': ignore})
    self.assertEquals(
        1, self.mr.LookupResult(('some', 'values'), {'test': 'bla'}))

  def testRegexMatching(self):
    """Regex matching."""
    self.mr.AddResultForParams((partial_mock.Regex('pre.ix'),), 1)
    self.mr.AddResultForParams((partial_mock.Regex('suffi.'),), 2)
    self.assertEquals(1, self.mr.LookupResult(('prefix',)))
    self.assertEquals(2, self.mr.LookupResult(('suffix',)))

  def testMultipleMatches(self):
    """Lookup matches mutilple results."""
    self.mr.AddResultForParams((partial_mock.Ignore(),), 1)
    self.mr.AddResultForParams((partial_mock.In('test'),), 2)
    self.assertRaises(AssertionError, self.mr.LookupResult, ('test',))

  def testDefaultResult(self):
    """Test default result matching."""
    self.mr.SetDefaultResult(1)
    self.mr.AddResultForParams((partial_mock.In('test'),), 2)
    self.assertEquals(1, self.mr.LookupResult(self.ARGS))
    self.assertEquals(2, self.mr.LookupResult(('test',)))

  def _ExampleHook(self, *args, **kwargs):
    """Example hook for testing."""
    self.assertEquals(args, self.LIST_ARGS)
    self.assertEquals(kwargs, self.KWARGS)
    return 2

  def testHook(self):
    """Return value of hook is used as the final result."""
    self.mr.AddResultForParams(self.ARGS, 1, side_effect=self._ExampleHook)
    self.assertEqual(
        2, self.mr.LookupResult(self.ARGS, hook_args=self.LIST_ARGS,
                                hook_kwargs=self.KWARGS))

  def testDefaultHook(self):
    """Verify default hooks are used."""
    self.mr.SetDefaultResult(1, self._ExampleHook)
    self.mr.AddResultForParams((partial_mock.In('test'),), 3)
    self.assertEqual(
        2, self.mr.LookupResult(self.ARGS, hook_args=self.LIST_ARGS,
                                hook_kwargs=self.KWARGS))
    self.assertEquals(3, self.mr.LookupResult(('test',)))


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