# -*- coding: utf-8 -*-
# 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 json

from chromite.lib import config_lib
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['amd64-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(
      'amd64-generic-paladin',
      boards=['amd64-generic'],
      display_label='MockLabel',
      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',
      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 testAppendUseflags(self):
    base_config = config_lib.BuildConfig(useflags=[])
    inherited_config_1 = base_config.derive(
        useflags=config_lib.append_useflags(
            ['foo', 'bar', '-baz']))
    inherited_config_2 = inherited_config_1.derive(
        useflags=config_lib.append_useflags(['-bar', 'baz']))
    self.assertEqual(base_config.useflags, [])
    self.assertEqual(inherited_config_1.useflags, ['-baz', 'bar', 'foo'])
    self.assertEqual(inherited_config_2.useflags, ['-bar', 'baz', 'foo'])

  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.
    def append(x):
      return 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.
      # pylint: disable=consider-using-enumerate
      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))

  def testPickle(self):
    bc1 = MockBuildConfig()
    bc2 = cPickle.loads(cPickle.dumps(bc1))

    self.assertEquals(bc1.boards, bc2.boards)
    self.assertEquals(bc1.name, bc2.name)


class GetSiteParamsTest(cros_test_lib.TestCase):
  """Tests for the return value from config_lib.GetSiteParams()."""

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

    # Ensure our test key is not in site_params.
    self.assertNotIn('foo', site_params)

    # 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',
    }

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

    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.Add(
        'tast_vm_tests',
        tast_vm_tests=[config_lib.TastVMTestConfig('tast_vm_suite',
                                                   ['(!disabled)'])])

    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')],
        },
        'tast_vm_tests': {
            '_template': None,
            'name': 'tast_vm_tests',
            'tast_vm_tests': [
                config_lib.TastVMTestConfig('tast_vm_suite', ['(!disabled)'])],
        },
        '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):
      # pylint: disable=pointless-statement
      self.site_config.templates.no_such_template
      # pylint: enable=pointless-statement

  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.keys():
      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(), '')
    self.assertNotEqual(loaded.DumpConfigCsv(), '')

    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())

  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)

    # 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(['amd64-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(['amd64-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 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)


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

  def setUp(self):
    self._fake_ge_build_config_json = """
{
  "metadata_version": "1.0",
  "reference_board_unified_builds": [
    {
      "name": "reef",
      "reference_board_name": "reef",
      "builder": "RELEASE",
      "experimental": true,
      "arch": "X86_INTERNAL",
      "models" : [
        {
          "board_name": "reef"
        },
        {
          "board_name": "pyro"
        }
      ]
    }
  ],
  "boards": [
    {
      "name": "reef",
      "configs": [
        {
          "builder": "RELEASE",
          "experimental": false,
          "leader_board": true,
          "board_group": "reef",
          "arch": "X86_INTERNAL"
        }
      ]
    }
  ]
}
    """
    self._fake_ge_build_config = json.loads(self._fake_ge_build_config_json)

  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)

  def testGetArchBoardDictUnifiedBuilds(self):
    """Test GetArchBoardDict."""
    arch_board_dict = config_lib.GetArchBoardDict(self._fake_ge_build_config)
    self.assertIsNotNone(arch_board_dict)
    self.assertIs(1, len(arch_board_dict[config_lib.CONFIG_X86_INTERNAL]))

  def testGetUnifiedBuildConfigAllBuilds(self):
    uni_builds = config_lib.GetUnifiedBuildConfigAllBuilds(
        self._fake_ge_build_config)
    self.assertEquals(1, len(uni_builds))

  def testGetUnifiedBuildConfigAllBuildsWithNoBuilds(self):
    uni_builds = config_lib.GetUnifiedBuildConfigAllBuilds({})
    self.assertEquals(0, len(uni_builds))
