| # Copyright 2023 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. |
| |
| import("//build/host.gni") |
| import("//build/images/tools/fastboot.gni") |
| import("//build/python/python_binary.gni") |
| import("//build/testing/host_test.gni") |
| import("//build/testing/host_test_data.gni") |
| |
| # Declares a host-side Python E2E Mobly test. |
| # |
| # Mobly is an open-source Python test framework |
| # that specializes at E2E tests with complex testbeds |
| # such as multi-device testing. |
| # |
| # Example |
| # ``` |
| # python_mobly_test("hello_world_test") { |
| # main_source = "my_mobly_test.py" |
| # sources = [ |
| # "test_helpers_foo.py", |
| # "test_helpers_bar.py", |
| # ] |
| # libraries = [ |
| # "//path/to/foo:lib", |
| # "//path/to/bar:lib", |
| # ] |
| # extra_args = [ "--a_mobly_test_flag" ] |
| # local_config_source = "mobly_config.yaml" |
| # params_source = "mobly_params.yaml" |
| # } |
| # ``` |
| # |
| # Example local Mobly config YAML content |
| # ``` |
| # TestBeds: |
| # - Name: LocalTestbed |
| # Controllers: |
| # FuchsiaDevice: |
| # - nodename: "fuchsia-LOCAL_NODE_NAME" |
| # ``` |
| # |
| # Example Mobly test params YAML content |
| # ``` |
| # bool_param: True |
| # str_param: some_string |
| # dict_param: |
| # fld_1: val_1 |
| # fld_2: val_2 |
| # list_param: |
| # - 1 |
| # - 2 |
| # - 3 |
| # - 4 |
| # ``` |
| # |
| # Parameters |
| # |
| # main_source (required) |
| # The Mobly .py test file that will be interpreted. |
| # Type: path |
| # |
| # test_name (optional) |
| # The name of the generated test. |
| # Type: string |
| # Default: target_name |
| # |
| # sources (optional) |
| # Other files that are used in the Mobly test. |
| # Type: list(path) |
| # Default: empty list |
| # |
| # libraries (optional) |
| # Paths to python_libraries this Mobly test imports. |
| # Type: list(string) |
| # Default: empty list |
| # |
| # test_dir (optional) |
| # Path to where the test executes. |
| # Type: string |
| # Default: "${target_out_dir}/${target_name}" |
| # |
| # extra_args (optional) |
| # Additional arguments to pass to the test. |
| # Type: list(string) |
| # Default: empty list |
| # |
| # local_config_source (optional) |
| # Path to the Mobly YAML config file to use for local execution. |
| # If not provided, Mobly test will generate a best-effort config based on the |
| # host environment. Note that config generation assumes connected Fuchsia |
| # devices are provisioned using the SSH credentials from Fuchsia.git |
| # workflows. If provisioned via other means (e.g. SDK, Sonic), users are |
| # advised to provide a local config instead. |
| # Type: string |
| # |
| # params_source (optional) |
| # Path to the Mobly test params config file (typically YAML or JSON). |
| # If not provided, Mobly test will execute without test params. |
| # Type: string |
| # |
| # params_source_deps (optional) |
| # This does not need to be provided if the params_source file is checked in |
| # to the source tree. It only needs to be provided if params_source is |
| # generated by a GN target. |
| # Type: string |
| # |
| # transport (required) |
| # Transport to be used by HoneyDew while performing majority of the |
| # host-target interactions. Valid values are "sl4f", "fuchsia-controller". |
| # Type: String |
| # |
| # test_data_deps (optional) |
| # List of test data GN targets that are needed at runtime. |
| # Type: list(string) |
| # Default: empty list |
| # |
| # multi_fuchsia_device (optional) |
| # Whether a test is a multi-device test (requires 2+ fuchsia devices). |
| # Type: boolean |
| # Default: false |
| # |
| # timeout_secs (optional) |
| # [int] The infra timeout in seconds for the test. |
| # |
| # deps |
| # environments |
| # visibility |
| |
| template("python_mobly_test") { |
| assert(defined(invoker.main_source), "main_source is required") |
| assert(defined(invoker.transport), "transport is required") |
| assert( |
| invoker.transport == "sl4f" || invoker.transport == "fuchsia-controller", |
| "transport should be either 'sl4f' or 'fuchsia-controller' but received: " + invoker.transport) |
| |
| # |
| # Define Mobly test python_binary(). |
| # |
| _test_name = "${target_name}" |
| if (defined(invoker.test_name)) { |
| _test_name = invoker.test_name |
| } |
| _test_binary_name = "${_test_name}.pyz" |
| _test_binary_target = "${_test_name}_python_binary" |
| python_binary(_test_binary_target) { |
| forward_variables_from(invoker, |
| [ |
| "main_source", |
| "sources", |
| ]) |
| |
| testonly = true |
| visibility = [ ":*" ] |
| |
| output_name = _test_binary_name |
| |
| # Mobly-specific entry point. |
| main_callable = "test_runner.main" |
| |
| deps = [ "//third_party/mobly" ] |
| if (defined(invoker.libraries)) { |
| deps += invoker.libraries |
| } |
| } |
| |
| _test_dir = "${target_out_dir}/${_test_name}" |
| if (defined(invoker.test_dir)) { |
| _test_dir = invoker.test_dir |
| } |
| |
| # |
| # Define Mobly test host_test_data(). |
| # |
| _mobly_test_data_target = "${_test_name}_test_data" |
| host_test_data(_mobly_test_data_target) { |
| visibility = [ ":*" ] |
| |
| sources = [ get_label_info(":${_test_binary_target}", "target_out_dir") + |
| "/${_test_binary_name}" ] |
| outputs = [ "${_test_dir}/${_test_binary_name}" ] |
| deps = [ ":${_test_binary_target}" ] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| } |
| |
| # |
| # Define FFX binary host_test_data() |
| # |
| |
| # This is currently required by Honeydew for Fuchsia device interactions. |
| # It's safe to assume that any python_mobly_test() will be performing some |
| # form of Fuchsia interactions so including FFX in this template would |
| # centralize this data deps for all users. |
| |
| # TODO(fxbug.dev/308682042): ideally the `host_test` below depends directly |
| # on the data_dep: `//src/developer/ffx:suite_test_data` and uses ffx from |
| # `rebase_path("${root_out_dir}/ffx", root_build_dir)`. That works locally, |
| # but it fails in CQ due to the mobly driver ignoring this arg. |
| _ffx_test_data_target = "${_test_name}_ffx_bin_test_data" |
| host_test_data(_ffx_test_data_target) { |
| sources = [ "${host_tools_dir}/ffx" ] |
| deps = [ |
| "//src/developer/ffx:host", |
| "//src/developer/ffx:suite_test_data", |
| ] |
| outputs = [ "${_test_dir}/ffx" ] |
| } |
| |
| # |
| # Define Fastboot binary host_test_data() |
| # |
| |
| # This is currently required by Honeydew for Fuchsia device interactions when |
| # in fastboot mode. It's safe to assume that some of the python_mobly_test() |
| # will be performing some form of Fuchsia interactions when in fastboot mode |
| # so including Fastboot in this template would centralize this data deps for |
| # all users. |
| |
| _fastboot_test_data_target = "${_test_name}_fastboot_bin_test_data" |
| host_test_data(_fastboot_test_data_target) { |
| sources = [ "${prebuilt_fastboot}" ] |
| outputs = [ "${_test_dir}/fastboot" ] |
| } |
| |
| # |
| # Construct host test arguments. |
| # |
| |
| # Mobly Driver is provided as the first host test argument so that it's the |
| # interpreter's entry-point. This allows Mobly Driver to wrap the execution |
| # lifecycle of the underlying Mobly test. |
| # |
| # We define Mobly Driver outside of this template so that the Mobly Driver |
| # binary is built only once but can be used/referenced for any Mobly tests. |
| |
| _md_test_data_dir = |
| get_label_info("//src/testing/end_to_end/mobly_driver", "target_out_dir") |
| _host_test_args = [ |
| rebase_path("${_md_test_data_dir}/test_data/mobly_driver.pyz", |
| root_build_dir), |
| rebase_path("${_test_dir}/${_test_binary_name}", root_build_dir), |
| "-test_data_path", |
| rebase_path(_test_dir, root_build_dir), |
| "-ffx_path", |
| rebase_path("${_test_dir}/ffx", root_build_dir), |
| "-transport", |
| invoker.transport, |
| ] |
| if (defined(invoker.multi_fuchsia_device) && invoker.multi_fuchsia_device) { |
| _host_test_args += [ "-multi_device" ] |
| } |
| |
| _additional_deps = [] |
| |
| # If specified, define test params data target and data path add to host args. |
| if (defined(invoker.params_source)) { |
| _param_yaml_data_target = "${_test_name}_params_data" |
| host_test_data(_param_yaml_data_target) { |
| sources = [ invoker.params_source ] |
| outputs = [ "${_test_dir}/test_params.yaml" ] |
| if (defined(invoker.params_source_deps)) { |
| deps = invoker.params_source_deps |
| } |
| } |
| |
| _host_test_args += [ |
| "-params_yaml_path", |
| rebase_path("${_test_dir}/test_params.yaml", root_build_dir), |
| ] |
| |
| _additional_deps += [ ":${_param_yaml_data_target}" ] |
| } |
| |
| # If specified, define test config data target and add data path to host args. |
| if (defined(invoker.local_config_source)) { |
| _config_yaml_data_target = "${_test_name}_config_data" |
| host_test_data(_config_yaml_data_target) { |
| sources = [ invoker.local_config_source ] |
| outputs = [ "${_test_dir}/config.yaml" ] |
| } |
| |
| _host_test_args += [ |
| "-config_yaml_path", |
| rebase_path("${_test_dir}/config.yaml", root_build_dir), |
| ] |
| |
| _additional_deps += [ ":${_config_yaml_data_target}" ] |
| } |
| |
| # |
| # Define the Mobly host_test(). |
| # |
| host_test(_test_name) { |
| forward_variables_from(invoker, |
| [ |
| "environments", |
| "visibility", |
| "timeout_secs", |
| ]) |
| |
| binary_path = python_exe_src |
| args = _host_test_args |
| |
| if (defined(invoker.extra_args)) { |
| args += invoker.extra_args |
| } |
| |
| deps = |
| [ |
| ":${_fastboot_test_data_target}", |
| ":${_ffx_test_data_target}", |
| ":${_mobly_test_data_target}", |
| "//build/python:interpreter", |
| "//src/testing/end_to_end/mobly_driver:mobly_driver_test_data_target", |
| ] + _additional_deps |
| if (defined(invoker.test_data_deps)) { |
| deps += invoker.test_data_deps |
| } |
| } |
| } |