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

"""Unittests for config."""

from __future__ import print_function

import copy
import cPickle
import mock

from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import cros_test_lib

# pylint: disable=protected-access



def MockBuildConfig():
  """Create a BuildConfig object for convenient testing pleasure."""
  site_config = MockSiteConfig()
  return site_config['x86-generic-paladin']


def MockSiteConfig():
  """Create a SiteConfig object for convenient testing pleasure.

  Shared amoung a number of unittest files, so be careful if changing it.
  """
  result = config_lib.SiteConfig()

  # Add a single, simple build config.
  result.Add(
      'x86-generic-paladin',
      active_waterfall='chromiumos',
      boards=['x86-generic'],
      build_type='paladin',
      chrome_sdk=True,
      chrome_sdk_build_chrome=False,
      description='Commit Queue',
      doc='http://mock_url/',
      image_test=True,
      images=['base', 'test'],
      important=True,
      manifest_version=True,
      prebuilts='public',
      trybot_list=True,
      upload_standalone_images=False,
      vm_tests=[config_lib.VMTestConfig('smoke_suite')],
  )

  return result


def AssertSiteIndependentParameters(site_config):
  """Helper function to test that SiteConfigs contain site-independent values.

  Args:
    site_config: A SiteConfig object.

  Returns:
    A boolean. True if the config contained all site-independent values.
    False otherwise.
  """
  # Enumerate the necessary site independent parameter keys.
  # All keys must be documented.
  # TODO (msartori): Fill in this list.
  site_independent_params = [
  ]

  site_params = site_config.params
  return all([x in site_params for x in site_independent_params])


class _CustomObject(object):
  """Simple object. For testing deepcopy."""

  def __init__(self, x):
    self.x = x

  def __eq__(self, other):
    return self.x == other.x


class _CustomObjectWithSlots(object):
  """Simple object with slots. For testing deepcopy."""

  __slots__ = ['x']

  def __init__(self, x):
    self.x = x

  def __eq__(self, other):
    return self.x == other.x


