From a46ac84206ff3e4aacfbfa15a750098af320d253 Mon Sep 17 00:00:00 2001 From: Zijie He Date: Tue, 3 Oct 2023 22:56:39 +0000 Subject: [PATCH] [Fuchsia] Allows FuchsiaEmulatorCFv2 to start daemon and emulator This change updates the FuchsiaEmulatorCFv2 to start the daemon and emulator before executing the tests. Meanwhile, instead of "dummy", this change uses "echo" as the dummy command to allow `FUCHSIA_CFV2=1 tools/test.py --progress=status -nvm-fuchsia-release-x64 ffi` running. This change requires `"fuchsia_sdk_version": "version:15.20230909.2.1",` in DEPS to function, which isn't included due to the CFv1 implementation currently running. Bug: #38752 Change-Id: I5011b6ff39b73955002431650d973d6adcfa6246 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/328766 Reviewed-by: Ryan Macnak Commit-Queue: Zijie He Reviewed-by: Alexander Thomas --- DEPS | 4 +- build/fuchsia/with_envs.py | 21 +++++++- pkg/test_runner/lib/src/fuchsia_cfv2.dart | 64 +++++++++++++++++++++-- 3 files changed, 81 insertions(+), 8 deletions(-) diff --git a/DEPS b/DEPS index 884a16e8f4b..b93d0dcf9e3 100644 --- a/DEPS +++ b/DEPS @@ -646,7 +646,7 @@ Var("dart_root") + "/third_party/pkg/tar": "packages": [ { "package": "chromium/fuchsia/test-scripts/fuchsia", - "version": "version:2@0d97902a72c9bc224f64630177cf95cd632604a2", + "version": "version:2@30ecdcc6666ac09845a2e2d4fe7d8d5714230fba", } ], "condition": @@ -807,7 +807,7 @@ hooks = [ 'python3', 'sdk/build/fuchsia/with_envs.py', 'sdk/third_party/fuchsia/test_scripts/update_product_bundles.py', - 'terminal.qemu-x64', + 'terminal.x64', ], 'condition': 'download_fuchsia_deps' }, diff --git a/build/fuchsia/with_envs.py b/build/fuchsia/with_envs.py index b98caa6718e..8bbfcd3fceb 100755 --- a/build/fuchsia/with_envs.py +++ b/build/fuchsia/with_envs.py @@ -5,8 +5,18 @@ import os import platform +import signal import subprocess import sys +import time + +sys.path.insert( + 0, + os.path.abspath( + os.path.join(os.path.dirname(__file__), + '../../third_party/fuchsia/test_scripts/test/'))) + +from common import catch_sigterm, wait_for_sigterm def Main(): @@ -15,6 +25,9 @@ def Main(): /usr/bin/env, but provides some extra functionality to dynamically set up the environment variables. """ + # Ensures the signals can be correctly forwarded to the subprocesses. + catch_sigterm() + os.environ['SRC_ROOT'] = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) os.environ['FUCHSIA_IMAGES_ROOT'] = os.path.join(os.environ['SRC_ROOT'], @@ -36,7 +49,13 @@ def Main(): os.path.join(os.environ['FUCHSIA_SDK_ROOT'], 'tools', 'x64', 'ffx'), 'config', 'set', 'product.experimental', 'true' ]) - subprocess.call(sys.argv[1:]) + + with subprocess.Popen(sys.argv[1:]) as proc: + try: + proc.wait() + except: + # Use terminate / SIGTERM to allow the subprocess exiting cleanly. + proc.terminate() if __name__ == '__main__': diff --git a/pkg/test_runner/lib/src/fuchsia_cfv2.dart b/pkg/test_runner/lib/src/fuchsia_cfv2.dart index 8dd71cad164..a4e4e6cb445 100644 --- a/pkg/test_runner/lib/src/fuchsia_cfv2.dart +++ b/pkg/test_runner/lib/src/fuchsia_cfv2.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; import 'command.dart'; import 'fuchsia.dart'; @@ -11,15 +13,67 @@ import 'fuchsia.dart'; // CFv2 targets. // TODO(#38752): Need implementation. class FuchsiaEmulatorCFv2 extends FuchsiaEmulator { - @override - Future publishPackage( - String buildDir, String mode, String arch) async {} + static const String ffx = "./third_party/fuchsia/sdk/linux/tools/x64/ffx"; + static const String testScriptRoot = + "./third_party/fuchsia/test_scripts/test/"; + + Process? daemonProc; + Process? emuProc; + String? emuName; @override - void stop() {} + Future publishPackage(String buildDir, String mode, String arch) async { + housekeeping(); + + assert(daemonProc == null); + daemonProc = await runWithOutput("isolate_daemon.py", []); + assert(emuProc == null); + emuProc = await run( + "start_emulator.py", ["--disable-graphics", "--target-id-only"]); + emuName = await emuProc!.stdout.transform(utf8.decoder).first; + print("+ Targeting emu name $emuName"); + } + + @override + void stop() { + // isolate_daemon.py should respect the sigterm and gracefully stop the + // daemon process. + assert(daemonProc != null); + daemonProc!.kill(); + emuProc!.kill(); + + // In case anything goes wrong, ensure everything is cleaned up. + housekeeping(); + } @override VMCommand getTestCommand(String mode, String arch, List arguments) { - return VMCommand("dummy", arguments, {}); + return VMCommand("echo", arguments, {}); + } + + static void housekeeping() { + Process.runSync(ffx, ["emu", "stop", "--all"]); + Process.runSync(ffx, ["repository", "server", "stop"]); + Process.runSync(ffx, ["daemon", "stop", "-t", "10000"]); + } + + // Same as run, but capture the stdout and stderr. + static Future runWithOutput(String script, List args) async { + return run(script, args).then((proc) { + proc.stdout.transform(utf8.decoder).forEach((x) { + print("++ [$script] stdout: $x"); + }); + proc.stderr.transform(utf8.decoder).forEach((x) { + print("++ [$script] stderr: $x"); + }); + return proc; + }); + } + + // Executes a test script inside of third_party/fuchsia/test_scripts/test/ + // with the required environment setup and the arguments. + static Future run(String script, List args) async { + return Process.start("./build/fuchsia/with_envs.py", + [Uri.directory(testScriptRoot).resolve(script).toString(), ...args]); } }