1use crate::{CheckUse, ExpectedResult, RoutingTestModel, RoutingTestModelBuilder};
6use cm_rust::offer::*;
7use cm_rust::*;
8use cm_rust_testing::*;
9use fidl_fuchsia_io as fio;
10use std::marker::PhantomData;
11use zx_status;
12
13pub struct CommonRightsTest<T: RoutingTestModelBuilder> {
14 builder: PhantomData<T>,
15}
16
17impl<T: RoutingTestModelBuilder> CommonRightsTest<T> {
18 pub fn new() -> Self {
19 Self { builder: PhantomData }
20 }
21
22 pub async fn test_offer_increasing_rights(&self) {
23 let components = vec![
24 (
25 "a",
26 ComponentDeclBuilder::new()
27 .offer(
28 OfferBuilder::directory()
29 .name("bar_data")
30 .target_name("baz_data")
31 .source_static_child("b")
32 .target_static_child("c")
33 .rights(fio::RW_STAR_DIR),
34 )
35 .child_default("b")
36 .child_default("c")
37 .build(),
38 ),
39 (
40 "b",
41 ComponentDeclBuilder::new()
42 .capability(
43 CapabilityBuilder::directory()
44 .name("foo_data")
45 .path("/data/foo")
46 .rights(fio::RW_STAR_DIR),
47 )
48 .expose(
49 ExposeBuilder::directory()
50 .name("foo_data")
51 .source(ExposeSource::Self_)
52 .target_name("bar_data")
53 .rights(fio::RW_STAR_DIR),
54 )
55 .build(),
56 ),
57 (
58 "c",
59 ComponentDeclBuilder::new()
60 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
61 .build(),
62 ),
63 ];
64 let model = T::new("a", components).build().await;
65 model
66 .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
67 .await;
68 }
69
70 pub async fn test_offer_incompatible_rights(&self) {
71 let components = vec![
72 (
73 "a",
74 ComponentDeclBuilder::new()
75 .offer(
76 OfferBuilder::directory()
77 .name("bar_data")
78 .target_name("baz_data")
79 .source_static_child("b")
80 .target_static_child("c")
81 .rights(fio::W_STAR_DIR),
82 )
83 .child_default("b")
84 .child_default("c")
85 .build(),
86 ),
87 (
88 "b",
89 ComponentDeclBuilder::new()
90 .capability(
91 CapabilityBuilder::directory()
92 .name("foo_data")
93 .path("/data/foo")
94 .rights(fio::RW_STAR_DIR),
95 )
96 .expose(
97 ExposeBuilder::directory()
98 .name("foo_data")
99 .source(ExposeSource::Self_)
100 .target_name("bar_data")
101 .rights(fio::RW_STAR_DIR),
102 )
103 .build(),
104 ),
105 (
106 "c",
107 ComponentDeclBuilder::new()
108 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
110 .build(),
111 ),
112 ];
113 let model = T::new("a", components).build().await;
114 model
115 .check_use(
116 ["c"].try_into().unwrap(),
117 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
118 )
119 .await;
120 }
121
122 pub async fn test_expose_increasing_rights(&self) {
123 let components = vec![
124 (
125 "a",
126 ComponentDeclBuilder::new()
127 .offer(
128 OfferBuilder::directory()
129 .name("bar_data")
130 .target_name("baz_data")
131 .source_static_child("b")
132 .target_static_child("c")
133 .rights(fio::R_STAR_DIR),
134 )
135 .child_default("b")
136 .child_default("c")
137 .build(),
138 ),
139 (
140 "b",
141 ComponentDeclBuilder::new()
142 .capability(
143 CapabilityBuilder::directory()
144 .name("foo_data")
145 .path("/data/foo")
146 .rights(fio::RW_STAR_DIR),
147 )
148 .expose(
149 ExposeBuilder::directory()
150 .name("foo_data")
151 .source(ExposeSource::Self_)
152 .target_name("bar_data")
153 .rights(fio::RW_STAR_DIR),
154 )
155 .build(),
156 ),
157 (
158 "c",
159 ComponentDeclBuilder::new()
160 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
161 .build(),
162 ),
163 ];
164 let model = T::new("a", components).build().await;
165 model
166 .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
167 .await;
168 }
169
170 pub async fn test_expose_incompatible_rights(&self) {
171 let components = vec![
172 (
173 "a",
174 ComponentDeclBuilder::new()
175 .offer(
176 OfferBuilder::directory()
177 .name("bar_data")
178 .target_name("baz_data")
179 .source_static_child("b")
180 .target_static_child("c")
181 .rights(fio::RW_STAR_DIR),
182 )
183 .child_default("b")
184 .child_default("c")
185 .build(),
186 ),
187 (
188 "b",
189 ComponentDeclBuilder::new()
190 .capability(
191 CapabilityBuilder::directory()
192 .name("foo_data")
193 .path("/data/foo")
194 .rights(fio::RW_STAR_DIR),
195 )
196 .expose(
197 ExposeBuilder::directory()
198 .name("foo_data")
199 .source(ExposeSource::Self_)
200 .target_name("bar_data")
201 .rights(fio::W_STAR_DIR),
202 )
203 .build(),
204 ),
205 (
206 "c",
207 ComponentDeclBuilder::new()
208 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
209 .build(),
210 ),
211 ];
212 let model = T::new("a", components).build().await;
213 model
214 .check_use(
215 ["c"].try_into().unwrap(),
216 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
217 )
218 .await;
219 }
220
221 pub async fn test_capability_increasing_rights(&self) {
222 let components = vec![
223 (
224 "a",
225 ComponentDeclBuilder::new()
226 .offer(
227 OfferBuilder::directory()
228 .name("bar_data")
229 .target_name("baz_data")
230 .source_static_child("b")
231 .target_static_child("c")
232 .rights(fio::R_STAR_DIR),
233 )
234 .child_default("b")
235 .child_default("c")
236 .build(),
237 ),
238 (
239 "b",
240 ComponentDeclBuilder::new()
241 .capability(
242 CapabilityBuilder::directory()
243 .name("foo_data")
244 .path("/data/foo")
245 .rights(fio::RW_STAR_DIR),
246 )
247 .expose(
248 ExposeBuilder::directory()
249 .name("foo_data")
250 .source(ExposeSource::Self_)
251 .target_name("bar_data")
252 .rights(fio::R_STAR_DIR),
253 )
254 .build(),
255 ),
256 (
257 "c",
258 ComponentDeclBuilder::new()
259 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
260 .build(),
261 ),
262 ];
263 let model = T::new("a", components).build().await;
264 model
265 .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
266 .await;
267 }
268
269 pub async fn test_capability_incompatible_rights(&self) {
270 let components = vec![
271 (
272 "a",
273 ComponentDeclBuilder::new()
274 .offer(
275 OfferBuilder::directory()
276 .name("bar_data")
277 .target_name("baz_data")
278 .source_static_child("b")
279 .target_static_child("c")
280 .rights(fio::RW_STAR_DIR),
281 )
282 .child_default("b")
283 .child_default("c")
284 .build(),
285 ),
286 (
287 "b",
288 ComponentDeclBuilder::new()
289 .capability(
290 CapabilityBuilder::directory()
291 .name("foo_data")
292 .path("/data/foo")
293 .rights(fio::W_STAR_DIR),
294 )
295 .expose(
296 ExposeBuilder::directory()
297 .name("foo_data")
298 .source(ExposeSource::Self_)
299 .target_name("bar_data")
300 .rights(fio::RW_STAR_DIR),
301 )
302 .build(),
303 ),
304 (
305 "c",
306 ComponentDeclBuilder::new()
307 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
308 .build(),
309 ),
310 ];
311 let model = T::new("a", components).build().await;
312 model
313 .check_use(
314 ["c"].try_into().unwrap(),
315 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
316 )
317 .await;
318 }
319
320 pub async fn test_offer_from_component_manager_namespace_directory_incompatible_rights(&self) {
329 let components = vec![
330 (
331 "a",
332 ComponentDeclBuilder::new()
333 .offer(
334 OfferBuilder::directory()
335 .name("foo_data")
336 .target_name("bar_data")
337 .source(OfferSource::Parent)
338 .target_static_child("b"),
339 )
340 .child_default("b")
341 .build(),
342 ),
343 (
344 "b",
345 ComponentDeclBuilder::new()
346 .use_(UseBuilder::directory().name("bar_data").path("/data/hippo"))
347 .build(),
348 ),
349 ];
350 let namespace_capabilities = vec![
351 CapabilityBuilder::directory()
352 .name("foo_data")
353 .path("/offer_from_cm_namespace/data/foo")
354 .rights(fio::W_STAR_DIR)
355 .build(),
356 ];
357 let mut builder = T::new("a", components);
358 builder.set_namespace_capabilities(namespace_capabilities);
359 let model = builder.build().await;
360
361 model.install_namespace_directory("/offer_from_cm_namespace");
362 model
363 .check_use(
364 ["b"].try_into().unwrap(),
365 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
366 )
367 .await;
368 }
369}