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"))
109 .build(),
110 ),
111 ];
112 let model = T::new("a", components).build().await;
113 model
114 .check_use(
115 ["c"].try_into().unwrap(),
116 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
117 )
118 .await;
119 }
120
121 pub async fn test_expose_increasing_rights(&self) {
122 let components = vec![
123 (
124 "a",
125 ComponentDeclBuilder::new()
126 .offer(
127 OfferBuilder::directory()
128 .name("bar_data")
129 .target_name("baz_data")
130 .source_static_child("b")
131 .target_static_child("c")
132 .rights(fio::R_STAR_DIR),
133 )
134 .child_default("b")
135 .child_default("c")
136 .build(),
137 ),
138 (
139 "b",
140 ComponentDeclBuilder::new()
141 .capability(
142 CapabilityBuilder::directory()
143 .name("foo_data")
144 .path("/data/foo")
145 .rights(fio::RW_STAR_DIR),
146 )
147 .expose(
148 ExposeBuilder::directory()
149 .name("foo_data")
150 .source(ExposeSource::Self_)
151 .target_name("bar_data")
152 .rights(fio::RW_STAR_DIR),
153 )
154 .build(),
155 ),
156 (
157 "c",
158 ComponentDeclBuilder::new()
159 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
160 .build(),
161 ),
162 ];
163 let model = T::new("a", components).build().await;
164 model
165 .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
166 .await;
167 }
168
169 pub async fn test_expose_incompatible_rights(&self) {
170 let components = vec![
171 (
172 "a",
173 ComponentDeclBuilder::new()
174 .offer(
175 OfferBuilder::directory()
176 .name("bar_data")
177 .target_name("baz_data")
178 .source_static_child("b")
179 .target_static_child("c")
180 .rights(fio::RW_STAR_DIR),
181 )
182 .child_default("b")
183 .child_default("c")
184 .build(),
185 ),
186 (
187 "b",
188 ComponentDeclBuilder::new()
189 .capability(
190 CapabilityBuilder::directory()
191 .name("foo_data")
192 .path("/data/foo")
193 .rights(fio::RW_STAR_DIR),
194 )
195 .expose(
196 ExposeBuilder::directory()
197 .name("foo_data")
198 .source(ExposeSource::Self_)
199 .target_name("bar_data")
200 .rights(fio::W_STAR_DIR),
201 )
202 .build(),
203 ),
204 (
205 "c",
206 ComponentDeclBuilder::new()
207 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
208 .build(),
209 ),
210 ];
211 let model = T::new("a", components).build().await;
212 model
213 .check_use(
214 ["c"].try_into().unwrap(),
215 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
216 )
217 .await;
218 }
219
220 pub async fn test_capability_increasing_rights(&self) {
221 let components = vec![
222 (
223 "a",
224 ComponentDeclBuilder::new()
225 .offer(
226 OfferBuilder::directory()
227 .name("bar_data")
228 .target_name("baz_data")
229 .source_static_child("b")
230 .target_static_child("c")
231 .rights(fio::R_STAR_DIR),
232 )
233 .child_default("b")
234 .child_default("c")
235 .build(),
236 ),
237 (
238 "b",
239 ComponentDeclBuilder::new()
240 .capability(
241 CapabilityBuilder::directory()
242 .name("foo_data")
243 .path("/data/foo")
244 .rights(fio::RW_STAR_DIR),
245 )
246 .expose(
247 ExposeBuilder::directory()
248 .name("foo_data")
249 .source(ExposeSource::Self_)
250 .target_name("bar_data")
251 .rights(fio::R_STAR_DIR),
252 )
253 .build(),
254 ),
255 (
256 "c",
257 ComponentDeclBuilder::new()
258 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
259 .build(),
260 ),
261 ];
262 let model = T::new("a", components).build().await;
263 model
264 .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
265 .await;
266 }
267
268 pub async fn test_capability_incompatible_rights(&self) {
269 let components = vec![
270 (
271 "a",
272 ComponentDeclBuilder::new()
273 .offer(
274 OfferBuilder::directory()
275 .name("bar_data")
276 .target_name("baz_data")
277 .source_static_child("b")
278 .target_static_child("c")
279 .rights(fio::RW_STAR_DIR),
280 )
281 .child_default("b")
282 .child_default("c")
283 .build(),
284 ),
285 (
286 "b",
287 ComponentDeclBuilder::new()
288 .capability(
289 CapabilityBuilder::directory()
290 .name("foo_data")
291 .path("/data/foo")
292 .rights(fio::W_STAR_DIR),
293 )
294 .expose(
295 ExposeBuilder::directory()
296 .name("foo_data")
297 .source(ExposeSource::Self_)
298 .target_name("bar_data")
299 .rights(fio::RW_STAR_DIR),
300 )
301 .build(),
302 ),
303 (
304 "c",
305 ComponentDeclBuilder::new()
306 .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
307 .build(),
308 ),
309 ];
310 let model = T::new("a", components).build().await;
311 model
312 .check_use(
313 ["c"].try_into().unwrap(),
314 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
315 )
316 .await;
317 }
318
319 pub async fn test_offer_from_component_manager_namespace_directory_incompatible_rights(&self) {
328 let components = vec![
329 (
330 "a",
331 ComponentDeclBuilder::new()
332 .offer(
333 OfferBuilder::directory()
334 .name("foo_data")
335 .target_name("bar_data")
336 .source(OfferSource::Parent)
337 .target_static_child("b"),
338 )
339 .child_default("b")
340 .build(),
341 ),
342 (
343 "b",
344 ComponentDeclBuilder::new()
345 .use_(UseBuilder::directory().name("bar_data").path("/data/hippo"))
346 .build(),
347 ),
348 ];
349 let namespace_capabilities = vec![
350 CapabilityBuilder::directory()
351 .name("foo_data")
352 .path("/offer_from_cm_namespace/data/foo")
353 .rights(fio::W_STAR_DIR)
354 .build(),
355 ];
356 let mut builder = T::new("a", components);
357 builder.set_namespace_capabilities(namespace_capabilities);
358 let model = builder.build().await;
359
360 model.install_namespace_directory("/offer_from_cm_namespace");
361 model
362 .check_use(
363 ["b"].try_into().unwrap(),
364 CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
365 )
366 .await;
367 }
368}