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