1# Copyright 2018 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import("//build/config/chrome_build.gni")
6import("//build/config/chromeos/args.gni")
7import("//build/config/gclient_args.gni")
8
9assert(is_chromeos)
10
11# Determine the real paths for various items in the SDK, which may be used
12# in the 'generate_runner_script' template below. We do so outside the template
13# to confine exec_script to a single invocation.
14cros_is_vm = false
15if (is_chromeos_device && cros_sdk_version != "") {
16  _cache_path_prefix =
17      "//build/cros_cache/chrome-sdk/symlinks/${cros_board}+${cros_sdk_version}"
18
19  foreach(b, string_split(cros_boards_with_qemu_images, ":")) {
20    if (cros_board == b) {
21      cros_is_vm = true
22    }
23  }
24
25  _symlinks = [
26    # Tast harness & test data.
27    rebase_path("${_cache_path_prefix}+chromeos-base/tast-cmd"),
28    rebase_path("${_cache_path_prefix}+chromeos-base/tast-remote-tests-cros"),
29
30    # Binutils (and other toolchain tools) used to deploy Chrome to the device.
31    rebase_path(
32        "${_cache_path_prefix}+environment_chromeos-base_chromeos-chrome.tar.xz"),
33    rebase_path("${_cache_path_prefix}+target_toolchain"),
34  ]
35  if (cros_is_vm) {
36    # VM-related tools.
37    _symlinks += [
38      rebase_path("${_cache_path_prefix}+sys-firmware/seabios"),
39      rebase_path("${_cache_path_prefix}+chromiumos_qemu_image.tar.xz"),
40      rebase_path("${_cache_path_prefix}+app-emulation/qemu"),
41    ]
42  }
43  _symlink_targets =
44      exec_script("//build/get_symlink_targets.py", _symlinks, "list lines")
45  tast_sdk_items = [
46    _symlink_targets[0],
47    _symlink_targets[1],
48  ]
49  toolchain_sdk_items = [
50    _symlink_targets[2],
51    _symlink_targets[3],
52  ]
53  if (cros_is_vm) {
54    vm_sdk_items = [
55      _symlink_targets[4],
56      _symlink_targets[5],
57      _symlink_targets[6],
58    ]
59  }
60}
61
62# Creates a script at $generated_script that can be used to launch a cros VM
63# and optionally run a test within it.
64# Args:
65#   test_exe: Name of test binary located in the out dir. This will get copied
66#       to the VM and executed there.
67#   tast_attr_expr: Tast expression to pass to local_test_runner on the VM.
68#   tast_tests: List of Tast tests to run on the VM. Note that when this is
69#       specified, the target name used to invoke this template will be
70#       designated as the "name" of this test and will primarly used for test
71#       results tracking and displaying (eg: flakiness dashboard).
72#   generated_script: Path to place the generated script.
73#   deploy_chrome: If true, deploys a locally built chrome located in the root
74#       build dir to the VM after launching it.
75#   runtime_deps_file: Path to file listing runtime deps for the test. If set,
76#       all files listed will be copied to the VM before testing.
77template("generate_runner_script") {
78  forward_variables_from(invoker,
79                         [
80                           "deploy_chrome",
81                           "generated_script",
82                           "runtime_deps_file",
83                           "tast_attr_expr",
84                           "tast_tests",
85                           "testonly",
86                           "test_exe",
87                         ])
88  if (!defined(deploy_chrome)) {
89    deploy_chrome = false
90  }
91
92  assert(defined(generated_script),
93         "Must specify where to place generated test launcher script via " +
94             "'generated_script'")
95  is_tast = defined(tast_attr_expr) || defined(tast_tests)
96  assert(!(is_tast && defined(test_exe)),
97         "Tast tests are invoked from binaries shipped with the VM image. " +
98             "There should be no locally built binary needed.")
99
100  action(target_name) {
101    if (defined(runtime_deps_file)) {
102      write_runtime_deps = runtime_deps_file
103    }
104    script = "//build/chromeos/create_test_runner_script.py"
105
106    outputs = [ generated_script ]
107
108    deps = [ "//testing/buildbot/filters:chromeos_filters" ]
109    if (defined(invoker.deps)) {
110      deps += invoker.deps
111    }
112
113    data = [
114      # We use android test-runner's results libs to construct gtest output
115      # json.
116      "//build/android/pylib/__init__.py",
117      "//build/android/pylib/base/",
118      "//build/android/pylib/results/",
119      generated_script,
120      "//build/chromeos/",
121
122      # Needed for various SDK components used below.
123      "//build/cros_cache/chrome-sdk/misc/",
124      "//build/cros_cache/chrome-sdk/symlinks/",
125
126      # The LKGM file controls what version of the VM image to download. Add it
127      # as data here so that changes to it will trigger analyze.
128      "//chromeos/CHROMEOS_LKGM",
129      "//third_party/chromite/",
130    ]
131
132    if (defined(invoker.data)) {
133      deps += invoker.data
134    }
135
136    if (defined(invoker.data_deps)) {
137      data_deps = invoker.data_deps
138    }
139
140    # Required arguments used at build time by the runner script generator.
141    args = [
142      "--script-output-path",
143      rebase_path(generated_script, root_build_dir),
144      "--cros-cache",
145      rebase_path("//build/cros_cache/", root_build_dir),
146      "--board",
147      cros_board,
148      "--output-directory",
149      rebase_path(root_out_dir, root_build_dir),
150    ]
151
152    if (cros_is_vm) {
153      args += [ "--use-vm" ]
154    }
155
156    # If we have public Chromium builds, use public Chromium OS images when
157    # flashing the test device.
158    if (!is_chrome_branded) {
159      args += [ "--public-image" ]
160    }
161
162    if (deploy_chrome) {
163      args += [ "--deploy-chrome" ]
164    }
165
166    # If we're in the cros chrome-sdk (and not the raw ebuild), the test will
167    # need some additional runtime data located in the SDK cache.
168    if (cros_sdk_version != "") {
169      # Add the VM/QEMU-launching bits if needed.
170      if (cros_is_vm) {
171        data += vm_sdk_items
172      }
173      if (is_tast) {
174        data += tast_sdk_items
175      }
176      if (deploy_chrome) {
177        # To deploy chrome to the VM, it needs to be stripped down to fit into
178        # the VM. This is done by using binutils in the toolchain. So add the
179        # toolchain to the data.
180        data += toolchain_sdk_items
181      }
182    }
183
184    # When --test-exe is specified, test_runner.py will push the exe to the VM
185    # and execute it. Otherwise it wraps a host-side command and just takes care
186    # launching & tearing-down the VM.
187    if (defined(test_exe)) {
188      args += [
189        "--test-exe",
190        test_exe,
191      ]
192      if (defined(runtime_deps_file)) {
193        args += [
194          "--runtime-deps-path",
195          rebase_path(runtime_deps_file, root_build_dir),
196        ]
197      }
198    } else if (is_tast) {
199      # When --tast-tests is specified, test_runner.py will call
200      # local_test_runner on the VM to run the set of tests.
201      args += [
202        "--suite-name",
203        target_name,
204      ]
205      if (defined(tast_attr_expr)) {
206        args += [
207          "--tast-attr-expr",
208          tast_attr_expr,
209        ]
210      } else {
211        foreach(test, tast_tests) {
212          args += [
213            "--tast-tests",
214            test,
215          ]
216        }
217      }
218    }
219  }
220}
221
222template("tast_test") {
223  forward_variables_from(invoker, "*")
224
225  # Default the expression to match any chrome-related test.
226  if (!defined(tast_attr_expr) && !defined(tast_tests)) {
227    # The following expression filters out all non-critical tests. See the link
228    # below for more details:
229    # https://chromium.googlesource.com/chromiumos/platform/tast/+/master/docs/test_attributes.md
230    tast_attr_expr = "\"group:mainline\" && \"dep:chrome\""
231
232    if (defined(enable_tast_informational_tests) &&
233        enable_tast_informational_tests) {
234      tast_attr_expr += " && informational"
235    } else {
236      tast_attr_expr += " && !informational"
237    }
238    if (!is_chrome_branded) {
239      tast_attr_expr += " && !\"dep:chrome_internal\""
240    }
241  } else {
242    assert(defined(tast_attr_expr) != defined(tast_tests),
243           "Specify one of tast_tests or tast_attr_expr.")
244  }
245
246  # Append any disabled tests to the expression.
247  if (defined(tast_disabled_tests)) {
248    assert(defined(tast_attr_expr),
249           "tast_attr_expr must be used when specifying tast_disabled_tests.")
250    foreach(test, tast_disabled_tests) {
251      tast_attr_expr += " && !\"name:${test}\""
252    }
253  }
254  if (defined(tast_attr_expr)) {
255    tast_attr_expr = "( " + tast_attr_expr + " )"
256  }
257  generate_runner_script(target_name) {
258    testonly = true
259    generated_script = "$root_build_dir/bin/run_${target_name}"
260    runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
261    deploy_chrome = true
262    data_deps = [
263      "//:chromiumos_preflight",  # Builds the browser.
264      "//chromeos:cros_chrome_deploy",  # Adds additional browser run-time deps.
265    ]
266  }
267}
268