class BuildConfigClassTest(cros_test_lib.TestCase):
  """BuildConfig tests."""

  def setUp(self):
    self.fooConfig = config_lib.BuildConfig(name='foo', foo=1)
    self.barConfig = config_lib.BuildConfig(name='bar', bar=2)
    self.deepConfig = config_lib.BuildConfig(
        name='deep', nested=[1, 2, 3], deep=3,
        child_configs=[self.fooConfig, self.barConfig])

  def testMockSiteConfig(self):
    """Make sure Mock generator fucntion doesn't crash."""
    site_config = MockSiteConfig()
    self.assertIsNotNone(site_config)

    build_config = MockBuildConfig()
    self.assertIsNotNone(build_config)

  def testValueAccess(self):
    self.assertEqual(self.fooConfig.name, 'foo')
    self.assertEqual(self.fooConfig.name, self.fooConfig['name'])

    self.assertRaises(AttributeError, getattr, self.fooConfig, 'foobar')

  def testApplyEmpty(self):
    orig = self.fooConfig.deepcopy()

    # Do nothing.
    self.fooConfig.apply()
    self.assertEqual(self.fooConfig, orig)

  def testApplyValues(self):
    # Apply simple values..
    self.fooConfig.apply(a=1, b=2)
    self.assertEqual(self.fooConfig, dict(name='foo', foo=1, a=1, b=2))

  def testApplyBuildConfig(self):
    # Apply a BuildConfig.
    self.fooConfig.apply(self.barConfig)
    self.assertEqual(self.fooConfig, dict(name='bar', foo=1, bar=2))

  def testApplyMixed(self):
    # Apply simple values..
    config = config_lib.BuildConfig()
    config.apply(self.fooConfig, self.barConfig, a=1, b=2, bar=3)
    self.assertEqual(config, dict(name='bar', foo=1, bar=3, a=1, b=2))

  def testDeriveMixed(self):
    config = config_lib.BuildConfig()
    result = config.derive(self.fooConfig, self.barConfig, a=1, b=2, bar=3)

    self.assertIsNot(config, result)
    self.assertEqual(config, dict())
    self.assertEqual(result, dict(name='bar', foo=1, bar=3, a=1, b=2))

  def testApplyCallable(self):
    # Callable that adds a configurable amount.
    append = lambda x: lambda base: base + ' ' + x

    site_config = config_lib.SiteConfig()

    site_config.AddTemplate('add1', foo=append('one'))
    site_config.AddTemplate('add2', foo=append('two'))
    site_config.AddTemplate('fixed', foo='fixed')

    site_config.AddTemplate('derived',
                            site_config.templates.add1)

    site_config.AddTemplate('stacked',
                            site_config.templates.add1,
                            site_config.templates.add2)

    site_config.AddTemplate('stackedDeep',
                            site_config.templates.fixed,
                            site_config.templates.add1,
                            site_config.templates.add1,
                            site_config.templates.add1,
                            foo=append('deep'))

    site_config.AddTemplate('stackedDeeper',
                            site_config.templates.stacked,
                            site_config.templates.stackedDeep,
                            foo=append('deeper'))

    base = config_lib.BuildConfig(foo='base')

    # Basic apply.
    result = base.derive(site_config.templates.add1)
    self.assertEqual(result.foo, 'base one')

    # Callable template + local callable.
    result = base.derive(site_config.templates.add1, foo=append('local'))
    self.assertEqual(result.foo, 'base one local')

    # Callable template + local fixed.
    result = base.derive(site_config.templates.add1, foo='local')
    self.assertEqual(result.foo, 'local')

    # Derived template.
    result = base.derive(site_config.templates.derived)
    self.assertEqual(result.foo, 'base one')

    # Template with fixed override after stacking template (all callable magic
    # should disappear).
    result = base.derive(site_config.templates.fixed)
    self.assertEqual(result.foo, 'fixed')

    # Template with stacked.
    result = base.derive(site_config.templates.stacked)
    self.assertEqual(result.foo, 'base one two')

    # Callables on top of fixed from template.
    result = base.derive(site_config.templates.stackedDeep)
    self.assertEqual(result.foo, 'fixed one one one deep')

    # Just get crazy with it.
    result = base.derive(site_config.templates.stackedDeeper)
    self.assertEqual(result.foo, 'fixed one one one deep deeper')

    # Ensure objects derived from weren't modified.
    self.assertEqual(base.foo, 'base')
    self.assertEqual(site_config.templates.fixed.foo, 'fixed')

  def AssertDeepCopy(self, obj1, obj2, obj3):
    """Assert that |obj3| is a deep copy of |obj1|.

    Args:
      obj1: Object that was copied.
      obj2: A true deep copy of obj1 (produced using copy.deepcopy).
      obj3: The purported deep copy of obj1.
    """
    # Check whether the item was copied by deepcopy. If so, then it
    # must have been copied by our algorithm as well.
    if obj1 is not obj2:
      self.assertIsNot(obj1, obj3)

    # Assert the three items are all equal.
    self.assertEqual(obj1, obj2)
    self.assertEqual(obj1, obj3)

    if isinstance(obj1, (tuple, list)):
      # Copy tuples and lists item by item.
      for i in range(len(obj1)):
        self.AssertDeepCopy(obj1[i], obj2[i], obj3[i])
    elif isinstance(obj1, set):
      # Compare sorted versions of the set.
      self.AssertDeepCopy(list(sorted(obj1)), list(sorted(obj2)),
                          list(sorted(obj3)))
    elif isinstance(obj1, dict):
      # Copy dicts item by item.
      for k in obj1:
        self.AssertDeepCopy(obj1[k], obj2[k], obj3[k])
    elif hasattr(obj1, '__dict__'):
      # Make sure the dicts are copied.
      self.AssertDeepCopy(obj1.__dict__, obj2.__dict__, obj3.__dict__)
    elif hasattr(obj1, '__slots__'):
      # Make sure the slots are copied.
      for attr in obj1.__slots__:
        self.AssertDeepCopy(getattr(obj1, attr), getattr(obj2, attr),
                            getattr(obj3, attr))
    else:
      # This should be an object that copy.deepcopy didn't copy (probably an
      # immutable object.) If not, the test needs to be updated to handle this
      # kind of object.
      self.assertIs(obj1, obj2)

  def testDeepCopy(self):
    """Test that we deep copy correctly."""
    for cfg in [self.fooConfig, self.barConfig, self.deepConfig]:
      self.AssertDeepCopy(cfg, copy.deepcopy(cfg), cfg.deepcopy())

  def testAssertDeepCopy(self):
    """Test that we test deep copy correctly."""
    test1 = ['foo', 'bar', ['hey']]
    tests = [test1,
             set([tuple(x) for x in test1]),
             dict(zip([tuple(x) for x in test1], test1)),
             _CustomObject(test1),
             _CustomObjectWithSlots(test1)]

    for x in tests + [[tests]]:
      copy_x = copy.deepcopy(x)
      self.AssertDeepCopy(x, copy_x, copy.deepcopy(x))
      self.AssertDeepCopy(x, copy_x, cPickle.loads(cPickle.dumps(x, -1)))
      self.assertRaises(AssertionError, self.AssertDeepCopy, x,
                        copy_x, x)
      if not isinstance(x, set):
        self.assertRaises(AssertionError, self.AssertDeepCopy, x,
                          copy_x, copy.copy(x))

