vfs/directory/
test_utils.rs
1#[doc(hidden)]
12pub mod reexport {
13 pub use fuchsia_async::Channel;
14 pub use zx_status::Status;
15 pub use {fidl, fidl_fuchsia_io as fio};
16
17 #[cfg(not(target_os = "fuchsia"))]
18 pub use fuchsia_async::emulated_handle::MessageBuf;
19 #[cfg(target_os = "fuchsia")]
20 pub use zx::MessageBuf;
21}
22
23use crate::directory::entry::DirectoryEntry;
24use crate::test_utils::run::{self, AsyncServerClientTestParams};
25
26use byteorder::{LittleEndian, WriteBytesExt};
27use fidl_fuchsia_io as fio;
28use futures::Future;
29use std::convert::TryInto as _;
30use std::io::Write;
31use std::sync::Arc;
32
33pub use run::{run_client, test_client};
34
35pub fn run_server_client<GetClientRes>(
39 flags: fio::OpenFlags,
40 server: Arc<dyn DirectoryEntry>,
41 get_client: impl FnOnce(fio::DirectoryProxy) -> GetClientRes,
42) where
43 GetClientRes: Future<Output = ()>,
44{
45 run::run_server_client::<fio::DirectoryMarker, _, _>(flags, server, get_client)
46}
47
48pub fn test_server_client<'test_refs, GetClientRes>(
52 flags: fio::OpenFlags,
53 server: Arc<dyn DirectoryEntry>,
54 get_client: impl FnOnce(fio::DirectoryProxy) -> GetClientRes + 'test_refs,
55) -> AsyncServerClientTestParams<'test_refs, fio::DirectoryMarker>
56where
57 GetClientRes: Future<Output = ()> + 'test_refs,
58{
59 run::test_server_client::<fio::DirectoryMarker, _, _>(flags, server, get_client)
60}
61
62pub struct DirentsSameInodeBuilder {
65 expected: Vec<u8>,
66 inode: u64,
67}
68
69impl DirentsSameInodeBuilder {
70 pub fn new(inode: u64) -> Self {
71 DirentsSameInodeBuilder { expected: vec![], inode }
72 }
73
74 pub fn add(&mut self, type_: fio::DirentType, name: &[u8]) -> &mut Self {
75 assert!(
76 name.len() <= fio::MAX_NAME_LENGTH as usize,
77 "Expected entry name should not exceed MAX_FILENAME ({}) bytes.\n\
78 Got: {:?}\n\
79 Length: {} bytes",
80 fio::MAX_NAME_LENGTH,
81 name,
82 name.len()
83 );
84
85 self.expected.write_u64::<LittleEndian>(self.inode).unwrap();
86 self.expected.write_u8(name.len().try_into().unwrap()).unwrap();
87 self.expected.write_u8(type_.into_primitive()).unwrap();
88 self.expected.write_all(name).unwrap();
89
90 self
91 }
92
93 pub fn into_vec(self) -> Vec<u8> {
94 self.expected
95 }
96}
97
98#[macro_export]
100macro_rules! assert_rewind {
101 ($proxy:expr) => {{
102 use $crate::directory::test_utils::reexport::Status;
103
104 let status = $proxy.rewind().await.expect("rewind failed");
105 assert_eq!(Status::from_raw(status), Status::OK);
106 }};
107}
108
109#[macro_export]
112macro_rules! open_as_vmo_file_assert_content {
113 ($proxy:expr, $flags:expr, $path:expr, $expected_content:expr) => {{
114 let file = open_get_vmo_file_proxy_assert_ok!($proxy, $flags, $path);
115 assert_read!(file, $expected_content);
116 assert_close!(file);
117 }};
118}
119
120#[macro_export]
121macro_rules! assert_watch {
122 ($proxy:expr, $mask:expr) => {{
123 use $crate::directory::test_utils::reexport::{fidl, Channel, Status};
124
125 let (client, server) = fidl::endpoints::create_endpoints();
126
127 let status = $proxy.watch($mask, 0, server).await.expect("watch failed");
128 assert_eq!(Status::from_raw(status), Status::OK);
129
130 Channel::from_channel(client.into_channel())
131 }};
132}
133
134#[macro_export]
135macro_rules! assert_watch_err {
136 ($proxy:expr, $mask:expr, $expected_status:expr) => {{
137 use $crate::directory::test_utils::reexport::{fidl, Status};
138
139 let (_client, server) = fidl::endpoints::create_endpoints();
140
141 let status = $proxy.watch($mask, 0, server).await.expect("watch failed");
142 assert_eq!(Status::from_raw(status), $expected_status);
143 }};
144}
145
146#[macro_export]
147macro_rules! assert_watcher_one_message_watched_events {
148 ($watcher:expr, $( { $type:tt, $name:expr $(,)* } ),* $(,)*) => {{
149 #[allow(unused)]
150 use $crate::directory::test_utils::reexport::{MessageBuf, fio::WatchEvent};
151 use std::convert::TryInto as _;
152
153 let mut buf = MessageBuf::new();
154 $watcher.recv_msg(&mut buf).await.unwrap();
155
156 let (bytes, handles) = buf.split();
157 assert_eq!(
158 handles.len(),
159 0,
160 "Received buffer with handles.\n\
161 Handle count: {}\n\
162 Buffer: {:X?}",
163 handles.len(),
164 bytes
165 );
166
167 let expected = &mut vec![];
168 $({
169 let type_ = assert_watcher_one_message_watched_events!(@expand_event_type $type);
170 let name = Vec::<u8>::from($name);
171 assert!(name.len() <= std::u8::MAX as usize);
172
173 expected.push(type_.into_primitive());
174 expected.push(name.len().try_into().unwrap());
175 expected.extend_from_slice(&name);
176 })*
177
178 assert!(bytes == *expected,
179 "Received buffer does not match the expectation.\n\
180 Expected: {:X?}\n\
181 Received: {:X?}\n\
182 Expected as UTF-8 lossy: {:?}\n\
183 Received as UTF-8 lossy: {:?}",
184 *expected, bytes,
185 String::from_utf8_lossy(expected), String::from_utf8_lossy(&bytes));
186 }};
187
188 (@expand_event_type EXISTING) => { fio::WatchEvent::Existing };
189 (@expand_event_type IDLE) => { fio::WatchEvent::Idle };
190 (@expand_event_type ADDED) => { fio::WatchEvent::Added };
191 (@expand_event_type REMOVED) => { fio::WatchEvent::Removed };
192}