# 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.
"""Tests for gerrit exonerating code.."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import contextlib
import functools
import glob
import json
import os

from chromite.lib import clactions
import mock
import pytest

from exonerator import gerrit_cq


_TEST_CASE_DIR = os.path.join(os.path.dirname(__file__), 'test_cases')
CQ_BIT_REMOVED_BY_HUMAN = 'CQ_bit_removed_by_human_*.json'
CQ_BIT_REMOVED_BY_BOT = 'CQ_bit_removed_by_bot_*.json'
READY_CASES = 'ready_for_exoneration_*.json'
NOT_READY_CASES = 'not_ready_for_exoneration_*.json'


def GlobChangeDetails(test_case_pattern):
  """Globs a test case pattern and reads the files as JSON."""
  for fname in glob.glob(os.path.join(_TEST_CASE_DIR, test_case_pattern)):
    with open(fname) as fh:
      yield json.load(fh)


def _GetFakeHelper(change_details):
  """Returns a fake GerritHelper which only returns the given |change_details|

  Args:
    change_details: A change_details dict of the form returned by Gerrit's API

  Returns:
    A mock object with a .GetChangeDetail method which always returns
    |change_details|.
  """
  return mock.Mock(
      GetChangeDetail=lambda *args, **kwargs: change_details)


@contextlib.contextmanager
def FakeChangeDetails(module, details):
  """Mocks out the _GetHelper method to return the given test case.

  Args:
    module: The module to patch
    details: The test case change details to use
  """
  with mock.patch.object(module, 'GetHelper',
                         return_value=_GetFakeHelper(details)):
    yield


_FakeChangeDetails = functools.partial(FakeChangeDetails, gerrit_cq)


@pytest.mark.parametrize('change_details',
                         GlobChangeDetails(READY_CASES))
def TestCanBeMarkedReady(change_details):
  with _FakeChangeDetails(change_details):
    assert gerrit_cq.CanBeMarkedReady(
        clactions.GerritPatchTuple(1, 5, False))


@pytest.mark.parametrize('change_details',
                         GlobChangeDetails(NOT_READY_CASES))
def TestCanNotBeMarkedReady(change_details):
  with _FakeChangeDetails(change_details):
    assert not gerrit_cq.CanBeMarkedReady(
        clactions.GerritPatchTuple(1, 5, False))




@pytest.mark.parametrize('change_details',
                         GlobChangeDetails(CQ_BIT_REMOVED_BY_BOT))
def TestDontExonerateSubmitted(change_details):
  with _FakeChangeDetails(change_details):
    assert not gerrit_cq.CanBeMarkedReady(
        clactions.GerritPatchTuple(1, 5, False))


# pylint: disable=protected-access
@pytest.mark.parametrize('change_details',
                         GlobChangeDetails(CQ_BIT_REMOVED_BY_BOT))
def TestCQBitWasRemovedByBot(change_details):
  assert gerrit_cq.CQApprovalWasRemovedByBot(change_details)


@pytest.mark.parametrize('change_details',
                         GlobChangeDetails(CQ_BIT_REMOVED_BY_HUMAN))
def TestCQBitWasRemovedByHuman(change_details):
  assert not gerrit_cq.CQApprovalWasRemovedByBot(change_details)
