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_async as fasync;
35 use fuchsia_component_client::connect_to_protocol_at_dir_svc;
36
37 async fn read_blob(
39 blob_volume_outgoing_dir: &fio::DirectoryProxy,
40 hash: Hash,
41 ) -> Result<Vec<u8>, Error> {
42 let blob_proxy = connect_to_protocol_at_dir_svc::<fidl_fuchsia_fxfs::BlobReaderMarker>(
43 &blob_volume_outgoing_dir,
44 )
45 .expect("failed to connect to the BlobReader service");
46 let vmo = blob_proxy
47 .get_vmo(&hash.into())
48 .await
49 .expect("transport error on blobreader")
50 .map_err(zx::Status::from_raw)?;
51 let vmo_size = vmo.get_stream_size().expect("failed to get vmo size") as usize;
52 let mut buf = vec![0; vmo_size];
53 vmo.read(&mut buf[..], 0)?;
54 Ok(buf)
55 }
56
57 #[fasync::run(10, test)]
58 async fn test_blob_reader_uncompressed() {
59 const NEVER_COMPRESS: CompressionMode = CompressionMode::Never;
60 let fixture = new_blob_fixture().await;
61 let empty_blob_hash = fixture.write_blob(&[], NEVER_COMPRESS).await;
62 let short_data = b"This is some data";
63 let short_blob_hash = fixture.write_blob(short_data, NEVER_COMPRESS).await;
64 let long_data = &[0x65u8; 30000];
65 let long_blob_hash = fixture.write_blob(long_data, NEVER_COMPRESS).await;
66
67 assert_eq!(
68 &*read_blob(fixture.volume_out_dir(), empty_blob_hash).await.expect("read empty"),
69 &[0u8; 0]
70 );
71 assert_eq!(
72 &*read_blob(fixture.volume_out_dir(), short_blob_hash).await.expect("read short"),
73 short_data
74 );
75 assert_eq!(
76 &*read_blob(fixture.volume_out_dir(), long_blob_hash).await.expect("read long"),
77 long_data
78 );
79 let missing_hash = Hash::from([0x77u8; 32]);
80 assert!(read_blob(fixture.volume_out_dir(), missing_hash).await.is_err());
81
82 fixture.close().await;
83 }
84
85 #[fasync::run(10, test)]
86 async fn test_blob_reader_compressed() {
87 const ALWAYS_COMPRESS: CompressionMode = CompressionMode::Always;
88 let fixture = new_blob_fixture().await;
89 let empty_blob_hash = fixture.write_blob(&[], ALWAYS_COMPRESS).await;
90 let short_data = b"This is some data";
91 let short_blob_hash = fixture.write_blob(short_data, ALWAYS_COMPRESS).await;
92 let long_data = &[0x65u8; 30000];
93 let long_blob_hash = fixture.write_blob(long_data, ALWAYS_COMPRESS).await;
94
95 assert_eq!(
96 &*read_blob(fixture.volume_out_dir(), empty_blob_hash).await.expect("read empty"),
97 &[0u8; 0]
98 );
99 assert_eq!(
100 &*read_blob(fixture.volume_out_dir(), short_blob_hash).await.expect("read short"),
101 short_data
102 );
103 assert_eq!(
104 &*read_blob(fixture.volume_out_dir(), long_blob_hash).await.expect("read long"),
105 long_data
106 );
107 let missing_hash = Hash::from([0x77u8; 32]);
108 assert!(read_blob(fixture.volume_out_dir(), missing_hash).await.is_err());
109
110 fixture.close().await;
111 }
112}