fxfs_platform/fuchsia/fxblob/
reader.rs1use crate::fxblob::directory::BlobDirectory;
8use anyhow::Error;
9use fuchsia_hash::Hash;
10
11use std::sync::Arc;
12
13impl BlobDirectory {
14 pub async fn get_blob_vmo(self: &Arc<Self>, hash: Hash) -> Result<zx::Vmo, Error> {
17 let (blob, vmo) = self.open_blob_get_vmo(&hash.into()).await?;
18 {
19 let mut guard = self.volume().pager().recorder();
20 if let Some(recorder) = &mut (*guard) {
21 let _ = recorder.record_open(blob);
22 }
23 }
24 Ok(vmo)
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use crate::fuchsia::fxblob::testing::{BlobFixture, new_blob_fixture};
32 use delivery_blob::CompressionMode;
33 use fidl_fuchsia_io::{self as fio};
34 use fuchsia_component_client::connect_to_protocol_at_dir_svc;
35
36 async fn read_blob(
38 blob_volume_outgoing_dir: &fio::DirectoryProxy,
39 hash: Hash,
40 ) -> Result<Vec<u8>, Error> {
41 let blob_proxy = connect_to_protocol_at_dir_svc::<fidl_fuchsia_fxfs::BlobReaderMarker>(
42 &blob_volume_outgoing_dir,
43 )
44 .expect("failed to connect to the BlobReader service");
45 let vmo = blob_proxy
46 .get_vmo(&hash.into())
47 .await
48 .expect("transport error on blobreader")
49 .map_err(zx::Status::from_raw)?;
50 let vmo_size = vmo.get_stream_size().expect("failed to get vmo size") as usize;
51 let mut buf = vec![0; vmo_size];
52 vmo.read(&mut buf[..], 0)?;
53 Ok(buf)
54 }
55
56 #[fuchsia::test(threads = 10)]
57 async fn test_blob_reader_uncompressed() {
58 const NEVER_COMPRESS: CompressionMode = CompressionMode::Never;
59 let fixture = new_blob_fixture().await;
60 let empty_blob_hash = fixture.write_blob(&[], NEVER_COMPRESS).await;
61 let short_data = b"This is some data";
62 let short_blob_hash = fixture.write_blob(short_data, NEVER_COMPRESS).await;
63 let long_data = &[0x65u8; 30000];
64 let long_blob_hash = fixture.write_blob(long_data, NEVER_COMPRESS).await;
65
66 assert_eq!(
67 &*read_blob(fixture.volume_out_dir(), empty_blob_hash).await.expect("read empty"),
68 &[0u8; 0]
69 );
70 assert_eq!(
71 &*read_blob(fixture.volume_out_dir(), short_blob_hash).await.expect("read short"),
72 short_data
73 );
74 assert_eq!(
75 &*read_blob(fixture.volume_out_dir(), long_blob_hash).await.expect("read long"),
76 long_data
77 );
78 let missing_hash = Hash::from([0x77u8; 32]);
79 assert!(read_blob(fixture.volume_out_dir(), missing_hash).await.is_err());
80
81 fixture.close().await;
82 }
83
84 #[fuchsia::test(threads = 10)]
85 async fn test_blob_reader_compressed() {
86 const ALWAYS_COMPRESS: CompressionMode = CompressionMode::Always;
87 let fixture = new_blob_fixture().await;
88 let empty_blob_hash = fixture.write_blob(&[], ALWAYS_COMPRESS).await;
89 let short_data = b"This is some data";
90 let short_blob_hash = fixture.write_blob(short_data, ALWAYS_COMPRESS).await;
91 let long_data = &[0x65u8; 30000];
92 let long_blob_hash = fixture.write_blob(long_data, ALWAYS_COMPRESS).await;
93
94 assert_eq!(
95 &*read_blob(fixture.volume_out_dir(), empty_blob_hash).await.expect("read empty"),
96 &[0u8; 0]
97 );
98 assert_eq!(
99 &*read_blob(fixture.volume_out_dir(), short_blob_hash).await.expect("read short"),
100 short_data
101 );
102 assert_eq!(
103 &*read_blob(fixture.volume_out_dir(), long_blob_hash).await.expect("read long"),
104 long_data
105 );
106 let missing_hash = Hash::from([0x77u8; 32]);
107 assert!(read_blob(fixture.volume_out_dir(), missing_hash).await.is_err());
108
109 fixture.close().await;
110 }
111}