blob: 83896f1aaa6c5158f85a121ec0f7c377d5f75884 [file] [log] [blame]
// Copyright 2023 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 {
crate::fuchsia::{
testing::{TestFixture, TestFixtureOptions},
volume::FxVolume,
},
async_trait::async_trait,
blob_writer::BlobWriter,
delivery_blob::{CompressionMode, Type1Blob},
fidl_fuchsia_fxfs::{BlobCreatorMarker, BlobReaderMarker, BlobWriterProxy, CreateBlobError},
fuchsia_component::client::connect_to_protocol_at_dir_svc,
fuchsia_merkle::Hash,
fuchsia_zircon as zx,
fxfs::object_store::{directory::Directory, DataObjectHandle, HandleOptions, ObjectStore},
storage_device::{fake_device::FakeDevice, DeviceHolder},
};
pub async fn new_blob_fixture() -> TestFixture {
TestFixture::open(
DeviceHolder::new(FakeDevice::new(16384, 512)),
TestFixtureOptions { encrypted: false, as_blob: true, format: true, serve_volume: true },
)
.await
}
pub async fn open_blob_fixture(device_holder: DeviceHolder) -> TestFixture {
TestFixture::open(
device_holder,
TestFixtureOptions { encrypted: false, as_blob: true, format: false, serve_volume: true },
)
.await
}
#[async_trait]
pub trait BlobFixture {
async fn write_blob(&self, data: &[u8], mode: CompressionMode) -> Hash;
async fn read_blob(&self, hash: Hash) -> Vec<u8>;
async fn get_blob_handle(&self, name: &str) -> DataObjectHandle<FxVolume>;
async fn get_blob_vmo(&self, hash: Hash) -> zx::Vmo;
async fn create_blob(
&self,
hash: &[u8; 32],
allow_existing: bool,
) -> Result<BlobWriterProxy, CreateBlobError>;
}
#[async_trait]
impl BlobFixture for TestFixture {
async fn write_blob(&self, data: &[u8], mode: CompressionMode) -> Hash {
let hash = fuchsia_merkle::from_slice(data).root();
let delivery_data: Vec<u8> = Type1Blob::generate(&data, mode);
let writer = self.create_blob(&hash.into(), false).await.expect("failed to create blob");
let mut blob_writer = BlobWriter::create(writer, delivery_data.len() as u64)
.await
.expect("failed to create BlobWriter");
blob_writer.write(&delivery_data).await.unwrap();
hash
}
async fn read_blob(&self, hash: Hash) -> Vec<u8> {
let vmo = self.get_blob_vmo(hash).await;
vmo.read_to_vec(0, vmo.get_content_size().unwrap()).expect("vmo read failed")
}
async fn get_blob_handle(&self, name: &str) -> DataObjectHandle<FxVolume> {
let root_object_id = self.volume().volume().store().root_directory_object_id();
let root_dir =
Directory::open(self.volume().volume(), root_object_id).await.expect("open failed");
let (object_id, _) =
root_dir.lookup(name).await.expect("lookup failed").expect("file doesn't exist yet");
ObjectStore::open_object(self.volume().volume(), object_id, HandleOptions::default(), None)
.await
.expect("open_object failed")
}
async fn get_blob_vmo(&self, hash: Hash) -> zx::Vmo {
let blob_reader = connect_to_protocol_at_dir_svc::<BlobReaderMarker>(self.volume_out_dir())
.expect("failed to connect to the BlobReader service");
blob_reader
.get_vmo(&hash.into())
.await
.expect("transport error on BlobReader.GetVmo")
.expect("get_vmo failed")
}
async fn create_blob(
&self,
hash: &[u8; 32],
allow_existing: bool,
) -> Result<BlobWriterProxy, CreateBlobError> {
let blob_proxy = connect_to_protocol_at_dir_svc::<BlobCreatorMarker>(self.volume_out_dir())
.expect("failed to connect to the BlobCreator service");
let blob_writer =
blob_proxy.create(hash, allow_existing).await.expect("transport error on create")?;
Ok(blob_writer.into_proxy().expect("into_proxy failed"))
}
}