# 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.

"""Unit tests for config stages"""

import builtins
import os
from unittest import mock

from chromite.cbuildbot import repository
from chromite.cbuildbot.stages import config_stages
from chromite.cbuildbot.stages import generic_stages_unittest
from chromite.lib import cros_build_lib
from chromite.lib import git
from chromite.lib import gs
from chromite.lib import gs_unittest
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) -> None:
        self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
        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) -> None:
        """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) -> None:
        """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) -> None:
        """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) -> None:
        """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,
    gs_unittest.AbstractGSContextTest,
):
    """Tests for UpdateConfigStage."""

    def setUp(self) -> None:
        self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
        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.project = "chromite"
        self.chromite_dir = os.path.join(self.tempdir, self.project)
        self.buildstore = FakeBuildStore()

    # 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) -> None:
        """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) -> None:
        """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) -> None:
        """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) -> None:
        """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 testMainBasic(self) -> None:
        """Basic test on main branch."""
        template = "build_config.ToT.json"
        stage = self.ConstructStage(template)
        stage.PerformStage()
        self.assertTrue(stage.branch == "main")

    def testReleaseBasic(self) -> None:
        """Basic test on release branch."""
        template = "build_config.release-R50-7978.B.json"
        stage = self.ConstructStage(template)
        stage.PerformStage()
        self.assertTrue(stage.branch == "release-R50-7978.B")
