# -*- coding: utf-8 -*-
# Copyright 2016 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.

"""Unit tests for config stages"""

from __future__ import print_function

import os

import mock
from six.moves import builtins

from chromite.cbuildbot import repository
from chromite.cbuildbot.stages import config_stages
from chromite.cbuildbot.stages import generic_stages_unittest
from chromite.cbuildbot.stages import test_stages
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import git
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib.buildstore import FakeBuildStore

# pylint: disable=protected-access


class CheckTemplateStageTest(generic_stages_unittest.AbstractStageTestCase):
  """Tests for CheckTemplateStage."""

  TOT_PATH = (config_stages.GS_GE_TEMPLATE_BUCKET + 'build_config.ToT.json')
  R52_PATH = (
      config_stages.GS_GE_TEMPLATE_BUCKET +
      'build_config.release-R52-7978.B.json')
  R53_PATH = (
      config_stages.GS_GE_TEMPLATE_BUCKET +
      'build_config.release-R53-7978.B.json')
  R54_PATH = (
      config_stages.GS_GE_TEMPLATE_BUCKET +
      'build_config.release-R54-7978.B.json')

  def setUp(self):
    self._Prepare()
    self.PatchObject(repository, 'CloneWorkingRepo')
    self.PatchObject(gs, 'GSContext')
    self.update_mock = self.PatchObject(config_stages.UpdateConfigStage, 'Run')
    self.buildstore = FakeBuildStore()

  def ConstructStage(self):
    return config_stages.CheckTemplateStage(self._run, self.buildstore)

  def testListTemplates(self):
    """Test _ListTemplates."""
    self.PatchObject(
        config_stages.CheckTemplateStage,
        'SortAndGetReleasePaths',
        return_value=['R_template.json'])
    stage = self.ConstructStage()
    stage.ctx = mock.Mock()
    stage.ctx.LS.return_value = ['template.json']

    gs_paths = stage._ListTemplates()
    self.assertCountEqual(gs_paths, ['R_template.json', 'template.json'])

  def test_ListTemplatesWithNoSuchKeyError(self):
    """Test _ListTemplates with NoSuchKeyError."""
    stage = self.ConstructStage()
    stage.ctx = mock.Mock()
    stage.ctx.LS.side_effect = gs.GSNoSuchKey()

    gs_paths = stage._ListTemplates()
    self.assertEqual(gs_paths, [])

  def testBasicPerformStage(self):
    """Test basic PerformStage."""
    self.PatchObject(
        config_stages.CheckTemplateStage,
        '_ListTemplates',
        return_value=[self.TOT_PATH, self.R54_PATH])
    stage = self.ConstructStage()

    stage.PerformStage()
    self.assertEqual(self.update_mock.call_count, 2)

  def testSortAndGetReleasePaths(self):
    """Test SortAndGetReleasePaths."""
    stage = self.ConstructStage()

    paths = stage.SortAndGetReleasePaths(
        [self.R54_PATH, self.R53_PATH, self.R52_PATH])
    self.assertTrue(len(paths) == 1)
    self.assertEqual(paths[0], self.R54_PATH)


