1use crate::{CheckUse, ExpectedResult, RoutingTestModel, RoutingTestModelBuilder};
6use cm_rust::offer::*;
7use cm_rust::*;
8use cm_rust_testing::*;
9use fidl_fuchsia_io as fio;
10use moniker::Moniker;
11use routing::debug_route_sandbox_path;
12use std::marker::PhantomData;
13use std::path::PathBuf;
14use zx_status::Status;
15
16pub struct CommonDictionaryTest<T: RoutingTestModelBuilder> {
17 builder: PhantomData<T>,
18}
19
20impl<T: RoutingTestModelBuilder> CommonDictionaryTest<T> {
21 pub fn new() -> Self {
22 Self { builder: PhantomData }
23 }
24
25 pub async fn test_use_protocol_from_dictionary(&self) {
26 let components = vec![
28 (
29 "root",
30 ComponentDeclBuilder::new()
31 .protocol_default("foo")
32 .dictionary_default("parent_dict")
33 .offer(
34 OfferBuilder::protocol()
35 .name("foo")
36 .target_name("B")
37 .source(OfferSource::Self_)
38 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
39 )
40 .offer(
41 OfferBuilder::dictionary()
42 .name("parent_dict")
43 .source(OfferSource::Self_)
44 .target_static_child("mid"),
45 )
46 .child_default("mid")
47 .build(),
48 ),
49 (
50 "mid",
51 ComponentDeclBuilder::new()
52 .protocol_default("foo")
53 .dictionary_default("self_dict")
54 .offer(
55 OfferBuilder::protocol()
56 .name("foo")
57 .target_name("A")
58 .source(OfferSource::Self_)
59 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
60 )
61 .use_(
62 UseBuilder::protocol()
63 .source(UseSource::Self_)
64 .name("A")
65 .from_dictionary("self_dict"),
66 )
67 .use_(UseBuilder::protocol().name("B").from_dictionary("parent_dict"))
68 .use_(
69 UseBuilder::protocol()
70 .source_static_child("leaf")
71 .name("C")
72 .from_dictionary("child_dict"),
73 )
74 .child_default("leaf")
75 .build(),
76 ),
77 (
78 "leaf",
79 ComponentDeclBuilder::new()
80 .protocol_default("foo")
81 .dictionary_default("child_dict")
82 .offer(
83 OfferBuilder::protocol()
84 .name("foo")
85 .target_name("C")
86 .source(OfferSource::Self_)
87 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
88 )
89 .expose(
90 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
91 )
92 .build(),
93 ),
94 ];
95
96 let test = T::new("root", components).build().await;
97 for path in ["/svc/A", "/svc/B", "/svc/C"] {
98 test.check_use(
99 "mid".try_into().unwrap(),
100 CheckUse::Protocol {
101 path: path.parse().unwrap(),
102 expected_res: ExpectedResult::Ok,
103 },
104 )
105 .await;
106 }
107 }
108
109 pub async fn test_use_protocol_from_dictionary_not_a_dictionary(&self) {
110 let components = vec![
113 (
114 "root",
115 ComponentDeclBuilder::new()
116 .protocol_default("parent_not_dict")
117 .offer(
118 OfferBuilder::protocol()
119 .name("parent_not_dict")
120 .source(OfferSource::Self_)
121 .target_static_child("mid"),
122 )
123 .child_default("mid")
124 .build(),
125 ),
126 (
127 "mid",
128 ComponentDeclBuilder::new()
129 .use_(UseBuilder::protocol().name("A").from_dictionary("parent_not_dict"))
132 .use_(
133 UseBuilder::protocol()
134 .source_static_child("leaf")
135 .name("B")
136 .from_dictionary("child_not_dict"),
137 )
138 .child_default("leaf")
139 .build(),
140 ),
141 (
142 "leaf",
143 ComponentDeclBuilder::new()
144 .protocol_default("child_not_dict")
145 .expose(
146 ExposeBuilder::protocol()
147 .name("child_not_dict")
148 .source(ExposeSource::Self_),
149 )
150 .build(),
151 ),
152 ];
153
154 let test = T::new("root", components).build().await;
155 for path in ["/svc/A", "/svc/B"] {
156 test.check_use(
157 "mid".try_into().unwrap(),
158 CheckUse::Protocol {
159 path: path.parse().unwrap(),
160 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
161 },
162 )
163 .await;
164 }
165 }
166
167 pub async fn test_use_protocol_from_dictionary_not_used(&self) {
168 let components = vec![
171 (
172 "root",
173 ComponentDeclBuilder::new()
174 .protocol_default("foo")
175 .protocol_default("bar")
176 .dictionary_default("parent_dict")
177 .offer(
178 OfferBuilder::protocol()
179 .name("foo")
180 .target_name("A")
181 .source(OfferSource::Self_)
182 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
183 )
184 .offer(
185 OfferBuilder::protocol()
186 .name("bar")
187 .target_name("B")
188 .source(OfferSource::Self_)
189 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
190 )
191 .offer(
192 OfferBuilder::dictionary()
193 .name("parent_dict")
194 .source(OfferSource::Self_)
195 .target_static_child("leaf"),
196 )
197 .child_default("leaf")
198 .build(),
199 ),
200 (
201 "leaf",
202 ComponentDeclBuilder::new()
203 .use_(UseBuilder::protocol().name("A").from_dictionary("parent_dict"))
204 .build(),
205 ),
206 ];
207
208 let test = T::new("root", components).build().await;
209 test.check_use(
210 "leaf".try_into().unwrap(),
211 CheckUse::Protocol {
212 path: "/svc/A".parse().unwrap(),
213 expected_res: ExpectedResult::Ok,
214 },
215 )
216 .await;
217 test.check_use(
218 "leaf".try_into().unwrap(),
219 CheckUse::Protocol {
220 path: "/svc/B".parse().unwrap(),
221 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
222 },
223 )
224 .await;
225 }
226
227 pub async fn test_use_protocol_from_dictionary_not_found(&self) {
228 let components = vec![
231 (
232 "root",
233 ComponentDeclBuilder::new()
234 .protocol_default("foo")
235 .dictionary_default("dict")
236 .offer(
237 OfferBuilder::protocol()
238 .name("foo")
239 .target_name("B")
240 .source(OfferSource::Self_)
241 .target(OfferTarget::Capability("dict".parse().unwrap())),
242 )
243 .offer(
244 OfferBuilder::dictionary()
245 .name("dict")
246 .source(OfferSource::Self_)
247 .target_static_child("leaf"),
248 )
249 .child_default("leaf")
250 .build(),
251 ),
252 (
253 "leaf",
254 ComponentDeclBuilder::new()
255 .use_(UseBuilder::protocol().name("A").from_dictionary("dict"))
256 .build(),
257 ),
258 ];
259
260 let test = T::new("root", components).build().await;
261 test.check_use(
262 "leaf".try_into().unwrap(),
263 CheckUse::Protocol {
264 path: "/svc/A".parse().unwrap(),
265 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
266 },
267 )
268 .await;
269
270 let components = vec![
273 (
274 "root",
275 ComponentDeclBuilder::new()
276 .protocol_default("foo")
277 .dictionary_default("dict")
278 .offer(
279 OfferBuilder::protocol()
280 .name("foo")
281 .target_name("A")
282 .source(OfferSource::Self_)
283 .target(OfferTarget::Capability("dict".parse().unwrap())),
284 )
285 .offer(
286 OfferBuilder::dictionary()
287 .name("dict")
288 .target_name("other_dict")
289 .source(OfferSource::Self_)
290 .target_static_child("leaf"),
291 )
292 .child_default("leaf")
293 .build(),
294 ),
295 (
296 "leaf",
297 ComponentDeclBuilder::new()
298 .use_(UseBuilder::protocol().name("A").from_dictionary("dict"))
299 .build(),
300 ),
301 ];
302
303 let test = T::new("root", components).build().await;
304 test.check_use(
305 "leaf".try_into().unwrap(),
306 CheckUse::Protocol {
307 path: "/svc/A".parse().unwrap(),
308 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
309 },
310 )
311 .await;
312 }
313
314 pub async fn test_use_directory_from_dictionary(&self) {
315 let components = vec![
316 (
317 "root",
318 ComponentDeclBuilder::new()
319 .capability(CapabilityBuilder::directory().name("bar_data").path("/data/foo"))
320 .dictionary_default("parent_dict")
321 .offer(
322 OfferBuilder::dictionary()
323 .name("parent_dict")
324 .source(OfferSource::Self_)
325 .target_static_child("leaf"),
326 )
327 .offer(
328 OfferBuilder::directory()
329 .name("bar_data")
330 .target_name("B")
331 .source(OfferSource::Self_)
332 .target(OfferTarget::Capability("parent_dict".parse().unwrap()))
333 .rights(fio::R_STAR_DIR),
334 )
335 .child_default("leaf")
336 .build(),
337 ),
338 (
339 "leaf",
340 ComponentDeclBuilder::new()
341 .capability(CapabilityBuilder::directory().name("foo_data").path("/data/foo"))
342 .dictionary_default("self_dict")
343 .offer(
344 OfferBuilder::directory()
345 .name("foo_data")
346 .target_name("A")
347 .source(OfferSource::Self_)
348 .target(OfferTarget::Capability("self_dict".parse().unwrap()))
349 .rights(fio::R_STAR_DIR),
350 )
351 .use_(
352 UseBuilder::directory()
353 .source(UseSource::Self_)
354 .name("A")
355 .from_dictionary("self_dict")
356 .path("/A"),
357 )
358 .use_(
359 UseBuilder::directory().name("B").from_dictionary("parent_dict").path("/B"),
360 )
361 .build(),
362 ),
363 ];
364
365 let test = T::new("root", components).build().await;
366 test.check_use(
367 "leaf".try_into().unwrap(),
368 CheckUse::Directory {
369 path: "/A".parse().unwrap(),
370 file: PathBuf::from("hippo"),
371 expected_res: ExpectedResult::Ok,
372 },
373 )
374 .await;
375 test.check_use(
376 "leaf".try_into().unwrap(),
377 CheckUse::Directory {
378 path: "/B".parse().unwrap(),
379 file: PathBuf::from("hippo"),
380 expected_res: ExpectedResult::Ok,
381 },
382 )
383 .await;
384 }
385
386 pub async fn test_expose_directory_from_dictionary(&self) {
387 let components = vec![
389 (
390 "root",
391 ComponentDeclBuilder::new()
392 .use_(UseBuilder::directory().source_static_child("mid").name("A").path("/A"))
393 .use_(UseBuilder::directory().source_static_child("mid").name("B").path("/B"))
394 .child_default("mid")
395 .build(),
396 ),
397 (
398 "mid",
399 ComponentDeclBuilder::new()
400 .capability(CapabilityBuilder::directory().name("foo_data").path("/data/foo"))
401 .dictionary_default("self_dict")
402 .offer(
403 OfferBuilder::directory()
404 .name("foo_data")
405 .target_name("A")
406 .source(OfferSource::Self_)
407 .target(OfferTarget::Capability("self_dict".parse().unwrap()))
408 .rights(fio::R_STAR_DIR),
409 )
410 .expose(
411 ExposeBuilder::directory()
412 .name("A")
413 .source(ExposeSource::Self_)
414 .from_dictionary("self_dict"),
415 )
416 .expose(
417 ExposeBuilder::directory()
418 .name("B")
419 .source_static_child("leaf")
420 .from_dictionary("child_dict"),
421 )
422 .child_default("leaf")
423 .build(),
424 ),
425 (
426 "leaf",
427 ComponentDeclBuilder::new()
428 .capability(CapabilityBuilder::directory().name("bar_data").path("/data/foo"))
429 .dictionary_default("child_dict")
430 .expose(
431 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
432 )
433 .offer(
434 OfferBuilder::directory()
435 .name("bar_data")
436 .target_name("B")
437 .source(OfferSource::Self_)
438 .target(OfferTarget::Capability("child_dict".parse().unwrap()))
439 .rights(fio::R_STAR_DIR),
440 )
441 .build(),
442 ),
443 ];
444
445 let test = T::new("root", components).build().await;
446 test.check_use(
447 ".".try_into().unwrap(),
448 CheckUse::Directory {
449 path: "/A".parse().unwrap(),
450 file: PathBuf::from("hippo"),
451 expected_res: ExpectedResult::Ok,
452 },
453 )
454 .await;
455 test.check_use(
456 ".".try_into().unwrap(),
457 CheckUse::Directory {
458 path: "/B".parse().unwrap(),
459 file: PathBuf::from("hippo"),
460 expected_res: ExpectedResult::Ok,
461 },
462 )
463 .await;
464 }
465
466 pub async fn test_use_protocol_from_nested_dictionary(&self) {
467 let components = vec![
470 (
471 "root",
472 ComponentDeclBuilder::new()
473 .protocol_default("foo")
474 .dictionary_default("nested")
475 .dictionary_default("parent_dict")
476 .offer(
477 OfferBuilder::protocol()
478 .name("foo")
479 .target_name("B")
480 .source(OfferSource::Self_)
481 .target(OfferTarget::Capability("nested".parse().unwrap())),
482 )
483 .offer(
484 OfferBuilder::dictionary()
485 .name("nested")
486 .source(OfferSource::Self_)
487 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
488 )
489 .offer(
490 OfferBuilder::dictionary()
491 .name("parent_dict")
492 .source(OfferSource::Self_)
493 .target_static_child("mid"),
494 )
495 .child_default("mid")
496 .build(),
497 ),
498 (
499 "mid",
500 ComponentDeclBuilder::new()
501 .protocol_default("foo")
502 .dictionary_default("nested")
503 .dictionary_default("self_dict")
504 .offer(
505 OfferBuilder::protocol()
506 .name("foo")
507 .target_name("A")
508 .source(OfferSource::Self_)
509 .target(OfferTarget::Capability("nested".parse().unwrap())),
510 )
511 .offer(
512 OfferBuilder::dictionary()
513 .name("nested")
514 .source(OfferSource::Self_)
515 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
516 )
517 .use_(
518 UseBuilder::protocol()
519 .source(UseSource::Self_)
520 .name("A")
521 .from_dictionary("self_dict/nested"),
522 )
523 .use_(UseBuilder::protocol().name("B").from_dictionary("parent_dict/nested"))
524 .use_(
525 UseBuilder::protocol()
526 .source_static_child("leaf")
527 .name("C")
528 .from_dictionary("child_dict/nested"),
529 )
530 .child_default("leaf")
531 .build(),
532 ),
533 (
534 "leaf",
535 ComponentDeclBuilder::new()
536 .protocol_default("foo")
537 .dictionary_default("nested")
538 .dictionary_default("child_dict")
539 .offer(
540 OfferBuilder::protocol()
541 .name("foo")
542 .target_name("C")
543 .source(OfferSource::Self_)
544 .target(OfferTarget::Capability("nested".parse().unwrap())),
545 )
546 .offer(
547 OfferBuilder::dictionary()
548 .name("nested")
549 .source(OfferSource::Self_)
550 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
551 )
552 .expose(
553 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
554 )
555 .build(),
556 ),
557 ];
558
559 let test = T::new("root", components).build().await;
560 for path in ["/svc/A", "/svc/B", "/svc/C"] {
561 test.check_use(
562 "mid".try_into().unwrap(),
563 CheckUse::Protocol {
564 path: path.parse().unwrap(),
565 expected_res: ExpectedResult::Ok,
566 },
567 )
568 .await;
569 }
570 }
571
572 pub async fn test_offer_protocol_from_dictionary(&self) {
573 let components = vec![
575 (
576 "root",
577 ComponentDeclBuilder::new()
578 .protocol_default("foo")
579 .dictionary_default("parent_dict")
580 .offer(
581 OfferBuilder::protocol()
582 .name("foo")
583 .target_name("B")
584 .source(OfferSource::Self_)
585 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
586 )
587 .offer(
588 OfferBuilder::dictionary()
589 .name("parent_dict")
590 .source(OfferSource::Self_)
591 .target_static_child("mid"),
592 )
593 .child_default("mid")
594 .build(),
595 ),
596 (
597 "mid",
598 ComponentDeclBuilder::new()
599 .protocol_default("foo")
600 .dictionary_default("self_dict")
601 .offer(
602 OfferBuilder::protocol()
603 .name("A")
604 .target_name("A_svc")
605 .source(OfferSource::Self_)
606 .target_static_child("leaf")
607 .from_dictionary("self_dict"),
608 )
609 .offer(
610 OfferBuilder::protocol()
611 .name("foo")
612 .target_name("A")
613 .source(OfferSource::Self_)
614 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
615 )
616 .offer(
617 OfferBuilder::protocol()
618 .name("B")
619 .target_name("B_svc")
620 .source(OfferSource::Parent)
621 .target_static_child("leaf")
622 .from_dictionary("parent_dict"),
623 )
624 .offer(
625 OfferBuilder::protocol()
626 .name("C")
627 .target_name("C_svc")
628 .source_static_child("provider")
629 .target_static_child("leaf")
630 .from_dictionary("child_dict"),
631 )
632 .child_default("provider")
633 .child_default("leaf")
634 .build(),
635 ),
636 (
637 "provider",
638 ComponentDeclBuilder::new()
639 .protocol_default("foo")
640 .dictionary_default("child_dict")
641 .offer(
642 OfferBuilder::protocol()
643 .name("foo")
644 .target_name("C")
645 .source(OfferSource::Self_)
646 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
647 )
648 .expose(
649 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
650 )
651 .build(),
652 ),
653 (
654 "leaf",
655 ComponentDeclBuilder::new()
656 .use_(UseBuilder::protocol().name("A_svc").path("/svc/A"))
657 .use_(UseBuilder::protocol().name("B_svc").path("/svc/B"))
658 .use_(UseBuilder::protocol().name("C_svc").path("/svc/C"))
659 .build(),
660 ),
661 ];
662
663 let test = T::new("root", components).build().await;
664 for path in ["/svc/A", "/svc/B", "/svc/C"] {
665 test.check_use(
666 "mid/leaf".try_into().unwrap(),
667 CheckUse::Protocol {
668 path: path.parse().unwrap(),
669 expected_res: ExpectedResult::Ok,
670 },
671 )
672 .await;
673 }
674 }
675
676 pub async fn test_offer_protocol_from_dictionary_not_found(&self) {
677 let components = vec![
680 (
681 "root",
682 ComponentDeclBuilder::new()
683 .protocol_default("foo")
684 .dictionary_default("dict")
685 .offer(
686 OfferBuilder::protocol()
687 .name("foo")
688 .target_name("B")
689 .source(OfferSource::Self_)
690 .target(OfferTarget::Capability("dict".parse().unwrap())),
691 )
692 .offer(
693 OfferBuilder::dictionary()
694 .name("dict")
695 .source(OfferSource::Self_)
696 .target_static_child("mid"),
697 )
698 .child_default("mid")
699 .build(),
700 ),
701 (
702 "mid",
703 ComponentDeclBuilder::new()
704 .offer(
705 OfferBuilder::protocol()
706 .name("A")
707 .target_name("A_svc")
708 .source(OfferSource::Parent)
709 .target_static_child("leaf")
710 .from_dictionary("dict"),
711 )
712 .child_default("leaf")
713 .build(),
714 ),
715 (
716 "leaf",
717 ComponentDeclBuilder::new()
718 .use_(UseBuilder::protocol().name("A_svc").path("/svc/A"))
719 .build(),
720 ),
721 ];
722
723 let test = T::new("root", components).build().await;
724 test.check_use(
725 "mid/leaf".try_into().unwrap(),
726 CheckUse::Protocol {
727 path: "/svc/A".parse().unwrap(),
728 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
729 },
730 )
731 .await;
732 }
733
734 pub async fn test_offer_protocol_from_dictionary_to_dictionary(&self) {
735 let components = vec![
736 (
737 "root",
738 ComponentDeclBuilder::new()
739 .dictionary_default("dict1")
740 .dictionary_default("dict2")
741 .offer(
742 OfferBuilder::protocol()
743 .name("foo")
744 .target_name("A")
745 .source_static_child("provider")
746 .target(OfferTarget::Capability("dict1".parse().unwrap())),
747 )
748 .offer(
749 OfferBuilder::protocol()
750 .name("A")
751 .target_name("A")
752 .from_dictionary("dict1")
753 .source(OfferSource::Self_)
754 .target(OfferTarget::Capability("dict2".parse().unwrap())),
755 )
756 .offer(
757 OfferBuilder::dictionary()
758 .name("dict2")
759 .source(OfferSource::Self_)
760 .target_static_child("leaf"),
761 )
762 .child_default("provider")
763 .child_default("leaf")
764 .build(),
765 ),
766 (
767 "provider",
768 ComponentDeclBuilder::new()
769 .protocol_default("foo")
770 .expose(ExposeBuilder::protocol().name("foo").source(ExposeSource::Self_))
771 .build(),
772 ),
773 (
774 "leaf",
775 ComponentDeclBuilder::new()
776 .use_(UseBuilder::protocol().name("A").from_dictionary("dict2").path("/svc/A"))
777 .build(),
778 ),
779 ];
780
781 let test = T::new("root", components).build().await;
782 test.check_use(
783 "leaf".try_into().unwrap(),
784 CheckUse::Protocol {
785 path: "/svc/A".parse().unwrap(),
786 expected_res: ExpectedResult::Ok,
787 },
788 )
789 .await;
790 }
791
792 pub async fn test_offer_protocol_from_nested_dictionary(&self) {
793 let components = vec![
796 (
797 "root",
798 ComponentDeclBuilder::new()
799 .protocol_default("foo")
800 .dictionary_default("nested")
801 .dictionary_default("parent_dict")
802 .offer(
803 OfferBuilder::protocol()
804 .name("foo")
805 .target_name("B")
806 .source(OfferSource::Self_)
807 .target(OfferTarget::Capability("nested".parse().unwrap())),
808 )
809 .offer(
810 OfferBuilder::dictionary()
811 .name("nested")
812 .source(OfferSource::Self_)
813 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
814 )
815 .offer(
816 OfferBuilder::dictionary()
817 .name("parent_dict")
818 .source(OfferSource::Self_)
819 .target_static_child("mid"),
820 )
821 .child_default("mid")
822 .build(),
823 ),
824 (
825 "mid",
826 ComponentDeclBuilder::new()
827 .protocol_default("foo")
828 .dictionary_default("self_dict")
829 .dictionary_default("nested")
830 .offer(
831 OfferBuilder::protocol()
832 .name("A")
833 .target_name("A_svc")
834 .source(OfferSource::Self_)
835 .target_static_child("leaf")
836 .from_dictionary("self_dict/nested"),
837 )
838 .offer(
839 OfferBuilder::protocol()
840 .name("foo")
841 .target_name("A")
842 .source(OfferSource::Self_)
843 .target(OfferTarget::Capability("nested".parse().unwrap())),
844 )
845 .offer(
846 OfferBuilder::dictionary()
847 .name("nested")
848 .source(OfferSource::Self_)
849 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
850 )
851 .offer(
852 OfferBuilder::protocol()
853 .name("B")
854 .target_name("B_svc")
855 .source(OfferSource::Parent)
856 .target_static_child("leaf")
857 .from_dictionary("parent_dict/nested"),
858 )
859 .offer(
860 OfferBuilder::protocol()
861 .name("C")
862 .target_name("C_svc")
863 .source_static_child("provider")
864 .target_static_child("leaf")
865 .from_dictionary("child_dict/nested"),
866 )
867 .child_default("provider")
868 .child_default("leaf")
869 .build(),
870 ),
871 (
872 "provider",
873 ComponentDeclBuilder::new()
874 .protocol_default("foo")
875 .dictionary_default("child_dict")
876 .dictionary_default("nested")
877 .offer(
878 OfferBuilder::protocol()
879 .name("foo")
880 .target_name("C")
881 .source(OfferSource::Self_)
882 .target(OfferTarget::Capability("nested".parse().unwrap())),
883 )
884 .offer(
885 OfferBuilder::dictionary()
886 .name("nested")
887 .source(OfferSource::Self_)
888 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
889 )
890 .expose(
891 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
892 )
893 .build(),
894 ),
895 (
896 "leaf",
897 ComponentDeclBuilder::new()
898 .use_(UseBuilder::protocol().name("A_svc").path("/svc/A"))
899 .use_(UseBuilder::protocol().name("B_svc").path("/svc/B"))
900 .use_(UseBuilder::protocol().name("C_svc").path("/svc/C"))
901 .build(),
902 ),
903 ];
904
905 let test = T::new("root", components).build().await;
906 for path in ["/svc/A", "/svc/B", "/svc/C"] {
907 test.check_use(
908 "mid/leaf".try_into().unwrap(),
909 CheckUse::Protocol {
910 path: path.parse().unwrap(),
911 expected_res: ExpectedResult::Ok,
912 },
913 )
914 .await;
915 }
916 }
917
918 pub async fn test_expose_protocol_from_dictionary(&self) {
919 let components = vec![
921 (
922 "root",
923 ComponentDeclBuilder::new()
924 .use_(
925 UseBuilder::protocol()
926 .source_static_child("mid")
927 .name("A_svc")
928 .path("/svc/A"),
929 )
930 .use_(
931 UseBuilder::protocol()
932 .source_static_child("mid")
933 .name("B_svc")
934 .path("/svc/B"),
935 )
936 .child_default("mid")
937 .build(),
938 ),
939 (
940 "mid",
941 ComponentDeclBuilder::new()
942 .protocol_default("foo")
943 .dictionary_default("self_dict")
944 .expose(
945 ExposeBuilder::protocol()
946 .name("A")
947 .target_name("A_svc")
948 .from_dictionary("self_dict")
949 .source(ExposeSource::Self_),
950 )
951 .expose(
952 ExposeBuilder::protocol()
953 .name("B")
954 .target_name("B_svc")
955 .from_dictionary("child_dict")
956 .source_static_child("leaf"),
957 )
958 .offer(
959 OfferBuilder::protocol()
960 .name("foo")
961 .target_name("A")
962 .source(OfferSource::Self_)
963 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
964 )
965 .child_default("leaf")
966 .build(),
967 ),
968 (
969 "leaf",
970 ComponentDeclBuilder::new()
971 .protocol_default("foo")
972 .dictionary_default("child_dict")
973 .offer(
974 OfferBuilder::protocol()
975 .name("foo")
976 .target_name("B")
977 .source(OfferSource::Self_)
978 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
979 )
980 .expose(
981 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
982 )
983 .build(),
984 ),
985 ];
986
987 let test = T::new("root", components).build().await;
988 for path in ["/svc/A", "/svc/B"] {
989 test.check_use(
990 ".".try_into().unwrap(),
991 CheckUse::Protocol {
992 path: path.parse().unwrap(),
993 expected_res: ExpectedResult::Ok,
994 },
995 )
996 .await;
997 }
998 }
999
1000 pub async fn test_expose_protocol_from_dictionary_not_found(&self) {
1001 let components = vec![
1003 (
1004 "root",
1005 ComponentDeclBuilder::new()
1006 .use_(
1007 UseBuilder::protocol()
1008 .source_static_child("mid")
1009 .name("A_svc")
1010 .path("/svc/A"),
1011 )
1012 .child_default("mid")
1013 .build(),
1014 ),
1015 (
1016 "mid",
1017 ComponentDeclBuilder::new()
1018 .expose(
1019 ExposeBuilder::protocol()
1020 .name("A")
1021 .target_name("A_svc")
1022 .source(ExposeSource::Self_)
1023 .from_dictionary("dict")
1024 .build(),
1025 )
1026 .child_default("leaf")
1027 .build(),
1028 ),
1029 (
1030 "leaf",
1031 ComponentDeclBuilder::new()
1032 .protocol_default("foo")
1033 .dictionary_default("dict")
1034 .offer(
1035 OfferBuilder::protocol()
1036 .name("foo")
1037 .target_name("B")
1038 .source(OfferSource::Self_)
1039 .target(OfferTarget::Capability("dict".parse().unwrap())),
1040 )
1041 .expose(ExposeBuilder::dictionary().name("dict").source(ExposeSource::Self_))
1042 .build(),
1043 ),
1044 ];
1045
1046 let test = T::new("root", components).build().await;
1047 test.check_use(
1048 ".".try_into().unwrap(),
1049 CheckUse::Protocol {
1050 path: "/svc/A".parse().unwrap(),
1051 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1052 },
1053 )
1054 .await;
1055 }
1056
1057 pub async fn test_expose_protocol_from_nested_dictionary(&self) {
1058 let components = vec![
1061 (
1062 "root",
1063 ComponentDeclBuilder::new()
1064 .use_(
1065 UseBuilder::protocol()
1066 .source_static_child("mid")
1067 .name("A_svc")
1068 .path("/svc/A"),
1069 )
1070 .use_(
1071 UseBuilder::protocol()
1072 .source_static_child("mid")
1073 .name("B_svc")
1074 .path("/svc/B"),
1075 )
1076 .child_default("mid")
1077 .build(),
1078 ),
1079 (
1080 "mid",
1081 ComponentDeclBuilder::new()
1082 .protocol_default("foo")
1083 .dictionary_default("self_dict")
1084 .dictionary_default("nested")
1085 .expose(
1086 ExposeBuilder::protocol()
1087 .name("A")
1088 .target_name("A_svc")
1089 .from_dictionary("self_dict/nested")
1090 .source(ExposeSource::Self_),
1091 )
1092 .expose(
1093 ExposeBuilder::protocol()
1094 .name("B")
1095 .target_name("B_svc")
1096 .from_dictionary("child_dict/nested")
1097 .source_static_child("leaf"),
1098 )
1099 .offer(
1100 OfferBuilder::protocol()
1101 .name("foo")
1102 .target_name("A")
1103 .source(OfferSource::Self_)
1104 .target(OfferTarget::Capability("nested".parse().unwrap())),
1105 )
1106 .offer(
1107 OfferBuilder::dictionary()
1108 .name("nested")
1109 .source(OfferSource::Self_)
1110 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
1111 )
1112 .child_default("leaf")
1113 .build(),
1114 ),
1115 (
1116 "leaf",
1117 ComponentDeclBuilder::new()
1118 .protocol_default("foo")
1119 .dictionary_default("child_dict")
1120 .dictionary_default("nested")
1121 .offer(
1122 OfferBuilder::dictionary()
1123 .name("nested")
1124 .source(OfferSource::Self_)
1125 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
1126 )
1127 .offer(
1128 OfferBuilder::protocol()
1129 .name("foo")
1130 .target_name("B")
1131 .source(OfferSource::Self_)
1132 .target(OfferTarget::Capability("nested".parse().unwrap())),
1133 )
1134 .expose(
1135 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
1136 )
1137 .build(),
1138 ),
1139 ];
1140
1141 let test = T::new("root", components).build().await;
1142 for path in ["/svc/A", "/svc/B"] {
1143 test.check_use(
1144 ".".try_into().unwrap(),
1145 CheckUse::Protocol {
1146 path: path.parse().unwrap(),
1147 expected_res: ExpectedResult::Ok,
1148 },
1149 )
1150 .await;
1151 }
1152 }
1153
1154 pub async fn test_dictionary_in_exposed_dir(&self) {
1155 let components = vec![
1157 (
1158 "root",
1159 ComponentDeclBuilder::new()
1160 .protocol_default("foo")
1161 .dictionary_default("self_dict")
1162 .expose(
1163 ExposeBuilder::dictionary().name("self_dict").source(ExposeSource::Self_),
1164 )
1165 .expose(
1166 ExposeBuilder::dictionary().name("child_dict").source_static_child("leaf"),
1167 )
1168 .offer(
1169 OfferBuilder::protocol()
1170 .name("foo")
1171 .target_name("A")
1172 .source(OfferSource::Self_)
1173 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
1174 )
1175 .child_default("leaf")
1176 .build(),
1177 ),
1178 (
1179 "leaf",
1180 ComponentDeclBuilder::new()
1181 .protocol_default("foo")
1182 .dictionary_default("nested")
1183 .dictionary_default("child_dict")
1184 .offer(
1185 OfferBuilder::dictionary()
1186 .name("nested")
1187 .source(OfferSource::Self_)
1188 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
1189 )
1190 .offer(
1191 OfferBuilder::protocol()
1192 .name("foo")
1193 .target_name("B")
1194 .source(OfferSource::Self_)
1195 .target(OfferTarget::Capability("nested".parse().unwrap())),
1196 )
1197 .expose(
1198 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
1199 )
1200 .build(),
1201 ),
1202 ];
1203
1204 let test = T::new("root", components).build().await;
1205 for path in ["/self_dict/A", "/child_dict/nested/B"] {
1207 test.check_use_exposed_dir(
1208 ".".try_into().unwrap(),
1209 CheckUse::Protocol {
1210 path: path.parse().unwrap(),
1211 expected_res: ExpectedResult::Ok,
1212 },
1213 )
1214 .await;
1215 }
1216 }
1217
1218 pub async fn test_offer_dictionary_to_dictionary(&self) {
1219 let components = vec![
1221 (
1222 "root",
1223 ComponentDeclBuilder::new()
1224 .protocol_default("foo")
1225 .dictionary_default("parent_dict")
1226 .offer(
1227 OfferBuilder::protocol()
1228 .name("foo")
1229 .target_name("B")
1230 .source(OfferSource::Self_)
1231 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
1232 )
1233 .offer(
1234 OfferBuilder::dictionary()
1235 .name("parent_dict")
1236 .source(OfferSource::Self_)
1237 .target_static_child("mid"),
1238 )
1239 .child_default("mid")
1240 .build(),
1241 ),
1242 (
1243 "mid",
1244 ComponentDeclBuilder::new()
1245 .protocol_default("foo")
1246 .dictionary_default("self_dict")
1247 .dictionary_default("root_dict")
1248 .offer(
1249 OfferBuilder::protocol()
1250 .name("foo")
1251 .target_name("A")
1252 .source(OfferSource::Self_)
1253 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
1254 )
1255 .offer(
1256 OfferBuilder::dictionary()
1257 .name("self_dict")
1258 .source(OfferSource::Self_)
1259 .target(OfferTarget::Capability("root_dict".parse().unwrap())),
1260 )
1261 .offer(
1262 OfferBuilder::dictionary()
1263 .name("parent_dict")
1264 .source(OfferSource::Parent)
1265 .target(OfferTarget::Capability("root_dict".parse().unwrap())),
1266 )
1267 .offer(
1268 OfferBuilder::dictionary()
1269 .name("child_dict")
1270 .source_static_child("leaf")
1271 .target(OfferTarget::Capability("root_dict".parse().unwrap())),
1272 )
1273 .use_(
1274 UseBuilder::protocol()
1275 .source(UseSource::Self_)
1276 .name("A")
1277 .from_dictionary("root_dict/self_dict"),
1278 )
1279 .use_(
1280 UseBuilder::protocol()
1281 .source(UseSource::Self_)
1282 .name("B")
1283 .from_dictionary("root_dict/parent_dict"),
1284 )
1285 .use_(
1286 UseBuilder::protocol()
1287 .source(UseSource::Self_)
1288 .name("C")
1289 .from_dictionary("root_dict/child_dict"),
1290 )
1291 .child_default("leaf")
1292 .build(),
1293 ),
1294 (
1295 "leaf",
1296 ComponentDeclBuilder::new()
1297 .protocol_default("foo")
1298 .dictionary_default("child_dict")
1299 .offer(
1300 OfferBuilder::protocol()
1301 .name("foo")
1302 .target_name("C")
1303 .source(OfferSource::Self_)
1304 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
1305 )
1306 .expose(
1307 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
1308 )
1309 .build(),
1310 ),
1311 ];
1312
1313 let test = T::new("root", components).build().await;
1314 for path in ["/svc/A", "/svc/B", "/svc/C"] {
1315 test.check_use(
1316 "mid".try_into().unwrap(),
1317 CheckUse::Protocol {
1318 path: path.parse().unwrap(),
1319 expected_res: ExpectedResult::Ok,
1320 },
1321 )
1322 .await;
1323 }
1324 }
1325
1326 pub async fn test_use_from_dictionary_availability_attenuated(&self) {
1327 let components = vec![
1331 (
1332 "root",
1333 ComponentDeclBuilder::new()
1334 .protocol_default("foo")
1335 .protocol_default("bar")
1336 .dictionary_default("nested")
1337 .dictionary_default("dict")
1338 .offer(
1339 OfferBuilder::protocol()
1340 .name("foo")
1341 .target_name("A")
1342 .source(OfferSource::Self_)
1343 .target(OfferTarget::Capability("dict".parse().unwrap())),
1344 )
1345 .offer(
1346 OfferBuilder::protocol()
1347 .name("bar")
1348 .target_name("B")
1349 .source(OfferSource::Self_)
1350 .target(OfferTarget::Capability("nested".parse().unwrap())),
1351 )
1352 .offer(
1353 OfferBuilder::dictionary()
1354 .name("nested")
1355 .source(OfferSource::Self_)
1356 .target(OfferTarget::Capability("dict".parse().unwrap())),
1357 )
1358 .offer(
1359 OfferBuilder::dictionary()
1360 .name("dict")
1361 .source(OfferSource::Self_)
1362 .target_static_child("leaf"),
1363 )
1364 .child_default("leaf")
1365 .build(),
1366 ),
1367 (
1368 "leaf",
1369 ComponentDeclBuilder::new()
1370 .use_(
1371 UseBuilder::protocol()
1372 .name("A")
1373 .from_dictionary("dict")
1374 .availability(Availability::Optional),
1375 )
1376 .use_(
1377 UseBuilder::protocol()
1378 .name("B")
1379 .from_dictionary("dict/nested")
1380 .availability(Availability::Optional),
1381 )
1382 .build(),
1383 ),
1384 ];
1385
1386 let test = T::new("root", components).build().await;
1387 test.check_use(
1388 "leaf".try_into().unwrap(),
1389 CheckUse::Protocol {
1390 path: "/svc/A".parse().unwrap(),
1391 expected_res: ExpectedResult::Ok,
1392 },
1393 )
1394 .await;
1395 test.check_use(
1396 "leaf".try_into().unwrap(),
1397 CheckUse::Protocol {
1398 path: "/svc/B".parse().unwrap(),
1399 expected_res: ExpectedResult::Ok,
1400 },
1401 )
1402 .await;
1403 }
1404
1405 pub async fn test_use_from_dictionary_availability_invalid(&self) {
1406 let components = vec![
1411 (
1412 "root",
1413 ComponentDeclBuilder::new()
1414 .protocol_default("foo")
1415 .protocol_default("bar")
1416 .protocol_default("qux")
1417 .dictionary_default("required_dict")
1418 .dictionary_default("optional_dict")
1419 .dictionary_default("nested")
1420 .dictionary_default("dict_with_optional_nested")
1421 .offer(
1422 OfferBuilder::protocol()
1423 .name("foo")
1424 .target_name("A")
1425 .source(OfferSource::Self_)
1426 .target(OfferTarget::Capability("required_dict".parse().unwrap()))
1427 .availability(Availability::Optional),
1428 )
1429 .offer(
1430 OfferBuilder::protocol()
1431 .name("bar")
1432 .target_name("B")
1433 .source(OfferSource::Self_)
1434 .target(OfferTarget::Capability("optional_dict".parse().unwrap())),
1435 )
1436 .offer(
1437 OfferBuilder::protocol()
1438 .name("qux")
1439 .target_name("C")
1440 .source(OfferSource::Self_)
1441 .target(OfferTarget::Capability("nested".parse().unwrap())),
1442 )
1443 .offer(
1444 OfferBuilder::dictionary()
1445 .name("nested")
1446 .source(OfferSource::Self_)
1447 .target(OfferTarget::Capability(
1448 "dict_with_optional_nested".parse().unwrap(),
1449 ))
1450 .availability(Availability::Optional),
1451 )
1452 .offer(
1453 OfferBuilder::dictionary()
1454 .name("required_dict")
1455 .source(OfferSource::Self_)
1456 .target_static_child("leaf"),
1457 )
1458 .offer(
1459 OfferBuilder::dictionary()
1460 .name("optional_dict")
1461 .source(OfferSource::Self_)
1462 .target_static_child("leaf")
1463 .availability(Availability::Optional),
1464 )
1465 .offer(
1466 OfferBuilder::dictionary()
1467 .name("dict_with_optional_nested")
1468 .source(OfferSource::Self_)
1469 .target_static_child("leaf"),
1470 )
1471 .child_default("leaf")
1472 .build(),
1473 ),
1474 (
1475 "leaf",
1476 ComponentDeclBuilder::new()
1477 .use_(UseBuilder::protocol().name("A").from_dictionary("required_dict"))
1478 .use_(UseBuilder::protocol().name("B").from_dictionary("optional_dict"))
1479 .use_(
1480 UseBuilder::protocol()
1481 .name("C")
1482 .from_dictionary("dict_with_optional_nested/nested"),
1483 )
1484 .build(),
1485 ),
1486 ];
1487
1488 let test = T::new("root", components).build().await;
1489 test.check_use(
1490 "leaf".try_into().unwrap(),
1491 CheckUse::Protocol {
1492 path: "/svc/A".parse().unwrap(),
1493 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1494 },
1495 )
1496 .await;
1497 test.check_use(
1498 "leaf".try_into().unwrap(),
1499 CheckUse::Protocol {
1500 path: "/svc/B".parse().unwrap(),
1501 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1502 },
1503 )
1504 .await;
1505 test.check_use(
1506 "leaf".try_into().unwrap(),
1507 CheckUse::Protocol {
1508 path: "/svc/C".parse().unwrap(),
1509 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1510 },
1511 )
1512 .await;
1513 }
1514
1515 pub async fn test_offer_from_dictionary_availability_attenuated(&self) {
1516 let components = vec![
1520 (
1521 "root",
1522 ComponentDeclBuilder::new()
1523 .protocol_default("foo")
1524 .protocol_default("bar")
1525 .dictionary_default("nested")
1526 .dictionary_default("dict")
1527 .offer(
1528 OfferBuilder::protocol()
1529 .name("foo")
1530 .target_name("A")
1531 .source(OfferSource::Self_)
1532 .target(OfferTarget::Capability("dict".parse().unwrap())),
1533 )
1534 .offer(
1535 OfferBuilder::protocol()
1536 .name("bar")
1537 .target_name("B")
1538 .source(OfferSource::Self_)
1539 .target(OfferTarget::Capability("nested".parse().unwrap())),
1540 )
1541 .offer(
1542 OfferBuilder::dictionary()
1543 .name("nested")
1544 .source(OfferSource::Self_)
1545 .target(OfferTarget::Capability("dict".parse().unwrap())),
1546 )
1547 .offer(
1548 OfferBuilder::protocol()
1549 .name("A")
1550 .source(OfferSource::Self_)
1551 .target_static_child("leaf")
1552 .from_dictionary("dict"),
1553 )
1554 .offer(
1555 OfferBuilder::protocol()
1556 .name("B")
1557 .source(OfferSource::Self_)
1558 .target_static_child("leaf")
1559 .from_dictionary("dict/nested"),
1560 )
1561 .child_default("leaf")
1562 .build(),
1563 ),
1564 (
1565 "leaf",
1566 ComponentDeclBuilder::new()
1567 .use_(UseBuilder::protocol().name("A").availability(Availability::Optional))
1568 .use_(UseBuilder::protocol().name("B").availability(Availability::Optional))
1569 .build(),
1570 ),
1571 ];
1572
1573 let test = T::new("root", components).build().await;
1574 test.check_use(
1575 "leaf".try_into().unwrap(),
1576 CheckUse::Protocol {
1577 path: "/svc/A".parse().unwrap(),
1578 expected_res: ExpectedResult::Ok,
1579 },
1580 )
1581 .await;
1582 test.check_use(
1583 "leaf".try_into().unwrap(),
1584 CheckUse::Protocol {
1585 path: "/svc/B".parse().unwrap(),
1586 expected_res: ExpectedResult::Ok,
1587 },
1588 )
1589 .await;
1590 }
1591
1592 pub async fn test_offer_from_dictionary_availability_invalid(&self) {
1593 let components = vec![
1598 (
1599 "root",
1600 ComponentDeclBuilder::new()
1601 .protocol_default("foo")
1602 .protocol_default("bar")
1603 .protocol_default("qux")
1604 .dictionary_default("required_dict")
1605 .dictionary_default("optional_dict")
1606 .dictionary_default("nested")
1607 .dictionary_default("dict_with_optional_nested")
1608 .offer(
1609 OfferBuilder::protocol()
1610 .name("foo")
1611 .target_name("A")
1612 .source(OfferSource::Self_)
1613 .target(OfferTarget::Capability("required_dict".parse().unwrap()))
1614 .availability(Availability::Optional),
1615 )
1616 .offer(
1617 OfferBuilder::protocol()
1618 .name("bar")
1619 .target_name("B")
1620 .source(OfferSource::Self_)
1621 .target(OfferTarget::Capability("optional_dict".parse().unwrap())),
1622 )
1623 .offer(
1624 OfferBuilder::protocol()
1625 .name("qux")
1626 .target_name("C")
1627 .source(OfferSource::Self_)
1628 .target(OfferTarget::Capability("nested".parse().unwrap())),
1629 )
1630 .offer(
1631 OfferBuilder::dictionary()
1632 .name("nested")
1633 .source(OfferSource::Self_)
1634 .target(OfferTarget::Capability(
1635 "dict_with_optional_nested".parse().unwrap(),
1636 ))
1637 .availability(Availability::Optional),
1638 )
1639 .offer(
1640 OfferBuilder::dictionary()
1641 .name("required_dict")
1642 .source(OfferSource::Self_)
1643 .target_static_child("mid"),
1644 )
1645 .offer(
1646 OfferBuilder::dictionary()
1647 .name("optional_dict")
1648 .source(OfferSource::Self_)
1649 .target_static_child("mid")
1650 .availability(Availability::Optional),
1651 )
1652 .offer(
1653 OfferBuilder::dictionary()
1654 .name("dict_with_optional_nested")
1655 .source(OfferSource::Self_)
1656 .target_static_child("mid"),
1657 )
1658 .child_default("mid")
1659 .build(),
1660 ),
1661 (
1662 "mid",
1663 ComponentDeclBuilder::new()
1664 .offer(
1665 OfferBuilder::protocol()
1666 .name("A")
1667 .source(OfferSource::Parent)
1668 .target_static_child("leaf")
1669 .from_dictionary("required_dict"),
1670 )
1671 .offer(
1672 OfferBuilder::protocol()
1673 .name("B")
1674 .source(OfferSource::Parent)
1675 .target_static_child("leaf")
1676 .from_dictionary("optional_dict"),
1677 )
1678 .offer(
1679 OfferBuilder::protocol()
1680 .name("C")
1681 .source(OfferSource::Parent)
1682 .target_static_child("leaf")
1683 .from_dictionary("dict_with_optional_nested/nested"),
1684 )
1685 .child_default("leaf")
1686 .build(),
1687 ),
1688 (
1689 "leaf",
1690 ComponentDeclBuilder::new()
1691 .use_(UseBuilder::protocol().name("A"))
1692 .use_(UseBuilder::protocol().name("B"))
1693 .use_(UseBuilder::protocol().name("C"))
1694 .build(),
1695 ),
1696 ];
1697
1698 let test = T::new("root", components).build().await;
1699 test.check_use(
1700 "mid/leaf".try_into().unwrap(),
1701 CheckUse::Protocol {
1702 path: "/svc/A".parse().unwrap(),
1703 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1704 },
1705 )
1706 .await;
1707 test.check_use(
1708 "mid/leaf".try_into().unwrap(),
1709 CheckUse::Protocol {
1710 path: "/svc/B".parse().unwrap(),
1711 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1712 },
1713 )
1714 .await;
1715 test.check_use(
1716 "mid/leaf".try_into().unwrap(),
1717 CheckUse::Protocol {
1718 path: "/svc/C".parse().unwrap(),
1719 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1720 },
1721 )
1722 .await;
1723 }
1724
1725 pub async fn test_expose_from_dictionary_availability_attenuated(&self) {
1726 let components = vec![
1730 (
1731 "root",
1732 ComponentDeclBuilder::new()
1733 .use_(
1734 UseBuilder::protocol()
1735 .source_static_child("leaf")
1736 .name("A")
1737 .availability(Availability::Optional),
1738 )
1739 .use_(
1740 UseBuilder::protocol()
1741 .source_static_child("leaf")
1742 .name("B")
1743 .availability(Availability::Optional),
1744 )
1745 .child_default("leaf")
1746 .build(),
1747 ),
1748 (
1749 "leaf",
1750 ComponentDeclBuilder::new()
1751 .protocol_default("foo")
1752 .protocol_default("bar")
1753 .dictionary_default("nested")
1754 .dictionary_default("dict")
1755 .offer(
1756 OfferBuilder::protocol()
1757 .name("foo")
1758 .target_name("A")
1759 .source(OfferSource::Self_)
1760 .target(OfferTarget::Capability("dict".parse().unwrap())),
1761 )
1762 .offer(
1763 OfferBuilder::protocol()
1764 .name("bar")
1765 .target_name("B")
1766 .source(OfferSource::Self_)
1767 .target(OfferTarget::Capability("nested".parse().unwrap())),
1768 )
1769 .offer(
1770 OfferBuilder::dictionary()
1771 .name("nested")
1772 .source(OfferSource::Self_)
1773 .target(OfferTarget::Capability("dict".parse().unwrap())),
1774 )
1775 .expose(
1776 ExposeBuilder::protocol()
1777 .name("A")
1778 .from_dictionary("dict")
1779 .source(ExposeSource::Self_),
1780 )
1781 .expose(
1782 ExposeBuilder::protocol()
1783 .name("B")
1784 .from_dictionary("dict/nested")
1785 .source(ExposeSource::Self_),
1786 )
1787 .build(),
1788 ),
1789 ];
1790
1791 let test = T::new("root", components).build().await;
1792 test.check_use(
1793 ".".try_into().unwrap(),
1794 CheckUse::Protocol {
1795 path: "/svc/A".parse().unwrap(),
1796 expected_res: ExpectedResult::Ok,
1797 },
1798 )
1799 .await;
1800 test.check_use(
1801 ".".try_into().unwrap(),
1802 CheckUse::Protocol {
1803 path: "/svc/B".parse().unwrap(),
1804 expected_res: ExpectedResult::Ok,
1805 },
1806 )
1807 .await;
1808 }
1809
1810 pub async fn test_expose_from_dictionary_availability_invalid(&self) {
1811 let components = vec![
1816 (
1817 "root",
1818 ComponentDeclBuilder::new()
1819 .use_(UseBuilder::protocol().source_static_child("mid").name("A"))
1820 .use_(UseBuilder::protocol().source_static_child("mid").name("B"))
1821 .use_(UseBuilder::protocol().source_static_child("mid").name("C"))
1822 .child_default("mid")
1823 .build(),
1824 ),
1825 (
1826 "mid",
1827 ComponentDeclBuilder::new()
1828 .expose(
1829 ExposeBuilder::protocol()
1830 .name("A")
1831 .from_dictionary("required_dict")
1832 .source_static_child("leaf"),
1833 )
1834 .expose(
1835 ExposeBuilder::protocol()
1836 .name("B")
1837 .from_dictionary("optional_dict")
1838 .source_static_child("leaf"),
1839 )
1840 .expose(
1841 ExposeBuilder::protocol()
1842 .name("C")
1843 .from_dictionary("dict_with_optional_nested/nested")
1844 .source_static_child("leaf"),
1845 )
1846 .child_default("leaf")
1847 .build(),
1848 ),
1849 (
1850 "leaf",
1851 ComponentDeclBuilder::new()
1852 .protocol_default("foo")
1853 .protocol_default("bar")
1854 .protocol_default("qux")
1855 .dictionary_default("required_dict")
1856 .dictionary_default("optional_dict")
1857 .dictionary_default("nested")
1858 .dictionary_default("dict")
1859 .dictionary_default("dict_with_optional_nested")
1860 .offer(
1861 OfferBuilder::protocol()
1862 .name("foo")
1863 .target_name("A")
1864 .source(OfferSource::Self_)
1865 .target(OfferTarget::Capability("dict".parse().unwrap()))
1866 .availability(Availability::Optional),
1867 )
1868 .offer(
1869 OfferBuilder::protocol()
1870 .name("bar")
1871 .target_name("B")
1872 .source(OfferSource::Self_)
1873 .target(OfferTarget::Capability("optional_dict".parse().unwrap())),
1874 )
1875 .offer(
1876 OfferBuilder::protocol()
1877 .name("qux")
1878 .target_name("C")
1879 .source(OfferSource::Self_)
1880 .target(OfferTarget::Capability("nested".parse().unwrap())),
1881 )
1882 .offer(
1883 OfferBuilder::dictionary()
1884 .name("nested")
1885 .source(OfferSource::Self_)
1886 .target(OfferTarget::Capability(
1887 "dict_with_optional_nested".parse().unwrap(),
1888 ))
1889 .availability(Availability::Optional),
1890 )
1891 .expose(
1892 ExposeBuilder::dictionary()
1893 .name("required_dict")
1894 .source(ExposeSource::Self_),
1895 )
1896 .expose(
1897 ExposeBuilder::dictionary()
1898 .name("optional_dict")
1899 .source(ExposeSource::Self_)
1900 .availability(Availability::Optional),
1901 )
1902 .expose(
1903 ExposeBuilder::dictionary()
1904 .name("dict_with_optional_nested")
1905 .source(ExposeSource::Self_),
1906 )
1907 .build(),
1908 ),
1909 ];
1910
1911 let test = T::new("root", components).build().await;
1912 test.check_use(
1913 ".".try_into().unwrap(),
1914 CheckUse::Protocol {
1915 path: "/svc/A".parse().unwrap(),
1916 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1917 },
1918 )
1919 .await;
1920 test.check_use(
1921 ".".try_into().unwrap(),
1922 CheckUse::Protocol {
1923 path: "/svc/B".parse().unwrap(),
1924 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1925 },
1926 )
1927 .await;
1928 test.check_use(
1929 ".".try_into().unwrap(),
1930 CheckUse::Protocol {
1931 path: "/svc/C".parse().unwrap(),
1932 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1933 },
1934 )
1935 .await;
1936 }
1937
1938 pub async fn test_use_runner_from_dictionary(&self) {
1939 let components = vec![
1940 (
1941 "root",
1942 ComponentDeclBuilder::new()
1943 .runner_default("foo")
1944 .dictionary_default("dict")
1945 .offer(
1946 OfferBuilder::runner()
1947 .name("foo")
1948 .target_name("bar")
1949 .source(OfferSource::Self_)
1950 .target(OfferTarget::Capability("dict".parse().unwrap())),
1951 )
1952 .offer(
1953 OfferBuilder::dictionary()
1954 .name("dict")
1955 .source(OfferSource::Self_)
1956 .target_static_child("mid"),
1957 )
1958 .child_default("mid")
1959 .build(),
1960 ),
1961 (
1962 "mid",
1963 ComponentDeclBuilder::new_empty_component()
1964 .use_(UseBuilder::runner().name("bar").from_dictionary("dict"))
1965 .build(),
1966 ),
1967 ];
1968
1969 let test = T::new("root", components).build().await;
1970 let mid_component =
1971 test.look_up_instance(&["mid"].try_into().unwrap()).await.expect("mid instance");
1972 let source = debug_route_sandbox_path(
1973 &mid_component,
1974 &UseDecl::Runner(UseRunnerDecl {
1975 source: UseSource::Parent,
1976 source_name: "bar".parse().unwrap(),
1977 source_dictionary: "dict".parse().unwrap(),
1978 }),
1979 )
1980 .await
1981 .expect("failed to route runner");
1982
1983 match source {
1984 capability_source::CapabilitySource::Component(
1985 capability_source::ComponentSource {
1986 capability:
1987 capability_source::ComponentCapability::Runner(RunnerDecl { name, .. }),
1988 moniker,
1989 },
1990 ) => {
1991 assert_eq!(name, "foo");
1992 assert_eq!(moniker, Moniker::root());
1993 }
1994 _ => panic!("unexpected source: {:?}", source),
1995 }
1996 }
1997
1998 pub async fn test_offer_runner_from_dictionary(&self) {
1999 let components = vec![
2000 (
2001 "root",
2002 ComponentDeclBuilder::new()
2003 .runner_default("foo")
2004 .dictionary_default("dict")
2005 .offer(
2006 OfferBuilder::runner()
2007 .name("foo")
2008 .target_name("bar")
2009 .source(OfferSource::Self_)
2010 .target(OfferTarget::Capability("dict".parse().unwrap())),
2011 )
2012 .offer(
2013 OfferBuilder::dictionary()
2014 .name("dict")
2015 .source(OfferSource::Self_)
2016 .target_static_child("mid"),
2017 )
2018 .child_default("mid")
2019 .build(),
2020 ),
2021 (
2022 "mid",
2023 ComponentDeclBuilder::new()
2024 .offer(
2025 OfferBuilder::runner()
2026 .name("bar")
2027 .target_name("baz")
2028 .from_dictionary("dict")
2029 .source(OfferSource::Parent)
2030 .target_static_child("leaf"),
2031 )
2032 .child_default("leaf")
2033 .build(),
2034 ),
2035 (
2036 "leaf",
2037 ComponentDeclBuilder::new_empty_component()
2038 .use_(UseBuilder::runner().name("baz"))
2039 .build(),
2040 ),
2041 ];
2042
2043 let test = T::new("root", components).build().await;
2044 let leaf_component = test
2045 .look_up_instance(&["mid", "leaf"].try_into().unwrap())
2046 .await
2047 .expect("leaf instance");
2048 let source = debug_route_sandbox_path(
2049 &leaf_component,
2050 &UseDecl::Runner(UseRunnerDecl {
2051 source: UseSource::Parent,
2052 source_name: "baz".parse().unwrap(),
2053 source_dictionary: Default::default(),
2054 }),
2055 )
2056 .await
2057 .expect("failed to route runner");
2058
2059 match source {
2060 capability_source::CapabilitySource::Component(
2061 capability_source::ComponentSource {
2062 capability:
2063 capability_source::ComponentCapability::Runner(RunnerDecl { name, .. }),
2064 moniker,
2065 },
2066 ) => {
2067 assert_eq!(name, "foo");
2068 assert_eq!(moniker, Moniker::root());
2069 }
2070 _ => panic!("unexpected source: {:?}", source),
2071 }
2072 }
2073
2074 pub async fn test_offer_directory_from_dictionary(&self) {
2075 let use_decl =
2076 UseBuilder::directory().name("baz").rights(fio::R_STAR_DIR).path("/foo").build();
2077 let components = vec![
2078 (
2079 "root",
2080 ComponentDeclBuilder::new()
2081 .capability(
2082 CapabilityBuilder::directory()
2083 .name("foo")
2084 .rights(fio::R_STAR_DIR)
2085 .path("/foo"),
2086 )
2087 .dictionary_default("dict")
2088 .offer(
2089 OfferBuilder::directory()
2090 .name("foo")
2091 .target_name("bar")
2092 .source(OfferSource::Self_)
2093 .target(OfferTarget::Capability("dict".parse().unwrap())),
2094 )
2095 .offer(
2096 OfferBuilder::dictionary()
2097 .name("dict")
2098 .source(OfferSource::Self_)
2099 .target_static_child("mid"),
2100 )
2101 .child_default("mid")
2102 .build(),
2103 ),
2104 (
2105 "mid",
2106 ComponentDeclBuilder::new()
2107 .offer(
2108 OfferBuilder::directory()
2109 .name("bar")
2110 .target_name("baz")
2111 .from_dictionary("dict")
2112 .source(OfferSource::Parent)
2113 .target_static_child("leaf"),
2114 )
2115 .child_default("leaf")
2116 .build(),
2117 ),
2118 ("leaf", ComponentDeclBuilder::new().use_(use_decl.clone()).build()),
2119 ];
2120
2121 let test = T::new("root", components).build().await;
2122 let leaf_component = test
2123 .look_up_instance(&["mid", "leaf"].try_into().unwrap())
2124 .await
2125 .expect("leaf instance");
2126
2127 let source = debug_route_sandbox_path(&leaf_component, &use_decl)
2128 .await
2129 .expect("failed to route resolver");
2130
2131 match source {
2132 capability_source::CapabilitySource::StorageBackingDirectory(
2133 capability_source::StorageBackingDirectorySource {
2134 capability:
2135 capability_source::ComponentCapability::Directory(DirectoryDecl {
2136 name, ..
2137 }),
2138 moniker,
2139 ..
2140 },
2141 ) => {
2142 assert_eq!(name, "foo");
2143 assert_eq!(moniker, Moniker::root());
2144 }
2145 _ => panic!("unexpected source: {:?}", source),
2146 }
2147 }
2148
2149 pub async fn test_use_config_from_dictionary(&self) {
2150 let components = vec![
2151 (
2152 "root",
2153 ComponentDeclBuilder::new()
2154 .capability(CapabilityBuilder::config().name("foo").value(10_i32.into()))
2155 .dictionary_default("dict")
2156 .offer(
2157 OfferBuilder::config()
2158 .name("foo")
2159 .target_name("bar")
2160 .source(OfferSource::Self_)
2161 .target(OfferTarget::Capability("dict".parse().unwrap())),
2162 )
2163 .offer(
2164 OfferBuilder::dictionary()
2165 .name("dict")
2166 .source(OfferSource::Self_)
2167 .target_static_child("leaf"),
2168 )
2169 .child_default("leaf")
2170 .build(),
2171 ),
2172 (
2173 "leaf",
2174 ComponentDeclBuilder::new()
2175 .use_(
2176 UseBuilder::config()
2177 .name("bar")
2178 .config_type(ConfigValueType::Int32)
2179 .from_dictionary("dict"),
2180 )
2181 .build(),
2182 ),
2183 ];
2184
2185 let test = T::new("root", components).build().await;
2186 let leaf_component =
2187 test.look_up_instance(&["leaf"].try_into().unwrap()).await.expect("leaf instance");
2188 let source = debug_route_sandbox_path(
2189 &leaf_component,
2190 &UseDecl::Config(Box::new(UseConfigurationDecl {
2191 source: UseSource::Parent,
2192 source_name: "bar".parse().unwrap(),
2193 target_name: "bar".parse().unwrap(),
2194 availability: Availability::Required,
2195 type_: ConfigValueType::Int32,
2196 default: None,
2197 source_dictionary: "dict".parse().unwrap(),
2198 })),
2199 )
2200 .await
2201 .expect("failed to route config");
2202
2203 match source {
2204 capability_source::CapabilitySource::Component(
2205 capability_source::ComponentSource {
2206 capability: capability_source::ComponentCapability::Config(_),
2207 moniker,
2208 },
2209 ) => {
2210 assert_eq!(moniker, moniker::Moniker::root());
2211 }
2212 _ => panic!("unexpected source: {:?}", source),
2213 }
2214 }
2215
2216 pub async fn test_offer_config_from_dictionary(&self) {
2217 let components = vec![
2218 (
2219 "root",
2220 ComponentDeclBuilder::new()
2221 .capability(CapabilityBuilder::config().name("foo").value(10_i32.into()))
2222 .dictionary_default("dict")
2223 .offer(
2224 OfferBuilder::config()
2225 .name("foo")
2226 .target_name("bar")
2227 .source(OfferSource::Self_)
2228 .target(OfferTarget::Capability("dict".parse().unwrap())),
2229 )
2230 .offer(
2231 OfferBuilder::dictionary()
2232 .name("dict")
2233 .source(OfferSource::Self_)
2234 .target_static_child("mid"),
2235 )
2236 .child_default("mid")
2237 .build(),
2238 ),
2239 (
2240 "mid",
2241 ComponentDeclBuilder::new()
2242 .offer(
2243 OfferBuilder::config()
2244 .name("bar")
2245 .target_name("baz")
2246 .from_dictionary("dict")
2247 .source(OfferSource::Parent)
2248 .target_static_child("leaf"),
2249 )
2250 .child_default("leaf")
2251 .build(),
2252 ),
2253 (
2254 "leaf",
2255 ComponentDeclBuilder::new()
2256 .use_(UseBuilder::config().name("baz").config_type(ConfigValueType::Int32))
2257 .build(),
2258 ),
2259 ];
2260
2261 let test = T::new("root", components).build().await;
2262 let leaf_component = test
2263 .look_up_instance(&["mid", "leaf"].try_into().unwrap())
2264 .await
2265 .expect("leaf instance");
2266 let source = debug_route_sandbox_path(
2267 &leaf_component,
2268 &UseDecl::Config(Box::new(UseConfigurationDecl {
2269 source: UseSource::Parent,
2270 source_name: "baz".parse().unwrap(),
2271 target_name: "baz".parse().unwrap(),
2272 availability: Availability::Required,
2273 type_: ConfigValueType::Int32,
2274 default: None,
2275 source_dictionary: Default::default(),
2276 })),
2277 )
2278 .await
2279 .expect("failed to route config");
2280
2281 match source {
2282 capability_source::CapabilitySource::Component(
2283 capability_source::ComponentSource {
2284 capability: capability_source::ComponentCapability::Config(_),
2285 moniker,
2286 },
2287 ) => {
2288 assert_eq!(moniker, moniker::Moniker::root());
2289 }
2290 _ => panic!("unexpected source: {:?}", source),
2291 }
2292 }
2293}