# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Code for testing recipes."""

import datetime
import fnmatch

from google.protobuf import timestamp_pb2

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
from PB.go.chromium.org.luci.buildbucket.proto import (
    builds_service as builds_service_pb2,
)
from PB.recipe_modules.fuchsia.recipe_testing import properties as properties_pb2
from recipe_engine import recipe_api
from RECIPE_MODULES.fuchsia.swarming_retry import api as swarming_retry_api
from RECIPE_MODULES.fuchsia.utils import memoize


class Build(swarming_retry_api.LedTask):
    def include_cl(self, cl):
        self._led_data = self._led_data.then("edit-cr-cl", cl)

    def include_recipe_bundle(self):
        self._led_data = self._led_data.then("edit-recipe-bundle")

    def use_realms(self):
        self._led_data = self._led_data.then(
            "edit", "-experiment", "luci.use_realms=true"
        )

    def set_recipe_testing_properties(self, properties):
        self._led_data = self._led_data.then(
            "edit",
            "-pa",
            "$fuchsia/recipe_testing=%s" % self._api.proto.encode(properties, "JSONPB"),
        )


def led_task_name(builder):
    """Returns the name to use for the led swarming task for the builder."""
    return "recipes-cq:%s" % builder


class RecipeTestingApi(recipe_api.RecipeApi):
    """API for running tests and processing test results."""

    def __init__(self, props, *args, **kwargs):
        super(RecipeTestingApi, self).__init__(*args, **kwargs)
        self._recipe_depth = props.recipe_depth
        self.enabled = props.enabled
        self.max_build_age_seconds = int(datetime.timedelta(days=28).total_seconds())
        self.projects = ("fuchsia",)

    def _get_affected_recipes(self, recipes_path):
        """Collect affected recipes.

        For now assume we care about all recipes.
        """

        with self.m.step.nest("get_affected_recipes") as parent_step:
            recipes_dir = recipes_path.join("recipes")
            recipe_files = self.m.file.listdir(
                "ls-recipes", recipes_dir, recursive=True
            )

            all_recipes = []
            for recipe_file in recipe_files:
                path = self.m.path.relpath(
                    self.m.path.realpath(recipe_file), self.m.path.realpath(recipes_dir)
                )
                # Files inside folders that end in ".resources" are never recipes.
                if self.m.path.dirname(path).endswith(".resources"):
                    continue

                name, ext = self.m.path.splitext(path)
                if ext == ".py":
                    all_recipes.append(name)

            parent_step.logs["all recipes"] = all_recipes

            with self.m.context(cwd=recipes_path):
                changed_files = self.m.git.get_changed_files(commit="HEAD")
            parent_step.logs["changed files (raw)"] = changed_files

            def is_expected_json(path):
                # We want to ignore expected JSON files--they won't affect how recipes
                # run. It's possible there are JSON files used as data for recipes
                # instead of as expected test outputs, so determine which files to
                # ignore very narrowly.
                return self.m.path.splitext(path)[1] == ".json" and self.m.path.dirname(
                    path
                ).endswith(".expected")

            def is_python_test_file(path):
                """Return True if this is a test file that we should ignore."""
                # We want to ignore test_api.py files--they won't affect how recipes
                # run in led, they only affect how recipes run in
                # './recipes test run', and we test that every time any recipe is
                # changed.
                if (
                    self.m.path.basename(path) == "test_api.py"
                    and self.m.path.dirname(self.m.path.dirname(path))
                    == "recipe_modules"
                ):
                    return True

                # Also ignore test definitions themselves. By convention these are
                # given the filename 'full.py' in Fuchsia, but there is no
                # guarantee this will remain the case.
                test_dir_names = ("tests", "examples")
                if (
                    self.m.path.splitext(path)[1] == ".py"
                    and self.m.path.basename(self.m.path.dirname(path))
                    in test_dir_names
                ):
                    return True

                return False

            def is_ignored_file(path):
                return is_expected_json(path) or is_python_test_file(path)

            filtered_changed_files = [
                x for x in changed_files if not is_ignored_file(x)
            ]
            parent_step.logs["changed files (filtered)"] = filtered_changed_files or [
                "no changed files"
            ]

            res = self.m.step(
                "recipes-analyze",
                [
                    recipes_path.join("recipes.py"),
                    "analyze",
                    self.m.json.input(
                        {"recipes": all_recipes, "files": filtered_changed_files}
                    ),
                    self.m.json.output(),
                ],
            )

            affected_recipes = res.json.output["recipes"]

            def should_test_all_recipes(path):
                globs = (
                    "infra/config/recipes.cfg",
                    # We particularly care about running CQ for fuchsia.proto changes.
                    "recipe_proto/*.proto",
                )
                return any(fnmatch.fnmatch(path, glob) for glob in globs)

            special_changed_files = [
                f for f in changed_files if should_test_all_recipes(f)
            ]
            if special_changed_files:
                step = self.m.step("mark all recipes as affected", None)
                step.presentation.step_summary_text = (
                    "because these files were changed:"
                )
                step.presentation.step_text = "\n" + "\n".join(special_changed_files)
                affected_recipes = all_recipes

            parent_step.logs["affected recipes"] = affected_recipes

            # Skip running recipes in the `recipes/contrib` directory, because
            # they are generally lower-priority and not worth running by default
            # in recipes CQ.
            return {r for r in affected_recipes if not r.startswith("contrib/")}

    def _get_last_green_build(self, builder):
        """Returns the build proto for a builder's most recent successful build.

        If no build younger than `self.max_build_age_seconds` is found, returns
        None.

        Args:
          builder: builder protobuf object
        """
        project, bucket, builder = builder.split("/")
        # "infra" is not returned by default, so we have to specify it.
        build = self.m.buildbucket_util.last_build(
            project, bucket, builder, status=common_pb2.SUCCESS
        )
        if not build:
            return None

        age_seconds = self.m.time.time() - build.end_time.seconds
        if age_seconds > self.max_build_age_seconds:
            return None
        return build

    def _create_led_build(self, orig_build, selftest_cl):
        builder = orig_build.builder
        builder_lookup_name = "{project}/{bucket}:{builder}".format(
            project=builder.project,
            bucket=builder.bucket,
            builder=builder.builder,
        )
        # Using `led get-builder` instead of `led get-build` ensures that we
        # won't use an outdated version of the builder (e.g. with deprecated
        # dimensions).
        # By default the priority is increased by 10 (resulting in a "lower"
        # priority), but we want it to stay the same.
        led_data = self.m.led(
            "get-builder", "-adjust-priority", "0", builder_lookup_name
        )

        led_data = led_data.then("edit", "-name", led_task_name(builder.builder))
        build = Build(api=self.m, name=builder.builder, led_data=led_data)

        # Signal to the launched build that it's being tested by this module.
        properties = properties_pb2.InputProperties(enabled=True)
        if orig_build.input.properties["recipe"] == "recipes":
            build.include_cl(selftest_cl)
            properties.recipe_depth = self._recipe_depth + 1
        elif orig_build.input.gerrit_changes:
            orig_cl = orig_build.input.gerrit_changes[0]
            cl_id, patchset = self._get_latest_cl(orig_cl.host, orig_cl.project)
            # Setting the CL to a more recent CL helps avoid rebase errors, but
            # if unable to find a recent CL, fall back to the original build's
            # triggering CL. It usually works.
            if not cl_id:
                cl_id = orig_cl.change
                patchset = orig_cl.patchset
            url = "https://%s/c/%s/+/%d/%d" % (
                orig_cl.host,
                orig_cl.project,
                cl_id,
                patchset,
            )
            build.include_cl(url)
        build.set_recipe_testing_properties(properties)
        build.use_realms()

        return build

    @memoize
    def _get_latest_cl(self, gerrit_host, project):
        """Returns number and patchset for a project's most recently landed CL.

        Args:
          gerrit_host (str): E.g., fuchsia-review.googlesource.com
          project (str): The name of the project in gerrit, e.g. "fuchsia"

        Returns:
          A tuple of
          * The integer change number for the CL corresponding to the commit at
            the tip of the main branch.
          * The last patchset of that CL.
        """
        gitiles_host = gerrit_host.replace("-review", "")
        remote = "https://%s/%s" % (gitiles_host, project)
        ref = self.m.git.get_default_remote_branch(remote)
        log = self.m.gitiles.log(remote, ref, limit=10, step_name="log %s" % project)

        for log_entry in log:
            commit_hash = log_entry["id"]
            step = self.m.gerrit.change_details(
                "latest change details for %s" % project,
                commit_hash,
                query_params=("CURRENT_REVISION",),
                host=gerrit_host,
                test_data=self.m.json.test_api.output(
                    {
                        "_number": 12345,
                        "current_revision": "5" * 40,
                        "revisions": {"5" * 40: {"_number": 6}},
                    }
                ),
                ok_ret=(0, 1),
            )
            # A commit that is committed directly without code review won't have a
            # corresponding Gerrit CL, so fetching it will fail (which is fine, we'll
            # just skip it and try the next one).
            if step.retcode == 0:
                cl_number = step.json.output["_number"]
                rev = step.json.output["current_revision"]
                ps_number = step.json.output["revisions"][rev]["_number"]
                return (cl_number, ps_number)
        return None, None

    def run_lint(self, recipes_path, allowlist=""):
        """Run lint on recipes.

        Args:
          recipes_path (Path): The path to the root of the recipes repo.
          allowlist (str): A regex of import names to allow.
        """
        args = ["lint"]
        if allowlist:
            args.extend(["--allowlist", allowlist])
        with self.m.context(cwd=recipes_path):
            self.m.step(
                "lint",
                cmd=[self.m.context.cwd.join("recipes.py")] + args,
            )

    def run_unit_tests(self, recipes_path):
        """Run the recipe unit tests."""
        with self.m.context(cwd=recipes_path):
            self.m.step(
                "test",
                cmd=[
                    self.m.context.cwd.join("recipes.py"),
                    "test",
                    "run",
                ],
            )

    def run_tests(
        self,
        recipes_path,
        selftest_cl,
        config,
        selftest_builder=None,
    ):
        """Launch CQ builders.

        Args:
          recipes_path (Path): Path to recipes repo checkout.
          selftest_cl (str): The CL to use to test a recursive recipe testing
            invocation.
          config (RecipeTesting proto): Many options for led/bb tests.
            TODO(fxbug.dev/88439): Make this a formal proto under
            recipe_modules/recipe_testing.
          selftest_builder (str|None): Builder to use to guarantee that we
            exercise the scheduling codepath when `use_buildbucket` is True.
        """
        # When run against a change to the recipes recipe, this is what the
        # swarming task stack should look like:
        #
        # * recipes.py from current recipe bundle, run against current CL
        # * recipes.py from current CL, run against SELFTEST_CL
        # * cobalt.py from current CL, run against current CL
        #
        # This works, but in case something goes wrong we need to make sure we
        # don't enter infinite recursion. We should never get to a third call to
        # recipes.py, so if we do we should exit.
        if self._recipe_depth >= 2:
            raise self.m.step.InfraFailure("recursion limit reached")

        builders = set()
        for project in config.projects:
            builders.update(
                self.m.commit_queue.all_tryjobs(
                    project=project.name,
                    include_unrestricted=project.include_unrestricted,
                    include_restricted=project.include_restricted,
                    config_name=project.cq_config_name or "commit-queue.cfg",
                )
            )

        builders = sorted(builders)

        affected_recipes = self._get_affected_recipes(recipes_path=recipes_path)
        if not affected_recipes:
            return

        if config.use_buildbucket:
            self._run_buildbucket_tests(selftest_builder, builders, affected_recipes)
        else:
            self._run_led_tests(recipes_path, selftest_cl, builders, affected_recipes)

    def _is_build_affected(self, orig_build, affected_recipes, presentation):
        if not orig_build:
            presentation.step_summary_text = "no recent builds found"
            return False

        recipe = orig_build.input.properties["recipe"]
        assert recipe

        is_recipe_affected = recipe in affected_recipes
        presentation.step_summary_text = "SELECTED" if is_recipe_affected else "skipped"
        presentation.logs["recipe_used"] = recipe
        return is_recipe_affected

    def _get_green_tryjobs(self, expiry_secs=24 * 60 * 60):
        """Return the set of tryjobs that are green on the current patchset.

        Args:
          expiry_secs (int): Do not return tryjobs which are older than this
            value in seconds.
        """
        builds = self.m.buildbucket.search(
            builds_service_pb2.BuildPredicate(
                gerrit_changes=list(self.m.buildbucket.build.input.gerrit_changes),
                status=common_pb2.SUCCESS,
                create_time=common_pb2.TimeRange(
                    start_time=timestamp_pb2.Timestamp(
                        seconds=int(self.m.time.time()) - expiry_secs,
                    ),
                ),
            ),
            fields=["builder"],
            step_name="get green tryjobs",
        )
        return {self.m.buildbucket_util.full_builder_name(b.builder) for b in builds}

    def _run_buildbucket_tests(self, selftest_builder, builders, affected_recipes):
        affected_builders = []
        recipes_is_affected = False

        with self.m.step.nest("get builders"), self.m.context(infra_steps=True):
            green_tryjobs = self._get_green_tryjobs()
            builders = [b for b in builders if b not in green_tryjobs]
            for builder in builders:
                with self.m.step.nest(builder) as presentation:
                    orig_build = self._get_last_green_build(builder)
                    if self._is_build_affected(
                        orig_build, affected_recipes, presentation
                    ):
                        # With recipe versioning, the `recipes` recipe is
                        # already tested in this invocation, so don't schedule
                        # any more `recipes` builds.
                        if orig_build.input.properties["recipe"] == "recipes":
                            recipes_is_affected = True
                            continue
                        affected_builders.append(builder)

        # If `affected_builders` is empty, but the current recipe was affected,
        # then we should schedule one self-test builder so we can still exercise
        # the scheduling codepath.
        if not affected_builders and recipes_is_affected:
            affected_builders = [selftest_builder]

        with self.m.step.nest("launch builds") as presentation:
            builds = self.m.subbuild.launch(
                # TODO(atyfto): Fix subbuild.launch so it can accept builders
                # with `bucket`s and/or `project`s which don't necessarily match
                # the current build's.
                builder_names=[b.split("/")[-1] for b in affected_builders],
                presentation=presentation,
                # Present tryjobs in Gerrit since they are effectively
                # top-level builds.
                hide_in_gerrit=False,
            )
        with self.m.step.nest("collect builds"):
            results = self.m.subbuild.collect(
                build_ids=[b.build_id for b in builds.values()],
            )
            self.m.display_util.display_builds(
                "check builds",
                [b.build_proto for b in results.values()],
                raise_on_failure=True,
            )

    def _run_led_tests(self, recipes_path, selftest_cl, builders, affected_recipes):
        builds = []
        with self.m.step.nest("get builders") as nest, self.m.context(
            cwd=recipes_path, infra_steps=True
        ):
            for builder in builders:
                with self.m.step.nest(builder) as presentation:
                    orig_build = self._get_last_green_build(builder)
                    if self._is_build_affected(
                        orig_build, affected_recipes, presentation
                    ):
                        build = self._create_led_build(orig_build, selftest_cl)
                        build.include_recipe_bundle()
                        builds.append(build)

            nest.step_summary_text = "selected {} builds".format(len(builds))

        if not builds:
            return

        self.m.swarming_retry.run_and_present_tasks(builds)
