| // 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 writes_bootloader() { |
| let env = TestEnv::builder().build(); |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("zbi", "fake zbi") |
| .add_file("bootloader", "new bootloader"); |
| |
| env.run_update().await.expect("success"); |
| |
| 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::WriteFirmware { |
| configuration: paver::Configuration::B, |
| firmware_type: "".to_string(), |
| payload: b"new bootloader".to_vec() |
| }), |
| 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 writes_firmware() { |
| let env = TestEnv::builder().build(); |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("zbi", "fake zbi") |
| .add_file("firmware", "fake firmware"); |
| |
| env.run_update().await.expect("success"); |
| |
| 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::WriteFirmware { |
| configuration: paver::Configuration::B, |
| firmware_type: "".to_string(), |
| payload: b"fake firmware".to_vec() |
| }), |
| 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 writes_multiple_firmware_types() { |
| let env = TestEnv::builder().build(); |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("zbi", "fake zbi") |
| .add_file("firmware_a", "fake firmware A") |
| .add_file("firmware_b", "fake firmware B"); |
| |
| 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 |
| // firmware could be written in either order. Sort by type string so |
| // we can easily validate contents. |
| interactions[9..11].sort_by_key(|event| { |
| if let Paver(PaverEvent::WriteFirmware { configuration: _, firmware_type, payload: _ }) = |
| event |
| { |
| return firmware_type.clone(); |
| } else { |
| panic!("Not a WriteFirmware event: {:?}", event); |
| } |
| }); |
| |
| assert_eq!( |
| 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::WriteFirmware { |
| configuration: paver::Configuration::B, |
| firmware_type: "a".to_string(), |
| payload: b"fake firmware A".to_vec() |
| }), |
| Paver(PaverEvent::WriteFirmware { |
| configuration: paver::Configuration::B, |
| firmware_type: "b".to_string(), |
| payload: b"fake firmware B".to_vec() |
| }), |
| 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 skips_unsupported_firmware_type() { |
| let env = TestEnv::builder() |
| .paver_service(|builder| { |
| builder.firmware_hook(|_| paver::WriteFirmwareResult::Unsupported(true)) |
| }) |
| .build(); |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("zbi", "fake zbi") |
| .add_file("firmware", "fake firmware"); |
| |
| // Update should still succeed, we want to skip unsupported firmware types. |
| env.run_update().await.expect("success"); |
| |
| 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::WriteFirmware { |
| configuration: paver::Configuration::B, |
| firmware_type: "".to_string(), |
| payload: b"fake firmware".to_vec(), |
| }), |
| 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 fails_on_firmware_write_error() { |
| let env = TestEnv::builder() |
| .paver_service(|builder| { |
| builder |
| .firmware_hook(|_| paver::WriteFirmwareResult::Status(Status::INTERNAL.into_raw())) |
| }) |
| .build(); |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("zbi", "fake zbi") |
| .add_file("firmware", "fake firmware"); |
| |
| env.run_update().await.expect_err("update should fail"); |
| } |