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

"""Test the archive_lib module."""

from __future__ import print_function

import mock

from chromite.cbuildbot import archive_lib
from chromite.cbuildbot import cbuildbot_config
from chromite.cbuildbot import cbuildbot_run
from chromite.lib import cros_test_lib
from chromite.lib import parallel_unittest


DEFAULT_ARCHIVE_PREFIX = 'bogus_bucket/TheArchiveBase'
DEFAULT_ARCHIVE_BASE = 'gs://%s' % DEFAULT_ARCHIVE_PREFIX
DEFAULT_BUILDROOT = '/tmp/foo/bar/buildroot'
DEFAULT_BUILDNUMBER = 12345
DEFAULT_BRANCH = 'TheBranch'
DEFAULT_CHROME_BRANCH = 'TheChromeBranch'
DEFAULT_VERSION_STRING = 'TheVersionString'
DEFAULT_BOARD = 'TheBoard'
DEFAULT_BOT_NAME = 'TheCoolBot'

# Access to protected member.
# pylint: disable=W0212

DEFAULT_OPTIONS = cros_test_lib.EasyAttr(
    archive_base=DEFAULT_ARCHIVE_BASE,
    buildroot=DEFAULT_BUILDROOT,
    buildnumber=DEFAULT_BUILDNUMBER,
    buildbot=True,
    branch=DEFAULT_BRANCH,
    remote_trybot=False,
    debug=False,
)
DEFAULT_CONFIG = cbuildbot_config._config(
    name=DEFAULT_BOT_NAME,
    master=True,
    boards=[DEFAULT_BOARD],
    child_configs=[cbuildbot_config._config(name='foo'),
                   cbuildbot_config._config(name='bar'),
                  ],
)


def _ExtendDefaultOptions(**kwargs):
  """Extend DEFAULT_OPTIONS with keys/values in kwargs."""
  options_kwargs = DEFAULT_OPTIONS.copy()
  options_kwargs.update(kwargs)
  return cros_test_lib.EasyAttr(**options_kwargs)


def _ExtendDefaultConfig(**kwargs):
  """Extend DEFAULT_CONFIG with keys/values in kwargs."""
  config_kwargs = DEFAULT_CONFIG.copy()
  config_kwargs.update(kwargs)
  return cbuildbot_config._config(**config_kwargs)


def _NewBuilderRun(options=None, config=None):
  """Create a BuilderRun objection from options and config values.

  Args:
    options: Specify options or default to DEFAULT_OPTIONS.
    config: Specify build config or default to DEFAULT_CONFIG.

  Returns:
    BuilderRun object.
  """
  manager = parallel_unittest.FakeMultiprocessManager()
  options = options or DEFAULT_OPTIONS
  config = config or DEFAULT_CONFIG
  return cbuildbot_run.BuilderRun(options, config, manager)


