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

import("//build/config/cast.gni")
import("//build/config/fuchsia/config.gni")
import("//build/config/fuchsia/fuchsia_package_metadata.gni")
import("//build/config/gclient_args.gni")
import("//build/config/sysroot.gni")
import("//build/util/generate_wrapper.gni")

assert(is_fuchsia)

declare_args() {
  # Sets the Fuchsia Amber repository which will be used by default by the
  # generated installation scripts. If not specified, then no default directory
  # will be used.
  default_fuchsia_out_dir = ""

  # Sets the Fuchsia device node name which will be used by default by the
  # generated runner scripts. If not specficed, then no default node name will
  # be used.
  default_fuchsia_device_node_name = ""

  # CPU architecture of the host used to run the tests.
  test_host_cpu = host_cpu

  # Sets whether emulators need to be included in the test isolates
  test_isolate_uses_emulator = true

  # A list of additional Fuchsia boot images to include in the test isolates.
  fuchsia_additional_boot_images = []

  # This variable controls the browser included in the Telemetry based test
  # targets.
  fuchsia_browser_type = "web_engine_shell"
}

# Generates a wrapper script under root_build_dir/bin that performs an
# operation, such as deployment or execution, using a package and its
# dependencies.
#
# Parameters:
#   output_name_format: The format string for the generated script's filename.
#                       The placeholder string %package% will be substituted
#                       with |package| (or |package_name|, if set).
#                       Examples: "run_%package%", "install_%package%"
#   package: The package() target to run.
#   package_name: Specifies the name of the generated package, if its
#       filename is different than the |package| target name. This value must
#       match package_name in the |package| target.
#   package_deps: An array of [package, package_name] array pairs
#       which specify additional dependency packages to be installed
#       prior to execution.
#   executable: The underlying script to be called by the script.
#   executable_args: The list of arguments to pass to |executable|.
#                    Runtime commandline arguments can be passed to
#                    |executable| using the placeholder %args%.
#
#                    In addition, the script is passed the following
#                    executable_args:
#                      --package - the path to a .FAR package to install.
#                      --package_name - the name of the package to use as an
#                                       entry point.
#   include_fuchsia_out_dir: If true, adds |default_fuchsia_out_dir|
#                            to executable_args (when set in GN args).
template("fuchsia_run_script_with_packages") {
  if (defined(invoker.package_name)) {
    _pkg_shortname = invoker.package_name
  } else {
    _pkg_shortname = get_label_info(invoker.package, "name")
  }

  _generated_script_path =
      "$root_build_dir/bin/" +
      string_replace(invoker.output_name_format, "%package%", _pkg_shortname)

  generate_wrapper(target_name) {
    forward_variables_from(invoker,
                           TESTONLY_AND_VISIBILITY + [
                                 "executable",
                                 "executable_args",
                                 "data",
                                 "include_fuchsia_out_dir",
                                 "target",
                               ])

    wrapper_script = _generated_script_path
    deps = [ invoker.package ]

    if (!defined(data_deps)) {
      data_deps = []
    }
    data_deps += [ "//build/config/fuchsia:deployment_resources" ]

    _combined_package_list = [ invoker.package ]

    if (defined(invoker.package_deps)) {
      foreach(package_dep, invoker.package_deps) {
        _combined_package_list += [ package_dep[0] ]
      }
    }
    foreach(package_dep, _combined_package_list) {
      data_deps += [
        package_dep,
        package_dep + "__archive-manifest",
        package_dep + "__archive-metadata",
      ]
    }

    if (defined(invoker.data_deps)) {
      data_deps += invoker.data_deps
    }

    # Compute the list of full paths to package files, including dependencies.
    if (defined(invoker.package_deps)) {
      foreach(package_dep, invoker.package_deps) {
        package_dep_target = package_dep[0]
        deps += [ package_dep_target ]
        data_deps += [ package_dep_target ]
      }
    }

    # Include package information inside the wrapper script.
    if (!defined(executable_args)) {
      executable_args = []
    }

    if (defined(include_fuchsia_out_dir) && include_fuchsia_out_dir &&
        default_fuchsia_out_dir != "") {
      executable_args += [
        "--fuchsia-out-dir",
        default_fuchsia_out_dir,
      ]
    }
  }

  # Create a wrapper script rather than using a group() in order to ensure
  # "ninja $target_name" always works.
  if (defined(invoker.executable_wrapper)) {
    generate_wrapper(invoker.executable_wrapper) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      executable = _generated_script_path
      wrapper_script = "$root_build_dir/${invoker.executable_wrapper}"
      deps = [
        ":${invoker._install_target}",
        ":${invoker._run_target}",
      ]
    }
  }
}

# Generates a script which deploys a package to the TUF repo of a Fuchsia
# build output directory.
template("fuchsia_package_installer") {
  if (defined(invoker.package_name)) {
    pkg_shortname = invoker.package_name
  } else {
    pkg_shortname = get_label_info(invoker.package, "name")
  }
  fuchsia_package_metadata(pkg_shortname) {
    forward_variables_from(invoker,
                           TESTONLY_AND_VISIBILITY + [
                                 "package",
                                 "package_deps",
                               ])
  }
  fuchsia_run_script_with_packages(target_name) {
    forward_variables_from(invoker,
                           "*",
                           TESTONLY_AND_VISIBILITY + [ "executable_args" ])
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    executable = rebase_path("//build/fuchsia/test/deploy_to_fuchsia.py")
    executable_args = [
      "--out-dir",
      "@WrappedPath(.)",
      pkg_shortname,
    ]
    output_name_format = "deploy_%package%"
    include_fuchsia_out_dir = true
  }
}

# Generates scripts for installing and running test packages.
# See fuchsia_run_script_with_packages() for the full list of parameters.
template("fuchsia_test_runner") {
  _run_target = "${target_name}__runner"
  _install_target = "${target_name}__installer"

  fuchsia_run_script_with_packages(_run_target) {
    forward_variables_from(invoker,
                           TESTONLY_AND_VISIBILITY + [
                                 "data",
                                 "data_deps",
                                 "package",
                                 "package_name",
                                 "package_deps",
                               ])

    _test_runner_py = "//build/fuchsia/test/run_test.py"

    executable = rebase_path(_test_runner_py)

    if (defined(invoker.is_test_exe) && invoker.is_test_exe) {
      data += [ "//.vpython3" ]
    }
    output_name_format = "run_%package%"
    executable_wrapper = invoker.target_name

    # Populate the arguments used by the test runner, defined at build-time.
    executable_args = [
      "--out-dir",
      "@WrappedPath(.)",
    ]

    executable_args += [ package_name ]

    if (defined(invoker.use_test_server) && invoker.use_test_server) {
      executable_args += [ "--enable-test-server" ]
    }

    if (default_fuchsia_device_node_name != "") {
      executable_args += [
        "--target-id",
        default_fuchsia_device_node_name,
      ]
    }

    # Declare the files that are needed for test execution on LUCI swarming
    # test clients, both directly (via data) or indirectly (via data_deps).
    if (!defined(data)) {
      data = []
    }
    data += [
      _test_runner_py,
      "$root_gen_dir/package_metadata/${invoker.package_name}.meta",
    ]

    # TODO(crbug.com/1256870): Remove this once all out-of-tree references
    # to "package_name_override" are migrated to "package_name".
    if (defined(invoker.package_name_override)) {
      package_name = invoker.package_name_override
    }
  }
  fuchsia_package_installer(_install_target) {
    forward_variables_from(invoker,
                           TESTONLY_AND_VISIBILITY + [
                                 "package",
                                 "package_name",
                                 "package_deps",
                               ])
  }
}