xref: /aosp_15_r20/external/cronet/build/config/chromeos/rules.gni (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1# Copyright 2018 The Chromium Authors
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/chromeos/ui_mode.gni")
8import("//build/config/dcheck_always_on.gni")
9import("//build/config/gclient_args.gni")
10import("//build/config/python.gni")
11import("//build/util/generate_wrapper.gni")
12
13assert(is_chromeos)
14assert(is_chromeos_device)
15
16# Determine the real paths for various items in the SDK, which may be used
17# in the 'generate_runner_script' template below. We do so outside the template
18# to confine exec_script to a single invocation.
19if (cros_sdk_version != "") {
20  # Ideally these should be maps, however, gn doesn't support map, so using a
21  # list of list to simulate a map:
22  # [key1, [value1, value2, ...]], [key2, [value1, value2, ...]], where
23  # the keys are boards and values are symlinks or symlink targets, and the
24  # mapping shouldn't be used for anything else.
25  #
26  # A sample usage is:
27  # foreach(m, _symlink_targets_map) {
28  #   if(m[0] == target_key) {
29  #     target_value = m[1]
30  #   }
31  # }
32  #
33  _symlink_map = []
34  _symlink_targets_map = []
35
36  if (is_chromeos_ash) {
37    _potential_test_boards = [ cros_board ]
38  } else {
39    _potential_test_boards = []
40    if (cros_boards != "") {
41      _potential_test_boards += string_split(cros_boards, ":")
42    }
43    if (cros_boards_with_qemu_images != "") {
44      _potential_test_boards += string_split(cros_boards_with_qemu_images, ":")
45    }
46  }
47
48  foreach(b, _potential_test_boards) {
49    _cache_path_prefix =
50        "//build/cros_cache/chrome-sdk/symlinks/${b}+${cros_sdk_version}"
51
52    _cros_is_vm = false
53    foreach(b1, string_split(cros_boards_with_qemu_images, ":")) {
54      if (b == b1) {
55        _cros_is_vm = true
56      }
57    }
58
59    _symlinks = []
60    _symlinks = [
61      # Tast harness & test data.
62      rebase_path("${_cache_path_prefix}+autotest_server_package.tar.bz2"),
63
64      # Binutils (and other toolchain tools) used to deploy Chrome to the device.
65      rebase_path(
66          "${_cache_path_prefix}+environment_chromeos-base_chromeos-chrome.tar.xz"),
67      rebase_path("${_cache_path_prefix}+target_toolchain"),
68    ]
69    if (_cros_is_vm) {
70      # VM-related tools.
71      _symlinks +=
72          [ rebase_path("${_cache_path_prefix}+chromiumos_test_image.tar.xz") ]
73    }
74    _symlink_map += [ [
75          b,
76          _symlinks,
77        ] ]
78  }
79
80  _all_symlinks = []
81  foreach(m, _symlink_map) {
82    _all_symlinks += m[1]
83  }
84  _all_symlink_targets =
85      exec_script("//build/get_symlink_targets.py", _all_symlinks, "list lines")
86  _index = 0
87  foreach(m, _symlink_map) {
88    _symlink_targets = []
89    foreach(_, m[1]) {
90      _symlink_targets += [ _all_symlink_targets[_index] ]
91      _index += 1
92    }
93
94    _symlink_targets_map += [ [
95          m[0],
96          _symlink_targets,
97        ] ]
98  }
99}
100
101template("generate_chromeos_sdk_deps") {
102  forward_variables_from(invoker,
103                         [
104                           "deploy_chrome",
105                           "is_tast",
106                         ])
107  if (!defined(deploy_chrome)) {
108    deploy_chrome = false
109  }
110  if (!defined(is_tast)) {
111    is_tast = false
112  }
113
114  _sdk_data = []
115  assert(cros_sdk_version != "", "cros sdk version is not defined")
116  foreach(b, _potential_test_boards) {
117    _cros_is_vm = false
118    foreach(b1, string_split(cros_boards_with_qemu_images, ":")) {
119      if (b == b1) {
120        _cros_is_vm = true
121      }
122    }
123
124    # Determine the real paths for various items in the SDK, which may be used
125    # in the 'generate_runner_script' template below.
126    if (is_tast || _cros_is_vm || deploy_chrome) {
127      _symlink_targets = []
128      foreach(m, _symlink_targets_map) {
129        if (b == m[0]) {
130          _symlink_targets = []
131          _symlink_targets = m[1]
132        }
133      }
134
135      if (is_tast) {
136        # Add tast sdk items.
137        _sdk_data += [ _symlink_targets[0] ]
138      }
139      if (deploy_chrome) {
140        # To deploy chrome to the VM, it needs to be stripped down to fit into
141        # the VM. This is done by using binutils in the toolchain. So add the
142        # toolchain to the data.
143        _sdk_data += [
144          _symlink_targets[1],
145          _symlink_targets[2],
146        ]
147      }
148      if (_cros_is_vm) {
149        # Add vm sdk items.
150        _sdk_data += [ _symlink_targets[3] ]
151      }
152    }
153  }
154  group(target_name) {
155    data = _sdk_data
156    data += [
157      # Needed for various SDK components used below.
158      "//build/cros_cache/chrome-sdk/misc/",
159      "//build/cros_cache/chrome-sdk/symlinks/",
160      "//chrome/VERSION",
161
162      # The LKGM file controls what version of the VM image to download. Add it
163      # as data here so that changes to it will trigger analyze.
164      "//chromeos/CHROMEOS_LKGM",
165    ]
166    if (cros_boards_with_qemu_images != "") {
167      data += [ "//build/cros_cache/cipd/" ]
168    }
169  }
170}
171
172# Creates tast filter files for skylab tast tests.
173# Args:
174#   tast_attr_expr: Tast expression to determine tests to run. This creates the
175#       initial set of tests that can be further filtered..
176#   tast_tests: Names of tests to enable in tast. All other tests will be
177#       disabled that are not listed.
178#   tast_disabled_tests: Names of tests to disable in tast. All other tests that
179#       match the tast expression will still run.
180#   tast_control: gni file with collections of tests to be used for specific
181#       filters (e.g. "//chromeos/tast_control.gni"). Any lists of strings in
182#       this file will be used to generate additional tast expressions with
183#       those strings expanded into tests to disable (i.e. as && !"name:test").
184#       The name of those lists are then intended to be used to specify in
185#       test_suites.pyl which collection to be used on specific test suites.
186template("generate_skylab_tast_filter") {
187  forward_variables_from(invoker,
188                         [
189                           "tast_attr_expr",
190                           "tast_tests",
191                           "tast_disabled_tests",
192                           "tast_control",
193                         ])
194
195  if (defined(tast_disabled_tests)) {
196    assert(defined(tast_attr_expr),
197           "tast_attr_expr must be used when specifying tast_disabled_tests.")
198  }
199  _generated_filter = "$root_build_dir/bin/${target_name}.filter"
200  _skylab_args = [
201    "generate-filter",
202    "--output",
203    rebase_path(_generated_filter),
204  ]
205  if (defined(tast_control)) {
206    _skylab_args += [
207      "--tast-control",
208      rebase_path(tast_control),
209    ]
210  }
211  if (defined(tast_attr_expr)) {
212    _skylab_args += [
213      "--tast-expr",
214      tast_attr_expr,
215    ]
216  }
217  if (defined(tast_tests)) {
218    foreach(_test, tast_tests) {
219      _skylab_args += [
220        "--enabled-tests",
221        _test,
222      ]
223    }
224  }
225  if (defined(tast_disabled_tests)) {
226    foreach(_test_name, tast_disabled_tests) {
227      _skylab_args += [
228        "--disabled-tests",
229        _test_name,
230      ]
231    }
232  }
233  action(target_name) {
234    testonly = true
235    script = "//build/chromeos/generate_skylab_tast_filter.py"
236    if (defined(tast_control)) {
237      sources = [ tast_control ]
238    }
239    outputs = [ _generated_filter ]
240    args = _skylab_args
241    if (defined(invoker.data_deps)) {
242      data_deps = invoker.data_deps
243    }
244    data = [ _generated_filter ]
245    if (defined(invoker.data)) {
246      data += invoker.data
247    }
248    if (defined(invoker.deps)) {
249      deps = invoker.deps
250    }
251  }
252}
253
254# Creates a script at $generated_script that can be used to launch a cros VM
255# and optionally run a test within it.
256# Args:
257#   test_exe: Name of test binary located in the out dir. This will get copied
258#       to the VM and executed there.
259#   tast_attr_expr: Tast expression to pass to local_test_runner on the VM.
260#   tast_tests: List of Tast tests to run on the VM. Note that when this is
261#       specified, the target name used to invoke this template will be
262#       designated as the "name" of this test and will primarly used for test
263#       results tracking and displaying (eg: flakiness dashboard).
264#   generated_script: Path to place the generated script.
265#   deploy_chrome: If true, deploys a locally built chrome located in the root
266#       build dir to the VM or DUT after launching it.
267#   deploy_lacros: If true, deploys a locally built Lacros located in the root
268#       build dir to the VM or DUT after launching it.
269#   runtime_deps_file: Path to file listing runtime deps for the test. If set,
270#       all files listed will be copied to the VM before testing.
271#   skip_generating_board_args: By default, this template generates an '--board'
272#       arg with corresponding '--flash' or '--use-vm' args for device and vm
273#       respectively. This argument instructs the template to skip generating
274#       them, and it's designed for use cases where one builds for one board
275#       (e.g. amd64-generic), but tests on a different board (e.g. eve).
276#   tast_vars: A list of "key=value" runtime variable pairs to pass to invoke
277#   strip_chrome: If true, strips Chrome before deploying it for non-Tast tests.
278#       the Tast tests. For more details, please see:
279#       https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/docs/writing_tests.md#Runtime-variables
280template("generate_runner_script") {
281  forward_variables_from(invoker,
282                         [
283                           "deploy_chrome",
284                           "deploy_lacros",
285                           "generated_script",
286                           "runtime_deps_file",
287                           "skip_generating_board_args",
288                           "strip_chrome",
289                           "tast_attr_expr",
290                           "tast_tests",
291                           "tast_vars",
292                           "testonly",
293                           "test_exe",
294                         ])
295
296  if (!defined(skip_generating_board_args)) {
297    # --board should be assigned by the autotest wrapper on skylab builders
298    skip_generating_board_args = is_skylab
299  }
300
301  if (skip_generating_board_args) {
302    # cros_board is not needed, so setting it to empty to avoid being used
303    # accidentally below.
304    cros_board = ""
305    not_needed([ cros_board ])
306  }
307
308  if (!defined(deploy_chrome)) {
309    deploy_chrome = false
310  }
311  if (!defined(deploy_lacros)) {
312    deploy_lacros = false
313  }
314  if (!defined(strip_chrome)) {
315    strip_chrome = false
316  }
317  is_tast = defined(tast_attr_expr) || defined(tast_tests)
318  assert(!(is_tast && defined(test_exe)),
319         "Tast tests are invoked from binaries shipped with the VM image. " +
320             "There should be no locally built binary needed.")
321  assert(is_tast || !defined(tast_vars),
322         "tast_vars is only support for Tast tests")
323
324  if (is_tast) {
325    not_needed([ "strip_chrome" ])
326  }
327
328  # If we're in the cros chrome-sdk (and not the raw ebuild), the test will
329  # need some additional runtime data located in the SDK cache.
330  if (cros_sdk_version != "") {
331    assert(defined(generated_script),
332           "Must specify where to place generated test launcher script via " +
333               "'generated_script'")
334
335    generate_chromeos_sdk_deps(target_name + "_cros_deps__helper") {
336      is_tast = is_tast
337      deploy_chrome = deploy_chrome
338    }
339  }
340
341  generate_wrapper(target_name) {
342    executable = "//build/chromeos/test_runner.py"
343    wrapper_script = generated_script
344    executable_args = []
345
346    if (defined(runtime_deps_file)) {
347      write_runtime_deps = runtime_deps_file
348    }
349
350    # Build executable_args for the three different test types: GTest, Tast,
351    # and host-side commands (eg telemetry).
352    if (defined(test_exe)) {
353      executable_args += [
354        "gtest",
355        "--test-exe",
356        test_exe,
357      ]
358
359      # This target is not a gtest unit test, but an integration test suite.
360      # Similar to interactive ui tests, it would start a full browser and
361      # then do testing.
362      # See more at //docs/testing/chromeos_integration.
363      if (test_exe == "chromeos_integration_tests") {
364        # Run the test sudo helper.
365        executable_args += [ "--run-test-sudo-helper" ]
366
367        if (is_chromeos_ash) {
368          # For ash, it need to first stop the existing ash.
369          executable_args += [ "--stop-ui" ]
370        }
371
372        # Lacros need to know the wayland socket file created by Ash.
373        # In this way, Lacros will be connected to the system Ash.
374        if (is_chromeos_lacros) {
375          executable_args += [
376            "--env-var",
377            "XDG_RUNTIME_DIR",
378            "/run/chrome",
379          ]
380        }
381
382        # Make the tests match the browser's selinux tags so it gets the same
383        # security context as the browser would.
384        executable_args += [ "--set-selinux-label=chromeos_integration_tests=u:object_r:chrome_browser_exec:s0" ]
385      }
386      if (defined(runtime_deps_file)) {
387        executable_args += [
388          "--runtime-deps-path",
389          rebase_path(runtime_deps_file, root_build_dir),
390        ]
391      }
392    } else if (is_tast) {
393      # When --tast-tests is specified, test_runner.py will call
394      # local_test_runner on the VM to run the set of tests.
395      executable_args += [
396        "tast",
397        "--suite-name",
398        target_name,
399      ]
400      if (defined(tast_attr_expr)) {
401        executable_args += [
402          "--attr-expr",
403          tast_attr_expr,
404        ]
405      } else {
406        foreach(test, tast_tests) {
407          executable_args += [
408            "-t",
409            test,
410          ]
411        }
412      }
413      if (defined(tast_vars)) {
414        foreach(var, tast_vars) {
415          executable_args += [
416            "--tast-var",
417            var,
418          ]
419        }
420      }
421      if (dcheck_always_on) {
422        executable_args += [
423          "--tast-extra-use-flags",
424          "chrome_dcheck",
425        ]
426      }
427    } else {
428      executable_args += [ "host-cmd" ]
429    }
430    executable_args += [
431      "--cros-cache",
432      "build/cros_cache/",
433      "--path-to-outdir",
434      rebase_path(root_out_dir, "//"),
435      "-v",
436    ]
437
438    if (!is_tast && strip_chrome) {
439      executable_args += [ "--strip-chrome" ]
440    }
441
442    if (!skip_generating_board_args) {
443      executable_args += [
444        "--board",
445        cros_board,
446      ]
447
448      _cros_is_vm = false
449      foreach(b, string_split(cros_boards_with_qemu_images, ":")) {
450        if (cros_board == b) {
451          _cros_is_vm = true
452        }
453      }
454      if (_cros_is_vm) {
455        executable_args += [ "--use-vm" ]
456      } else {
457        executable_args += [ "--flash" ]
458      }
459    }
460
461    # If we have public Chromium builds, use public Chromium OS images when
462    # flashing the test device.
463    if (!is_chrome_branded) {
464      executable_args += [ "--public-image" ]
465    }
466
467    if (deploy_lacros) {
468      executable_args += [ "--deploy-lacros" ]
469    }
470
471    if (deploy_chrome && !defined(test_exe)) {
472      executable_args += [ "--deploy-chrome" ]
473    }
474
475    # executable_args should be finished, now build the data and deps lists.
476    deps = [ "//testing/buildbot/filters:chromeos_filters" ]
477    if (defined(invoker.deps)) {
478      deps += invoker.deps
479    }
480    data = [
481      "//.vpython3",
482
483      # We use android test-runner's results libs to construct gtest output
484      # json.
485      "//build/android/pylib/__init__.py",
486      "//build/android/pylib/base/",
487      "//build/android/pylib/results/",
488      "//build/chromeos/",
489      "//build/util/",
490      "//third_party/chromite/",
491    ]
492
493    if (defined(invoker.data)) {
494      data += invoker.data
495    }
496
497    data_deps = [ "//testing:test_scripts_shared" ]
498    if (cros_sdk_version != "") {
499      data_deps += [ ":" + target_name + "_cros_deps__helper" ]
500    }
501    if (defined(invoker.data_deps)) {
502      data_deps += invoker.data_deps
503    }
504  }
505}
506
507template("tast_test") {
508  forward_variables_from(invoker, "*")
509
510  # Default the expression to match any chrome-related test.
511  if (!defined(tast_attr_expr) && !defined(tast_tests)) {
512    # The following expression filters out all non-critical tests. See the link
513    # below for more details:
514    # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md
515    tast_attr_expr = "\"group:mainline\" && \"dep:chrome\""
516
517    if (defined(enable_tast_informational_tests) &&
518        enable_tast_informational_tests) {
519      tast_attr_expr += " && informational"
520    } else {
521      tast_attr_expr += " && !informational"
522    }
523    if (!is_chrome_branded) {
524      tast_attr_expr += " && !\"dep:chrome_internal\""
525    }
526  } else {
527    assert(defined(tast_attr_expr) != defined(tast_tests),
528           "Specify one of tast_tests or tast_attr_expr.")
529  }
530
531  _data_deps = [
532    "//:chromiumos_preflight",  # Builds the browser.
533    "//chromeos:cros_chrome_deploy",  # Adds additional browser run-time deps.
534
535    # Tools used to symbolize Chrome crash dumps.
536    # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by
537    # default.
538    "//third_party/breakpad:dump_syms",
539    "//third_party/breakpad:minidump_dump",
540    "//third_party/breakpad:minidump_stackwalk",
541  ]
542  _data = [ "//components/crash/content/tools/generate_breakpad_symbols.py" ]
543
544  if (is_skylab) {
545    generate_skylab_tast_filter(target_name) {
546      # chromite.deploy_chrome is needed for sideloading Chrome.
547      data = _data + [ "//third_party/chromite/" ]
548      data_deps = _data_deps
549
550      # To disable a test on specific milestones, add it to the appropriate
551      # collection in the following file
552      tast_control = "//chromeos/tast_control.gni"
553    }
554  } else {
555    # Append any disabled tests to the expression.
556    if (defined(tast_disabled_tests)) {
557      assert(defined(tast_attr_expr),
558             "tast_attr_expr must be used when specifying tast_disabled_tests.")
559      foreach(_test_name, tast_disabled_tests) {
560        tast_attr_expr += " && !\"name:${_test_name}\""
561      }
562    }
563    if (defined(tast_attr_expr)) {
564      tast_attr_expr = "( " + tast_attr_expr + " )"
565    }
566    generate_runner_script(target_name) {
567      testonly = true
568      generated_script = "$root_build_dir/bin/run_${target_name}"
569      runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
570      deploy_chrome = true
571
572      data_deps = _data_deps
573      if (!defined(deploy_lacros_chrome)) {
574        deploy_lacros_chrome = false
575      }
576      deploy_lacros = deploy_lacros_chrome
577      data = _data
578      if (deploy_lacros_chrome) {
579        data += [
580          # A script needed to launch Lacros in Lacros Tast tests.
581          "//build/lacros/mojo_connection_lacros_launcher.py",
582        ]
583
584        # By default, tast tests download a lacros-chrome from a gcs location and
585        # use it for testing. To support running lacros tast tests from Chromium CI,
586        # a Var is added to support pointing the tast tests to use a specified
587        # pre-deployed lacros-chrome. The location is decided by:
588        # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61
589        tast_vars = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ]
590      }
591    }
592  }
593}
594
595template("lacros_tast_tests") {
596  forward_variables_from(invoker,
597                         [
598                           "tast_attr_expr",
599                           "tast_disabled_tests",
600                           "tast_tests",
601                           "tast_control",
602                         ])
603  assert(defined(tast_attr_expr) != defined(tast_tests),
604         "Specify one of tast_tests or tast_attr_expr.")
605
606  _lacros_data_deps = [
607    "//chrome",  # Builds the browser.
608
609    # Tools used to symbolize Chrome crash dumps.
610    # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by
611    # default.
612    "//third_party/breakpad:dump_syms",
613    "//third_party/breakpad:minidump_dump",
614    "//third_party/breakpad:minidump_stackwalk",
615  ]
616
617  _lacros_data = [
618    "//components/crash/content/tools/generate_breakpad_symbols.py",
619
620    # A script needed to launch Lacros in Lacros Tast tests.
621    "//build/lacros/mojo_connection_lacros_launcher.py",
622  ]
623
624  if (is_skylab) {
625    generate_skylab_tast_filter(target_name) {
626      data = _lacros_data + [
627               "//.vpython3",
628               "//third_party/chromite/",
629             ]
630      data_deps = _lacros_data_deps
631
632      # To disable a test on specific milestones, add it to the appropriate
633      # collection in the following file
634      tast_control = "//chromeos/tast_control.gni"
635    }
636  } else {
637    # Append any disabled tests to the expression.
638    if (defined(tast_disabled_tests)) {
639      assert(defined(tast_attr_expr),
640             "tast_attr_expr must be used when specifying tast_disabled_tests.")
641      foreach(_test, tast_disabled_tests) {
642        _excluded_test_name_and_board = []
643        _excluded_test_name_and_board = string_split(_test, "@") + [ "" ]
644        _excluded_test_name = _excluded_test_name_and_board[0]
645        _excluded_board = _excluded_test_name_and_board[1]
646        if (_excluded_board == "" || _excluded_board == cros_board) {
647          tast_attr_expr += " && !\"name:${_excluded_test_name}\""
648        }
649      }
650    }
651    if (defined(tast_attr_expr)) {
652      tast_attr_expr = "( " + tast_attr_expr + " )"
653    }
654    generate_runner_script(target_name) {
655      testonly = true
656      deploy_lacros = true
657      generated_script = "$root_build_dir/bin/run_${target_name}"
658      runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
659
660      # At build time, Lacros tests don't know whether they'll run on VM or HW,
661      # and instead, these flags are specified at runtime when invoking the
662      # generated runner script.
663      skip_generating_board_args = true
664
665      # By default, tast tests download a lacros-chrome from a gcs location and
666      # use it for testing. To support running lacros tast tests from Chromium CI,
667      # a Var is added to support pointing the tast tests to use a specified
668      # pre-deployed lacros-chrome. The location is decided by:
669      # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61
670      tast_vars = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ]
671
672      data_deps = _lacros_data_deps
673
674      data = _lacros_data
675    }
676  }
677}
678