[system-updater] Remove oneshot support.
Fixed: 55414
Change-Id: Idef138822a011ad3c9fa49d0948ddd96adcb6c8a
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/441850
Commit-Queue: Sen Jiang <senj@google.com>
Reviewed-by: Kevin Wells <kevinwells@google.com>
Testability-Review: Kevin Wells <kevinwells@google.com>
diff --git a/src/sys/pkg/bin/system-updater/BUILD.gn b/src/sys/pkg/bin/system-updater/BUILD.gn
index c8127b9..b17aa4e 100644
--- a/src/sys/pkg/bin/system-updater/BUILD.gn
+++ b/src/sys/pkg/bin/system-updater/BUILD.gn
@@ -38,7 +38,6 @@
"//src/sys/pkg/lib/update-package",
"//third_party/cobalt/src/lib/client/rust:cobalt-client",
"//third_party/rust_crates:anyhow",
- "//third_party/rust_crates:argh",
"//third_party/rust_crates:async-trait",
"//third_party/rust_crates:chrono",
"//third_party/rust_crates:futures",
@@ -60,7 +59,6 @@
]
sources = [
- "src/args.rs",
"src/fidl.rs",
"src/install_manager.rs",
"src/main.rs",
diff --git a/src/sys/pkg/bin/system-updater/src/args.rs b/src/sys/pkg/bin/system-updater/src/args.rs
deleted file mode 100644
index b6d6f98..0000000
--- a/src/sys/pkg/bin/system-updater/src/args.rs
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use {
- argh::FromArgs,
- fidl_fuchsia_update_installer_ext::Initiator as ExtInitiator,
- fuchsia_url::pkg_url::PkgUrl,
- std::time::{Duration, SystemTime},
-};
-
-#[derive(Debug, Eq, FromArgs, PartialEq)]
-/// Arguments for the system updater.
-pub struct Args {
- /// what started this update: manual or automatic
- #[argh(option, default = "Initiator::Automatic")]
- pub initiator: Initiator,
-
- /// current OS version
- #[argh(option, default = "String::from(\"\")")]
- pub source: String,
-
- /// target OS version
- #[argh(option, default = "String::from(\"\")")]
- pub target: String,
-
- /// update package url
- #[argh(option, default = "\"fuchsia-pkg://fuchsia.com/update\".parse().unwrap()")]
- pub update: PkgUrl,
-
- /// if true, reboot the system after successful OTA
- #[argh(option, default = "true")]
- pub reboot: bool,
-
- /// if true, don't write the recovery image
- #[argh(option, default = "false")]
- pub skip_recovery: bool,
-
- /// start time of update attempt, as unix nanosecond timestamp
- #[argh(option, from_str_fn(parse_wall_time))]
- pub start: Option<SystemTime>,
-
- /// if true, the system updater will install a single update and exit
- #[argh(option, default = "false")]
- pub oneshot: bool,
-}
-
-fn parse_wall_time(value: &str) -> Result<SystemTime, String> {
- let since_unix_epoch =
- Duration::from_nanos(value.parse().map_err(|e: std::num::ParseIntError| e.to_string())?);
-
- Ok(SystemTime::UNIX_EPOCH + since_unix_epoch)
-}
-
-#[derive(Debug, Clone, Copy, Eq, PartialEq)]
-pub enum Initiator {
- Automatic,
- Manual,
-}
-
-impl From<Initiator> for ExtInitiator {
- fn from(args_initiator: Initiator) -> Self {
- match args_initiator {
- Initiator::Manual => ExtInitiator::User,
- Initiator::Automatic => ExtInitiator::Service,
- }
- }
-}
-
-impl From<ExtInitiator> for Initiator {
- fn from(ext_initiator: ExtInitiator) -> Self {
- match ext_initiator {
- ExtInitiator::User => Initiator::Manual,
- ExtInitiator::Service => Initiator::Automatic,
- }
- }
-}
-
-impl std::str::FromStr for Initiator {
- type Err = anyhow::Error;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s {
- "automatic" => Ok(Initiator::Automatic),
- "manual" => Ok(Initiator::Manual),
- not_supported => Err(anyhow::anyhow!("initiator not supported: {:?}", not_supported)),
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use {super::*, matches::assert_matches};
-
- #[test]
- fn test_initiator() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--initiator", "manual"]),
- Ok(Args { initiator: Initiator::Manual, .. })
- );
- }
-
- #[test]
- fn test_unknown_initiator() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--initiator", "P Sherman"]),
- Err(_)
- );
- }
-
- #[test]
- fn test_start() {
- use chrono::prelude::*;
-
- const NANOS_IN_1970: u64 = 365 * 24 * 60 * 60 * 1_000_000_000;
- let nanos_in_1970 = NANOS_IN_1970.to_string();
-
- let args = Args::from_args(&["system-updater"], &["--start", &nanos_in_1970]).unwrap();
- assert_eq!(args.start, Some(Utc.ymd(1971, 1, 1).and_hms(0, 0, 0).into()));
- }
-
- #[test]
- fn test_source() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--source", "Wallaby Way"]),
- Ok(Args {
- source: source_version,
- ..
- }) if source_version=="Wallaby Way"
- );
- }
-
- #[test]
- fn test_target() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--target", "Sydney"]),
- Ok(Args {
- target: target_version,
- ..
- }) if target_version=="Sydney"
- );
- }
-
- #[test]
- fn test_update() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--update", "fuchsia-pkg://fuchsia.com/foo"]),
- Ok(Args {
- update: update_pkg_url,
- ..
- }) if update_pkg_url.to_string() == "fuchsia-pkg://fuchsia.com/foo"
- );
- }
-
- #[test]
- fn test_reboot() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--reboot", "false"]),
- Ok(Args { reboot: false, .. })
- );
- }
-
- #[test]
- fn test_skip_recovery() {
- assert_matches!(
- Args::from_args(&["system-updater"], &["--skip-recovery", "true"]),
- Ok(Args { skip_recovery: true, .. })
- );
- }
-
- #[test]
- fn test_defaults() {
- assert_matches!(
- Args::from_args(&["system-updater"], &[]),
- Ok(Args {
- initiator: Initiator::Automatic,
- source: source_version,
- target: target_version,
- update: update_pkg_url,
- reboot: true,
- skip_recovery: false,
- ..
- }) if source_version == "" &&
- target_version == "" &&
- update_pkg_url.to_string() == "fuchsia-pkg://fuchsia.com/update"
- );
- }
-}
diff --git a/src/sys/pkg/bin/system-updater/src/install_manager.rs b/src/sys/pkg/bin/system-updater/src/install_manager.rs
index bfeeb1b..d6ac1ea 100644
--- a/src/sys/pkg/bin/system-updater/src/install_manager.rs
+++ b/src/sys/pkg/bin/system-updater/src/install_manager.rs
@@ -81,8 +81,7 @@
// Now we can actually start the task that manages the update attempt.
let update_url = &config.update_url.clone();
let should_write_recovery = config.should_write_recovery;
- let (attempt_id, attempt_stream) =
- updater.update(config, env, Some(reboot_controller)).await;
+ let (attempt_id, attempt_stream) = updater.update(config, env, reboot_controller).await;
futures::pin_mut!(attempt_stream);
// Set up inspect nodes.
@@ -392,7 +391,7 @@
&mut self,
_config: Config,
_env: Environment,
- _reboot_controller: Option<RebootController>,
+ _reboot_controller: RebootController,
) -> (String, Self::UpdateStream) {
self.0.next().await.unwrap()
}
diff --git a/src/sys/pkg/bin/system-updater/src/main.rs b/src/sys/pkg/bin/system-updater/src/main.rs
index 77b17fe..8860beb 100644
--- a/src/sys/pkg/bin/system-updater/src/main.rs
+++ b/src/sys/pkg/bin/system-updater/src/main.rs
@@ -4,24 +4,18 @@
use {
crate::{
- args::Args,
fidl::{FidlServer, UpdateStateNotifier},
install_manager::start_install_manager,
- update::{
- EnvironmentConnector, NamespaceEnvironmentConnector, RealUpdater, UpdateHistory,
- Updater,
- },
+ update::{NamespaceEnvironmentConnector, RealUpdater, UpdateHistory},
},
anyhow::anyhow,
fuchsia_async as fasync,
fuchsia_component::server::ServiceFs,
fuchsia_syslog::{fx_log_err, fx_log_info, fx_log_warn},
- futures::prelude::*,
parking_lot::Mutex,
std::sync::Arc,
};
-mod args;
mod fidl;
mod install_manager;
pub(crate) mod update;
@@ -31,62 +25,11 @@
fuchsia_syslog::init_with_tags(&["system-updater"]).expect("can't init logger");
fx_log_info!("starting system updater");
- let args: Args = argh::from_env();
let inspector = fuchsia_inspect::Inspector::new();
let history_node = inspector.root().create_child("history");
let history = Arc::new(Mutex::new(UpdateHistory::load(history_node).await));
- if args.oneshot {
- // We don't need inspect in oneshot mode, and it won't be served anyway.
- drop(inspector);
-
- oneshot_update(args, Arc::clone(&history)).await;
- } else {
- serve_fidl(history, inspector).await;
- }
-}
-
-/// In the oneshot code path, we do NOT serve FIDL.
-/// Instead, we perform a single update based on the provided CLI args, then exit.
-async fn oneshot_update(args: Args, history: Arc<Mutex<UpdateHistory>>) {
- let config = update::Config::from_args(args);
-
- let env = match NamespaceEnvironmentConnector::connect() {
- Ok(env) => env,
- Err(e) => {
- fx_log_err!("Error connecting to services: {:#}", anyhow!(e));
- std::process::exit(1);
- }
- };
-
- let mut done = false;
- let mut failed = false;
- let (_, attempt) = RealUpdater::new(history).update(config, env, None).await;
- futures::pin_mut!(attempt);
- while let Some(state) = attempt.next().await {
- assert!(!done, "update stream continued after a terminal state");
-
- if state.is_terminal() {
- done = true;
- }
- if state.is_failure() {
- failed = true;
- // Intentionally don't short circuit on failure. Dropping attempt before the stream
- // terminates will drop any pending cleanup work the update attempt hasn't had a chance
- // to do yet.
- }
- }
- assert!(done, "update stream did not include a terminal state");
-
- if failed {
- std::process::exit(1);
- }
-}
-
-/// In the non-oneshot path, we serve FIDL, ignore any other provided CLI args, and do NOT
-/// perform an update on start. Instead, we wait for a FIDL request to start an update.
-async fn serve_fidl(history: Arc<Mutex<UpdateHistory>>, inspector: fuchsia_inspect::Inspector) {
let mut fs = ServiceFs::new_local();
if let Err(e) = fs.take_and_serve_directory_handle() {
fx_log_err!("error encountered serving directory handle: {:#}", anyhow!(e));
diff --git a/src/sys/pkg/bin/system-updater/src/update.rs b/src/sys/pkg/bin/system-updater/src/update.rs
index 6bfe7e8..ba917bb 100644
--- a/src/sys/pkg/bin/system-updater/src/update.rs
+++ b/src/sys/pkg/bin/system-updater/src/update.rs
@@ -68,7 +68,7 @@
&mut self,
config: Config,
env: Environment,
- reboot_controller: Option<RebootController>,
+ reboot_controller: RebootController,
) -> (String, Self::UpdateStream);
}
@@ -90,7 +90,7 @@
&mut self,
config: Config,
env: Environment,
- reboot_controller: Option<RebootController>,
+ reboot_controller: RebootController,
) -> (String, Self::UpdateStream) {
let (attempt_id, attempt) =
update(config, env, Arc::clone(&self.history), reboot_controller).await;
@@ -111,7 +111,7 @@
config: Config,
env: Environment,
history: Arc<Mutex<UpdateHistory>>,
- reboot_controller: Option<RebootController>,
+ reboot_controller: RebootController,
) -> (String, impl FusedStream<Item = State>) {
let attempt_fut = history.lock().start_update_attempt(
Options {
@@ -143,7 +143,7 @@
let cobalt_forwarder_task = Task::spawn(cobalt_forwarder_task);
fx_log_info!("starting system update with config: {:?}", config);
- cobalt.log_ota_start(&config.target_version, config.initiator, config.start_time);
+ cobalt.log_ota_start("", config.initiator, config.start_time);
let mut target_version = history::Version::default();
@@ -152,15 +152,16 @@
.await;
let status_code = metrics::result_to_status_code(attempt_res.as_ref().map(|_| ()));
+ let target_build_version = target_version.build_version.to_string();
cobalt.log_ota_result_attempt(
- &config.target_version,
+ &target_build_version,
config.initiator,
history.lock().attempts_for(&source_version, &target_version) + 1,
phase,
status_code,
);
cobalt.log_ota_result_duration(
- &config.target_version,
+ &target_build_version,
config.initiator,
phase,
status_code,
@@ -184,14 +185,14 @@
};
// Figure out if we should reboot.
- match (mode, reboot_controller, config.should_reboot) {
+ match mode {
// First priority: Always reboot on ForceRecovery success, even if the caller
// asked to defer the reboot.
- (UpdateMode::ForceRecovery, _, _) => {
+ UpdateMode::ForceRecovery => {
fx_log_info!("system update in ForceRecovery mode complete, rebooting...");
}
// Second priority: Use the attached reboot controller.
- (UpdateMode::Normal, Some(reboot_controller), _) => {
+ UpdateMode::Normal => {
fx_log_info!("system update complete, waiting for initiator to signal reboot.");
match reboot_controller.wait_to_reboot().await {
CommitAction::Reboot => {
@@ -204,15 +205,6 @@
}
}
}
- // Last priority: Reboot depending on the config.
- (UpdateMode::Normal, None, true) => {
- fx_log_info!("system update complete, rebooting...");
- }
- (UpdateMode::Normal, None, false) => {
- fx_log_info!("system update complete, reboot to new version deferred to caller.");
- state.enter_defer_reboot(&mut co).await;
- return target_version;
- }
}
state.enter_reboot(&mut co).await;
diff --git a/src/sys/pkg/bin/system-updater/src/update/config.rs b/src/sys/pkg/bin/system-updater/src/update/config.rs
index 69c5faa..cf1d282 100644
--- a/src/sys/pkg/bin/system-updater/src/update/config.rs
+++ b/src/sys/pkg/bin/system-updater/src/update/config.rs
@@ -4,8 +4,7 @@
use {
super::metrics,
- crate::args,
- fidl_fuchsia_update_installer_ext::Options,
+ fidl_fuchsia_update_installer_ext::{Initiator as ExtInitiator, Options},
fuchsia_url::pkg_url::PkgUrl,
std::time::{Instant, SystemTime},
};
@@ -13,11 +12,8 @@
/// Configuration for an update attempt.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Config {
- pub(super) initiator: args::Initiator,
- pub(super) source_version: String,
- pub(super) target_version: String,
+ pub(super) initiator: Initiator,
pub update_url: PkgUrl,
- pub(super) should_reboot: bool,
pub should_write_recovery: bool,
pub(super) start_time: SystemTime,
pub(super) start_time_mono: Instant,
@@ -25,27 +21,6 @@
}
impl Config {
- /// Constructs update configuration from command line arguments, filling in details as needed.
- pub fn from_args(args: args::Args) -> Self {
- // The OTA attempt started during the update check, so use that time if possible. Fallback
- // to now if that data wasn't provided.
- let start_time = args.start.unwrap_or_else(SystemTime::now);
- let start_time_mono =
- metrics::system_time_to_monotonic_time(start_time).unwrap_or_else(Instant::now);
-
- Self {
- initiator: args.initiator,
- source_version: args.source,
- target_version: args.target,
- update_url: args.update,
- should_reboot: args.reboot,
- should_write_recovery: !args.skip_recovery,
- start_time,
- start_time_mono,
- allow_attach_to_existing_attempt: false,
- }
- }
-
/// Constructs update configuration from PkgUrl and Options.
pub fn from_url_and_options(update_url: PkgUrl, options: Options) -> Self {
let start_time = SystemTime::now();
@@ -54,10 +29,7 @@
Self {
initiator: options.initiator.into(),
- source_version: "".to_string(),
- target_version: "".to_string(),
update_url,
- should_reboot: true,
should_write_recovery: options.should_write_recovery,
start_time,
start_time_mono,
@@ -66,6 +38,30 @@
}
}
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub enum Initiator {
+ Automatic,
+ Manual,
+}
+
+impl From<Initiator> for ExtInitiator {
+ fn from(args_initiator: Initiator) -> Self {
+ match args_initiator {
+ Initiator::Manual => ExtInitiator::User,
+ Initiator::Automatic => ExtInitiator::Service,
+ }
+ }
+}
+
+impl From<ExtInitiator> for Initiator {
+ fn from(ext_initiator: ExtInitiator) -> Self {
+ match ext_initiator {
+ ExtInitiator::User => Initiator::Manual,
+ ExtInitiator::Service => Initiator::Automatic,
+ }
+ }
+}
+
#[cfg(test)]
pub struct ConfigBuilder<'a> {
update_url: &'a str,
@@ -103,7 +99,7 @@
Options {
allow_attach_to_existing_attempt: self.allow_attach_to_existing_attempt,
should_write_recovery: self.should_write_recovery,
- initiator: fidl_fuchsia_update_installer_ext::Initiator::User,
+ initiator: ExtInitiator::User,
},
))
}
@@ -111,55 +107,12 @@
#[cfg(test)]
mod tests {
- use {super::*, std::time::Duration};
-
- #[test]
- fn config_from_args() {
- let now = SystemTime::now() - Duration::from_secs(3600);
-
- let args = args::Args {
- initiator: args::Initiator::Manual,
- source: "source-version".to_string(),
- target: "target-version".to_string(),
- update: "fuchsia-pkg://example.com/foo".parse().unwrap(),
- reboot: true,
- skip_recovery: false,
- start: Some(now),
- oneshot: true,
- };
-
- let mut config = Config::from_args(args);
-
- let d = config.start_time_mono.elapsed();
- assert!(
- d > Duration::from_secs(3550) && d < Duration::from_secs(3650),
- "expected start_time_mono to be an hour before now, got delta of: {:?}",
- d
- );
-
- let now_mono = Instant::now();
-
- config.start_time_mono = now_mono;
- assert_eq!(
- config,
- Config {
- initiator: args::Initiator::Manual,
- source_version: "source-version".to_string(),
- target_version: "target-version".to_string(),
- update_url: "fuchsia-pkg://example.com/foo".parse().unwrap(),
- should_reboot: true,
- should_write_recovery: true,
- start_time: now,
- start_time_mono: now_mono,
- allow_attach_to_existing_attempt: false,
- }
- );
- }
+ use super::*;
#[test]
fn config_from_url_and_options() {
let options = Options {
- initiator: fidl_fuchsia_update_installer_ext::Initiator::User,
+ initiator: ExtInitiator::User,
allow_attach_to_existing_attempt: true,
should_write_recovery: true,
};
@@ -170,7 +123,7 @@
matches::assert_matches!(
config,
Config {
- initiator: args::Initiator::Manual,
+ initiator: Initiator::Manual,
update_url: url,
should_write_recovery: true,
allow_attach_to_existing_attempt: true,
diff --git a/src/sys/pkg/bin/system-updater/src/update/metrics.rs b/src/sys/pkg/bin/system-updater/src/update/metrics.rs
index 2e4a88f..0709120 100644
--- a/src/sys/pkg/bin/system-updater/src/update/metrics.rs
+++ b/src/sys/pkg/bin/system-updater/src/update/metrics.rs
@@ -3,7 +3,7 @@
// found in the LICENSE file.
use {
- crate::args::Initiator,
+ crate::update::config::Initiator,
cobalt_client::traits::AsEventCode,
cobalt_sw_delivery_registry as metrics,
futures::future::Future,
diff --git a/src/sys/pkg/tests/system-updater/BUILD.gn b/src/sys/pkg/tests/system-updater/BUILD.gn
index 321779b..742751e 100644
--- a/src/sys/pkg/tests/system-updater/BUILD.gn
+++ b/src/sys/pkg/tests/system-updater/BUILD.gn
@@ -13,14 +13,12 @@
deps = [
"//sdk/fidl/fuchsia.cobalt:fuchsia.cobalt-rustc",
- "//sdk/fidl/fuchsia.hardware.power.statecontrol:fuchsia.hardware.power.statecontrol-rustc",
"//sdk/fidl/fuchsia.io:fuchsia.io-rustc",
"//sdk/fidl/fuchsia.logger:fuchsia.logger-rustc",
"//sdk/fidl/fuchsia.mem:fuchsia.mem-rustc",
"//sdk/fidl/fuchsia.paver:fuchsia.paver-rustc",
"//sdk/fidl/fuchsia.pkg:fuchsia.pkg-rustc",
"//sdk/fidl/fuchsia.space:fuchsia.space-rustc",
- "//sdk/fidl/fuchsia.sys:fuchsia.sys-rustc",
"//src/lib/fdio/rust:fdio",
"//src/lib/fidl/rust/fidl",
"//src/lib/fuchsia-async",
@@ -38,6 +36,7 @@
"//src/sys/pkg/testing/mock-reboot",
"//src/sys/pkg/testing/mock-resolver",
"//third_party/rust_crates:anyhow",
+ "//third_party/rust_crates:chrono",
"//third_party/rust_crates:futures",
"//third_party/rust_crates:hex",
"//third_party/rust_crates:log",
@@ -59,7 +58,6 @@
"src/lib.rs",
"src/mode_force_recovery.rs",
"src/mode_normal.rs",
- "src/options.rs",
"src/progress_reporting.rs",
"src/reboot_controller.rs",
"src/update_package.rs",
diff --git a/src/sys/pkg/tests/system-updater/src/board.rs b/src/sys/pkg/tests/system-updater/src/board.rs
index 1b1a731..b1a4c8f 100644
--- a/src/sys/pkg/tests/system-updater/src/board.rs
+++ b/src/sys/pkg/tests/system-updater/src/board.rs
@@ -6,7 +6,7 @@
#[fasync::run_singlethreaded(test)]
async fn validates_board() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.set_board_name("x64");
@@ -17,20 +17,14 @@
.add_file("zbi", "fake zbi")
.add_file("bootloader", "new bootloader");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(resolved_urls(Arc::clone(&env.interactions)), vec![UPDATE_PKG_URL]);
}
#[fasync::run_singlethreaded(test)]
async fn rejects_mismatched_board() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.set_board_name("x64");
@@ -39,32 +33,23 @@
.add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
.add_file("board", "arm")
.add_file("zbi", "fake zbi")
- .add_file("bootloader", "new bootloader");
+ .add_file("bootloader", "new bootloader")
+ .add_file("version", "1.2.3.4");
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
// Expect to have failed prior to downloading images.
assert_eq!(resolved_urls(Arc::clone(&env.interactions)), vec![UPDATE_PKG_URL]);
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
- let events = OtaMetrics::from_events(logger.cobalt_events.lock().clone());
assert_eq!(
- events,
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::Tufupdate as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Error as u32,
- target: "m3rk13".into(),
+ target: "1.2.3.4".into(),
}
);
}
diff --git a/src/sys/pkg/tests/system-updater/src/channel.rs b/src/sys/pkg/tests/system-updater/src/channel.rs
index 708cb74..95a6f2c 100644
--- a/src/sys/pkg/tests/system-updater/src/channel.rs
+++ b/src/sys/pkg/tests/system-updater/src/channel.rs
@@ -6,7 +6,7 @@
#[fasync::run_singlethreaded(test)]
async fn promotes_target_channel_as_current_channel() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.set_target_channel("target-channel");
@@ -15,7 +15,7 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs { ..Default::default() }).await.unwrap();
+ env.run_update().await.unwrap();
env.verify_current_channel(Some(b"target-channel"));
@@ -23,31 +23,29 @@
env.set_target_channel("target-channel-2");
- env.run_system_updater_oneshot(SystemUpdaterArgs { ..Default::default() }).await.unwrap();
+ env.run_update().await.unwrap();
env.verify_current_channel(Some(b"target-channel-2"));
}
#[fasync::run_singlethreaded(test)]
async fn succeeds_even_if_target_channel_does_not_exist() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs { ..Default::default() }).await.unwrap();
+ env.run_update().await.unwrap();
env.verify_current_channel(None);
}
#[fasync::run_singlethreaded(test)]
async fn does_not_promote_target_channel_on_failure() {
- let env = TestEnv::builder()
- .paver_service(|builder| builder.call_hook(|_| Status::INTERNAL))
- .oneshot(true)
- .build();
+ let env =
+ TestEnv::builder().paver_service(|builder| builder.call_hook(|_| Status::INTERNAL)).build();
env.set_target_channel("target-channel");
@@ -56,7 +54,7 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake zbi");
- let result = env.run_system_updater_oneshot(SystemUpdaterArgs { ..Default::default() }).await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
env.verify_current_channel(None);
diff --git a/src/sys/pkg/tests/system-updater/src/cobalt_metrics.rs b/src/sys/pkg/tests/system-updater/src/cobalt_metrics.rs
index ecdbf66..116cdd9 100644
--- a/src/sys/pkg/tests/system-updater/src/cobalt_metrics.rs
+++ b/src/sys/pkg/tests/system-updater/src/cobalt_metrics.rs
@@ -8,7 +8,7 @@
status: Status,
expected_status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode,
) {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
let pkg_url = "fuchsia-pkg://fuchsia.com/failure/0?hash=00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100";
@@ -19,26 +19,17 @@
env.resolver.url(pkg_url).fail(status);
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::PackageDownload as u32,
status_code: expected_status_code as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
}
@@ -81,20 +72,14 @@
#[fasync::run_singlethreaded(test)]
async fn succeeds_even_if_metrics_fail_to_send() {
- let env = TestEnvBuilder::new().unregister_protocol(Protocol::Cobalt).oneshot(true).build();
+ let env = TestEnvBuilder::new().unregister_protocol(Protocol::Cobalt).build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("run system updater");
+ env.run_update().await.expect("run system updater");
let loggers = env.logger_factory.loggers.lock().clone();
assert_eq!(loggers.len(), 0);
diff --git a/src/sys/pkg/tests/system-updater/src/fetch_packages.rs b/src/sys/pkg/tests/system-updater/src/fetch_packages.rs
index d858cb1..e2c3077 100644
--- a/src/sys/pkg/tests/system-updater/src/fetch_packages.rs
+++ b/src/sys/pkg/tests/system-updater/src/fetch_packages.rs
@@ -10,16 +10,9 @@
#[fasync::run_singlethreaded(test)]
async fn fails_on_package_resolver_connect_error() {
- let env =
- TestEnvBuilder::new().unregister_protocol(Protocol::PackageResolver).oneshot(true).build();
+ let env = TestEnvBuilder::new().unregister_protocol(Protocol::PackageResolver).build();
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
assert_eq!(
@@ -45,7 +38,7 @@
#[fasync::run_singlethreaded(test)]
async fn fails_on_update_package_fetch_error() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -54,26 +47,17 @@
let system_image_url = SYSTEM_IMAGE_URL;
env.resolver.mock_resolve_failure(system_image_url, Status::NOT_FOUND);
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::PackageDownload as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Error as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -101,7 +85,7 @@
#[fasync::run_singlethreaded(test)]
async fn fails_on_content_package_fetch_error() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
let pkg1_url = pinned_pkg_url!("package1/0", "aa");
let pkg2_url = pinned_pkg_url!("package2/0", "00");
@@ -141,13 +125,7 @@
let ((), ()) = future::join(
async {
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
},
async move {
@@ -170,17 +148,14 @@
)
.await;
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::PackageDownload as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Error as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -214,7 +189,7 @@
#[fasync::run_singlethreaded(test)]
async fn fails_when_package_cache_sync_fails() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.cache_service.set_sync_response(Err(Status::INTERNAL));
env.resolver
.register_package("update", "upd4t3")
@@ -223,13 +198,7 @@
.url(SYSTEM_IMAGE_URL)
.resolve(&env.resolver.package("system_image/0", SYSTEM_IMAGE_HASH));
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
diff --git a/src/sys/pkg/tests/system-updater/src/history.rs b/src/sys/pkg/tests/system-updater/src/history.rs
index 426f57a..3864631 100644
--- a/src/sys/pkg/tests/system-updater/src/history.rs
+++ b/src/sys/pkg/tests/system-updater/src/history.rs
@@ -3,49 +3,38 @@
// found in the LICENSE file.
use {
- super::{merkle_str, *},
+ super::*,
+ chrono::prelude::*,
fidl_fuchsia_pkg::PackageUrl,
fidl_fuchsia_update_installer::{
- CompleteData, FetchData, InstallationProgress, InstallerMarker, Options, State, UpdateInfo,
- UpdateResult,
+ CompleteData, FetchData, InstallationProgress, Options, State, UpdateInfo, UpdateResult,
},
+ matches::assert_matches,
pretty_assertions::assert_eq,
serde_json::json,
};
#[fasync::run_singlethreaded(test)]
async fn succeeds_without_writable_data() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().mount_data(false).build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake zbi");
- env.run_system_updater_oneshot_args(
- SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- },
- SystemUpdaterEnv { mount_data: false, ..Default::default() },
- )
- .await
- .expect("run system updater");
+ env.run_update().await.expect("run system updater");
assert_eq!(env.read_history(), None);
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -103,13 +92,31 @@
value
}
+/// Given a parsed update history value, verify each attempt contains a 'start' time that's later
+/// than 01/01/2020, and return the object with those fields removed.
+fn strip_start_time(mut value: serde_json::Value) -> serde_json::Value {
+ let min_start_time = Utc.ymd(2020, 1, 1).and_hms(0, 0, 0).timestamp_nanos() as u64;
+ value
+ .as_object_mut()
+ .expect("top level is object")
+ .get_mut("content")
+ .expect("top level 'content' key")
+ .as_array_mut()
+ .expect("'content' is array")
+ .iter_mut()
+ .map(|attempt| attempt.as_object_mut().expect("attempt is object"))
+ .for_each(|attempt| {
+ assert_matches!(
+ attempt.remove("start"),
+ Some(serde_json::Value::Number(start)) if start.as_u64().expect("start is u64") > min_start_time
+ );
+ });
+ value
+}
+
#[fasync::run_singlethreaded(test)]
async fn writes_history() {
- let env = TestEnv::builder().oneshot(true).build();
-
- // source/target CLI params are no longer trusted for update history values.
- let source = merkle_str!("ab");
- let target = merkle_str!("ba");
+ let env = TestEnv::builder().build();
assert_eq!(env.read_history(), None);
@@ -126,18 +133,19 @@
"838b5199d12c8ff4ef92bfd9771d2f8781b7b8fd739dd59bcf63f353a1a93f67",
);
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- source: Some(source),
- target: Some(target),
- start: Some(1234567890),
- ..Default::default()
- })
+ env.run_update_with_options(
+ UPDATE_PKG_URL,
+ fidl_fuchsia_update_installer_ext::Options {
+ initiator: Initiator::Service,
+ allow_attach_to_existing_attempt: false,
+ should_write_recovery: true,
+ },
+ )
.await
.unwrap();
assert_eq!(
- env.read_history().map(strip_attempt_ids),
+ env.read_history().map(strip_attempt_ids).map(strip_start_time),
Some(json!({
"version": "1",
"content": [{
@@ -157,11 +165,10 @@
},
"options": {
"allow_attach_to_existing_attempt": false,
- "initiator": "User",
+ "initiator": "Service",
"should_write_recovery": true,
},
- "url": "fuchsia-pkg://fuchsia.com/update",
- "start": 1234567890,
+ "url": UPDATE_PKG_URL,
"state": {
"id": "reboot",
"info": {
@@ -179,7 +186,7 @@
#[fasync::run_singlethreaded(test)]
async fn replaces_bogus_history() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.write_history(json!({
"valid": "no",
@@ -190,12 +197,10 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs { start: Some(42), ..Default::default() })
- .await
- .unwrap();
+ env.run_update().await.unwrap();
assert_eq!(
- env.read_history().map(strip_attempt_ids),
+ env.read_history().map(strip_attempt_ids).map(strip_start_time),
Some(json!({
"version": "1",
"content": [{
@@ -214,12 +219,11 @@
"build_version": ""
},
"options": {
- "allow_attach_to_existing_attempt": false,
- "initiator": "Service",
+ "allow_attach_to_existing_attempt": true,
+ "initiator": "User",
"should_write_recovery": true,
},
- "url": "fuchsia-pkg://fuchsia.com/update",
- "start": 42,
+ "url": UPDATE_PKG_URL,
"state": {
"id": "reboot",
"info": {
@@ -237,10 +241,7 @@
#[fasync::run_singlethreaded(test)]
async fn increments_attempts_counter_on_retry() {
- let env = TestEnv::builder().oneshot(true).build();
-
- let source = merkle_str!("ab");
- let target = merkle_str!("ba");
+ let env = TestEnv::builder().build();
env.resolver.url("fuchsia-pkg://fuchsia.com/not-found").fail(Status::NOT_FOUND);
env.resolver
@@ -249,27 +250,21 @@
.add_file("zbi", "fake zbi");
let _ = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- update: Some("fuchsia-pkg://fuchsia.com/not-found"),
- source: Some(source),
- target: Some(target),
- start: Some(10),
- ..Default::default()
- })
+ .run_update_with_options(
+ "fuchsia-pkg://fuchsia.com/not-found",
+ fidl_fuchsia_update_installer_ext::Options {
+ initiator: Initiator::Service,
+ allow_attach_to_existing_attempt: false,
+ should_write_recovery: true,
+ },
+ )
.await
.unwrap_err();
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- source: Some(source),
- target: Some(target),
- start: Some(20),
- ..Default::default()
- })
- .await
- .unwrap();
+ env.run_update().await.unwrap();
assert_eq!(
- env.read_history().map(strip_attempt_ids),
+ env.read_history().map(strip_attempt_ids).map(strip_start_time),
Some(json!({
"version": "1",
"content": [
@@ -289,12 +284,11 @@
"build_version": ""
},
"options": {
- "allow_attach_to_existing_attempt": false,
- "initiator": "Service",
+ "allow_attach_to_existing_attempt": true,
+ "initiator": "User",
"should_write_recovery": true,
},
"url": "fuchsia-pkg://fuchsia.com/update",
- "start": 20,
"state": {
"id": "reboot",
"info": {
@@ -327,7 +321,6 @@
"should_write_recovery": true,
},
"url": "fuchsia-pkg://fuchsia.com/not-found",
- "start": 10,
"state": {
"id": "fail_prepare",
},
@@ -416,8 +409,7 @@
}))
.build();
- let installer_proxy =
- env.system_updater.as_ref().unwrap().connect_to_service::<InstallerMarker>().unwrap();
+ let installer_proxy = env.installer_proxy();
assert_eq!(
installer_proxy.get_last_update_result().await.unwrap(),
@@ -483,8 +475,7 @@
async fn serves_fidl_without_history_present() {
let env = TestEnv::new();
- let installer_proxy =
- env.system_updater.as_ref().unwrap().connect_to_service::<InstallerMarker>().unwrap();
+ let installer_proxy = env.installer_proxy();
assert_eq!(
installer_proxy.get_last_update_result().await.unwrap(),
diff --git a/src/sys/pkg/tests/system-updater/src/lib.rs b/src/sys/pkg/tests/system-updater/src/lib.rs
index ca848ee..2b8e099 100644
--- a/src/sys/pkg/tests/system-updater/src/lib.rs
+++ b/src/sys/pkg/tests/system-updater/src/lib.rs
@@ -5,12 +5,13 @@
#![cfg(test)]
use {
self::SystemUpdaterInteraction::{BlobfsSync, Gc, PackageResolve, Paver, Reboot},
- anyhow::Error,
+ anyhow::{anyhow, Context as _, Error},
cobalt_sw_delivery_registry as metrics, fidl_fuchsia_paver as paver,
fidl_fuchsia_pkg::PackageResolverRequestStream,
- fidl_fuchsia_sys::{LauncherProxy, TerminationReason},
fidl_fuchsia_update_installer::{InstallerMarker, InstallerProxy},
- fidl_fuchsia_update_installer_ext::Options,
+ fidl_fuchsia_update_installer_ext::{
+ start_update, Initiator, Options, UpdateAttempt, UpdateAttemptError,
+ },
fuchsia_async as fasync,
fuchsia_component::{
client::{App, AppBuilder},
@@ -19,6 +20,7 @@
fuchsia_pkg_testing::make_packages_json,
fuchsia_zircon::Status,
futures::prelude::*,
+ matches::assert_matches,
mock_paver::{MockPaverService, MockPaverServiceBuilder, PaverEvent},
mock_reboot::MockRebootService,
mock_resolver::MockResolverService,
@@ -42,7 +44,6 @@
mod history;
mod mode_force_recovery;
mod mode_normal;
-mod options;
mod progress_reporting;
mod reboot_controller;
mod update_package;
@@ -76,7 +77,7 @@
struct TestEnvBuilder {
paver_service_builder: MockPaverServiceBuilder,
blocked_protocols: HashSet<Protocol>,
- oneshot: bool,
+ mount_data: bool,
history: Option<serde_json::Value>,
}
@@ -85,7 +86,7 @@
TestEnvBuilder {
paver_service_builder: MockPaverServiceBuilder::new(),
blocked_protocols: HashSet::new(),
- oneshot: false,
+ mount_data: true,
history: None,
}
}
@@ -103,8 +104,8 @@
self
}
- fn oneshot(mut self, oneshot: bool) -> Self {
- self.oneshot = oneshot;
+ fn mount_data(mut self, mount_data: bool) -> Self {
+ self.mount_data = mount_data;
self
}
@@ -114,7 +115,7 @@
}
fn build(self) -> TestEnv {
- let Self { paver_service_builder, blocked_protocols, oneshot, history } = self;
+ let Self { paver_service_builder, blocked_protocols, mount_data, history } = self;
// A buffer to store all the interactions the system-updater has with external services.
let interactions = Arc::new(Mutex::new(vec![]));
@@ -140,16 +141,8 @@
}
// Set up system-updater to run in --oneshot false code path.
- let mut system_updater_builder = None;
- if !oneshot {
- system_updater_builder = Some(system_updater_app_builder(
- &data_path,
- &build_info_path,
- &misc_path,
- RawSystemUpdaterArgs(&[]),
- Default::default(),
- ));
- }
+ let system_updater_builder =
+ system_updater_app_builder(&data_path, &build_info_path, &misc_path, mount_data);
// Set up the paver service to push events to our interactions buffer by overriding
// call_hook and firmware_hook.
@@ -262,11 +255,11 @@
.expect("nested environment to create successfully");
fasync::Task::spawn(fs.collect()).detach();
- let system_updater = system_updater_builder
- .map(|builder| builder.spawn(env.launcher()).expect("system updater to launch"));
+ let system_updater =
+ system_updater_builder.spawn(env.launcher()).expect("system updater to launch");
TestEnv {
- env,
+ _env: env,
resolver,
_paver_service: paver_service,
_reboot_service: reboot_service,
@@ -284,7 +277,7 @@
}
struct TestEnv {
- env: NestedEnvironment,
+ _env: NestedEnvironment,
resolver: Arc<MockResolverService>,
_paver_service: Arc<MockPaverService>,
_reboot_service: Arc<MockRebootService>,
@@ -296,7 +289,7 @@
build_info_path: PathBuf,
misc_path: PathBuf,
interactions: SystemUpdaterInteractions,
- system_updater: Option<App>,
+ system_updater: App,
}
impl TestEnv {
@@ -308,10 +301,6 @@
TestEnvBuilder::new()
}
- fn launcher(&self) -> &LauncherProxy {
- self.env.launcher()
- }
-
fn take_interactions(&self) -> Vec<SystemUpdaterInteraction> {
std::mem::replace(&mut *self.interactions.lock(), vec![])
}
@@ -364,48 +353,55 @@
.unwrap()
}
- async fn run_system_updater_oneshot<'a>(
+ async fn start_update(&self) -> Result<UpdateAttempt, UpdateAttemptError> {
+ self.start_update_with_options(&UPDATE_PKG_URL, default_options()).await
+ }
+
+ async fn start_update_with_options(
&self,
- args: SystemUpdaterArgs<'a>,
- ) -> Result<(), fuchsia_component::client::OutputError> {
- self.run_system_updater_oneshot_args(args, Default::default()).await
+ url: &str,
+ options: Options,
+ ) -> Result<UpdateAttempt, UpdateAttemptError> {
+ start_update(&url.parse().unwrap(), options, &self.installer_proxy(), None).await
}
- async fn run_system_updater_oneshot_args<'a>(
- &'a self,
- args: impl ToSystemUpdaterCliArgs,
- env: SystemUpdaterEnv,
- ) -> Result<(), fuchsia_component::client::OutputError> {
- let launcher = self.launcher();
-
- let output = system_updater_app_builder(
- &self.data_path,
- &self.build_info_path,
- &self.misc_path,
- args,
- env,
- )
- .output(launcher)
- .expect("system updater to launch")
- .await
- .expect("no errors while waiting for exit");
-
- if !output.stdout.is_empty() {
- eprintln!("TEST: system updater stdout:\n{}", String::from_utf8_lossy(&output.stdout));
- }
-
- if !output.stderr.is_empty() {
- eprintln!("TEST: system updater stderr:\n{}", String::from_utf8_lossy(&output.stderr));
- }
-
- assert_eq!(output.exit_status.reason(), TerminationReason::Exited);
- output.ok()
+ async fn run_update(&self) -> Result<(), Error> {
+ self.run_update_with_options(UPDATE_PKG_URL, default_options()).await
}
- /// Opens a connection to the installer fidl service, panicking if the system updater was not
- /// started as a fidl service.
+ async fn run_update_with_options(&self, url: &str, options: Options) -> Result<(), Error> {
+ let mut update_attempt = self.start_update_with_options(url, options).await?;
+
+ while let Some(state) =
+ update_attempt.try_next().await.context("fetching next update state")?
+ {
+ if state.is_success() {
+ // Wait until the stream terminates before returning so that interactions will
+ // include reboot.
+ assert_matches!(update_attempt.try_next().await, Ok(None));
+ return Ok(());
+ } else if state.is_failure() {
+ // Wait until the stream terminates before returning so that any subsequent
+ // attempts won't get already in progress error.
+ assert_matches!(update_attempt.try_next().await, Ok(None));
+ return Err(anyhow!("update attempt failed"));
+ }
+ }
+
+ Err(anyhow!("unexpected end of update attempt"))
+ }
+
+ /// Opens a connection to the installer fidl service.
fn installer_proxy(&self) -> InstallerProxy {
- self.system_updater.as_ref().unwrap().connect_to_service::<InstallerMarker>().unwrap()
+ self.system_updater.connect_to_service::<InstallerMarker>().unwrap()
+ }
+
+ async fn get_ota_metrics(&self) -> OtaMetrics {
+ let loggers = self.logger_factory.loggers.lock().clone();
+ assert_eq!(loggers.len(), 1);
+ let logger = loggers.into_iter().next().unwrap();
+ let events = logger.cobalt_events.lock().clone();
+ OtaMetrics::from_events(events)
}
}
@@ -413,8 +409,7 @@
data_path: &PathBuf,
build_info_path: &PathBuf,
misc_path: &PathBuf,
- args: impl ToSystemUpdaterCliArgs,
- env: SystemUpdaterEnv,
+ mount_data: bool,
) -> AppBuilder {
let data_dir = File::open(data_path).expect("open data dir");
let build_info_dir = File::open(build_info_path).expect("open config dir");
@@ -426,10 +421,9 @@
.add_dir_to_namespace("/config/build-info".to_string(), build_info_dir)
.expect("/config/build-info to mount")
.add_dir_to_namespace("/misc".to_string(), misc_dir)
- .expect("/misc to mount")
- .args(args.to_args());
+ .expect("/misc to mount");
- if env.mount_data {
+ if mount_data {
system_updater = system_updater
.add_dir_to_namespace("/data".to_string(), data_dir)
.expect("/data to mount");
@@ -438,99 +432,6 @@
system_updater
}
-trait ToSystemUpdaterCliArgs {
- fn to_args(self) -> Vec<String>;
-}
-
-impl ToSystemUpdaterCliArgs for SystemUpdaterArgs<'_> {
- fn to_args(self) -> Vec<String> {
- self.build()
- }
-}
-
-impl ToSystemUpdaterCliArgs for RawSystemUpdaterArgs {
- fn to_args(self) -> Vec<String> {
- self.0.into_iter().map(|s| (*s).to_owned()).collect()
- }
-}
-
-#[derive(Debug)]
-struct SystemUpdaterEnv {
- mount_data: bool,
-}
-
-impl Default for SystemUpdaterEnv {
- fn default() -> Self {
- Self { mount_data: true }
- }
-}
-
-#[derive(Debug)]
-struct RawSystemUpdaterArgs(&'static [&'static str]);
-
-#[derive(Debug, Default)]
-struct SystemUpdaterArgs<'a> {
- initiator: Option<Initiator>,
- source: Option<&'a str>,
- target: Option<&'a str>,
- start: Option<i64>,
- update: Option<&'a str>,
- reboot: Option<bool>,
- skip_recovery: Option<bool>,
-}
-
-#[derive(Debug, Clone, Copy)]
-enum Initiator {
- User,
- Service,
-}
-
-impl Default for Initiator {
- fn default() -> Self {
- Initiator::Service
- }
-}
-
-impl Initiator {
- fn to_cli_arg(self) -> String {
- match self {
- Initiator::User => "manual".to_string(),
- Initiator::Service => "automatic".to_string(),
- }
- }
-}
-
-impl SystemUpdaterArgs<'_> {
- fn build(&self) -> Vec<String> {
- let mut args = vec![];
-
- if let Some(initiator) = self.initiator {
- args.extend(vec!["--initiator".to_owned(), initiator.to_cli_arg()]);
- }
- if let Some(source) = self.source {
- args.extend(vec!["--source".to_owned(), source.to_owned()]);
- }
- if let Some(target) = self.target {
- args.extend(vec!["--target".to_owned(), target.to_owned()]);
- }
- if let Some(start) = self.start {
- args.extend(vec!["--start".to_owned(), start.to_string()]);
- }
- if let Some(update) = self.update {
- args.extend(vec!["--update".to_owned(), update.to_owned()]);
- }
- if let Some(reboot) = self.reboot {
- args.extend(vec!["--reboot".to_owned(), reboot.to_string()]);
- }
- if let Some(skip_recovery) = self.skip_recovery {
- args.extend(vec!["--skip-recovery".to_owned(), skip_recovery.to_string()]);
- }
- args.extend(vec!["--oneshot".to_owned(), "true".to_owned()]);
-
- args
- }
-}
-
struct MockCacheService {
sync_response: Mutex<Option<Result<(), Status>>>,
interactions: SystemUpdaterInteractions,
@@ -707,7 +608,7 @@
// OtaStart only has initiator and hour_of_day, so just check initiator.
assert_eq!(start.event_codes[0], event_codes[0]);
- assert_eq!(&start.component, &component);
+ assert_eq!(start.component, Some("".to_string()));
let target = component.expect("a target update merkle");
@@ -772,7 +673,7 @@
fn default_options() -> Options {
Options {
- initiator: fidl_fuchsia_update_installer_ext::Initiator::User,
+ initiator: Initiator::User,
allow_attach_to_existing_attempt: true,
should_write_recovery: true,
}
diff --git a/src/sys/pkg/tests/system-updater/src/mode_force_recovery.rs b/src/sys/pkg/tests/system-updater/src/mode_force_recovery.rs
index 8b64ffa..444c6a0 100644
--- a/src/sys/pkg/tests/system-updater/src/mode_force_recovery.rs
+++ b/src/sys/pkg/tests/system-updater/src/mode_force_recovery.rs
@@ -20,35 +20,25 @@
#[fasync::run_singlethreaded(test)]
async fn writes_recovery_and_force_reboots_into_it() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
- let package_url = SYSTEM_IMAGE_URL;
env.resolver
.register_package("update", "upd4t3")
- .add_file("packages.json", make_packages_json([package_url]))
+ .add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
.add_file("update-mode", &force_recovery_json())
.add_file("recovery", "the recovery image")
.add_file("recovery.vbmeta", "the recovery vbmeta");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("run system updater");
+ env.run_update().await.expect("run system updater");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -94,21 +84,14 @@
#[fasync::run_singlethreaded(test)]
async fn reboots_regardless_of_reboot_arg() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages", make_packages_json([]))
.add_file("update-mode", &force_recovery_json());
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- reboot: Some(false),
- ..Default::default()
- })
- .await
- .expect("run system updater");
+ env.run_update().await.expect("run system updater");
// Verify we made a reboot call.
assert_eq!(env.take_interactions().last().unwrap(), &Reboot);
@@ -145,7 +128,7 @@
#[fasync::run_singlethreaded(test)]
async fn rejects_zbi() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -154,13 +137,7 @@
.add_file("bootloader", "new bootloader")
.add_file("zbi", "fake zbi");
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
assert_eq!(
@@ -186,7 +163,7 @@
#[fasync::run_singlethreaded(test)]
async fn rejects_skip_recovery_flag() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -194,12 +171,14 @@
.add_file("update-mode", &force_recovery_json());
let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- skip_recovery: Some(true),
- ..Default::default()
- })
+ .run_update_with_options(
+ UPDATE_PKG_URL,
+ Options {
+ initiator: Initiator::User,
+ allow_attach_to_existing_attempt: true,
+ should_write_recovery: false,
+ },
+ )
.await;
assert!(result.is_err(), "system updater succeeded when it should fail");
}
diff --git a/src/sys/pkg/tests/system-updater/src/mode_normal.rs b/src/sys/pkg/tests/system-updater/src/mode_normal.rs
index 9af624c..82eb731 100644
--- a/src/sys/pkg/tests/system-updater/src/mode_normal.rs
+++ b/src/sys/pkg/tests/system-updater/src/mode_normal.rs
@@ -11,35 +11,27 @@
#[fasync::run_singlethreaded(test)]
async fn updates_the_system() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
- .add_file("zbi", "fake zbi");
+ .add_file("zbi", "fake zbi")
+ .add_file("version", "1.2.3.4");
env.resolver
.url(SYSTEM_IMAGE_URL)
.resolve(&env.resolver.package("system_image/0", SYSTEM_IMAGE_HASH));
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("run system updater");
+ env.run_update().await.expect("run system updater");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
+ target: "1.2.3.4".into(),
}
);
@@ -77,7 +69,7 @@
#[fasync::run_singlethreaded(test)]
async fn requires_zbi() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -87,13 +79,7 @@
.url(SYSTEM_IMAGE_URL)
.resolve(&env.resolver.package("system_image/0", SYSTEM_IMAGE_HASH));
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
assert_eq!(
@@ -120,13 +106,14 @@
}
#[fasync::run_singlethreaded(test)]
-async fn updates_the_system_no_oneshot() {
+async fn updates_the_system_with_progress() {
let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
- .add_file("zbi", "fake zbi");
+ .add_file("zbi", "fake zbi")
+ .add_file("version", "5.6.7.8");
env.resolver
.url(SYSTEM_IMAGE_URL)
.resolve(&env.resolver.package("system_image/0", SYSTEM_IMAGE_HASH));
@@ -148,17 +135,14 @@
);
// Verify metrics reported.
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "".into(),
+ target: "5.6.7.8".into(),
}
);
diff --git a/src/sys/pkg/tests/system-updater/src/options.rs b/src/sys/pkg/tests/system-updater/src/options.rs
deleted file mode 100644
index 003a9ea..0000000
--- a/src/sys/pkg/tests/system-updater/src/options.rs
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use {super::*, pretty_assertions::assert_eq};
-
-#[fasync::run_singlethreaded(test)]
-async fn uses_custom_update_package() {
- let env = TestEnv::builder().oneshot(true).build();
-
- env.resolver
- .register_custom_package("another-update/4", "update", "upd4t3r", "fuchsia.com")
- .add_file("packages.json", make_packages_json([]))
- .add_file("zbi", "fake zbi");
-
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- update: Some("fuchsia-pkg://fuchsia.com/another-update/4"),
- ..Default::default()
- })
- .await
- .expect("run system updater");
-
- assert_eq!(
- env.take_interactions(),
- vec![
- Paver(PaverEvent::QueryCurrentConfiguration),
- Paver(PaverEvent::ReadAsset {
- configuration: paver::Configuration::A,
- asset: paver::Asset::VerifiedBootMetadata
- }),
- Paver(PaverEvent::ReadAsset {
- configuration: paver::Configuration::A,
- asset: paver::Asset::Kernel
- }),
- Paver(PaverEvent::QueryCurrentConfiguration),
- Paver(PaverEvent::QueryActiveConfiguration),
- Gc,
- PackageResolve("fuchsia-pkg://fuchsia.com/another-update/4".to_string()),
- Gc,
- BlobfsSync,
- Paver(PaverEvent::WriteAsset {
- configuration: paver::Configuration::B,
- asset: paver::Asset::Kernel,
- payload: b"fake zbi".to_vec(),
- }),
- Paver(PaverEvent::SetConfigurationActive { configuration: paver::Configuration::B }),
- Paver(PaverEvent::DataSinkFlush),
- Paver(PaverEvent::BootManagerFlush),
- Reboot,
- ]
- );
-}
-
-#[fasync::run_singlethreaded(test)]
-async fn rejects_invalid_update_package_url() {
- let env = TestEnv::new();
-
- let bogus_url = "not-fuchsia-pkg://fuchsia.com/not-a-update";
-
- env.resolver.mock_resolve_failure(bogus_url, Status::INVALID_ARGS);
-
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- update: Some(bogus_url),
- ..Default::default()
- })
- .await;
- assert!(result.is_err(), "system updater succeeded when it should fail");
-
- assert_eq!(env.take_interactions(), vec![]);
-}
-
-#[fasync::run_singlethreaded(test)]
-async fn rejects_unknown_flags() {
- let env = TestEnv::builder().oneshot(true).build();
-
- env.resolver
- .register_package("update", "upd4t3")
- .add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
- .add_file("zbi", "fake zbi");
-
- let result = env
- .run_system_updater_oneshot_args(
- RawSystemUpdaterArgs(&["--initiator", "manual", "--target", "m3rk13", "--foo", "bar"]),
- Default::default(),
- )
- .await;
- assert!(result.is_err(), "system updater succeeded when it should fail");
- assert_eq!(env.take_interactions(), vec![]);
-}
-
-#[fasync::run_singlethreaded(test)]
-async fn rejects_extra_args() {
- let env = TestEnv::builder().oneshot(true).build();
-
- env.resolver
- .register_package("update", "upd4t3")
- .add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
- .add_file("zbi", "fake zbi");
-
- let result = env
- .run_system_updater_oneshot_args(
- RawSystemUpdaterArgs(&["--initiator", "manual", "--target", "m3rk13", "foo"]),
- Default::default(),
- )
- .await;
- assert!(result.is_err(), "system updater succeeded when it should fail");
-
- assert_eq!(env.take_interactions(), vec![]);
-}
-
-#[fasync::run_singlethreaded(test)]
-async fn does_not_reboot_if_requested_not_to_reboot() {
- let env = TestEnv::builder().oneshot(true).build();
-
- env.resolver
- .register_package("update", "upd4t3")
- .add_file("packages.json", make_packages_json([]))
- .add_file("zbi", "fake zbi");
-
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- reboot: Some(false),
- ..Default::default()
- })
- .await
- .expect("run system updater");
-
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
- assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
- OtaMetrics {
- initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
- as u32,
- phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
- status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
- }
- );
-
- assert_eq!(
- env.take_interactions(),
- vec![
- Paver(PaverEvent::QueryCurrentConfiguration),
- Paver(PaverEvent::ReadAsset {
- configuration: paver::Configuration::A,
- asset: paver::Asset::VerifiedBootMetadata
- }),
- Paver(PaverEvent::ReadAsset {
- configuration: paver::Configuration::A,
- asset: paver::Asset::Kernel
- }),
- Paver(PaverEvent::QueryCurrentConfiguration),
- Paver(PaverEvent::QueryActiveConfiguration),
- Gc,
- PackageResolve(UPDATE_PKG_URL.to_string()),
- Gc,
- BlobfsSync,
- Paver(PaverEvent::WriteAsset {
- configuration: paver::Configuration::B,
- asset: paver::Asset::Kernel,
- payload: b"fake zbi".to_vec(),
- }),
- Paver(PaverEvent::SetConfigurationActive { configuration: paver::Configuration::B }),
- Paver(PaverEvent::DataSinkFlush),
- Paver(PaverEvent::BootManagerFlush),
- ]
- );
-}
diff --git a/src/sys/pkg/tests/system-updater/src/progress_reporting.rs b/src/sys/pkg/tests/system-updater/src/progress_reporting.rs
index d4f78e41..94b2a6d 100644
--- a/src/sys/pkg/tests/system-updater/src/progress_reporting.rs
+++ b/src/sys/pkg/tests/system-updater/src/progress_reporting.rs
@@ -8,7 +8,6 @@
monitor_update, start_update, Initiator, Options, Progress, State, StateId,
UpdateAttemptError, UpdateInfo, UpdateInfoAndProgress,
},
- fuchsia_url::pkg_url::PkgUrl,
matches::assert_matches,
pretty_assertions::assert_eq,
};
@@ -38,11 +37,7 @@
let handle_pkg3 = env.resolver.url(pkg3_url).block_once();
// Start the system update.
- let installer_proxy = env.installer_proxy();
- let mut attempt =
- start_update(&UPDATE_PKG_URL.parse().unwrap(), default_options(), &installer_proxy, None)
- .await
- .unwrap();
+ let mut attempt = env.start_update().await.unwrap();
assert_eq!(attempt.next().await.unwrap().unwrap(), State::Prepare);
@@ -121,15 +116,11 @@
let handle_update_pkg = env.resolver.url(UPDATE_PKG_URL).block_once();
// Start the system update.
- let installer_proxy = env.installer_proxy();
- let attempt0 =
- start_update(&UPDATE_PKG_URL.parse().unwrap(), default_options(), &installer_proxy, None)
- .await
- .unwrap();
+ let attempt0 = env.start_update().await.unwrap();
// Attach monitor.
let attempt1 =
- monitor_update(Some(attempt0.attempt_id()), &installer_proxy).await.unwrap().unwrap();
+ monitor_update(Some(attempt0.attempt_id()), &env.installer_proxy()).await.unwrap().unwrap();
// Now that we attached both monitors to the current attempt, we can unblock the
// resolve and resume the update attempt.
@@ -164,21 +155,18 @@
// Start the system update, making 2 start_update requests. The second start_update request
// is essentially just a monitor_update request in this case.
- let installer_proxy = env.installer_proxy();
- let url: PkgUrl = UPDATE_PKG_URL.parse().unwrap();
- let attempt0 = start_update(&url, default_options(), &installer_proxy, None).await.unwrap();
- let attempt1 = start_update(
- &url,
- Options {
- initiator: Initiator::User,
- allow_attach_to_existing_attempt: true,
- should_write_recovery: true,
- },
- &installer_proxy,
- None,
- )
- .await
- .unwrap();
+ let attempt0 = env.start_update().await.unwrap();
+ let attempt1 = env
+ .start_update_with_options(
+ UPDATE_PKG_URL,
+ Options {
+ initiator: Initiator::User,
+ allow_attach_to_existing_attempt: true,
+ should_write_recovery: true,
+ },
+ )
+ .await
+ .unwrap();
// Now that we attached both monitors to the current attempt, we can unblock the
// resolve and resume the update attempt.
@@ -212,16 +200,14 @@
// Start the system update.
let installer_proxy = env.installer_proxy();
- let compatible_url: PkgUrl = UPDATE_PKG_URL.parse().unwrap();
+ let compatible_url = UPDATE_PKG_URL;
let compatible_options = Options {
initiator: Initiator::User,
allow_attach_to_existing_attempt: true,
should_write_recovery: true,
};
let _attempt =
- start_update(&compatible_url, compatible_options.clone(), &installer_proxy, None)
- .await
- .unwrap();
+ env.start_update_with_options(compatible_url, compatible_options.clone()).await.unwrap();
// Define incompatible options and url.
let incompatible_options0 = Options {
@@ -234,25 +220,25 @@
allow_attach_to_existing_attempt: false,
should_write_recovery: true,
};
- let incompatible_url = "fuchsia-pkg://fuchsia.com/different-url".parse().unwrap();
+ let incompatible_url = "fuchsia-pkg://fuchsia.com/different-url";
// Show that start_update requests fail with AlreadyInProgress errors.
assert_matches!(
- start_update(&compatible_url, incompatible_options0, &installer_proxy, None)
+ env.start_update_with_options(compatible_url, incompatible_options0)
.await
.map(|_| ())
.unwrap_err(),
UpdateAttemptError::InstallInProgress
);
assert_matches!(
- start_update(&compatible_url, incompatible_options1, &installer_proxy, None)
+ env.start_update_with_options(compatible_url, incompatible_options1)
.await
.map(|_| ())
.unwrap_err(),
UpdateAttemptError::InstallInProgress
);
assert_matches!(
- start_update(&incompatible_url, compatible_options.clone(), &installer_proxy, None)
+ env.start_update_with_options(incompatible_url, compatible_options.clone())
.await
.map(|_| ())
.unwrap_err(),
@@ -260,10 +246,15 @@
);
let (_, server_end) = fidl::endpoints::create_endpoints().unwrap();
assert_matches!(
- start_update(&compatible_url, compatible_options, &installer_proxy, Some(server_end))
- .await
- .map(|_| ())
- .unwrap_err(),
+ start_update(
+ &compatible_url.parse().unwrap(),
+ compatible_options,
+ &installer_proxy,
+ Some(server_end)
+ )
+ .await
+ .map(|_| ())
+ .unwrap_err(),
UpdateAttemptError::InstallInProgress
);
}
diff --git a/src/sys/pkg/tests/system-updater/src/update_package.rs b/src/sys/pkg/tests/system-updater/src/update_package.rs
index e7f8374..63bf260 100644
--- a/src/sys/pkg/tests/system-updater/src/update_package.rs
+++ b/src/sys/pkg/tests/system-updater/src/update_package.rs
@@ -6,7 +6,7 @@
#[fasync::run_singlethreaded(test)]
async fn rejects_invalid_package_name() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
// Name the update package something other than "update" and assert that the process fails to
// validate the update package.
@@ -14,18 +14,12 @@
.register_custom_package("not_update", "not_update", "upd4t3", "fuchsia.com")
.add_file("packages.json", make_packages_json([SYSTEM_IMAGE_URL]))
.add_file("zbi", "fake zbi")
- .add_file("zedboot", "new recovery");
+ .add_file("zedboot", "new recovery")
+ .add_file("version", "build version");
let not_update_package_url = "fuchsia-pkg://fuchsia.com/not_update";
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- update: Some(not_update_package_url),
- ..Default::default()
- })
- .await;
+ let result = env.run_update_with_options(not_update_package_url, default_options()).await;
assert!(result.is_err(), "system updater succeeded when it should fail");
// Expect to have failed prior to downloading images.
@@ -50,35 +44,25 @@
]
);
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
- let events = OtaMetrics::from_events(logger.cobalt_events.lock().clone());
assert_eq!(
- events,
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::Tufupdate as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Error as u32,
- target: "m3rk13".into(),
+ target: "build version".into(),
}
);
}
#[fasync::run_singlethreaded(test)]
async fn fails_if_package_unavailable() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver.mock_resolve_failure(UPDATE_PKG_URL, Status::NOT_FOUND);
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
assert_eq!(
@@ -100,3 +84,47 @@
]
);
}
+
+#[fasync::run_singlethreaded(test)]
+async fn uses_custom_update_package() {
+ let env = TestEnv::builder().build();
+
+ env.resolver
+ .register_custom_package("another-update/4", "update", "upd4t3r", "fuchsia.com")
+ .add_file("packages.json", make_packages_json([]))
+ .add_file("zbi", "fake zbi");
+
+ env.run_update_with_options("fuchsia-pkg://fuchsia.com/another-update/4", default_options())
+ .await
+ .expect("run system updater");
+
+ assert_eq!(
+ env.take_interactions(),
+ vec![
+ Paver(PaverEvent::QueryCurrentConfiguration),
+ Paver(PaverEvent::ReadAsset {
+ configuration: paver::Configuration::A,
+ asset: paver::Asset::VerifiedBootMetadata
+ }),
+ Paver(PaverEvent::ReadAsset {
+ configuration: paver::Configuration::A,
+ asset: paver::Asset::Kernel
+ }),
+ Paver(PaverEvent::QueryCurrentConfiguration),
+ Paver(PaverEvent::QueryActiveConfiguration),
+ Gc,
+ PackageResolve("fuchsia-pkg://fuchsia.com/another-update/4".to_string()),
+ Gc,
+ BlobfsSync,
+ Paver(PaverEvent::WriteAsset {
+ configuration: paver::Configuration::B,
+ asset: paver::Asset::Kernel,
+ payload: b"fake zbi".to_vec(),
+ }),
+ Paver(PaverEvent::SetConfigurationActive { configuration: paver::Configuration::B }),
+ Paver(PaverEvent::DataSinkFlush),
+ Paver(PaverEvent::BootManagerFlush),
+ Reboot,
+ ]
+ );
+}
diff --git a/src/sys/pkg/tests/system-updater/src/writes_firmware.rs b/src/sys/pkg/tests/system-updater/src/writes_firmware.rs
index 2fe51d4..4605358 100644
--- a/src/sys/pkg/tests/system-updater/src/writes_firmware.rs
+++ b/src/sys/pkg/tests/system-updater/src/writes_firmware.rs
@@ -6,7 +6,7 @@
#[fasync::run_singlethreaded(test)]
async fn writes_bootloader() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -14,13 +14,7 @@
.add_file("zbi", "fake zbi")
.add_file("bootloader", "new bootloader");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -60,7 +54,7 @@
#[fasync::run_singlethreaded(test)]
async fn writes_firmware() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -68,13 +62,7 @@
.add_file("zbi", "fake zbi")
.add_file("firmware", "fake firmware");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -114,7 +102,7 @@
#[fasync::run_singlethreaded(test)]
async fn writes_multiple_firmware_types() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -123,13 +111,7 @@
.add_file("firmware_a", "fake firmware A")
.add_file("firmware_b", "fake firmware B");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
let mut interactions = env.take_interactions();
// The order of files listed from a directory isn't guaranteed so the
@@ -192,7 +174,6 @@
.paver_service(|builder| {
builder.firmware_hook(|_| paver::WriteFirmwareResult::Unsupported(true))
})
- .oneshot(true)
.build();
env.resolver
@@ -202,13 +183,7 @@
.add_file("firmware", "fake firmware");
// Update should still succeed, we want to skip unsupported firmware types.
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -253,7 +228,6 @@
builder
.firmware_hook(|_| paver::WriteFirmwareResult::Status(Status::INTERNAL.into_raw()))
})
- .oneshot(true)
.build();
env.resolver
@@ -262,11 +236,5 @@
.add_file("zbi", "fake zbi")
.add_file("firmware", "fake firmware");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect_err("update should fail");
+ env.run_update().await.expect_err("update should fail");
}
diff --git a/src/sys/pkg/tests/system-updater/src/writes_images.rs b/src/sys/pkg/tests/system-updater/src/writes_images.rs
index 68ddb05..322bcaf 100644
--- a/src/sys/pkg/tests/system-updater/src/writes_images.rs
+++ b/src/sys/pkg/tests/system-updater/src/writes_images.rs
@@ -6,20 +6,14 @@
#[fasync::run_singlethreaded(test)]
async fn fails_on_paver_connect_error() {
- let env = TestEnv::builder().unregister_protocol(Protocol::Paver).oneshot(true).build();
+ let env = TestEnv::builder().unregister_protocol(Protocol::Paver).build();
env.resolver
.register_package("update", "upd4t3")
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake_zbi");
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
// Appmgr will close the paver service channel when it is unable to forward the channel to any
@@ -45,7 +39,6 @@
_ => Status::OK,
})
})
- .oneshot(true)
.build();
env.resolver
@@ -53,26 +46,17 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake_zbi");
- let result = env
- .run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await;
+ let result = env.run_update().await;
assert!(result.is_err(), "system updater succeeded when it should fail");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::ImageWrite as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Error as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -105,7 +89,7 @@
#[fasync::run_singlethreaded(test)]
async fn skip_recovery_does_not_write_recovery_or_vbmeta() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -114,12 +98,10 @@
.add_file("zedboot", "new recovery")
.add_file("recovery.vbmeta", "new recovery vbmeta");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- skip_recovery: Some(true),
- ..Default::default()
- })
+ env.run_update_with_options(
+ UPDATE_PKG_URL,
+ Options { should_write_recovery: false, ..default_options() },
+ )
.await
.expect("success");
@@ -158,7 +140,6 @@
async fn writes_to_both_configs_if_abr_not_supported() {
let env = TestEnv::builder()
.paver_service(|builder| builder.boot_manager_close_with_epitaph(Status::NOT_SUPPORTED))
- .oneshot(true)
.build();
env.resolver
@@ -166,25 +147,16 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake_zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -228,7 +200,6 @@
.current_config(current_config)
.active_config(active_config)
})
- .oneshot(true)
.build();
env.resolver
@@ -236,25 +207,16 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake_zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);
@@ -405,7 +367,7 @@
#[fasync::run_singlethreaded(test)]
async fn writes_recovery_called_legacy_zedboot() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -413,13 +375,7 @@
.add_file("zbi", "fake zbi")
.add_file("zedboot", "new recovery");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -460,7 +416,7 @@
// TODO(fxbug.dev/52356): drop this duplicate test when "zedboot" is no longer allowed/used.
#[fasync::run_singlethreaded(test)]
async fn writes_recovery() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -468,13 +424,7 @@
.add_file("zbi", "fake zbi")
.add_file("recovery", "new recovery");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -514,7 +464,7 @@
#[fasync::run_singlethreaded(test)]
async fn writes_recovery_vbmeta() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -523,13 +473,7 @@
.add_file("zedboot", "new recovery")
.add_file("recovery.vbmeta", "new recovery vbmeta");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -574,7 +518,7 @@
#[fasync::run_singlethreaded(test)]
async fn writes_fuchsia_vbmeta() {
- let env = TestEnv::builder().oneshot(true).build();
+ let env = TestEnv::builder().build();
env.resolver
.register_package("update", "upd4t3")
@@ -582,13 +526,7 @@
.add_file("zbi", "fake zbi")
.add_file("fuchsia.vbmeta", "fake zbi vbmeta");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
assert_eq!(
env.take_interactions(),
@@ -645,7 +583,6 @@
builder
}
})
- .oneshot(true)
.build();
env.resolver
@@ -653,25 +590,16 @@
.add_file("packages.json", make_packages_json([]))
.add_file("zbi", "fake_zbi");
- env.run_system_updater_oneshot(SystemUpdaterArgs {
- initiator: Some(Initiator::User),
- target: Some("m3rk13"),
- ..Default::default()
- })
- .await
- .expect("success");
+ env.run_update().await.expect("success");
- let loggers = env.logger_factory.loggers.lock().clone();
- assert_eq!(loggers.len(), 1);
- let logger = loggers.into_iter().next().unwrap();
assert_eq!(
- OtaMetrics::from_events(logger.cobalt_events.lock().clone()),
+ env.get_ota_metrics().await,
OtaMetrics {
initiator: metrics::OtaResultAttemptsMetricDimensionInitiator::UserInitiatedCheck
as u32,
phase: metrics::OtaResultAttemptsMetricDimensionPhase::SuccessPendingReboot as u32,
status_code: metrics::OtaResultAttemptsMetricDimensionStatusCode::Success as u32,
- target: "m3rk13".into(),
+ target: "".into(),
}
);