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

"""Module containing the unit tests for handle_changes_stages."""

from __future__ import print_function

import itertools
import mock

from chromite.cbuildbot import relevant_changes
from chromite.cbuildbot.stages import handle_changes_stages
from chromite.cbuildbot.stages import generic_stages
from chromite.cbuildbot.stages import generic_stages_unittest
from chromite.cbuildbot.stages import sync_stages
from chromite.lib import builder_status_lib
from chromite.lib import cidb
from chromite.lib import clactions
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import fake_cidb
from chromite.lib import hwtest_results
from chromite.lib import timeout_util
from chromite.lib import tree_status
from chromite.lib.buildstore import FakeBuildStore


# pylint: disable=protected-access


class CommitQueueHandleChangesStageTests(
    generic_stages_unittest.AbstractStageTestCase):
  """Tests for CommitQueueHandleChangesStag."""

  BOT_ID = 'master-paladin'

  def setUp(self):
    self._Prepare()
    self.buildstore = FakeBuildStore()

    self.partial_submit_changes = ['A', 'B']
    self.other_changes = ['C', 'D']
    self.changes = self.other_changes + self.partial_submit_changes
    self.PatchObject(builder_status_lib, 'GetFailedMessages')
    self.PatchObject(relevant_changes.RelevantChanges,
                     '_GetSlaveMappingAndCLActions',
                     return_value=(dict(), []))
    self.PatchObject(clactions, 'GetRelevantChangesForBuilds')
    self.PatchObject(tree_status, 'WaitForTreeStatus',
                     return_value=constants.TREE_OPEN)
    self.PatchObject(relevant_changes.RelevantChanges,
                     'GetPreviouslyPassedSlavesForChanges')
    self.mock_record_metrics = self.PatchObject(
        handle_changes_stages.CommitQueueHandleChangesStage,
        '_RecordSubmissionMetrics')

    self.sync_stage = self._MockSyncStage()
    self.completion_stage = mock.Mock()

  def tearDown(self):
    cidb.CIDBConnectionFactory.ClearMock()

  def _MockSyncStage(self, tree_was_open=True):
    sync_stage = sync_stages.CommitQueueSyncStage(self._run, self.buildstore)
    sync_stage.pool = mock.MagicMock()
    sync_stage.pool.applied = self.changes
    sync_stage.pool.tree_was_open = tree_was_open

    sync_stage.pool.handle_failure_mock = self.PatchObject(
        sync_stage.pool, 'HandleValidationFailure')
    sync_stage.pool.handle_timeout_mock = self.PatchObject(
        sync_stage.pool, 'HandleValidationTimeout')
    sync_stage.pool.submit_pool_mock = self.PatchObject(
        sync_stage.pool, 'SubmitPool')

    return sync_stage

  # pylint: disable=arguments-differ
  def ConstructStage(self, sync_stage=None, completion_stage=None):
    sync_stage = sync_stage or self.sync_stage
    completion_stage = completion_stage or self.completion_stage
    return handle_changes_stages.CommitQueueHandleChangesStage(
        self._run, self.buildstore, sync_stage, completion_stage)

  def test_GetBuildsPassedSyncStage(self):
    """Test _GetBuildsPassedSyncStage."""
    stage = self.ConstructStage()
    mock_cidb = mock.Mock()
    mock_cidb.GetBuildStatusesWithBuildbucketIds.return_value = []
    mock_cidb.GetBuildsStages.return_value = [
        {'build_config': 's_1', 'status': 'pass', 'name': 'CommitQueueSync'},
        {'build_config': 's_2', 'status': 'pass', 'name': 'CommitQueueSync'},
        {'build_config': 's_3', 'status': 'fail', 'name': 'CommitQueueSync'}]
    mock_cidb.GetBuildStages.return_value = [
        {'status': 'pass', 'name': 'CommitQueueSync'}]

    builds = stage._GetBuildsPassedSyncStage(
        'build_id', mock_cidb, ['id_1', 'id_2'])
    self.assertItemsEqual(builds, ['s_1', 's_2', 'master-paladin'])

  def _MockPartialSubmit(self, stage):
    self.PatchObject(relevant_changes.RelevantChanges,
                     'GetRelevantChangesForSlaves',
                     return_value={'master-paladin': {mock.Mock()}})
    self.PatchObject(handle_changes_stages.CommitQueueHandleChangesStage,
                     '_GetBuildsPassedSyncStage')
    stage.sync_stage.pool.SubmitPartialPool.return_value = self.changes

  def testHandleCommitQueueFailureWithOpenTree(self):
    """Test _HandleCommitQueueFailure with open tree."""
    stage = self.ConstructStage()
    self._MockPartialSubmit(stage)
    self.PatchObject(tree_status, 'WaitForTreeStatus',
                     return_value=constants.TREE_OPEN)
    self.PatchObject(generic_stages.BuilderStage,
                     'GetScheduledSlaveBuildbucketIds', return_value=[])

    stage._HandleCommitQueueFailure(set(['test1']), set(), set(), False)
    stage.sync_stage.pool.handle_failure_mock.assert_called_once_with(
        mock.ANY, sanity=True, no_stat=set(), changes=self.changes,
        failed_hwtests=None)

  def testHandleCommitQueueFailureWithThrottledTree(self):
    """Test _HandleCommitQueueFailure with throttled tree."""
    stage = self.ConstructStage()
    self._MockPartialSubmit(stage)
    self.PatchObject(tree_status, 'WaitForTreeStatus',
                     return_value=constants.TREE_THROTTLED)
    self.PatchObject(generic_stages.BuilderStage,
                     'GetScheduledSlaveBuildbucketIds', return_value=[])

    stage._HandleCommitQueueFailure(set(['test1']), set(), set(), False)
    stage.sync_stage.pool.handle_failure_mock.assert_called_once_with(
        mock.ANY, sanity=False, no_stat=set(), changes=self.changes,
        failed_hwtests=None)

  def testHandleCommitQueueFailureWithClosedTree(self):
    """Test _HandleCommitQueueFailure with closed tree."""
    stage = self.ConstructStage()
    self._MockPartialSubmit(stage)
    self.PatchObject(tree_status, 'WaitForTreeStatus',
                     side_effect=timeout_util.TimeoutError())
    self.PatchObject(generic_stages.BuilderStage,
                     'GetScheduledSlaveBuildbucketIds', return_value=[])

    stage._HandleCommitQueueFailure(set(['test1']), set(), set(), False)
    stage.sync_stage.pool.handle_failure_mock.assert_called_once_with(
        mock.ANY, sanity=False, no_stat=set(), changes=self.changes,
        failed_hwtests=None)

  def testHandleCommitQueueFailureWithFailedHWtests(self):
    """Test _HandleCommitQueueFailure with failed HWtests."""
    stage = self.ConstructStage()
    self._MockPartialSubmit(stage)
    master_build_id = stage._run.attrs.metadata.GetValue('build_id')
    db = fake_cidb.FakeCIDBConnection()
    slave_build_id = db.InsertBuild(
        'slave_1', 1, 'slave_1', 'bot_hostname',
        master_build_id=master_build_id, buildbucket_id='123')
    cidb.CIDBConnectionFactory.SetupMockCidb(db)
    mock_failed_hwtests = mock.Mock()
    mock_get_hwtests = self.PatchObject(
        hwtest_results.HWTestResultManager,
        'GetFailedHWTestsFromCIDB', return_value=mock_failed_hwtests)
    self.PatchObject(tree_status, 'WaitForTreeStatus',
                     return_value=constants.TREE_OPEN)
    self.PatchObject(generic_stages.BuilderStage,
                     'GetScheduledSlaveBuildbucketIds', return_value=['123'])

    stage._HandleCommitQueueFailure(set(['test1']), set(), set(), False)
    stage.sync_stage.pool.handle_failure_mock.assert_called_once_with(
        mock.ANY, sanity=True, no_stat=set(), changes=self.changes,
        failed_hwtests=mock_failed_hwtests)
    mock_get_hwtests.assert_called_once_with(db, [slave_build_id])

  def VerifyStage(self, failing, inflight, no_stat, handle_failure=False,
                  handle_timeout=False, sane_tot=True, stage=None,
                  all_slaves=None, slave_stages=None, fatal=True,
                  self_destructed=False):
    """Runs and Verifies PerformStage.

    Args:
      failing: The names of the builders that failed.
      inflight: The names of the buiders that timed out.
      no_stat: The names of the builders that had no status.
      handle_failure: If True, calls HandleValidationFailure.
      handle_timeout: If True, calls HandleValidationTimeout.
      sane_tot: If not true, assumes TOT is not sane.
      stage: If set, use this constructed stage, otherwise create own.
      all_slaves: Optional set of all slave configs.
      slave_stages: Optional list of slave stages.
      fatal: Optional boolean indicating whether the completion_stage failed
        with fatal. Default to True.
      self_destructed: Optional boolean indicating whether the completion_stage
        self_destructed. Default to False.
    """
    if not stage:
      stage = self.ConstructStage()

    stage._run.attrs.metadata.UpdateWithDict(
        {constants.SELF_DESTRUCTED_BUILD: self_destructed})

    # Setup the stage to look at the specified configs.
    all_slaves = list(all_slaves or set(failing + inflight + no_stat))
    all_started_slaves = list(all_slaves or set(failing + inflight))
    configs = [config_lib.BuildConfig(name=x) for x in all_slaves]
    self.PatchObject(stage, '_GetSlaveConfigs', return_value=configs)

    statuses = {}
    for x in failing:
      statuses[x] = builder_status_lib.BuilderStatus(
          constants.BUILDER_STATUS_FAILED, message=None)
    for x in inflight:
      statuses[x] = builder_status_lib.BuilderStatus(
          constants.BUILDER_STATUS_INFLIGHT, message=None)
    for x in no_stat:
      statuses[x] = builder_status_lib.BuilderStatus(
          constants.BUILDER_STATUS_MISSING, message=None)
    self.completion_stage.GetSlaveStatuses.return_value = statuses
    self.completion_stage.GetFatal.return_value = fatal

    # Setup DB and provide list of slave stages.
    mock_cidb = mock.MagicMock()
    cidb.CIDBConnectionFactory.SetupMockCidb(mock_cidb)
    if slave_stages is None:
      slave_stages = []
      critical_stages = (
          relevant_changes.TriageRelevantChanges.STAGE_SYNC)
      for stage_name, slave in itertools.product(
          critical_stages, all_started_slaves):
        slave_stages.append({'name': stage_name,
                             'build_config': slave,
                             'status': constants.BUILDER_STATUS_PASSED})
    self.PatchObject(self.buildstore, 'GetBuildStatuses', return_value=[])
    self.PatchObject(mock_cidb, 'GetBuildsStages', return_value=slave_stages)

    # Set up SubmitPartialPool to provide a list of changes to look at.
    self.PatchObject(stage.sync_stage.pool, 'SubmitPartialPool',
                     return_value=self.other_changes)

    # Actually run the stage.
    stage.PerformStage()

    if fatal:
      stage.sync_stage.pool.submit_pool_mock.assert_not_called()
      self.mock_record_metrics.assert_called_once_with(False)
    else:
      stage.sync_stage.pool.submit_pool_mock.assert_called_once_with(
          reason=constants.STRATEGY_CQ_SUCCESS)
      self.mock_record_metrics.assert_called_once_with(True)

    if handle_failure:
      stage.sync_stage.pool.handle_failure_mock.assert_called_once_with(
          mock.ANY, no_stat=set(no_stat), sanity=sane_tot,
          changes=self.other_changes, failed_hwtests=mock.ANY)

    if handle_timeout:
      stage.sync_stage.pool.handle_timeout_mock.assert_called_once_with(
          sanity=mock.ANY, changes=self.other_changes)

  def testCompletionSuccess(self):
    """Verify stage when the completion_stage succeeded."""
    self.VerifyStage([], [], [], fatal=False)

  def testCompletionWithInflightSlaves(self):
    """Verify stage when the completion_stage failed with inflight slaves."""
    self.VerifyStage([], ['foo'], [], handle_timeout=True)

  def testCompletionSelfDestructedWithInflightSlaves(self):
    """Verify stage when the completion_stage self_destructed with inflight."""
    self.VerifyStage([], ['foo'], [], self_destructed=True, handle_failure=True)

  def testCompletionSelfDestructedWithFailingSlaves(self):
    """Verify stage when the completion_stage self_destructed with failing."""
    self.VerifyStage(['foo'], [], [], self_destructed=True, handle_failure=True)

  def testCompletionSelfDestructedWithdNoStatSlaves(self):
    """Verify stage when the completion_stage self_destructed with no_stat."""
    self.VerifyStage([], [], ['foo'], self_destructed=True, handle_failure=True)
