• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      "//build/cros_cache/common/",
161      "//chrome/VERSION",
162
163      # The LKGM file controls what version of the VM image to download. Add it
164      # as data here so that changes to it will trigger analyze.
165      "//chromeos/CHROMEOS_LKGM",
166    ]
167    if (cros_boards_with_qemu_images != "") {
168      data += [ "//build/cros_cache/cipd/" ]
169    }
170  }
171}
172
173# Creates tast filter files for skylab tast tests.
174# Args:
175#   tast_attr_expr: Tast expression to determine tests to run. This creates the
176#       initial set of tests that can be further filtered..
177#   tast_tests: Names of tests to enable in tast. All other tests will be
178#       disabled that are not listed.
179#   tast_disabled_tests: Names of tests to disable in tast. All other tests that
180#       match the tast expression will still run.
181#   tast_control: gni file with collections of tests to be used for specific
182#       filters (e.g. "//chromeos/tast_control.gni"). Any lists of strings in
183#       this file will be used to generate additional tast expressions with
184#       those strings expanded into tests to disable (i.e. as && !"name:test").
185#       The name of those lists are then intended to be used to specify in
186#       test_suites.pyl which collection to be used on specific test suites.
187template("generate_skylab_tast_filter") {
188  forward_variables_from(invoker,
189                         [
190                           "tast_attr_expr",
191                           "tast_tests",
192                           "tast_disabled_tests",
193                           "tast_control",
194                         ])
195
196  if (defined(tast_disabled_tests)) {
197    assert(defined(tast_attr_expr),
198           "tast_attr_expr must be used when specifying tast_disabled_tests.")
199  }
200  _generated_filter = "$root_build_dir/bin/${target_name}.filter"
201  _skylab_args = [
202    "generate-filter",
203    "--output",
204    rebase_path(_generated_filter),
205  ]
206  if (defined(tast_control)) {
207    _skylab_args += [
208      "--tast-control",
209      rebase_path(tast_control),
210    ]
211  }
212  if (defined(tast_attr_expr)) {
213    _skylab_args += [
214      "--tast-expr",
215      tast_attr_expr,
216    ]
217  }
218  if (defined(tast_tests)) {
219    foreach(_test, tast_tests) {
220      _skylab_args += [
221        "--enabled-tests",
222        _test,
223      ]
224    }
225  }
226  if (defined(tast_disabled_tests)) {
227    foreach(_test_name, tast_disabled_tests) {
228      _skylab_args += [
229        "--disabled-tests",
230        _test_name,
231      ]
232    }
233  }
234  action(target_name) {
235    testonly = true
236    script = "//build/chromeos/generate_skylab_tast_filter.py"
237    if (defined(tast_control)) {
238      sources = [ tast_control ]
239    }
240    outputs = [ _generated_filter ]
241    args = _skylab_args
242    if (defined(invoker.data_deps)) {
243      data_deps = invoker.data_deps
244    }
245    data = [ _generated_filter ]
246    if (defined(invoker.data)) {
247      data += invoker.data
248    }
249    if (defined(invoker.deps)) {
250      deps = invoker.deps
251    }
252  }
253}
254
255# Creates a script at $generated_script that can be used to launch a cros VM
256# and optionally run a test within it.
257# Args:
258#   test_exe: Name of test binary located in the out dir. This will get copied
259#       to the VM and executed there.
260#   tast_attr_expr: Tast expression to pass to local_test_runner on the VM.
261#   tast_tests: List of Tast tests to run on the VM. Note that when this is
262#       specified, the target name used to invoke this template will be
263#       designated as the "name" of this test and will primarly used for test
264#       results tracking and displaying (eg: flakiness dashboard).
265#   generated_script: Path to place the generated script.
266#   deploy_chrome: If true, deploys a locally built chrome located in the root
267#       build dir to the VM or DUT after launching it.
268#   deploy_lacros: If true, deploys a locally built Lacros located in the root
269#       build dir to the VM or DUT after launching it.
270#   runtime_deps_file: Path to file listing runtime deps for the test. If set,
271#       all files listed will be copied to the VM before testing.
272#   skip_generating_board_args: By default, this template generates an '--board'
273#       arg with corresponding '--flash' or '--use-vm' args for device and vm
274#       respectively. This argument instructs the template to skip generating
275#       them, and it's designed for use cases where one builds for one board
276#       (e.g. amd64-generic), but tests on a different board (e.g. eve).
277#   tast_vars: A list of "key=value" runtime variable pairs to pass to invoke
278#   strip_chrome: If true, strips Chrome before deploying it for non-Tast tests.
279#       the Tast tests. For more details, please see:
280#       https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/docs/writing_tests.md#Runtime-variables
281template("generate_runner_script") {
282  forward_variables_from(invoker,
283                         [
284                           "deploy_chrome",
285                           "deploy_lacros",
286                           "generated_script",
287                           "runtime_deps_file",
288                           "skip_generating_board_args",
289                           "strip_chrome",
290                           "tast_attr_expr",
291                           "tast_tests",
292                           "tast_vars",
293                           "testonly",
294                           "test_exe",
295                         ])
296
297  if (!defined(skip_generating_board_args)) {
298    # --board should be assigned by the autotest wrapper on skylab builders
299    skip_generating_board_args = is_skylab
300  }
301
302  if (skip_generating_board_args) {
303    # cros_board is not needed, so setting it to empty to avoid being used
304    # accidentally below.
305    cros_board = ""
306    not_needed([ cros_board ])
307  }
308
309  if (!defined(deploy_chrome)) {
310    deploy_chrome = false
311  }
312  if (!defined(deploy_lacros)) {
313    deploy_lacros = false
314  }
315  if (!defined(strip_chrome)) {
316    strip_chrome = false
317  }
318  is_tast = defined(tast_attr_expr) || defined(tast_tests)
319  assert(!(is_tast && defined(test_exe)),
320         "Tast tests are invoked from binaries shipped with the VM image. " +
321             "There should be no locally built binary needed.")
322  assert(is_tast || !defined(tast_vars),
323         "tast_vars is only support for Tast tests")
324
325  if (is_tast) {
326    not_needed([ "strip_chrome" ])
327  }
328
329  # If we're in the cros chrome-sdk (and not the raw ebuild), the test will
330  # need some additional runtime data located in the SDK cache.
331  if (cros_sdk_version != "") {
332    assert(defined(generated_script),
333           "Must specify where to place generated test launcher script via " +
334               "'generated_script'")
335
336    generate_chromeos_sdk_deps(target_name + "_cros_deps__helper") {
337      is_tast = is_tast
338      deploy_chrome = deploy_chrome
339    }
340  }
341
342  generate_wrapper(target_name) {
343    executable = "//build/chromeos/test_runner.py"
344    wrapper_script = generated_script
345    executable_args = []
346
347    if (defined(runtime_deps_file)) {
348      write_runtime_deps = runtime_deps_file
349    }
350
351    # Build executable_args for the three different test types: GTest, Tast,
352    # and host-side commands (eg telemetry).
353    if (defined(test_exe)) {
354      executable_args += [
355        "gtest",
356        "--test-exe",
357        test_exe,
358      ]
359
360      # This target is not a gtest unit test, but an integration test suite.
361      # Similar to interactive ui tests, it would start a full browser and
362      # then do testing.
363      # See more at //docs/testing/chromeos_integration.
364      if (test_exe == "chromeos_integration_tests") {
365        # Run the test sudo helper.
366        executable_args += [ "--run-test-sudo-helper" ]
367
368        if (is_chromeos_ash) {
369          # For ash, it need to first stop the existing ash.
370          executable_args += [ "--stop-ui" ]
371
372          # Use the deployed dbus configs.
373          executable_args += [ "--use-deployed-dbus-configs" ]
374        }
375
376        # Lacros need to know the wayland socket file created by Ash.
377        # In this way, Lacros will be connected to the system Ash.
378        if (is_chromeos_lacros) {
379          executable_args += [
380            "--env-var",
381            "XDG_RUNTIME_DIR",
382            "/run/chrome",
383          ]
384        }
385
386        # Make the tests match the browser's selinux tags so it gets the same
387        # security context as the browser would.
388        executable_args += [ "--set-selinux-label=chromeos_integration_tests=u:object_r:chrome_browser_exec:s0" ]
389      }
390      if (defined(runtime_deps_file)) {
391        executable_args += [
392          "--runtime-deps-path",
393          rebase_path(runtime_deps_file, root_build_dir),
394        ]
395      }
396    } else if (is_tast) {
397      # When --tast-tests is specified, test_runner.py will call
398      # local_test_runner on the VM to run the set of tests.
399      executable_args += [
400        "tast",
401        "--suite-name",
402        target_name,
403      ]
404      if (defined(tast_attr_expr)) {
405        executable_args += [
406          "--attr-expr",
407          tast_attr_expr,
408        ]
409      } else {
410        foreach(test, tast_tests) {
411          executable_args += [
412            "-t",
413            test,
414          ]
415        }
416      }
417      if (defined(tast_vars)) {
418        foreach(var, tast_vars) {
419          executable_args += [
420            "--tast-var",
421            var,
422          ]
423        }
424      }
425      if (dcheck_always_on) {
426        executable_args += [
427          "--tast-extra-use-flags",
428          "chrome_dcheck",
429        ]
430      }
431    } else {
432      executable_args += [ "host-cmd" ]
433    }
434    executable_args += [
435      "--cros-cache",
436      "build/cros_cache/",
437      "--path-to-outdir",
438      rebase_path(root_out_dir, "//"),
439      "-v",
440    ]
441
442    if (!is_tast && strip_chrome) {
443      executable_args += [ "--strip-chrome" ]
444    }
445
446    if (!skip_generating_board_args) {
447      executable_args += [
448        "--board",
449        cros_board,
450      ]
451
452      _cros_is_vm = false
453      foreach(b, string_split(cros_boards_with_qemu_images, ":")) {
454        if (cros_board == b) {
455          _cros_is_vm = true
456        }
457      }
458      if (_cros_is_vm) {
459        executable_args += [ "--use-vm" ]
460      } else {
461        executable_args += [ "--flash" ]
462      }
463    }
464
465    # If we have public Chromium builds, use public Chromium OS images when
466    # flashing the test device.
467    if (!is_chrome_branded) {
468      executable_args += [ "--public-image" ]
469    }
470
471    if (deploy_lacros) {
472      executable_args += [ "--deploy-lacros" ]
473    }
474
475    if (deploy_chrome && !defined(test_exe)) {
476      executable_args += [ "--deploy-chrome" ]
477    }
478
479    # executable_args should be finished, now build the data and deps lists.
480    deps = [ "//testing/buildbot/filters:chromeos_filters" ]
481    if (defined(invoker.deps)) {
482      deps += invoker.deps
483    }
484    data = [
485      "//.vpython3",
486
487      # We use android test-runner's results libs to construct gtest output
488      # json.
489      "//build/android/pylib/__init__.py",
490      "//build/android/pylib/base/",
491      "//build/android/pylib/results/",
492      "//build/chromeos/",
493      "//build/util/",
494      "//third_party/chromite/",
495    ]
496
497    if (defined(invoker.data)) {
498      data += invoker.data
499    }
500
501    data_deps = [ "//testing:test_scripts_shared" ]
502    if (cros_sdk_version != "") {
503      data_deps += [ ":" + target_name + "_cros_deps__helper" ]
504    }
505    if (defined(invoker.data_deps)) {
506      data_deps += invoker.data_deps
507    }
508  }
509}
510
511template("tast_test") {
512  forward_variables_from(invoker, "*")
513
514  # Default the expression to match any chrome-related test.
515  if (!defined(tast_attr_expr) && !defined(tast_tests)) {
516    # The following expression filters out all non-critical tests. See the link
517    # below for more details:
518    # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md
519    tast_attr_expr = "\"group:mainline\" && \"dep:chrome\""
520
521    if (defined(enable_tast_informational_tests) &&
522        enable_tast_informational_tests) {
523      tast_attr_expr += " && informational"
524    } else {
525      tast_attr_expr += " && !informational"
526    }
527    if (!is_chrome_branded) {
528      tast_attr_expr += " && !\"dep:chrome_internal\""
529    }
530  } else {
531    assert(defined(tast_attr_expr) != defined(tast_tests),
532           "Specify one of tast_tests or tast_attr_expr.")
533  }
534
535  _data_deps = [
536    "//:chromiumos_preflight",  # Builds the browser.
537    "//chromeos:cros_chrome_deploy",  # Adds additional browser run-time deps.
538
539    # Tools used to symbolize Chrome crash dumps.
540    # TODO(crbug.com/40160552): Remove these if/when all tests pick them up by
541    # default.
542    "//third_party/breakpad:dump_syms",
543    "//third_party/breakpad:minidump_dump",
544    "//third_party/breakpad:minidump_stackwalk",
545  ]
546  _data = [ "//components/crash/content/tools/generate_breakpad_symbols.py" ]
547
548  if (is_skylab) {
549    generate_skylab_tast_filter(target_name) {
550      # chromite.deploy_chrome is needed for sideloading Chrome.
551      data = _data + [ "//third_party/chromite/" ]
552      data_deps = _data_deps
553
554      # To disable a test on specific milestones, add it to the appropriate
555      # collection in the following file
556      tast_control = "//chromeos/tast_control.gni"
557    }
558  } else {
559    # Append any disabled tests to the expression.
560    if (defined(tast_disabled_tests)) {
561      assert(defined(tast_attr_expr),
562             "tast_attr_expr must be used when specifying tast_disabled_tests.")
563      foreach(_test_name, tast_disabled_tests) {
564        tast_attr_expr += " && !\"name:${_test_name}\""
565      }
566    }
567    if (defined(tast_attr_expr)) {
568      tast_attr_expr = "( " + tast_attr_expr + " )"
569    }
570    generate_runner_script(target_name) {
571      testonly = true
572      generated_script = "$root_build_dir/bin/run_${target_name}"
573      runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
574      deploy_chrome = true
575
576      data_deps = _data_deps
577      if (!defined(deploy_lacros_chrome)) {
578        deploy_lacros_chrome = false
579      }
580      deploy_lacros = deploy_lacros_chrome
581      data = _data
582      if (deploy_lacros_chrome) {
583        data += [
584          # A script needed to launch Lacros in Lacros Tast tests.
585          "//build/lacros/mojo_connection_lacros_launcher.py",
586        ]
587
588        # By default, tast tests download a lacros-chrome from a gcs location and
589        # use it for testing. To support running lacros tast tests from Chromium CI,
590        # a Var is added to support pointing the tast tests to use a specified
591        # pre-deployed lacros-chrome. The location is decided by:
592        # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61
593        tast_vars = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ]
594      }
595    }
596  }
597}
598
599template("lacros_tast_tests") {
600  forward_variables_from(invoker,
601                         [
602                           "tast_attr_expr",
603                           "tast_disabled_tests",
604                           "tast_tests",
605                           "tast_control",
606                         ])
607  assert(defined(tast_attr_expr) != defined(tast_tests),
608         "Specify one of tast_tests or tast_attr_expr.")
609
610  _lacros_data_deps = [
611    "//chrome",  # Builds the browser.
612
613    # Tools used to symbolize Chrome crash dumps.
614    # TODO(crbug.com/40160552): Remove these if/when all tests pick them up by
615    # default.
616    "//third_party/breakpad:dump_syms",
617    "//third_party/breakpad:minidump_dump",
618    "//third_party/breakpad:minidump_stackwalk",
619  ]
620
621  _lacros_data = [
622    "//components/crash/content/tools/generate_breakpad_symbols.py",
623
624    # A script needed to launch Lacros in Lacros Tast tests.
625    "//build/lacros/mojo_connection_lacros_launcher.py",
626  ]
627
628  if (is_skylab) {
629    generate_skylab_tast_filter(target_name) {
630      data = _lacros_data + [
631               "//.vpython3",
632               "//third_party/chromite/",
633             ]
634      data_deps = _lacros_data_deps
635
636      # To disable a test on specific milestones, add it to the appropriate
637      # collection in the following file
638      tast_control = "//chromeos/tast_control.gni"
639    }
640  } else {
641    # Append any disabled tests to the expression.
642    if (defined(tast_disabled_tests)) {
643      assert(defined(tast_attr_expr),
644             "tast_attr_expr must be used when specifying tast_disabled_tests.")
645      foreach(_test, tast_disabled_tests) {
646        _excluded_test_name_and_board = []
647        _excluded_test_name_and_board = string_split(_test, "@") + [ "" ]
648        _excluded_test_name = _excluded_test_name_and_board[0]
649        _excluded_board = _excluded_test_name_and_board[1]
650        if (_excluded_board == "" || _excluded_board == cros_board) {
651          tast_attr_expr += " && !\"name:${_excluded_test_name}\""
652        }
653      }
654    }
655    if (defined(tast_attr_expr)) {
656      tast_attr_expr = "( " + tast_attr_expr + " )"
657    }
658    generate_runner_script(target_name) {
659      testonly = true
660      deploy_lacros = true
661      generated_script = "$root_build_dir/bin/run_${target_name}"
662      runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
663
664      # At build time, Lacros tests don't know whether they'll run on VM or HW,
665      # and instead, these flags are specified at runtime when invoking the
666      # generated runner script.
667      skip_generating_board_args = true
668
669      # By default, tast tests download a lacros-chrome from a gcs location and
670      # use it for testing. To support running lacros tast tests from Chromium CI,
671      # a Var is added to support pointing the tast tests to use a specified
672      # pre-deployed lacros-chrome. The location is decided by:
673      # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61
674      tast_vars = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ]
675
676      data_deps = _lacros_data_deps
677
678      data = _lacros_data
679    }
680  }
681}
682