class SiteParametersClassTest(cros_test_lib.TestCase):
  """SiteParameters tests."""

  def testAttributeAccess(self):
    """Test that SiteParameters dot-accessor works correctly."""
    site_params = config_lib.SiteParameters()

    # Ensure our test key is not in site_params.
    self.assertTrue(site_params.get('foo') is None)

    # Test that we raise when accessing a non-existent value.
    # pylint: disable=pointless-statement
    with self.assertRaises(AttributeError):
      site_params.foo

    # Test the dot-accessor.
    site_params.update({'foo': 'bar'})
    self.assertEquals('bar', site_params.foo)


class SiteConfigTest(cros_test_lib.TestCase):
  """Config tests."""

  @staticmethod
  def _callable(x):
    return x + ' extended'

  def setUp(self):
    self.complex_defaults = {
        'value': 'default',
    }

    self.complex_site_params = {
        'site_foo': True,
        'site_bar': False,
        'nested': {'sub1': 1, 'sub2': 2},
    }

    # Construct our test config.
    site_config = config_lib.SiteConfig(
        defaults=self.complex_defaults, site_params=self.complex_site_params)

    site_config.AddTemplate('match', value='default')
    site_config.AddTemplate('template', value='template')
    site_config.AddTemplate('mixin', value='mixin')
    site_config.AddTemplate('unused', value='unused')
    site_config.AddTemplate('callable', value=self._callable)

    default = site_config.Add('default')

    default_with_override = site_config.Add(
        'default_with_override',
        value='override')

    site_config.AddWithoutTemplate(
        'default_with_mixin',
        site_config.templates.mixin)

    site_config.AddWithoutTemplate(
        'mixin_with_override',
        site_config.templates.mixin,
        value='override')

    site_config.Add(
        'default_with_template',
        site_config.templates.template)

    site_config.Add(
        'template_with_override',
        site_config.templates.template,
        value='override')

    site_config.Add(
        'template_with_mixin',
        site_config.templates.template,
        site_config.templates.mixin)

    site_config.Add(
        'template_with_mixin_override',
        site_config.templates.template,
        site_config.templates.mixin,
        value='override')

    site_config.Add(
        'match',
        value='default')

    site_config.Add(
        'template_back_to_default',
        site_config.templates.template,
        value='default')

    site_config.Add(
        'calling',
        site_config.templates.callable)

    site_config.Add(
        'vm_tests',
        vm_tests=[config_lib.VMTestConfig('vm_suite')],
        vm_tests_override=[config_lib.VMTestConfig('vm_override')])

    site_config.Add(
        'hw_tests',
        hw_tests=[config_lib.HWTestConfig('hw_suite')],
        hw_tests_override=[config_lib.HWTestConfig('hw_override')])

    site_config.AddGroup(
        'parent',
        default,
        default_with_override)

    self.site_config = site_config

  def testAddedContents(self):
    """Verify that our complex config looks like we expect, before saving."""
    expected = {
        'default': {
            '_template': None,
            'name': 'default',
            'value': 'default',
        },
        'default_with_override': {
            '_template': None,
            'name': 'default_with_override',
            'value': 'override',
        },
        'default_with_mixin': {
            '_template': None,
            'name': 'default_with_mixin',
            'value': 'mixin',
        },
        'mixin_with_override': {
            '_template': None,
            'name': 'mixin_with_override',
            'value': 'override',
        },
        'default_with_template': {
            '_template': 'template',
            'name': 'default_with_template',
            'value': 'template',
        },
        'template_with_override': {
            '_template': 'template',
            'name': 'template_with_override',
            'value': 'override'
        },
        'template_with_mixin': {
            '_template': 'template',
            'name': 'template_with_mixin',
            'value': 'mixin',
        },
        'template_with_mixin_override': {
            '_template': 'template',
            'name': 'template_with_mixin_override',
            'value': 'override'
        },
        'calling': {
            '_template': 'callable',
            'name': 'calling',
            'value': 'default extended',
        },
        'match': {
            '_template': None,
            'name': 'match',
            'value': 'default',
        },
        'template_back_to_default': {
            '_template': 'template',
            'name': 'template_back_to_default',
            'value': 'default',
        },
        'vm_tests': {
            '_template': None,
            'name': 'vm_tests',
            'vm_tests': [config_lib.VMTestConfig('vm_suite')],
            'vm_tests_override': [config_lib.VMTestConfig('vm_override')],
        },
        'hw_tests': {
            '_template': None,
            'name': 'hw_tests',
            'hw_tests': [config_lib.HWTestConfig('hw_suite')],
            'hw_tests_override': [config_lib.HWTestConfig('hw_override')],
        },
        'parent': {
            '_template': None,
            'name': 'parent',
            'value': 'default',
        },
    }

    # Make sure our expected build configs exist.
    self.assertItemsEqual(self.site_config.keys(), expected.keys())

    # Make sure each one contains
    self.longMessage = True
    for name in expected.keys():
      self.assertDictContainsSubset(expected[name],
                                    self.site_config[name],
                                    name)

    # Special handling for child configs.

    children = self.site_config['parent'].child_configs
    self.assertEqual(len(children), 2)
    self.assertDictContainsSubset(
        {
            '_template': None,
            'name': 'default',
            'value': 'default',
            'grouped': True,
        },
        children[0])

    self.assertDictContainsSubset(
        {
            '_template': None,
            'name': 'default_with_override',
            'value': 'override',
            'grouped': True,
        },
        children[1])

  def testAddErrors(self):
    """Test the SiteConfig.Add behavior."""
    self.site_config.Add('foo')

    # Test we can't add the 'foo' config again.
    with self.assertRaises(AssertionError):
      self.site_config.Add('foo')

    # Create a template without using AddTemplate so the site config doesn't
    # know about it.
    fake_template = config_lib.BuildConfig(
        name='fake_template', _template='fake_template')

    with self.assertRaises(AssertionError):
      self.site_config.Add('bar', fake_template)

  def testTemplateAttr(self):
    """Test the SiteConfig.templates.name behavior."""
    template1 = self.site_config.AddTemplate('template1', value='template')
    template2 = self.site_config.AddTemplate('template2', value='template')

    self.assertIs(template1, self.site_config.templates.template1)
    self.assertIs(template2, self.site_config.templates.template2)

    # Try to fetch a non-existent template.
    with self.assertRaises(AttributeError):
      _ = self.site_config.templates.no_such_template

  def testAddForBoards(self):
    per_board = {
        'foo': config_lib.BuildConfig(value='foo'),
        'bar': config_lib.BuildConfig(value='bar'),
        'multiboard': config_lib.BuildConfig(boards=['foo', 'bar']),
    }

    # Test the minimal invocation.
    self.site_config.AddForBoards(
        'minimal',
        ['foo', 'bar'],
    )

    self.assertIn('foo-minimal', self.site_config)
    self.assertEqual(self.site_config['foo-minimal'].boards, ['foo'])
    self.assertEqual(self.site_config['bar-minimal'].boards, ['bar'])

    # Test a partial set of per-board values specified.
    self.site_config.AddForBoards(
        'partial_per_board',
        ['foo', 'no_per'],
        per_board,
    )

    self.assertIn('foo-partial_per_board', self.site_config)
    self.assertIn('no_per-partial_per_board', self.site_config)
    self.assertEqual(self.site_config['foo-partial_per_board'].value, 'foo')

    # Test all boards with per_board values specified, and test we can
    # override board listing in per_board values.
    self.site_config.AddForBoards(
        'per_board',
        ['foo', 'bar', 'multiboard'],
        per_board,
    )

    self.assertEqual(self.site_config['foo-per_board'].value, 'foo')
    self.assertEqual(self.site_config['bar-per_board'].value, 'bar')
    self.assertEqual(self.site_config['multiboard-per_board'].boards,
                     ['foo', 'bar'])

    # Test using a template
    self.site_config.AddForBoards(
        'template',
        ['foo', 'bar'],
        None,
        self.site_config.templates.template,
    )

    self.assertEqual(self.site_config['foo-template'].value, 'template')

    # Test a template, and a mixin.
    self.site_config.AddForBoards(
        'mixin',
        ['foo', 'bar'],
        None,
        self.site_config.templates.template,
        self.site_config.templates.mixin,
    )

    self.assertEqual(self.site_config['foo-mixin'].value, 'mixin')

    # Test a template, and a mixin, and a per-board.
    self.site_config.AddForBoards(
        'mixin_per_board',
        ['foo', 'bar'],
        per_board,
        self.site_config.templates.template,
        self.site_config.templates.mixin,
    )

    self.assertEqual(self.site_config['foo-mixin_per_board'].value, 'foo')

    # Test a template, and a mixin, and a per-board, and an override.
    self.site_config.AddForBoards(
        'override',
        ['foo', 'bar'],
        per_board,
        self.site_config.templates.template,
        self.site_config.templates.mixin,
        value='override',
    )

    self.assertEqual(self.site_config['foo-override'].value, 'override')

  def _verifyLoadSave(self, site_config):
    """Make sure that we can save and re-load a site."""
    config_str = site_config.SaveConfigToString()
    loaded = config_lib.LoadConfigFromString(config_str)

    #
    # BUG ALERT ON TEST FAILURE
    #
    # assertDictEqual can correctly compare these structs for equivalence, but
    # has a bug when displaying differences on failure. The embedded
    # HWTestConfig values are correctly compared, but ALWAYS display as
    # different, if something else triggers a failure.
    #

    # This for loop is to make differences easier to find/read.
    self.longMessage = True
    for name in site_config.iterkeys():
      self.assertDictEqual(loaded[name], site_config[name], name)

    # This includes templates and the default build config.
    self.assertEqual(site_config, loaded)

    loaded_str = loaded.SaveConfigToString()

    self.assertEqual(config_str, loaded_str)

    # Cycle through save load again, just for completeness.
    loaded2 = config_lib.LoadConfigFromString(loaded_str)
    loaded2_str = loaded2.SaveConfigToString()
    self.assertEqual(loaded_str, loaded2_str)

    # Make sure we can dump long content without crashing.
    self.assertNotEqual(site_config.DumpExpandedConfigToString(), '')
    self.assertNotEqual(loaded.DumpExpandedConfigToString(), '')

    return loaded

  def testSaveLoadEmpty(self):
    """Create, save, and reload an empty config."""
    site_config = config_lib.SiteConfig()

    loaded = self._verifyLoadSave(site_config)

    self.assertEqual(loaded.keys(), [])
    self.assertEqual(loaded._templates.keys(), [])
    self.assertDictEqual(
        loaded.GetDefault(), config_lib.DefaultSettings())
    self.assertDictEqual(
        loaded.params, config_lib.DefaultSiteParameters())

  def testSaveLoadComplex(self):
    """Create, save, and reload an complex config."""
    # Verify it.
    loaded = self._verifyLoadSave(self.site_config)

    # Verify default build config
    expected_defaults = config_lib.DefaultSettings()
    expected_defaults.update(self.complex_defaults)
    self.assertDictEqual(loaded.GetDefault(), expected_defaults)

    # Verify Site Params.
    expected_site_params = config_lib.DefaultSiteParameters()
    expected_site_params.update(self.complex_site_params)
    self.assertDictEqual(loaded.params, expected_site_params)

    # Ensure that expected templates are present.
    self.assertItemsEqual(loaded.templates.keys(), ['template', 'callable'])

  def testTemplatesToSave(self):
    def _invert(x):
      return not x

    config = config_lib.SiteConfig()
    config.AddTemplate('base', foo=True, important=False)
    config.AddTemplate('callable', important=_invert)
    config.AddTemplate('unused', bar=True)
    config.Add('build1', config.templates.base, var=1)
    config.Add('build2', var=2)
    config.Add('build3', config.templates.base, var=3)
    config.Add('build4', config.templates.callable, var=4)

    self.assertItemsEqual(
        config.templates,
        {
            'base': {'_template': 'base', 'foo': True, 'important': False},
            'callable': {'_template': 'callable', 'important': _invert},
            'unused': {'_template': 'unused', 'bar': True},
        }
    )

    results = config._MarshalTemplates()

    self.assertItemsEqual(
        results,
        {
            'base': {'_template': 'base', 'foo': True},
            'callable': {'_template': 'callable', 'important': True},
        }
    )