class UpdateConfigStageTest(generic_stages_unittest.AbstractStageTestCase):
  """Tests for UpdateConfigStage."""

  def setUp(self):
    self._Prepare()
    self.PatchObject(config_stages.UpdateConfigStage, '_DownloadTemplate')
    self.PatchObject(config_stages.UpdateConfigStage, '_CheckoutBranch')
    self.PatchObject(config_stages.UpdateConfigStage, '_RunUnitTest')
    self.PatchObject(git, 'PushBranch')
    self.PatchObject(git, 'RunGit')
    self.PatchObject(repository, 'CloneWorkingRepo')
    self.PatchObject(cros_build_lib, 'run')

    self.project = 'chromite'
    self.chromite_dir = config_stages.GetProjectRepoDir('chromite',
                                                        constants.CHROMITE_URL)
    self.buildstore = FakeBuildStore()

  def tearDown(self):
    osutils.RmDir(self.chromite_dir, ignore_missing=True)

  # pylint: disable=arguments-differ
  def ConstructStage(self, template, new_config=True):
    template_path = config_stages.GS_GE_TEMPLATE_BUCKET + template
    branch = config_stages.GetBranchName(template)
    stage = config_stages.UpdateConfigStage(self._run, self.buildstore,
                                            template_path, branch,
                                            self.chromite_dir, True)

    if new_config:
      fake_config_path = os.path.join(self.chromite_dir, 'config',
                                      config_stages.GE_BUILD_CONFIG_FILE)
    else:
      fake_config_path = os.path.join(self.chromite_dir, 'cbuildbot',
                                      config_stages.GE_BUILD_CONFIG_FILE)

    osutils.Touch(fake_config_path, makedirs=True)

    stage._SetupConfigPaths()
    return stage

  def testSetupConfigPathsOld(self):
    """Test _CreateConfigPatch."""
    template = 'build_config.ToT.json'
    stage = self.ConstructStage(template, new_config=False)

    expected = [
        os.path.join(self.chromite_dir, 'cbuildbot/ge_build_config.json'),
        os.path.join(self.chromite_dir, 'cbuildbot/config_dump.json'),
        os.path.join(self.chromite_dir, 'cbuildbot/waterfall_layout_dump.txt'),
    ]

    self.assertEqual(stage.config_paths, expected)
    self.assertEqual(stage.ge_config_local_path, expected[0])

  def testSetupConfigPathsNew(self):
    """Test _CreateConfigPatch."""
    template = 'build_config.ToT.json'
    stage = self.ConstructStage(template, new_config=True)

    expected = [
        os.path.join(self.chromite_dir, 'config/ge_build_config.json'),
        os.path.join(self.chromite_dir, 'config/config_dump.json'),
        os.path.join(self.chromite_dir, 'config/waterfall_layout_dump.txt'),
    ]

    self.assertEqual(stage.config_paths, expected)
    self.assertEqual(stage.ge_config_local_path, expected[0])

  def testCreateConfigPatch(self):
    """Test _CreateConfigPatch."""
    template = 'build_config.ToT.json'
    stage = self.ConstructStage(template)

    with mock.patch.object(builtins, 'open'):
      config_change_patch = stage._CreateConfigPatch()
      self.assertEqual(
          os.path.basename(config_change_patch), 'config_change.patch')

  def testCreateConfigPatchOldPath(self):
    """Test _CreateConfigPatch."""
    template = 'build_config.ToT.json'
    stage = self.ConstructStage(template, new_config=False)

    with mock.patch.object(builtins, 'open'):
      config_change_patch = stage._CreateConfigPatch()
      self.assertEqual(
          os.path.basename(config_change_patch), 'config_change.patch')

  def testRunBinhostTest(self):
    """Test RunBinhostTest."""
    self.PatchObject(
        config_stages.UpdateConfigStage,
        '_CreateConfigPatch',
        return_value='patch')
    mock_binhost_run = self.PatchObject(test_stages.BinhostTestStage, 'Run')
    mock_run_git = self.PatchObject(git, 'RunGit')
    template = 'build_config.ToT.json'
    stage = self.ConstructStage(template)

    stage._RunBinhostTest()
    self.assertEqual(mock_run_git.call_count, 2)
    mock_binhost_run.assert_called_once_with()

  def testMasterBasic(self):
    """Basic test on master branch."""
    mock_binhost_test = self.PatchObject(config_stages.UpdateConfigStage,
                                         '_RunBinhostTest')
    template = 'build_config.ToT.json'
    stage = self.ConstructStage(template)
    stage.PerformStage()
    self.assertTrue(stage.branch == 'master')
    mock_binhost_test.assert_called_once_with()

  def testReleaseBasic(self):
    """Basic test on release branch."""
    template = 'build_config.release-R50-7978.B.json'
    mock_binhost_test = self.PatchObject(config_stages.UpdateConfigStage,
                                         '_RunBinhostTest')
    stage = self.ConstructStage(template)
    stage.PerformStage()
    self.assertTrue(stage.branch == 'release-R50-7978.B')
    mock_binhost_test.assert_not_called()
