io_conformance_util/
test_harness.rs1use crate::flags::Rights;
6use fidl::endpoints::create_proxy;
7use fidl_fuchsia_component as fcomponent;
8use fidl_fuchsia_component_decl as fdecl;
9use fidl_fuchsia_io as fio;
10use fidl_fuchsia_io_test as io_test;
11
12pub struct TestHarness {
14 pub proxy: io_test::TestHarnessProxy,
16
17 pub config: io_test::HarnessConfig,
19
20 pub dir_rights: Rights,
22
23 pub file_rights: Rights,
25
26 pub executable_file_rights: Rights,
28
29 pub symlink_rights: Rights,
31}
32
33impl TestHarness {
34 pub async fn new() -> TestHarness {
36 let proxy = connect_to_harness();
37 let config = proxy.get_config().await.expect("Could not get config from proxy");
38
39 if config.supports_modify_directory {
41 assert!(
42 config.supports_get_token,
43 "GetToken must be supported for testing Rename/Link!"
44 );
45 }
46 if config.supports_append {
47 assert!(config.supports_mutable_file, "Files supporting append must also be mutable.");
48 }
49 if config.supports_truncate {
50 assert!(
51 config.supports_mutable_file,
52 "Files supporting truncate must also be mutable."
53 );
54 }
55
56 let dir_rights = Rights::new(get_supported_dir_rights(&config));
58 let file_rights = Rights::new(get_supported_file_rights(&config));
59 let executable_file_rights = Rights::new(fio::Rights::READ_BYTES | fio::Rights::EXECUTE);
60 let symlink_rights = Rights::new(get_supported_symlink_rights(&config));
61
62 TestHarness {
63 proxy,
64 config,
65 dir_rights,
66 file_rights,
67 executable_file_rights,
68 symlink_rights,
69 }
70 }
71
72 pub fn get_directory(
74 &self,
75 entries: Vec<io_test::DirectoryEntry>,
76 flags: fio::Flags,
77 ) -> fio::DirectoryProxy {
78 let contents: Vec<Option<Box<io_test::DirectoryEntry>>> =
79 entries.into_iter().map(|e| Some(Box::new(e))).collect();
80 let (client, server) = create_proxy::<fio::DirectoryMarker>();
81 self.proxy
82 .create_directory(contents, flags, server)
83 .expect("Cannot get directory from test harness");
84 client
85 }
86
87 pub async fn open_service_directory(&self) -> fio::DirectoryProxy {
90 assert!(self.config.supports_services);
91 let client_end = self.proxy.open_service_directory().await.unwrap();
92 client_end.into_proxy()
93 }
94
95 pub fn supported_file_abilities(&self) -> fio::Abilities {
97 let mut abilities = fio::Abilities::READ_BYTES | fio::Abilities::GET_ATTRIBUTES;
98 if self.config.supports_mutable_file {
99 abilities |= fio::Abilities::WRITE_BYTES;
100 }
101 if self.supports_mutable_attrs() {
102 abilities |= fio::Abilities::UPDATE_ATTRIBUTES;
103 }
104 abilities
105 }
106
107 pub fn supported_dir_abilities(&self) -> fio::Abilities {
109 if self.config.supports_modify_directory {
110 fio::Abilities::GET_ATTRIBUTES
111 | fio::Abilities::UPDATE_ATTRIBUTES
112 | fio::Abilities::ENUMERATE
113 | fio::Abilities::TRAVERSE
114 | fio::Abilities::MODIFY_DIRECTORY
115 } else {
116 fio::Abilities::GET_ATTRIBUTES | fio::Abilities::ENUMERATE | fio::Abilities::TRAVERSE
117 }
118 }
119
120 pub fn supported_symlink_abilities(&self) -> fio::Abilities {
122 let mut abilities = fio::Abilities::GET_ATTRIBUTES;
123 if self.supports_mutable_attrs() {
124 abilities |= fio::Abilities::UPDATE_ATTRIBUTES;
125 }
126 abilities
127 }
128
129 pub fn supports_mutable_attrs(&self) -> bool {
135 supports_mutable_attrs(&self.config)
136 }
137}
138
139fn connect_to_harness() -> io_test::TestHarnessProxy {
140 let (client, server) = zx::Channel::create();
142 fuchsia_component::client::connect_channel_to_protocol::<fcomponent::RealmMarker>(server)
143 .expect("Cannot connect to Realm service");
144 let realm = fcomponent::RealmSynchronousProxy::new(client);
145 let child_ref = fdecl::ChildRef { name: "fs_test".to_string(), collection: None };
147 let (client, server) = zx::Channel::create();
148 realm
149 .open_exposed_dir(
150 &child_ref,
151 fidl::endpoints::ServerEnd::<fio::DirectoryMarker>::new(server),
152 zx::MonotonicInstant::INFINITE,
153 )
154 .expect("FIDL error when binding to child in Realm")
155 .expect("Cannot bind to test harness child in Realm");
156
157 let exposed_dir = fio::DirectoryProxy::new(fidl::AsyncChannel::from_channel(client));
158
159 fuchsia_component::client::connect_to_protocol_at_dir_root::<io_test::TestHarnessMarker>(
160 &exposed_dir,
161 )
162 .expect("Cannot connect to test harness protocol")
163}
164
165fn get_supported_dir_rights(config: &io_test::HarnessConfig) -> fio::Rights {
168 fio::R_STAR_DIR
169 | fio::W_STAR_DIR
170 | if config.supports_executable_file { fio::X_STAR_DIR } else { fio::Rights::empty() }
171}
172
173fn get_supported_file_rights(config: &io_test::HarnessConfig) -> fio::Rights {
176 let mut rights = fio::Rights::READ_BYTES | fio::Rights::GET_ATTRIBUTES;
177 if config.supports_mutable_file {
178 rights |= fio::Rights::WRITE_BYTES;
179 }
180 if supports_mutable_attrs(&config) {
181 rights |= fio::Rights::WRITE_BYTES;
182 }
183 rights
184}
185
186fn get_supported_symlink_rights(config: &io_test::HarnessConfig) -> fio::Rights {
189 let mut rights = fio::Rights::GET_ATTRIBUTES | fio::Rights::READ_BYTES;
190 if config.supports_mutable_file {
191 rights |= fio::Rights::WRITE_BYTES;
192 }
193 if supports_mutable_attrs(&config) {
194 rights |= fio::Rights::WRITE_BYTES;
195 }
196 if config.supports_executable_file {
197 rights |= fio::Rights::EXECUTE;
198 }
199 rights
200}
201
202fn supports_mutable_attrs(config: &io_test::HarnessConfig) -> bool {
208 if !config.supports_mutable_file && !config.supports_modify_directory {
209 return false;
210 }
211 let all_mutable_attrs: fio::NodeAttributesQuery = fio::NodeAttributesQuery::ACCESS_TIME
212 | fio::NodeAttributesQuery::MODIFICATION_TIME
213 | fio::NodeAttributesQuery::CREATION_TIME
214 | fio::NodeAttributesQuery::MODE
215 | fio::NodeAttributesQuery::GID
216 | fio::NodeAttributesQuery::UID
217 | fio::NodeAttributesQuery::RDEV;
218 if config.supported_attributes.intersects(all_mutable_attrs) {
219 assert!(
220 config.supported_attributes.contains(
221 fio::NodeAttributesQuery::CREATION_TIME
222 | fio::NodeAttributesQuery::MODIFICATION_TIME
223 ),
224 "Harnesses must support at least CREATION_TIME if attributes are mutable."
225 );
226 return true;
227 }
228 false
229}