[flutter test] Make flutter_test portable
This change relativizes the paths used in the generated
invocation scripts - and adds 'test spec' support to the target (meaning
that the build will register these targets as tests to pass onto
the infrastructure, running these in a shard on separate bot). Moreover,
this change stops supplying the test source directory as this is not
portable.
Bug: IN-823
Change-Id: Ib1a30d1a407a72cbc94c2550f1109ece8fe91fea
diff --git a/runtime/dart/flutter_test.gni b/runtime/dart/flutter_test.gni
index 0a4e95a..280e7fb 100644
--- a/runtime/dart/flutter_test.gni
+++ b/runtime/dart/flutter_test.gni
@@ -4,6 +4,7 @@
import("//build/dart/dart_library.gni")
import("//build/dart/toolchain.gni")
+import("//build/testing/test_spec.gni")
import("//topaz/runtime/dart/dart_kernel.gni")
# Defines a flutter test suite
@@ -42,10 +43,12 @@
_main_target_name = target_name
_library_target_name = "${target_name}_library"
+ _copy_target_name = "${target_name}_copy"
+ _snapshot_target_name = "${target_name}_snapshot"
- _sources_dir = "test"
+ _source_dir = "test"
if (defined(invoker.source_dir)) {
- _sources_dir = invoker.source_dir
+ _source_dir = invoker.source_dir
}
dart_library(_library_target_name) {
@@ -58,17 +61,12 @@
infer_package_name = true
sources_required = false
- source_dir = _sources_dir
+ source_dir = _source_dir
sources = invoker.sources
}
_dot_packages_file = "$target_gen_dir/$_library_target_name.packages"
- _fuchsia_tester_label = "//third_party/dart-pkg/git/flutter/packages/flutter_tools:fuchsia_tester($host_toolchain)"
- _fuchsia_tester_out_dir =
- get_label_info(_fuchsia_tester_label, "root_out_dir")
- _fuchsia_tester_bin = "$_fuchsia_tester_out_dir/dart-tools/fuchsia_tester"
-
_flutter_shell_label =
"//third_party/flutter/shell/testing/($host_toolchain)"
_flutter_shell_out_dir =
@@ -79,8 +77,10 @@
_tests_json = []
_tests_filename = "$target_gen_dir/tests.json"
+ _test_runtime_deps = [ _tests_filename ]
+
foreach(_source_file, invoker.sources) {
- _source_path = "$_sources_dir/$_source_file"
+ _source_path = "$_source_dir/$_source_file"
_test_target =
exec_script("//topaz/runtime/dart/gen_flutter_test_target_name.py",
@@ -95,19 +95,19 @@
_kernel_target_name = "${_test_target_name}_dill"
_bootstrap_target_name = "${_test_target_name}_bootstrap"
- _bootstrap_file_name =
- "${target_gen_dir}/${_bootstrap_target_name}.dart"
+ _bootstrap_filename = "${target_gen_dir}/${_bootstrap_target_name}.dart"
+ _dill_filename = "$target_gen_dir/${_kernel_target_name}_kernel.dil"
action(_bootstrap_target_name) {
script = "$root_out_dir/dart-tools/build_test_bootstrap"
outputs = [
- _bootstrap_file_name,
+ _bootstrap_filename,
]
rebased_source = rebase_path(_source_path, target_gen_dir)
args = [
"--output",
- rebase_path(_bootstrap_file_name),
+ rebase_path(_bootstrap_filename),
"--test-name",
"$rebased_source",
]
@@ -120,7 +120,7 @@
dart_kernel(_kernel_target_name) {
platform_name = "flutter_runner"
disable_analysis = true
- main_dart = _bootstrap_file_name
+ main_dart = _bootstrap_filename
args = []
# TODO(tvolkert): Change to flutter platform once libraries.json works
@@ -134,7 +134,7 @@
platform_path = "$root_out_dir/flutter_runner_patched_sdk"
sources = [
- _bootstrap_file_name,
+ _bootstrap_filename,
]
sources_required = false
non_dart_deps = [ ":$_bootstrap_target_name" ]
@@ -150,18 +150,131 @@
_tests_json += [
{
- source = rebase_path(_bootstrap_file_name)
- dill =
- rebase_path("$target_gen_dir/${_kernel_target_name}_kernel.dil")
+ source = rebase_path(_bootstrap_filename, root_build_dir)
+ dill = rebase_path(_dill_filename, root_build_dir)
},
]
+ _test_runtime_deps += [
+ _bootstrap_filename,
+ _dill_filename,
+ ]
}
write_file(_tests_filename, _tests_json, "json")
}
+ # Copies resources to the build directory so that it may be archived
+ # with the test and the rest of the test's dependencies, so that the
+ # archiving happens with respect to the build directory.
+ _data_dir = "$target_gen_dir/${_main_target_name}_data"
+ _icudtl_file = "$_data_dir/icudtl.dat"
+ _dart_binary = "$_data_dir/dart"
+ copy(_copy_target_name) {
+ sources = [
+ "//third_party/icu/common/icudtl.dat",
+ "//topaz/tools/prebuilt-dart-sdk/$host_os-$host_cpu/bin/dart",
+ ]
+ outputs = [
+ "$_data_dir/{{source_file_part}}",
+ ]
+ }
+
+ # Creates a snapshot file of the fuchsia tester, which allows the test to
+ # be invoked hermetically.
+ _snapshot = "$target_gen_dir/${_main_target_name}.snapshot"
+ _flutter_tools_label = "//third_party/dart-pkg/git/flutter/packages/flutter_tools:flutter_tools"
+ _dart_flutter_tools_gen_dir =
+ get_label_info("$_flutter_tools_label($dart_toolchain)",
+ "target_gen_dir")
+ _packages_path =
+ "$_dart_flutter_tools_gen_dir/flutter_tools.packages"
+ _main_file = "//third_party/dart-pkg/git/flutter/packages/flutter_tools/bin/fuchsia_tester.dart"
+
+ action(_snapshot_target_name) {
+ depfile = "${_snapshot}.d"
+
+ outputs = [
+ _snapshot,
+ ]
+
+ script = _dart_binary
+
+ # The snapshot path needs to be rebased on top of the root build dir so
+ # that the resulting depfile gets properly formatted.
+ _rebased_snapshot = rebase_path(_snapshot, root_build_dir)
+ _rebased_depfile = rebase_path(depfile)
+ _rebased_packages_path = rebase_path(_packages_path)
+
+ args = [
+ "--snapshot=$_rebased_snapshot",
+ "--snapshot-depfile=$_rebased_depfile",
+ "--packages=$_rebased_packages_path",
+ rebase_path(_main_file),
+ ]
+
+ deps = dart_sdk_deps + [
+ "$_flutter_tools_label",
+ ":$_copy_target_name",
+ ]
+ }
+
+ _invocation_file = "$target_gen_dir/$target_name"
+
+ # _invocation_params encapsulates the parameters to pass to the
+ # invocation-generating action below. The utility lies in being able to
+ # construct the actions args and metadata at the same time.
+ _invocation_params = [
+ {
+ flag = "--wd"
+
+ # TODO(crbug.com/gn/56): Rebasing root_build_dir alone yields a path
+ # component that leaves root_build_dir, preventing portability.
+ path = "$root_build_dir/dummy/.."
+ base = get_path_info(_invocation_file, "dir")
+ },
+ {
+ flag = "--out"
+ path = _invocation_file
+ base = "" # Will result in an absolute path.
+ },
+ {
+ flag = "--dart"
+ path = _dart_binary
+ base = root_build_dir
+ },
+ {
+ flag = "--snapshot"
+ path = _snapshot
+ base = root_build_dir
+ },
+ {
+ flag = "--tests"
+ path = _tests_filename
+ base = root_build_dir
+ },
+ {
+ flag = "--dot-packages"
+ path = _dot_packages_file
+ base = root_build_dir
+ },
+ {
+ flag = "--flutter-shell"
+ path = _flutter_shell_bin
+ base = root_build_dir
+ },
+ {
+ flag = "--icudtl"
+ path = _icudtl_file
+ base = root_build_dir
+ },
+ {
+ flag = "--sdk-root"
+ path = "$root_out_dir/flutter_runner_patched_sdk"
+ base = root_build_dir
+ },
+ ]
+
action(_main_target_name) {
- _invocation_file = "$target_gen_dir/$target_name"
script = "//topaz/runtime/dart/gen_flutter_test_invocation.py"
testonly = true
outputs = [
@@ -170,41 +283,33 @@
inputs = [
_dot_packages_file,
- _bootstrap_file_name,
- _fuchsia_tester_bin,
+ _bootstrap_filename,
_flutter_shell_bin,
_tests_filename,
]
- args = [
- "--out",
- rebase_path(_invocation_file),
- "--tests",
- rebase_path(_tests_filename),
- "--source-dir",
- rebase_path(_sources_dir),
- "--dot-packages",
- rebase_path(_dot_packages_file),
- "--test-runner",
- rebase_path(_fuchsia_tester_bin),
- "--flutter-shell",
- rebase_path(_flutter_shell_bin),
- "--icudtl",
- rebase_path("//third_party/icu/common/icudtl.dat"),
- "--sdk-root",
- rebase_path("$root_out_dir/flutter_runner_patched_sdk"),
- ]
+ args = []
+ foreach(param, _invocation_params) {
+ args += [
+ param.flag,
+ rebase_path(param.path, param.base),
+ ]
+ if (param.flag != "--wd") {
+ _test_runtime_deps += [ param.path ]
+ }
+ }
deps = [
":$_library_target_name",
":$_bootstrap_target_name",
":${_kernel_target_name}_kernel",
+ ":$_snapshot_target_name",
+ ":$_copy_target_name",
_flutter_shell_label,
- _fuchsia_tester_label,
] + _precompiled_kernel_target_names
metadata = {
- test_runtime_deps = [ rebase_path(_invocation_file, root_build_dir) ]
+ test_runtime_deps = _test_runtime_deps
}
}
}
@@ -212,12 +317,24 @@
# Not the Dart toolchain.
template("flutter_test") {
_main_target_name = target_name
+ _spec_target_name = "${target_name}_spec"
_invocation_file = "$target_gen_dir/$target_name"
if (is_linux || is_mac) {
- # TODO(IN-819): Delete renaming when dart tests are no longer run out of one
- # directory
+ # TODO(IN-819): Delete renaming when dart tests are no longer run out of
+ # $root_build_dir/host_tests/.
_invocation_file = "$root_out_dir/$target_name"
+
+ test_spec(_spec_target_name) {
+ testonly = true
+ name = _main_target_name
+ location = _invocation_file
+ deps = [
+ ":$_main_target_name($dart_toolchain)",
+ ]
+ }
+ } else {
+ not_needed([ "_spec_target_name" ])
}
action(_main_target_name) {
@@ -231,13 +348,19 @@
_dart_target_gen_dir =
get_label_info(":bogus($dart_toolchain)", "target_gen_dir")
- _delegate_file = "$_dart_target_gen_dir/$target_name"
+ _delegate_file = "$_dart_target_gen_dir/$_main_target_name"
args = [
+ "--wd",
+
+ # TODO(crbug.com/gn/56): Rebasing root_build_dir alone yields a path
+ # component that leaves root_build_dir, preventing portability.
+ rebase_path("$root_build_dir/dummy/..",
+ get_path_info(_invocation_file, "dir")),
"--out",
rebase_path(_invocation_file),
"--test",
- rebase_path(_delegate_file),
+ rebase_path(_delegate_file, root_build_dir),
]
deps = [
@@ -259,6 +382,7 @@
},
]
}
+ deps += [ ":$_spec_target_name" ]
}
}
}
diff --git a/runtime/dart/gen_flutter_test_bundle_invocation.py b/runtime/dart/gen_flutter_test_bundle_invocation.py
index 2a3fd4e..a61a2d8 100755
--- a/runtime/dart/gen_flutter_test_bundle_invocation.py
+++ b/runtime/dart/gen_flutter_test_bundle_invocation.py
@@ -9,20 +9,19 @@
import string
import sys
-
def main():
parser = argparse.ArgumentParser(
- description='Generate a script that invokes multiple dart_test targets')
+ description='Generate a script that invokes multiple flutter_test targets')
+ parser.add_argument('--wd',
+ help='Path to the working directory, relative to that of the invocation file',
+ required=True)
parser.add_argument('--out',
help='Path to the invocation file to generate',
required=True)
parser.add_argument('--test',
action='append',
- help='Adds a target to the list of test executables',
+ help='Adds a target to the list of test executables, relative to the working directory',
required=True)
- parser.add_argument('--test-name',
- action='append',
- help='Adds a readable test name to the list of tests')
args = parser.parse_args()
test_file = args.out
@@ -30,52 +29,17 @@
if not os.path.exists(test_dir):
os.makedirs(test_dir)
- test_failed_definition_block = '''
-FAILED_TESTS=()
-PIDS_NAMES=()
+ script = '''#!/bin/bash
-function run_test () {
- local test_exe="$1"
- local test_name="$2"
- echo "Running $test_name"
- env $test_exe & PIDS_NAMES+=($!:$test_name)
-}
-
-function test_failed () {
- FAILED_TESTS+=("$1")
-}
+# DO NOT EDIT
+# This script is generated by:
+# //topaz/runtime/dart/gen_test_bundle_invocation.py
+# See: //topaz/runtime/dart/dart_test.gni
'''
-
- test_wait_to_complete_block = '''
-for pid_name in ${PIDS_NAMES[*]}; do
- pid="${pid_name%%:*}"
- name="${pid_name#*:}"
- wait $pid || test_failed $name
-done
-'''
-
- test_failed_check_block = '''
-if [ ${#FAILED_TESTS[@]} -gt 0 ]; then
- >&2 echo -e "\\e[91mThe following tests failed:\\e[0m"
- for test_name in "${FAILED_TESTS[@]}"; do
- >&2 echo -e "\\n - \\e[91m$test_name\\e[0m"
- done
- exit 1
-fi
-'''
-
- script = '#!/bin/bash\n\n'
- if args.test_name:
- script += test_failed_definition_block
- # TODO(FL-104): Limit concurrency to number of cores
- for test_executable, test_name in zip(args.test, args.test_name):
- script += "run_test %s '%s'\n" % (test_executable, test_name)
- script += test_wait_to_complete_block
- script += test_failed_check_block
- else:
- for test_executable in args.test:
- script += '%s "$@"\n' % test_executable
+ script += 'cd "$(dirname $0)/%s"\n' % args.wd
+ for test_executable in args.test:
+ script += '%s "$@"\n' % test_executable
with open(test_file, 'w') as file:
file.write(script)
diff --git a/runtime/dart/gen_flutter_test_invocation.py b/runtime/dart/gen_flutter_test_invocation.py
index e7fbb85..a3b182f 100755
--- a/runtime/dart/gen_flutter_test_invocation.py
+++ b/runtime/dart/gen_flutter_test_invocation.py
@@ -13,29 +13,32 @@
def main():
parser = argparse.ArgumentParser(
description='Generate a script that invokes the Dart tester')
+ parser.add_argument('--wd',
+ help='Path to the working directory, relative to that of the invocation file',
+ required=True)
parser.add_argument('--out',
help='Path to the invocation file to generate',
required=True)
- parser.add_argument('--source-dir',
- help='Path to test sources',
+ parser.add_argument('--dart',
+ help='Path to the dart binary, relative to the working directory',
+ required=True)
+ parser.add_argument('--snapshot',
+ help='Path to snapshot of the the test runner, relative to the working directory',
required=True)
parser.add_argument('--sdk-root',
- help='Path to the SDK platform files',
+ help='Path to the SDK platform files, relative to the working directory',
required=True)
parser.add_argument('--tests',
- help='Path to test-to-precompiled-kernel file list',
+ help='Path to test-to-precompiled-kernel file list, relative to the working directory',
required=True)
parser.add_argument('--dot-packages',
- help='Path to the .packages file',
- required=True)
- parser.add_argument('--test-runner',
- help='Path to the test runner',
+ help='Path to the .packages file, relative to the working directory',
required=True)
parser.add_argument('--flutter-shell',
- help='Path to the Flutter shell',
+ help='Path to the Flutter shell, relative to the working directory',
required=True)
parser.add_argument('--icudtl',
- help='Path to the ICU data file',
+ help='Path to the ICU data file, relative to the working directory',
required=True)
args = parser.parse_args()
@@ -50,10 +53,11 @@
# //topaz/runtime/dart/gen_flutter_test_invocation.py
# See: //topaz/runtime/dart/flutter_test.gni
-$test_runner \\
+cd "$$(dirname $$0)/$wd"
+
+$dart $snapshot \\
--packages=$dot_packages \\
--shell=$flutter_shell \\
- --test-directory=$source_dir \\
--tests=$tests \\
--sdk-root=$sdk_root \\
--icudtl=$icudtl \\