1use fuchsia_hash::Hash;
8use futures::StreamExt as _;
9use std::collections::HashSet;
10use std::convert::TryInto as _;
11use zx::HandleBased as _;
12use {fidl_fuchsia_fxfs as ffxfs, fidl_fuchsia_io as fio};
13
14pub struct Mock {
18 pub(super) stream: fio::DirectoryRequestStream,
19 pub(super) reader_stream: ffxfs::BlobReaderRequestStream,
20 pub(super) creator_stream: ffxfs::BlobCreatorRequestStream,
21}
22
23impl Mock {
24 pub async fn fail_create(&mut self, merkle: Hash, e: ffxfs::CreateBlobError) {
31 match self.creator_stream.next().await {
32 Some(Ok(ffxfs::BlobCreatorRequest::Create { hash, allow_existing, responder })) => {
33 assert_eq!(Hash::from(hash), merkle);
34 assert!(!allow_existing);
35 let () = responder.send(Err(e)).unwrap();
36 }
37 other => panic!("unexpected request: {other:?}"),
38 }
39 }
40
41 pub async fn expect_create_blob(&mut self, merkle: Hash) -> BlobWriter {
48 match self.creator_stream.next().await {
49 Some(Ok(ffxfs::BlobCreatorRequest::Create { hash, allow_existing, responder })) => {
50 assert_eq!(Hash::from(hash), merkle);
51 assert!(!allow_existing);
52 let (writer, stream) =
53 fidl::endpoints::create_request_stream::<ffxfs::BlobWriterMarker>();
54 let () = responder.send(Ok(writer)).unwrap();
55 BlobWriter { stream, vmo: None }
56 }
57 other => panic!("unexpected request: {other:?}"),
58 }
59 }
60
61 pub async fn expect_open_blob(&mut self, merkle: Hash, res: Result<Vec<u8>, zx::Status>) {
68 match self.reader_stream.next().await {
69 Some(Ok(ffxfs::BlobReaderRequest::GetVmo { blob_hash, responder })) => {
70 assert_eq!(Hash::from(blob_hash), merkle);
71 match res {
72 Ok(content) => {
73 let vmo = zx::Vmo::create(content.len().try_into().unwrap()).unwrap();
74 let () = vmo.write(&content, 0).unwrap();
75 let () = responder.send(Ok(vmo)).unwrap();
76 }
77 Err(s) => {
78 let () = responder.send(Err(s.into_raw())).unwrap();
79 }
80 }
81 }
82 other => panic!("unexpected request: {other:?}"),
83 }
84 }
85
86 pub async fn expect_readable_missing_checks(&mut self, readable: &[Hash], missing: &[Hash]) {
94 let mut readable = readable.iter().copied().collect::<HashSet<_>>();
95 let mut missing = missing.iter().copied().collect::<HashSet<_>>();
96
97 while !(readable.is_empty() && missing.is_empty()) {
98 match self.reader_stream.next().await {
99 Some(Ok(ffxfs::BlobReaderRequest::GetVmo { blob_hash, responder })) => {
100 let hash = Hash::from(blob_hash);
101 if readable.remove(&hash) {
102 let vmo = zx::Vmo::create(0).unwrap();
103 let () = responder.send(Ok(vmo)).unwrap();
104 } else if missing.remove(&hash) {
105 let () = responder.send(Err(zx::Status::NOT_FOUND.into_raw())).unwrap();
106 } else {
107 panic!("Unexpected blob existance check for {hash}");
108 }
109 }
110 other => panic!("unexpected request: {other:?}"),
111 }
112 }
113 }
114
115 pub async fn expect_filter_to_missing_blobs_with_readable_missing_ids(
124 &mut self,
125 readable: &[Hash],
126 missing: &[Hash],
127 ) {
128 self.expect_readable_missing_checks(readable, missing).await;
129 }
130
131 pub async fn expect_done(mut self) {
137 match self.stream.next().await {
138 None => {}
139 Some(request) => panic!("unexpected request: {request:?}"),
140 }
141 }
142}
143
144pub struct BlobWriter {
146 stream: ffxfs::BlobWriterRequestStream,
147 vmo: Option<zx::Vmo>,
148}
149
150impl BlobWriter {
151 pub async fn expect_done(mut self) {
157 match self.stream.next().await {
158 None => {}
159 Some(request) => panic!("unexpected request: {request:?}"),
160 }
161 }
162
163 pub async fn expect_get_vmo(&mut self, expected_size: u64) -> &mut Self {
169 match self.stream.next().await {
170 Some(Ok(ffxfs::BlobWriterRequest::GetVmo { size, responder })) => {
171 assert_eq!(expected_size, size);
172 let vmo = zx::Vmo::create(expected_size).unwrap();
173 assert!(self.vmo.is_none());
174 self.vmo = Some(vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap());
175 let () = responder.send(Ok(vmo)).unwrap();
176 }
177 req => panic!("unexpected request {req:?}"),
178 }
179 self
180 }
181
182 pub async fn fail_bytes_written(&mut self) -> &mut Self {
188 match self.stream.next().await {
189 Some(Ok(ffxfs::BlobWriterRequest::BytesReady { bytes_written: _, responder })) => {
190 let () = responder.send(Err(zx::Status::IO_DATA_INTEGRITY.into_raw())).unwrap();
191 }
192 req => panic!("unexpected request {req:?}"),
193 }
194 self
195 }
196
197 pub async fn expect_payload(mut self, content: &[u8]) {
204 self.expect_get_vmo(content.len().try_into().unwrap()).await;
205 match self.stream.next().await {
206 Some(Ok(ffxfs::BlobWriterRequest::BytesReady { bytes_written, responder })) => {
207 assert_eq!(bytes_written, u64::try_from(content.len()).unwrap());
208 let vmo = self.vmo.unwrap();
209 let mut buf = vec![0; content.len()];
210 let () = vmo.read(&mut buf, 0).unwrap();
211 assert_eq!(content, &buf[..content.len()]);
212 let () = responder.send(Ok(())).unwrap();
213 }
214 req => panic!("unexpected request {req:?}"),
215 }
216 }
217}