# Copyright 2016 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module that contains unittests for patch_series module."""

import contextlib
import os
from unittest import mock

from chromite.cbuildbot import patch_series
from chromite.lib import config_lib
from chromite.lib import cros_test_lib
from chromite.lib import gerrit
from chromite.lib import parallel_unittest
from chromite.lib import partial_mock
from chromite.lib import patch as cros_patch
from chromite.lib import patch_unittest


class MockManifest:
    """Helper class for Mocking Manifest objects."""

    def __init__(self, path, **kwargs) -> None:
        self.root = path
        for key, attr in kwargs.items():
            setattr(self, key, attr)


def FakeFetchChangesForRepo(fetched_changes, by_repo, repo) -> None:
    """Fake version of the "PatchSeries._FetchChangesForRepo" method.

    Thes does nothing to the changes and simply copies them into the output
    dict.
    """
    for c in by_repo[repo]:
        fetched_changes[c.id] = c


class FakePatch(partial_mock.PartialMock):
    """Mocks out dependency and fetch methods of GitRepoPatch.

    Examples:
        set FakePatch.parents and .build_roots per patch, and set
        FakePatch.assertEqual to your TestCase's assertEqual method.  The
        behavior of GerritDependencies, and Fetch` depends on the patch id.
    """

    TARGET = "chromite.lib.patch.GitRepoPatch"
    ATTRS = ("GerritDependencies", "Fetch")

    parents = {}
    build_root = None
    assertEqual = None

    def PreStart(self) -> None:
        FakePatch.parents = {}

    def PreStop(self) -> None:
        FakePatch.build_root = None
        FakePatch.assertEqual = None

    def GerritDependencies(self, patch):
        return [cros_patch.ParsePatchDep(x) for x in self.parents[patch.id]]

    def Fetch(self, patch, path):
        self._assertPath(patch, path)
        return patch.sha1

    def _assertPath(self, patch, path) -> None:
        # pylint: disable=not-callable
        self.assertEqual(path, os.path.join(self.build_root, patch.project))


class FakeGerritPatch(FakePatch):
    """Mocks out the "GerritDependencies" method of GerritPatch.

    This is necessary because GerritPatch overrides the GerritDependencies
    method.
    """

    TARGET = "chromite.lib.patch.GerritPatch"
    ATTRS = ("GerritDependencies",)


# pylint: disable=protected-access
# pylint: disable=too-many-ancestors
class PatchSeriesTestCase(
    patch_unittest.UploadedLocalPatchTestCase, cros_test_lib.MockTestCase
):
    """Base class for tests that need to test PatchSeries."""

    @contextlib.contextmanager
    def _ValidateTransactionCall(self, _changes):
        yield

    def setUp(self) -> None:
        self.StartPatcher(parallel_unittest.ParallelMock())
        self._patch_factory = patch_unittest.MockPatchFactory()
        self.build_root = "fakebuildroot"
        self.GetPatches = self._patch_factory.GetPatches
        self.MockPatch = self._patch_factory.MockPatch

    def MakeHelper(self, cros_internal=None, cros=None):
        # pylint: disable=attribute-defined-outside-init
        site_params = config_lib.GetSiteParams()
        if cros_internal:
            cros_internal = mock.create_autospec(gerrit.GerritHelper)
            cros_internal.version = "2.2"
            cros_internal.remote = site_params.INTERNAL_REMOTE
        if cros:
            cros = mock.create_autospec(gerrit.GerritHelper)
            cros.remote = site_params.EXTERNAL_REMOTE
            cros.version = "2.2"
        return patch_series.HelperPool(cros_internal=cros_internal, cros=cros)

    def GetPatchSeries(self, helper_pool=None):
        if helper_pool is None:
            helper_pool = self.MakeHelper(cros_internal=True, cros=True)
        series = patch_series.PatchSeries(self.build_root, helper_pool)

        # Suppress transactions.
        series._Transaction = self._ValidateTransactionCall
        series.GetGitRepoForChange = lambda change, **kwargs: os.path.join(
            self.build_root, change.project
        )
        series.GetGitReposForChange = lambda change, **kwargs: [
            os.path.join(self.build_root, change.project)
        ]

        return series

    def CheckPatchApply(self, apply_mocks) -> None:
        for apply_mock in apply_mocks:
            apply_mock.assert_called_once_with(mock.ANY, trivial=False)
            value = apply_mock.call_args[0][0]
            self.assertIsInstance(value, MockManifest)
            self.assertEqual(value.root, self.build_root)

    def SetPatchApply(self, patch):
        return self.PatchObject(patch, "ApplyAgainstManifest")

    def assertResults(
        self,
        series,
        changes,
        applied=(),
        failed_tot=(),
        failed_inflight=(),
        frozen=True,
    ):
        manifest = MockManifest(self.build_root)
        result = series.Apply(changes, frozen=frozen, manifest=manifest)

        _GetIds = lambda seq: [x.id for x in seq]
        _GetFailedIds = lambda seq: _GetIds(x.patch for x in seq)

        applied_result = _GetIds(result[0])
        failed_tot_result, failed_inflight_result = [
            _GetFailedIds(x) for x in result[1:]
        ]

        applied = _GetIds(applied)
        failed_tot = _GetIds(failed_tot)
        failed_inflight = _GetIds(failed_inflight)

        self.assertEqual(applied, applied_result)
        self.assertCountEqual(failed_inflight, failed_inflight_result)
        self.assertCountEqual(failed_tot, failed_tot_result)
        return result


class TestUploadedLocalPatch(PatchSeriesTestCase):
    """Test interaction between uploaded local git patches and PatchSeries."""

    def testFetchChanges(self) -> None:
        """Test fetching uploaded local patches."""
        git1, git2, patch1 = self._CommonGitSetup()
        patch2 = self.CommitFile(git1, "monkeys2", "foon2")
        patch3 = self._MkPatch(git1, None, original_sha1=patch1.sha1)
        patch4 = self._MkPatch(git1, None, original_sha1=patch2.sha1)
        self.assertEqual(patch3.id, patch1.id)
        self.assertEqual(patch4.id, patch2.id)
        self.assertNotEqual(patch3.id, patch4.id)
        series = self.GetPatchSeries()
        series.GetGitRepoForChange = lambda change, **kwargs: git2
        series.GetGitReposForChange = lambda change, **kwargs: [git2]
        patches, _ = series.FetchChanges([patch3, patch4])
        self.assertEqual(len(patches), 2)
        self.assertEqual(patches[0].id, patch3.id)
        self.assertEqual(patches[1].id, patch4.id)

    def testFetchChangesWithChangeNotInManifest(self) -> None:
        """test FetchChanges with ChangeNotInManifest."""

        # pylint: disable=unused-argument
        def raiseException(change, **kwargs) -> None:
            raise cros_patch.ChangeNotInManifest(change)

        patch_1, patch_2 = patches = self.GetPatches(2)

        series = self.GetPatchSeries()
        series.GetGitRepoForChange = raiseException
        series.GetGitReposForChange = raiseException

        changes, not_in_manifest = series.FetchChanges(patches)

        self.assertEqual(len(changes), 0)
        self.assertEqual(len(not_in_manifest), 2)
        self.assertEqual(not_in_manifest[0].patch, patch_1)
        self.assertEqual(not_in_manifest[1].patch, patch_2)
