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(
48 &mut self,
49 merkle: Hash,
50 expected_allow_existing: bool,
51 ) -> BlobWriter {
52 match self.creator_stream.next().await {
53 Some(Ok(ffxfs::BlobCreatorRequest::Create { hash, allow_existing, responder })) => {
54 assert_eq!(Hash::from(hash), merkle);
55 assert_eq!(allow_existing, expected_allow_existing);
56 let (writer, stream) =
57 fidl::endpoints::create_request_stream::<ffxfs::BlobWriterMarker>();
58 let () = responder.send(Ok(writer)).unwrap();
59 BlobWriter { stream, vmo: None }
60 }
61 other => panic!("unexpected request: {other:?}"),
62 }
63 }
64
65 pub async fn expect_open_blob(&mut self, merkle: Hash, res: Result<Vec<u8>, zx::Status>) {
72 match self.reader_stream.next().await {
73 Some(Ok(ffxfs::BlobReaderRequest::GetVmo { blob_hash, responder })) => {
74 assert_eq!(Hash::from(blob_hash), merkle);
75 match res {
76 Ok(content) => {
77 let vmo = zx::Vmo::create(content.len().try_into().unwrap()).unwrap();
78 let () = vmo.write(&content, 0).unwrap();
79 let () = responder.send(Ok(vmo)).unwrap();
80 }
81 Err(s) => {
82 let () = responder.send(Err(s.into_raw())).unwrap();
83 }
84 }
85 }
86 other => panic!("unexpected request: {other:?}"),
87 }
88 }
89
90 pub async fn expect_needs_overwrite(&mut self, merkle: Hash, res: Result<bool, zx::Status>) {
98 match self.creator_stream.next().await {
99 Some(Ok(ffxfs::BlobCreatorRequest::NeedsOverwrite { blob_hash, responder })) => {
100 assert_eq!(Hash::from(blob_hash), merkle);
101 match res {
102 Ok(needs_overwrite) => {
103 let () = responder.send(Ok(needs_overwrite)).unwrap();
104 }
105 Err(s) => {
106 let () = responder.send(Err(s.into_raw())).unwrap();
107 }
108 }
109 }
110 other => panic!("unexpected request: {other:?}"),
111 }
112 }
113
114 pub async fn expect_readable_missing_checks(&mut self, readable: &[Hash], missing: &[Hash]) {
122 let mut readable = readable.iter().copied().collect::<HashSet<_>>();
123 let mut missing = missing.iter().copied().collect::<HashSet<_>>();
124
125 while !(readable.is_empty() && missing.is_empty()) {
126 match self.creator_stream.next().await {
127 Some(Ok(ffxfs::BlobCreatorRequest::NeedsOverwrite { blob_hash, responder })) => {
128 let hash = Hash::from(blob_hash);
129 if readable.remove(&hash) {
130 let () = responder.send(Ok(false)).unwrap();
131 } else if missing.remove(&hash) {
132 let () = responder.send(Err(zx::Status::NOT_FOUND.into_raw())).unwrap();
133 } else {
134 panic!("Unexpected blob existance check for {hash}");
135 }
136 }
137 other => panic!("unexpected request: {other:?}"),
138 }
139 }
140 }
141
142 pub async fn expect_filter_to_missing_blobs_with_readable_missing_ids(
151 &mut self,
152 readable: &[Hash],
153 missing: &[Hash],
154 ) {
155 self.expect_readable_missing_checks(readable, missing).await;
156 }
157
158 pub async fn expect_done(mut self) {
164 match self.stream.next().await {
165 None => {}
166 Some(request) => panic!("unexpected request: {request:?}"),
167 }
168 }
169}
170
171pub struct BlobWriter {
173 stream: ffxfs::BlobWriterRequestStream,
174 vmo: Option<zx::Vmo>,
175}
176
177impl BlobWriter {
178 pub async fn expect_done(mut self) {
184 match self.stream.next().await {
185 None => {}
186 Some(request) => panic!("unexpected request: {request:?}"),
187 }
188 }
189
190 pub async fn expect_get_vmo(&mut self, expected_size: u64) -> &mut Self {
196 match self.stream.next().await {
197 Some(Ok(ffxfs::BlobWriterRequest::GetVmo { size, responder })) => {
198 assert_eq!(expected_size, size);
199 let vmo = zx::Vmo::create(expected_size).unwrap();
200 assert!(self.vmo.is_none());
201 self.vmo = Some(vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap());
202 let () = responder.send(Ok(vmo)).unwrap();
203 }
204 req => panic!("unexpected request {req:?}"),
205 }
206 self
207 }
208
209 pub async fn fail_bytes_written(&mut self) -> &mut Self {
215 match self.stream.next().await {
216 Some(Ok(ffxfs::BlobWriterRequest::BytesReady { bytes_written: _, responder })) => {
217 let () = responder.send(Err(zx::Status::IO_DATA_INTEGRITY.into_raw())).unwrap();
218 }
219 req => panic!("unexpected request {req:?}"),
220 }
221 self
222 }
223
224 pub async fn expect_payload(mut self, content: &[u8]) {
231 self.expect_get_vmo(content.len().try_into().unwrap()).await;
232 match self.stream.next().await {
233 Some(Ok(ffxfs::BlobWriterRequest::BytesReady { bytes_written, responder })) => {
234 assert_eq!(bytes_written, u64::try_from(content.len()).unwrap());
235 let vmo = self.vmo.unwrap();
236 let mut buf = vec![0; content.len()];
237 let () = vmo.read(&mut buf, 0).unwrap();
238 assert_eq!(content, &buf[..content.len()]);
239 let () = responder.send(Ok(())).unwrap();
240 }
241 req => panic!("unexpected request {req:?}"),
242 }
243 }
244}