class SiteConfigFindTests(cros_test_lib.TestCase):
  """Tests related to Find helpers on SiteConfig."""

  def testGetBoardsMockConfig(self):
    site_config = MockSiteConfig()
    self.assertEqual(
        site_config.GetBoards(),
        set(['x86-generic']))

  def testGetBoardsComplexConfig(self):
    site_config = MockSiteConfig()
    site_config.Add('build_a', boards=['foo_board'])
    site_config.Add('build_b', boards=['bar_board'])
    site_config.Add('build_c', boards=['foo_board', 'car_board'])

    self.assertEqual(
        site_config.GetBoards(),
        set(['x86-generic', 'foo_board', 'bar_board', 'car_board']))

  def testGetSlaveConfigMapForMasterAll(self):
    """Test GetSlaveConfigMapForMaster, GetSlavesForMaster all slaves."""

    site_config = MockSiteConfig()
    master = site_config.Add('master', master=True, manifest_version=True,
                             slave_configs=['slave_a', 'slave_b'])
    slave_a = site_config.Add('slave_a', important=True)
    slave_b = site_config.Add('slave_b', important=False)
    site_config.Add('other')

    results_map = site_config.GetSlaveConfigMapForMaster(master,
                                                         important_only=False)
    results_slaves = site_config.GetSlavesForMaster(master,
                                                    important_only=False)

    self.assertEqual(results_map, {'slave_a': slave_a, 'slave_b': slave_b})
    self.assertItemsEqual(results_slaves, [slave_a, slave_b])

  def testGetSlaveConfigMapForMasterImportant(self):
    """Test GetSlaveConfigMapForMaster, GetSlavesForMaster important only."""

    site_config = MockSiteConfig()
    master = site_config.Add('master', master=True, manifest_version=True,
                             slave_configs=['slave_a', 'slave_b'])
    slave_a = site_config.Add('slave_a', important=True)
    site_config.Add('slave_b', important=False)
    site_config.Add('other')

    results_map = site_config.GetSlaveConfigMapForMaster(master)
    results_slaves = site_config.GetSlavesForMaster(master)

    self.assertEqual(results_map, {'slave_a': slave_a})
    self.assertItemsEqual(results_slaves, [slave_a])


