由于 ffx
主要为开发者设计,因此它会检查当前环境的配置,并在后台启动守护程序以协调与 Fuchsia 设备的通信。这会使编写使用 ffx
的自动化测试变得更加复杂,因为配置和守护程序应该进行隔离,以避免测试之间的副作用或来自全局环境的干扰。
为了解决此问题,ffx
可以在隔离的环境中运行,以在集成测试中使用。
手动隔离设置
为了实现这种隔离,ffx
支持使用隔离目录。此功能指定了供 ffx
运行的新隔离环境,包括用户级配置。ascendd
套接字(与 ffx
守护程序的连接)也在此目录中创建。
所有使用隔离的 ffx
调用都必须在 ffx
命令行中使用 --isolate-dir
选项指定隔离环境。这也可以通过设置 __FFX_ISOLATE_DIR__
环境变量来指定。
以下伪 shell 脚本详细介绍了配置步骤和命令,以确保 ffx
是封闭的:
# Write all configuration and state to the isolate directory, using mktemp or
# something similar.
export FFX_ISOLATE_DIR = ...
# Disable analytics:
ffx config set ffx.analytics.disabled true
# Don't discover devices via mDNS:
ffx config set discovery.mdns.enabled false
# Don't discover fastboot devices connected via USB:
ffx config set fastboot.usb.disabled true
# Require manual process management for the daemon:
ffx config set daemon.autostart false
# If needed, start daemon:
# ffx outputs log files under $FUCHSIA_TEST_OUTDIR/ffx_logs by default.
LOG_DIR = "$FUCHSIA_TEST_OUTDIR/ffx_logs"
# Redirect stdout and stderr to the log file
ffx daemon start > "$LOG_DIR/ffx.daemon.log" 2> "$LOG_DIR/ffx.daemon.log" &
# If interacting with a device:
ffx config target.default "$FUCHSIA_DEVICE_ADDR"
ffx target add "$FUCHSIA_DEVICE_ADDR"
测试完成后,测试作者需要清理隔离目录。删除目录会关闭守护程序;建议使用 ffx daemon stop
,但不强制要求。我们不建议您终止守护程序进程,因为它可能会导致日志文件中遗漏信息。
树内 Rust 隔离库
在 Fuchsia 源代码树中,使用 Rust 编程语言的开发者应在测试中使用 //src/developer/ffx/lib/isolate
,以创建隔离目录并与其交互。
隔离库会自动遵循上述手动设置准则,并在拖放时清理隔离目录。
初始化测试的全局上下文
为避免从主机环境初始化全局上下文,测试需要创建一个测试环境来初始化全局数据。当返回值被丢弃时,环境将被清理,因此它必须在测试生命周期的范围内。
let test_env = ffx_config::test_init().await?;
创建隔离
您可以通过两种方法创建新的隔离,具体取决于 ffx 运行的环境。对于在树内测试中运行且依赖于 build 输出目录结构的测试,请使用 Isolate::new_in_test()
。对于属于 ffx 子工具或基于 SDK 的测试,请使用 Isolate::new_in_sdk()
。如果测试与外部预配的设备交互,则也应该传入 SSH 私钥的路径。如果测试是初始化设备或启动模拟器,则系统会根据需要生成 SSH 密钥,但需要在创建隔离后配置密钥的存储位置。
隔离被丢弃时,系统会清理隔离目录,因此该目录必须在整个测试中都存在。
Isolate::new_in_test() 示例
let test_case_name = "my test";
let ssh_path = std::env::var("FUCHSIA_SSH_KEY").unwrap().into();
let test_env = ffx_config::test_init().await
.expect("Setting up test environment");
// This takes advantage of knowing that Rust tests are down one level from the
// build output root directory.
let build_root =
std::env::current_exe().unwrap().canonicalize().unwrap().parent().unwrap().to_owned();
let isolate = ffx_isolate::Isolate::new_in_test(test_case_name,
build_root,
ssh_path,
&test_env.context).await
.expect("create isolate");
Isolate::new_in_sdk() 示例
let test_case_name = "my test";
let ssh_path = std::env::var("FUCHSIA_SSH_KEY").unwrap().into();
let test_env = ffx_config::test_init().await
.expect("Setting up test environment");
let isolate = ffx_isolate::Isolate::new_with_sdk(test_case_name, ssh_path, &test_env.context)
.await
.expect("create isolate");
启动 ffx 守护程序
ffx
守护程序必须通过 Isolate::start_daemon()
方法手动启动。并非所有命令都依赖于该守护程序,并且某些命令(如 ffx config set
)可能需要在启动该守护程序之前运行。
let _ = isolate.start_daemon().await?;
注意:直接运行 ffx daemon start
不会启动可正常运行的守护程序。
运行 ffx 命令
如需在隔离环境中运行命令,请使用 Isolate::ffx()
方法。此封装容器会将正确的选项添加到 ffx 命令行,以使用隔离目录。
let output = isolate.ffx(&["target", "list"]).await?;
隔离中的配置
您可以使用 ffx config
命令行在隔离中配置 ffx
的值和默认值:
let args = ["config", "set", "ssh.pub", &path_to_ssh_authorized_keys.to_string_lossy()];
let output = isolate.ffx(&args).await?;
日志文件
使用隔离时,系统会在创建隔离时配置 ffx
的日志文件路径。一种常见做法是,让测试框架为需要可作为测试输出访问的文件设置环境变量 __FUCHSIA_TEST_OUTDIR__
。如果已配置,系统会在 __FUCHSIA_TEST_OUTDIR__
的子目录中创建日志目录。可使用 log_dir()
访问日志目录的路径。
let log_dir = isolate.log_dir();
默认目标
某些测试框架可能会为运行测试分配设备。该隔离会读取 __FUCHSIA_DEVICE_ADDR__
环境变量,并将其设置为配置中的默认目标。
Analytics(分析)配置
该隔离会通过配置停用 Analytics 数据收集。