system_update_committer/metadata/
commit.rs1use super::configuration_without_recovery::ConfigurationWithoutRecovery;
6use super::errors::{BootManagerError, BootManagerResultExt};
7use fidl_fuchsia_paver as paver;
8
9pub async fn do_commit(
11 boot_manager: &paver::BootManagerProxy,
12 current_config: &ConfigurationWithoutRecovery,
13) -> Result<(), BootManagerError> {
14 async fn internal_write(
16 boot_manager: &paver::BootManagerProxy,
17 current_config: &ConfigurationWithoutRecovery,
18 ) -> Result<(), BootManagerError> {
19 let alternate_config = current_config.to_alternate().into();
20
21 let () = boot_manager
22 .set_configuration_healthy(current_config.into())
23 .await
24 .into_boot_manager_result("set_configuration_healthy")?;
25 let () = boot_manager
26 .set_configuration_unbootable(alternate_config)
27 .await
28 .into_boot_manager_result("set_configuration_unbootable")?;
29 Ok(())
30 }
31
32 let write_result = internal_write(boot_manager, current_config).await;
34
35 let () = boot_manager.flush().await.into_boot_manager_result("flush")?;
36
37 write_result
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use assert_matches::assert_matches;
44 use fuchsia_async as fasync;
45 use mock_paver::{hooks as mphooks, MockPaverServiceBuilder, PaverEvent};
46 use std::sync::Arc;
47 use zx::Status;
48
49 async fn run_success_test(current_config: &ConfigurationWithoutRecovery) {
51 let paver = Arc::new(MockPaverServiceBuilder::new().build());
52 let () = do_commit(&paver.spawn_boot_manager_service(), current_config).await.unwrap();
53
54 assert_eq!(
55 paver.take_events(),
56 vec![
57 PaverEvent::SetConfigurationHealthy { configuration: current_config.into() },
58 PaverEvent::SetConfigurationUnbootable {
59 configuration: current_config.to_alternate().into()
60 },
61 PaverEvent::BootManagerFlush,
62 ]
63 );
64 }
65
66 #[fasync::run_singlethreaded(test)]
67 async fn test_success_current_a() {
68 run_success_test(&ConfigurationWithoutRecovery::A).await;
69 }
70
71 #[fasync::run_singlethreaded(test)]
72 async fn test_success_current_b() {
73 run_success_test(&ConfigurationWithoutRecovery::B).await;
74 }
75
76 #[fasync::run_singlethreaded(test)]
77 async fn test_fails_when_set_healthy_fails() {
78 let paver = Arc::new(
79 MockPaverServiceBuilder::new()
80 .insert_hook(mphooks::return_error(|e| match e {
81 PaverEvent::SetConfigurationHealthy { .. } => Status::OUT_OF_RANGE,
82 _ => Status::OK,
83 }))
84 .build(),
85 );
86
87 assert_matches!(
88 do_commit(&paver.spawn_boot_manager_service(), &ConfigurationWithoutRecovery::A).await,
89 Err(BootManagerError::Status {
90 method_name: "set_configuration_healthy",
91 status: Status::OUT_OF_RANGE
92 })
93 );
94
95 assert_eq!(
96 paver.take_events(),
97 vec![
98 PaverEvent::SetConfigurationHealthy { configuration: paver::Configuration::A },
99 PaverEvent::BootManagerFlush,
100 ]
101 );
102 }
103}