class OverrideForTrybotTest(cros_test_lib.TestCase):
  """Test config override functionality."""

  # TODO(dgarrett): Test other override behaviors.

  def setUp(self):
    self.base_vmtests = [config_lib.VMTestConfig('base')]
    self.override_vmtests = [config_lib.VMTestConfig('override')]
    self.base_hwtests = [config_lib.HWTestConfig('base')]
    self.override_hwtests = [config_lib.HWTestConfig('override')]

    self.all_configs = MockSiteConfig()
    self.all_configs.Add(
        'no_tests_without_override',
        vm_tests=[],
    )
    self.all_configs.Add(
        'no_tests_with_override',
        vm_tests=[],
        vm_tests_override=self.override_vmtests,
        hw_tests_override=self.override_hwtests,
    )
    self.all_configs.Add(
        'tests_without_override',
        vm_tests=self.base_vmtests,
        hw_tests=self.base_hwtests,
    )
    self.all_configs.Add(
        'tests_with_override',
        vm_tests=self.base_vmtests,
        vm_tests_override=self.override_vmtests,
        hw_tests=self.base_hwtests,
        hw_tests_override=self.override_hwtests,
    )

  def _createMockOptions(self, **kwargs):
    mock_options = mock.Mock()
    for k, v in kwargs.iteritems():
      mock_options.__setattr__(k, v)

    return mock_options

  def testVmTestOverride(self):
    """Verify that vm_tests override for trybots pay heed to original config."""
    mock_options = self._createMockOptions(hwtest=False, remote_trybot=False)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['no_tests_without_override'], mock_options)
    self.assertEqual(result.vm_tests, [])

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['no_tests_with_override'], mock_options)
    self.assertEqual(result.vm_tests, self.override_vmtests)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['tests_without_override'], mock_options)
    self.assertEqual(result.vm_tests, self.base_vmtests)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['tests_with_override'], mock_options)
    self.assertEqual(result.vm_tests, self.override_vmtests)

  def testHwTestOverrideDisabled(self):
    """Verify that hw_tests_override is not used without --hwtest."""
    mock_options = self._createMockOptions(hwtest=False, remote_trybot=False)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['no_tests_without_override'], mock_options)
    self.assertEqual(result.hw_tests, [])

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['no_tests_with_override'], mock_options)
    self.assertEqual(result.hw_tests, [])

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['tests_without_override'], mock_options)
    self.assertEqual(result.hw_tests, self.base_hwtests)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['tests_with_override'], mock_options)
    self.assertEqual(result.hw_tests, self.base_hwtests)

  def testHwTestOverrideEnabled(self):
    """Verify that hw_tests_override is not used without --hwtest."""
    mock_options = self._createMockOptions(hwtest=True, remote_trybot=False)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['no_tests_without_override'], mock_options)
    self.assertEqual(result.hw_tests, [])

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['no_tests_with_override'], mock_options)
    self.assertEqual(result.hw_tests, self.override_hwtests)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['tests_without_override'], mock_options)
    self.assertEqual(result.hw_tests, self.base_hwtests)

    result = config_lib.OverrideConfigForTrybot(
        self.all_configs['tests_with_override'], mock_options)
    self.assertEqual(result.hw_tests, self.override_hwtests)


