| // 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().await; |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH)) |
| .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::QueryConfigurationStatus { configuration: paver::Configuration::A }), |
| Paver(PaverEvent::SetConfigurationUnbootable { |
| configuration: paver::Configuration::B |
| }), |
| Paver(PaverEvent::BootManagerFlush), |
| 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().await; |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH)) |
| .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::QueryConfigurationStatus { configuration: paver::Configuration::A }), |
| Paver(PaverEvent::SetConfigurationUnbootable { |
| configuration: paver::Configuration::B |
| }), |
| Paver(PaverEvent::BootManagerFlush), |
| 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().await; |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH)) |
| .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 interactions = env.take_interactions(); |
| |
| 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::QueryConfigurationStatus { configuration: paver::Configuration::A }), |
| Paver(PaverEvent::SetConfigurationUnbootable { |
| configuration: paver::Configuration::B |
| }), |
| Paver(PaverEvent::BootManagerFlush), |
| 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.insert_hook(mphooks::write_firmware(|_, _, _| { |
| paver::WriteFirmwareResult::Unsupported(true) |
| })) |
| }) |
| .build() |
| .await; |
| |
| env.resolver |
| .register_package("update", "upd4t3") |
| .add_file("packages.json", make_packages_json([])) |
| .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH)) |
| .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::QueryConfigurationStatus { configuration: paver::Configuration::A }), |
| Paver(PaverEvent::SetConfigurationUnbootable { |
| configuration: paver::Configuration::B |
| }), |
| Paver(PaverEvent::BootManagerFlush), |
| 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.insert_hook(mphooks::write_firmware(|_, _, _| { |
| paver::WriteFirmwareResult::Status(Status::INTERNAL.into_raw()) |
| })) |
| }) |
| .build() |
| .await; |
| |
| 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"); |
| } |