class GetBaseUploadURITest(cros_test_lib.TestCase):
  """Test the GetBaseUploadURI function."""

  ARCHIVE_BASE = '/tmp/the/archive/base'
  BOT_ID = 'TheNewBotId'

  def setUp(self):
    self.cfg = DEFAULT_CONFIG

  def _GetBaseUploadURI(self, *args, **kwargs):
    """Test GetBaseUploadURI with archive_base and no bot_id."""
    return archive_lib.GetBaseUploadURI(self.cfg, *args, **kwargs)

  def testArchiveBaseRemoteTrybotFalse(self):
    expected_result = '%s/%s' % (self.ARCHIVE_BASE, DEFAULT_BOT_NAME)
    result = self._GetBaseUploadURI(archive_base=self.ARCHIVE_BASE,
                                    remote_trybot=False)
    self.assertEqual(expected_result, result)

  def testArchiveBaseRemoteTrybotTrue(self):
    expected_result = '%s/trybot-%s' % (self.ARCHIVE_BASE, DEFAULT_BOT_NAME)
    result = self._GetBaseUploadURI(archive_base=self.ARCHIVE_BASE,
                                    remote_trybot=True)
    self.assertEqual(expected_result, result)

  def testArchiveBaseBotIdRemoteTrybotFalse(self):
    expected_result = '%s/%s' % (self.ARCHIVE_BASE, self.BOT_ID)
    result = self._GetBaseUploadURI(archive_base=self.ARCHIVE_BASE,
                                    bot_id=self.BOT_ID, remote_trybot=False)
    self.assertEqual(expected_result, result)

  def testArchiveBaseBotIdRemoteTrybotTrue(self):
    expected_result = '%s/%s' % (self.ARCHIVE_BASE, self.BOT_ID)
    result = self._GetBaseUploadURI(archive_base=self.ARCHIVE_BASE,
                                    bot_id=self.BOT_ID, remote_trybot=True)
    self.assertEqual(expected_result, result)

  def testRemoteTrybotTrue(self):
    """Test GetBaseUploadURI with no archive base but remote_trybot is True."""
    expected_result = ('%s/trybot-%s' %
                       (archive_lib.constants.DEFAULT_ARCHIVE_BUCKET,
                        DEFAULT_BOT_NAME))
    result = self._GetBaseUploadURI(remote_trybot=True)
    self.assertEqual(expected_result, result)

  def testBotIdRemoteTrybotTrue(self):
    expected_result = ('%s/%s' %
                       (archive_lib.constants.DEFAULT_ARCHIVE_BUCKET,
                        self.BOT_ID))
    result = self._GetBaseUploadURI(bot_id=self.BOT_ID, remote_trybot=True)
    self.assertEqual(expected_result, result)

  def testDefaultGSPathRemoteTrybotFalse(self):
    """Test GetBaseUploadURI with default gs_path value in config."""
    self.cfg = _ExtendDefaultConfig(gs_path=cbuildbot_config.GS_PATH_DEFAULT)

    # Test without bot_id.
    expected_result = ('%s/%s' %
                       (archive_lib.constants.DEFAULT_ARCHIVE_BUCKET,
                        DEFAULT_BOT_NAME))
    result = self._GetBaseUploadURI(remote_trybot=False)
    self.assertEqual(expected_result, result)

    # Test with bot_id.
    expected_result = ('%s/%s' %
                       (archive_lib.constants.DEFAULT_ARCHIVE_BUCKET,
                        self.BOT_ID))
    result = self._GetBaseUploadURI(bot_id=self.BOT_ID, remote_trybot=False)
    self.assertEqual(expected_result, result)

  def testOverrideGSPath(self):
    """Test GetBaseUploadURI with default gs_path value in config."""
    self.cfg = _ExtendDefaultConfig(gs_path='gs://funkytown/foo/bar')

    # Test without bot_id.
    expected_result = self.cfg.gs_path
    result = self._GetBaseUploadURI(remote_trybot=False)
    self.assertEqual(expected_result, result)

    # Test with bot_id.
    expected_result = self.cfg.gs_path
    result = self._GetBaseUploadURI(bot_id=self.BOT_ID, remote_trybot=False)
    self.assertEqual(expected_result, result)


class ArchiveTest(cros_test_lib.TestCase):
  """Test the Archive class."""
  _VERSION = '6543.2.1'

  def _GetAttributeValue(self, attr, options=None, config=None):
    with mock.patch.object(cbuildbot_run._BuilderRunBase, 'GetVersion') as m:
      m.return_value = self._VERSION

      run = _NewBuilderRun(options, config)
      return getattr(run.GetArchive(), attr)

  def testVersion(self):
    value = self._GetAttributeValue('version')
    self.assertEqual(self._VERSION, value)

  def testVersionNotReady(self):
    run = _NewBuilderRun()
    self.assertRaises(AttributeError, getattr, run, 'version')

  def testArchivePathTrybot(self):
    options = _ExtendDefaultOptions(buildbot=False)
    value = self._GetAttributeValue('archive_path', options=options)
    expected_value = ('%s/%s/%s/%s' %
                      (DEFAULT_BUILDROOT,
                       archive_lib.Archive._TRYBOT_ARCHIVE,
                       DEFAULT_BOT_NAME,
                       self._VERSION))
    self.assertEqual(expected_value, value)

  def testArchivePathBuildbot(self):
    value = self._GetAttributeValue('archive_path')
    expected_value = ('%s/%s/%s/%s' %
                      (DEFAULT_BUILDROOT,
                       archive_lib.Archive._BUILDBOT_ARCHIVE,
                       DEFAULT_BOT_NAME,
                       self._VERSION))
    self.assertEqual(expected_value, value)

  def testUploadUri(self):
    value = self._GetAttributeValue('upload_url')
    expected_value = '%s/%s/%s' % (DEFAULT_ARCHIVE_BASE,
                                   DEFAULT_BOT_NAME,
                                   self._VERSION)
    self.assertEqual(expected_value, value)

  def testDownloadURLBuildbot(self):
    value = self._GetAttributeValue('download_url')
    expected_value = ('%s%s/%s/%s' %
                      (archive_lib.gs.PRIVATE_BASE_HTTPS_URL,
                       DEFAULT_ARCHIVE_PREFIX,
                       DEFAULT_BOT_NAME,
                       self._VERSION))
    self.assertEqual(expected_value, value)