class GetConfigTests(cros_test_lib.TestCase):
  """Tests related to SiteConfig.GetConfig()."""

  def testGetConfigCaching(self):
    """Test that config_lib.GetConfig() caches it's results correctly."""
    config_a = config_lib.GetConfig()
    config_b = config_lib.GetConfig()

    # Ensure that we get a SiteConfig, and that the result is cached.
    self.assertIsInstance(config_a, config_lib.SiteConfig)
    self.assertIs(config_a, config_b)

    # Clear our cache.
    config_lib.ClearConfigCache()
    config_c = config_lib.GetConfig()
    config_d = config_lib.GetConfig()

    # Ensure that this gives us a new instance of the SiteConfig.
    self.assertIsNot(config_a, config_c)

    # But also that it's cached going forward.
    self.assertIsInstance(config_c, config_lib.SiteConfig)
    self.assertIs(config_c, config_d)

class ConfigLibHelperTests(cros_test_lib.TestCase):
  """Tests related to helper methods in config_lib."""

  def testUseBuildbucketScheduler(self):
    """Test UseBuildbucketScheduler."""
    cq_master_config = config_lib.BuildConfig(
        name=constants.CQ_MASTER,
        active_waterfall=constants.WATERFALL_INTERNAL)
    self.assertTrue(config_lib.UseBuildbucketScheduler(
        cq_master_config))

    pre_cq_config = config_lib.BuildConfig(
        name=constants.PRE_CQ_LAUNCHER_NAME,
        active_waterfall=constants.WATERFALL_INTERNAL)
    self.assertTrue(config_lib.UseBuildbucketScheduler(
        pre_cq_config))

    pfq_master_config = config_lib.BuildConfig(
        name=constants.PFQ_MASTER,
        active_waterfall=constants.WATERFALL_INTERNAL)
    self.assertTrue(config_lib.UseBuildbucketScheduler(
        pfq_master_config))

    toolchain_master = config_lib.BuildConfig(
        name=constants.TOOLCHAIN_MASTTER,
        active_waterfall=constants.WATERFALL_INTERNAL)
    self.assertTrue(config_lib.UseBuildbucketScheduler(
        toolchain_master))

    pre_cq_config = config_lib.BuildConfig(
        name=constants.BINHOST_PRE_CQ,
        active_waterfall=constants.WATERFALL_TRYBOT)
    self.assertFalse(config_lib.UseBuildbucketScheduler(
        pre_cq_config))

    release_branch_config = config_lib.BuildConfig(
        name=constants.CANARY_MASTER,
        active_waterfall=constants.WATERFALL_RELEASE)
    self.assertFalse(config_lib.UseBuildbucketScheduler(
        release_branch_config))

  def testScheduledByBuildbucket(self):
    """Test ScheduledByBuildbucket."""
    cq_master_config = config_lib.BuildConfig(
        name=constants.CQ_MASTER,
        build_type=constants.PALADIN_TYPE)
    self.assertFalse(config_lib.ScheduledByBuildbucket(
        cq_master_config))

    cq_slave_config = config_lib.BuildConfig(
        name='slave-paladin',
        build_type=constants.PALADIN_TYPE)
    self.assertTrue(config_lib.ScheduledByBuildbucket(
        cq_slave_config))

    pfq_master_config = config_lib.BuildConfig(
        name=constants.PFQ_MASTER,
        build_type=constants.PFQ_TYPE)

    self.assertFalse(config_lib.ScheduledByBuildbucket(
        pfq_master_config))

class GEBuildConfigTests(cros_test_lib.TestCase):
  """Test GE build config related methods."""

  def testGetArchBoardDict(self):
    """Test GetArchBoardDict."""
    ge_build_config = config_lib.LoadGEBuildConfigFromFile()
    arch_board_dict = config_lib.GetArchBoardDict(ge_build_config)
    self.assertIsNotNone(arch_board_dict)
