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![
317 (
318 "root",
319 ComponentDeclBuilder::new()
320 .capability(CapabilityBuilder::directory().name("bar_data").path("/data/foo"))
321 .dictionary_default("parent_dict")
322 .offer(
323 OfferBuilder::dictionary()
324 .name("parent_dict")
325 .source(OfferSource::Self_)
326 .target_static_child("leaf"),
327 )
328 .offer(
329 OfferBuilder::directory()
330 .name("bar_data")
331 .target_name("B")
332 .source(OfferSource::Self_)
333 .target(OfferTarget::Capability("parent_dict".parse().unwrap()))
334 .rights(fio::R_STAR_DIR),
335 )
336 .child_default("leaf")
337 .build(),
338 ),
339 (
340 "leaf",
341 ComponentDeclBuilder::new()
342 .capability(CapabilityBuilder::directory().name("foo_data").path("/data/foo"))
343 .dictionary_default("self_dict")
344 .offer(
345 OfferBuilder::directory()
346 .name("foo_data")
347 .target_name("A")
348 .source(OfferSource::Self_)
349 .target(OfferTarget::Capability("self_dict".parse().unwrap()))
350 .rights(fio::R_STAR_DIR),
351 )
352 .use_(
353 UseBuilder::directory()
354 .source(UseSource::Self_)
355 .name("A")
356 .from_dictionary("self_dict")
357 .path("/A"),
358 )
359 .use_(
360 UseBuilder::directory().name("B").from_dictionary("parent_dict").path("/B"),
361 )
362 .build(),
363 ),
364 ];
365
366 let test = T::new("root", components).build().await;
367 test.check_use(
368 "leaf".try_into().unwrap(),
369 CheckUse::Directory {
370 path: "/A".parse().unwrap(),
371 file: PathBuf::from("hippo"),
372 expected_res: ExpectedResult::Ok,
373 },
374 )
375 .await;
376 test.check_use(
377 "leaf".try_into().unwrap(),
378 CheckUse::Directory {
379 path: "/B".parse().unwrap(),
380 file: PathBuf::from("hippo"),
381 expected_res: ExpectedResult::Ok,
382 },
383 )
384 .await;
385 }
386
387 pub async fn test_expose_directory_from_dictionary(&self) {
388 let components = vec![
390 (
391 "root",
392 ComponentDeclBuilder::new()
393 .use_(UseBuilder::directory().source_static_child("mid").name("A").path("/A"))
394 .use_(UseBuilder::directory().source_static_child("mid").name("B").path("/B"))
395 .child_default("mid")
396 .build(),
397 ),
398 (
399 "mid",
400 ComponentDeclBuilder::new()
401 .capability(CapabilityBuilder::directory().name("foo_data").path("/data/foo"))
402 .dictionary_default("self_dict")
403 .offer(
404 OfferBuilder::directory()
405 .name("foo_data")
406 .target_name("A")
407 .source(OfferSource::Self_)
408 .target(OfferTarget::Capability("self_dict".parse().unwrap()))
409 .rights(fio::R_STAR_DIR),
410 )
411 .expose(
412 ExposeBuilder::directory()
413 .name("A")
414 .source(ExposeSource::Self_)
415 .from_dictionary("self_dict"),
416 )
417 .expose(
418 ExposeBuilder::directory()
419 .name("B")
420 .source_static_child("leaf")
421 .from_dictionary("child_dict"),
422 )
423 .child_default("leaf")
424 .build(),
425 ),
426 (
427 "leaf",
428 ComponentDeclBuilder::new()
429 .capability(CapabilityBuilder::directory().name("bar_data").path("/data/foo"))
430 .dictionary_default("child_dict")
431 .expose(
432 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
433 )
434 .offer(
435 OfferBuilder::directory()
436 .name("bar_data")
437 .target_name("B")
438 .source(OfferSource::Self_)
439 .target(OfferTarget::Capability("child_dict".parse().unwrap()))
440 .rights(fio::R_STAR_DIR),
441 )
442 .build(),
443 ),
444 ];
445
446 let test = T::new("root", components).build().await;
447 test.check_use(
448 ".".try_into().unwrap(),
449 CheckUse::Directory {
450 path: "/A".parse().unwrap(),
451 file: PathBuf::from("hippo"),
452 expected_res: ExpectedResult::Ok,
453 },
454 )
455 .await;
456 test.check_use(
457 ".".try_into().unwrap(),
458 CheckUse::Directory {
459 path: "/B".parse().unwrap(),
460 file: PathBuf::from("hippo"),
461 expected_res: ExpectedResult::Ok,
462 },
463 )
464 .await;
465 }
466
467 pub async fn test_use_protocol_from_nested_dictionary(&self) {
468 let components = vec![
471 (
472 "root",
473 ComponentDeclBuilder::new()
474 .protocol_default("foo")
475 .dictionary_default("nested")
476 .dictionary_default("parent_dict")
477 .offer(
478 OfferBuilder::protocol()
479 .name("foo")
480 .target_name("B")
481 .source(OfferSource::Self_)
482 .target(OfferTarget::Capability("nested".parse().unwrap())),
483 )
484 .offer(
485 OfferBuilder::dictionary()
486 .name("nested")
487 .source(OfferSource::Self_)
488 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
489 )
490 .offer(
491 OfferBuilder::dictionary()
492 .name("parent_dict")
493 .source(OfferSource::Self_)
494 .target_static_child("mid"),
495 )
496 .child_default("mid")
497 .build(),
498 ),
499 (
500 "mid",
501 ComponentDeclBuilder::new()
502 .protocol_default("foo")
503 .dictionary_default("nested")
504 .dictionary_default("self_dict")
505 .offer(
506 OfferBuilder::protocol()
507 .name("foo")
508 .target_name("A")
509 .source(OfferSource::Self_)
510 .target(OfferTarget::Capability("nested".parse().unwrap())),
511 )
512 .offer(
513 OfferBuilder::dictionary()
514 .name("nested")
515 .source(OfferSource::Self_)
516 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
517 )
518 .use_(
519 UseBuilder::protocol()
520 .source(UseSource::Self_)
521 .name("A")
522 .from_dictionary("self_dict/nested"),
523 )
524 .use_(UseBuilder::protocol().name("B").from_dictionary("parent_dict/nested"))
525 .use_(
526 UseBuilder::protocol()
527 .source_static_child("leaf")
528 .name("C")
529 .from_dictionary("child_dict/nested"),
530 )
531 .child_default("leaf")
532 .build(),
533 ),
534 (
535 "leaf",
536 ComponentDeclBuilder::new()
537 .protocol_default("foo")
538 .dictionary_default("nested")
539 .dictionary_default("child_dict")
540 .offer(
541 OfferBuilder::protocol()
542 .name("foo")
543 .target_name("C")
544 .source(OfferSource::Self_)
545 .target(OfferTarget::Capability("nested".parse().unwrap())),
546 )
547 .offer(
548 OfferBuilder::dictionary()
549 .name("nested")
550 .source(OfferSource::Self_)
551 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
552 )
553 .expose(
554 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
555 )
556 .build(),
557 ),
558 ];
559
560 let test = T::new("root", components).build().await;
561 for path in ["/svc/A", "/svc/B", "/svc/C"] {
562 test.check_use(
563 "mid".try_into().unwrap(),
564 CheckUse::Protocol {
565 path: path.parse().unwrap(),
566 expected_res: ExpectedResult::Ok,
567 },
568 )
569 .await;
570 }
571 }
572
573 pub async fn test_offer_protocol_from_dictionary(&self) {
574 let components = vec![
576 (
577 "root",
578 ComponentDeclBuilder::new()
579 .protocol_default("foo")
580 .dictionary_default("parent_dict")
581 .offer(
582 OfferBuilder::protocol()
583 .name("foo")
584 .target_name("B")
585 .source(OfferSource::Self_)
586 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
587 )
588 .offer(
589 OfferBuilder::dictionary()
590 .name("parent_dict")
591 .source(OfferSource::Self_)
592 .target_static_child("mid"),
593 )
594 .child_default("mid")
595 .build(),
596 ),
597 (
598 "mid",
599 ComponentDeclBuilder::new()
600 .protocol_default("foo")
601 .dictionary_default("self_dict")
602 .offer(
603 OfferBuilder::protocol()
604 .name("A")
605 .target_name("A_svc")
606 .source(OfferSource::Self_)
607 .target_static_child("leaf")
608 .from_dictionary("self_dict"),
609 )
610 .offer(
611 OfferBuilder::protocol()
612 .name("foo")
613 .target_name("A")
614 .source(OfferSource::Self_)
615 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
616 )
617 .offer(
618 OfferBuilder::protocol()
619 .name("B")
620 .target_name("B_svc")
621 .source(OfferSource::Parent)
622 .target_static_child("leaf")
623 .from_dictionary("parent_dict"),
624 )
625 .offer(
626 OfferBuilder::protocol()
627 .name("C")
628 .target_name("C_svc")
629 .source_static_child("provider")
630 .target_static_child("leaf")
631 .from_dictionary("child_dict"),
632 )
633 .child_default("provider")
634 .child_default("leaf")
635 .build(),
636 ),
637 (
638 "provider",
639 ComponentDeclBuilder::new()
640 .protocol_default("foo")
641 .dictionary_default("child_dict")
642 .offer(
643 OfferBuilder::protocol()
644 .name("foo")
645 .target_name("C")
646 .source(OfferSource::Self_)
647 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
648 )
649 .expose(
650 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
651 )
652 .build(),
653 ),
654 (
655 "leaf",
656 ComponentDeclBuilder::new()
657 .use_(UseBuilder::protocol().name("A_svc").path("/svc/A"))
658 .use_(UseBuilder::protocol().name("B_svc").path("/svc/B"))
659 .use_(UseBuilder::protocol().name("C_svc").path("/svc/C"))
660 .build(),
661 ),
662 ];
663
664 let test = T::new("root", components).build().await;
665 for path in ["/svc/A", "/svc/B", "/svc/C"] {
666 test.check_use(
667 "mid/leaf".try_into().unwrap(),
668 CheckUse::Protocol {
669 path: path.parse().unwrap(),
670 expected_res: ExpectedResult::Ok,
671 },
672 )
673 .await;
674 }
675 }
676
677 pub async fn test_offer_protocol_from_dictionary_not_found(&self) {
678 let components = vec![
681 (
682 "root",
683 ComponentDeclBuilder::new()
684 .protocol_default("foo")
685 .dictionary_default("dict")
686 .offer(
687 OfferBuilder::protocol()
688 .name("foo")
689 .target_name("B")
690 .source(OfferSource::Self_)
691 .target(OfferTarget::Capability("dict".parse().unwrap())),
692 )
693 .offer(
694 OfferBuilder::dictionary()
695 .name("dict")
696 .source(OfferSource::Self_)
697 .target_static_child("mid"),
698 )
699 .child_default("mid")
700 .build(),
701 ),
702 (
703 "mid",
704 ComponentDeclBuilder::new()
705 .offer(
706 OfferBuilder::protocol()
707 .name("A")
708 .target_name("A_svc")
709 .source(OfferSource::Parent)
710 .target_static_child("leaf")
711 .from_dictionary("dict"),
712 )
713 .child_default("leaf")
714 .build(),
715 ),
716 (
717 "leaf",
718 ComponentDeclBuilder::new()
719 .use_(UseBuilder::protocol().name("A_svc").path("/svc/A"))
720 .build(),
721 ),
722 ];
723
724 let test = T::new("root", components).build().await;
725 test.check_use(
726 "mid/leaf".try_into().unwrap(),
727 CheckUse::Protocol {
728 path: "/svc/A".parse().unwrap(),
729 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
730 },
731 )
732 .await;
733 }
734
735 pub async fn test_offer_protocol_from_dictionary_to_dictionary(&self) {
736 let components = vec![
737 (
738 "root",
739 ComponentDeclBuilder::new()
740 .dictionary_default("dict1")
741 .dictionary_default("dict2")
742 .offer(
743 OfferBuilder::protocol()
744 .name("foo")
745 .target_name("A")
746 .source_static_child("provider")
747 .target(OfferTarget::Capability("dict1".parse().unwrap())),
748 )
749 .offer(
750 OfferBuilder::protocol()
751 .name("A")
752 .target_name("A")
753 .from_dictionary("dict1")
754 .source(OfferSource::Self_)
755 .target(OfferTarget::Capability("dict2".parse().unwrap())),
756 )
757 .offer(
758 OfferBuilder::dictionary()
759 .name("dict2")
760 .source(OfferSource::Self_)
761 .target_static_child("leaf"),
762 )
763 .child_default("provider")
764 .child_default("leaf")
765 .build(),
766 ),
767 (
768 "provider",
769 ComponentDeclBuilder::new()
770 .protocol_default("foo")
771 .expose(ExposeBuilder::protocol().name("foo").source(ExposeSource::Self_))
772 .build(),
773 ),
774 (
775 "leaf",
776 ComponentDeclBuilder::new()
777 .use_(UseBuilder::protocol().name("A").from_dictionary("dict2").path("/svc/A"))
778 .build(),
779 ),
780 ];
781
782 let test = T::new("root", components).build().await;
783 test.check_use(
784 "leaf".try_into().unwrap(),
785 CheckUse::Protocol {
786 path: "/svc/A".parse().unwrap(),
787 expected_res: ExpectedResult::Ok,
788 },
789 )
790 .await;
791 }
792
793 pub async fn test_offer_protocol_from_nested_dictionary(&self) {
794 let components = vec![
797 (
798 "root",
799 ComponentDeclBuilder::new()
800 .protocol_default("foo")
801 .dictionary_default("nested")
802 .dictionary_default("parent_dict")
803 .offer(
804 OfferBuilder::protocol()
805 .name("foo")
806 .target_name("B")
807 .source(OfferSource::Self_)
808 .target(OfferTarget::Capability("nested".parse().unwrap())),
809 )
810 .offer(
811 OfferBuilder::dictionary()
812 .name("nested")
813 .source(OfferSource::Self_)
814 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
815 )
816 .offer(
817 OfferBuilder::dictionary()
818 .name("parent_dict")
819 .source(OfferSource::Self_)
820 .target_static_child("mid"),
821 )
822 .child_default("mid")
823 .build(),
824 ),
825 (
826 "mid",
827 ComponentDeclBuilder::new()
828 .protocol_default("foo")
829 .dictionary_default("self_dict")
830 .dictionary_default("nested")
831 .offer(
832 OfferBuilder::protocol()
833 .name("A")
834 .target_name("A_svc")
835 .source(OfferSource::Self_)
836 .target_static_child("leaf")
837 .from_dictionary("self_dict/nested"),
838 )
839 .offer(
840 OfferBuilder::protocol()
841 .name("foo")
842 .target_name("A")
843 .source(OfferSource::Self_)
844 .target(OfferTarget::Capability("nested".parse().unwrap())),
845 )
846 .offer(
847 OfferBuilder::dictionary()
848 .name("nested")
849 .source(OfferSource::Self_)
850 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
851 )
852 .offer(
853 OfferBuilder::protocol()
854 .name("B")
855 .target_name("B_svc")
856 .source(OfferSource::Parent)
857 .target_static_child("leaf")
858 .from_dictionary("parent_dict/nested"),
859 )
860 .offer(
861 OfferBuilder::protocol()
862 .name("C")
863 .target_name("C_svc")
864 .source_static_child("provider")
865 .target_static_child("leaf")
866 .from_dictionary("child_dict/nested"),
867 )
868 .child_default("provider")
869 .child_default("leaf")
870 .build(),
871 ),
872 (
873 "provider",
874 ComponentDeclBuilder::new()
875 .protocol_default("foo")
876 .dictionary_default("child_dict")
877 .dictionary_default("nested")
878 .offer(
879 OfferBuilder::protocol()
880 .name("foo")
881 .target_name("C")
882 .source(OfferSource::Self_)
883 .target(OfferTarget::Capability("nested".parse().unwrap())),
884 )
885 .offer(
886 OfferBuilder::dictionary()
887 .name("nested")
888 .source(OfferSource::Self_)
889 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
890 )
891 .expose(
892 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
893 )
894 .build(),
895 ),
896 (
897 "leaf",
898 ComponentDeclBuilder::new()
899 .use_(UseBuilder::protocol().name("A_svc").path("/svc/A"))
900 .use_(UseBuilder::protocol().name("B_svc").path("/svc/B"))
901 .use_(UseBuilder::protocol().name("C_svc").path("/svc/C"))
902 .build(),
903 ),
904 ];
905
906 let test = T::new("root", components).build().await;
907 for path in ["/svc/A", "/svc/B", "/svc/C"] {
908 test.check_use(
909 "mid/leaf".try_into().unwrap(),
910 CheckUse::Protocol {
911 path: path.parse().unwrap(),
912 expected_res: ExpectedResult::Ok,
913 },
914 )
915 .await;
916 }
917 }
918
919 pub async fn test_expose_protocol_from_dictionary(&self) {
920 let components = vec![
922 (
923 "root",
924 ComponentDeclBuilder::new()
925 .use_(
926 UseBuilder::protocol()
927 .source_static_child("mid")
928 .name("A_svc")
929 .path("/svc/A"),
930 )
931 .use_(
932 UseBuilder::protocol()
933 .source_static_child("mid")
934 .name("B_svc")
935 .path("/svc/B"),
936 )
937 .child_default("mid")
938 .build(),
939 ),
940 (
941 "mid",
942 ComponentDeclBuilder::new()
943 .protocol_default("foo")
944 .dictionary_default("self_dict")
945 .expose(
946 ExposeBuilder::protocol()
947 .name("A")
948 .target_name("A_svc")
949 .from_dictionary("self_dict")
950 .source(ExposeSource::Self_),
951 )
952 .expose(
953 ExposeBuilder::protocol()
954 .name("B")
955 .target_name("B_svc")
956 .from_dictionary("child_dict")
957 .source_static_child("leaf"),
958 )
959 .offer(
960 OfferBuilder::protocol()
961 .name("foo")
962 .target_name("A")
963 .source(OfferSource::Self_)
964 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
965 )
966 .child_default("leaf")
967 .build(),
968 ),
969 (
970 "leaf",
971 ComponentDeclBuilder::new()
972 .protocol_default("foo")
973 .dictionary_default("child_dict")
974 .offer(
975 OfferBuilder::protocol()
976 .name("foo")
977 .target_name("B")
978 .source(OfferSource::Self_)
979 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
980 )
981 .expose(
982 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
983 )
984 .build(),
985 ),
986 ];
987
988 let test = T::new("root", components).build().await;
989 for path in ["/svc/A", "/svc/B"] {
990 test.check_use(
991 ".".try_into().unwrap(),
992 CheckUse::Protocol {
993 path: path.parse().unwrap(),
994 expected_res: ExpectedResult::Ok,
995 },
996 )
997 .await;
998 }
999 }
1000
1001 pub async fn test_expose_protocol_from_dictionary_not_found(&self) {
1002 let components = vec![
1004 (
1005 "root",
1006 ComponentDeclBuilder::new()
1007 .use_(
1008 UseBuilder::protocol()
1009 .source_static_child("mid")
1010 .name("A_svc")
1011 .path("/svc/A"),
1012 )
1013 .child_default("mid")
1014 .build(),
1015 ),
1016 (
1017 "mid",
1018 ComponentDeclBuilder::new()
1019 .expose(
1020 ExposeBuilder::protocol()
1021 .name("A")
1022 .target_name("A_svc")
1023 .source(ExposeSource::Self_)
1024 .from_dictionary("dict")
1025 .build(),
1026 )
1027 .child_default("leaf")
1028 .build(),
1029 ),
1030 (
1031 "leaf",
1032 ComponentDeclBuilder::new()
1033 .protocol_default("foo")
1034 .dictionary_default("dict")
1035 .offer(
1036 OfferBuilder::protocol()
1037 .name("foo")
1038 .target_name("B")
1039 .source(OfferSource::Self_)
1040 .target(OfferTarget::Capability("dict".parse().unwrap())),
1041 )
1042 .expose(ExposeBuilder::dictionary().name("dict").source(ExposeSource::Self_))
1043 .build(),
1044 ),
1045 ];
1046
1047 let test = T::new("root", components).build().await;
1048 test.check_use(
1049 ".".try_into().unwrap(),
1050 CheckUse::Protocol {
1051 path: "/svc/A".parse().unwrap(),
1052 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1053 },
1054 )
1055 .await;
1056 }
1057
1058 pub async fn test_expose_protocol_from_nested_dictionary(&self) {
1059 let components = vec![
1062 (
1063 "root",
1064 ComponentDeclBuilder::new()
1065 .use_(
1066 UseBuilder::protocol()
1067 .source_static_child("mid")
1068 .name("A_svc")
1069 .path("/svc/A"),
1070 )
1071 .use_(
1072 UseBuilder::protocol()
1073 .source_static_child("mid")
1074 .name("B_svc")
1075 .path("/svc/B"),
1076 )
1077 .child_default("mid")
1078 .build(),
1079 ),
1080 (
1081 "mid",
1082 ComponentDeclBuilder::new()
1083 .protocol_default("foo")
1084 .dictionary_default("self_dict")
1085 .dictionary_default("nested")
1086 .expose(
1087 ExposeBuilder::protocol()
1088 .name("A")
1089 .target_name("A_svc")
1090 .from_dictionary("self_dict/nested")
1091 .source(ExposeSource::Self_),
1092 )
1093 .expose(
1094 ExposeBuilder::protocol()
1095 .name("B")
1096 .target_name("B_svc")
1097 .from_dictionary("child_dict/nested")
1098 .source_static_child("leaf"),
1099 )
1100 .offer(
1101 OfferBuilder::protocol()
1102 .name("foo")
1103 .target_name("A")
1104 .source(OfferSource::Self_)
1105 .target(OfferTarget::Capability("nested".parse().unwrap())),
1106 )
1107 .offer(
1108 OfferBuilder::dictionary()
1109 .name("nested")
1110 .source(OfferSource::Self_)
1111 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
1112 )
1113 .child_default("leaf")
1114 .build(),
1115 ),
1116 (
1117 "leaf",
1118 ComponentDeclBuilder::new()
1119 .protocol_default("foo")
1120 .dictionary_default("child_dict")
1121 .dictionary_default("nested")
1122 .offer(
1123 OfferBuilder::dictionary()
1124 .name("nested")
1125 .source(OfferSource::Self_)
1126 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
1127 )
1128 .offer(
1129 OfferBuilder::protocol()
1130 .name("foo")
1131 .target_name("B")
1132 .source(OfferSource::Self_)
1133 .target(OfferTarget::Capability("nested".parse().unwrap())),
1134 )
1135 .expose(
1136 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
1137 )
1138 .build(),
1139 ),
1140 ];
1141
1142 let test = T::new("root", components).build().await;
1143 for path in ["/svc/A", "/svc/B"] {
1144 test.check_use(
1145 ".".try_into().unwrap(),
1146 CheckUse::Protocol {
1147 path: path.parse().unwrap(),
1148 expected_res: ExpectedResult::Ok,
1149 },
1150 )
1151 .await;
1152 }
1153 }
1154
1155 pub async fn test_dictionary_in_exposed_dir(&self) {
1156 let components = vec![
1158 (
1159 "root",
1160 ComponentDeclBuilder::new()
1161 .protocol_default("foo")
1162 .dictionary_default("self_dict")
1163 .expose(
1164 ExposeBuilder::dictionary().name("self_dict").source(ExposeSource::Self_),
1165 )
1166 .expose(
1167 ExposeBuilder::dictionary().name("child_dict").source_static_child("leaf"),
1168 )
1169 .offer(
1170 OfferBuilder::protocol()
1171 .name("foo")
1172 .target_name("A")
1173 .source(OfferSource::Self_)
1174 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
1175 )
1176 .child_default("leaf")
1177 .build(),
1178 ),
1179 (
1180 "leaf",
1181 ComponentDeclBuilder::new()
1182 .protocol_default("foo")
1183 .dictionary_default("nested")
1184 .dictionary_default("child_dict")
1185 .offer(
1186 OfferBuilder::dictionary()
1187 .name("nested")
1188 .source(OfferSource::Self_)
1189 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
1190 )
1191 .offer(
1192 OfferBuilder::protocol()
1193 .name("foo")
1194 .target_name("B")
1195 .source(OfferSource::Self_)
1196 .target(OfferTarget::Capability("nested".parse().unwrap())),
1197 )
1198 .expose(
1199 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
1200 )
1201 .build(),
1202 ),
1203 ];
1204
1205 let test = T::new("root", components).build().await;
1206 for path in ["/self_dict/A", "/child_dict/nested/B"] {
1208 test.check_use_exposed_dir(
1209 ".".try_into().unwrap(),
1210 CheckUse::Protocol {
1211 path: path.parse().unwrap(),
1212 expected_res: ExpectedResult::Ok,
1213 },
1214 )
1215 .await;
1216 }
1217 }
1218
1219 pub async fn test_offer_dictionary_to_dictionary(&self) {
1220 let components = vec![
1222 (
1223 "root",
1224 ComponentDeclBuilder::new()
1225 .protocol_default("foo")
1226 .dictionary_default("parent_dict")
1227 .offer(
1228 OfferBuilder::protocol()
1229 .name("foo")
1230 .target_name("B")
1231 .source(OfferSource::Self_)
1232 .target(OfferTarget::Capability("parent_dict".parse().unwrap())),
1233 )
1234 .offer(
1235 OfferBuilder::dictionary()
1236 .name("parent_dict")
1237 .source(OfferSource::Self_)
1238 .target_static_child("mid"),
1239 )
1240 .child_default("mid")
1241 .build(),
1242 ),
1243 (
1244 "mid",
1245 ComponentDeclBuilder::new()
1246 .protocol_default("foo")
1247 .dictionary_default("self_dict")
1248 .dictionary_default("root_dict")
1249 .offer(
1250 OfferBuilder::protocol()
1251 .name("foo")
1252 .target_name("A")
1253 .source(OfferSource::Self_)
1254 .target(OfferTarget::Capability("self_dict".parse().unwrap())),
1255 )
1256 .offer(
1257 OfferBuilder::dictionary()
1258 .name("self_dict")
1259 .source(OfferSource::Self_)
1260 .target(OfferTarget::Capability("root_dict".parse().unwrap())),
1261 )
1262 .offer(
1263 OfferBuilder::dictionary()
1264 .name("parent_dict")
1265 .source(OfferSource::Parent)
1266 .target(OfferTarget::Capability("root_dict".parse().unwrap())),
1267 )
1268 .offer(
1269 OfferBuilder::dictionary()
1270 .name("child_dict")
1271 .source_static_child("leaf")
1272 .target(OfferTarget::Capability("root_dict".parse().unwrap())),
1273 )
1274 .use_(
1275 UseBuilder::protocol()
1276 .source(UseSource::Self_)
1277 .name("A")
1278 .from_dictionary("root_dict/self_dict"),
1279 )
1280 .use_(
1281 UseBuilder::protocol()
1282 .source(UseSource::Self_)
1283 .name("B")
1284 .from_dictionary("root_dict/parent_dict"),
1285 )
1286 .use_(
1287 UseBuilder::protocol()
1288 .source(UseSource::Self_)
1289 .name("C")
1290 .from_dictionary("root_dict/child_dict"),
1291 )
1292 .child_default("leaf")
1293 .build(),
1294 ),
1295 (
1296 "leaf",
1297 ComponentDeclBuilder::new()
1298 .protocol_default("foo")
1299 .dictionary_default("child_dict")
1300 .offer(
1301 OfferBuilder::protocol()
1302 .name("foo")
1303 .target_name("C")
1304 .source(OfferSource::Self_)
1305 .target(OfferTarget::Capability("child_dict".parse().unwrap())),
1306 )
1307 .expose(
1308 ExposeBuilder::dictionary().name("child_dict").source(ExposeSource::Self_),
1309 )
1310 .build(),
1311 ),
1312 ];
1313
1314 let test = T::new("root", components).build().await;
1315 for path in ["/svc/A", "/svc/B", "/svc/C"] {
1316 test.check_use(
1317 "mid".try_into().unwrap(),
1318 CheckUse::Protocol {
1319 path: path.parse().unwrap(),
1320 expected_res: ExpectedResult::Ok,
1321 },
1322 )
1323 .await;
1324 }
1325 }
1326
1327 pub async fn test_use_from_dictionary_availability_attenuated(&self) {
1328 let components = vec![
1332 (
1333 "root",
1334 ComponentDeclBuilder::new()
1335 .protocol_default("foo")
1336 .protocol_default("bar")
1337 .dictionary_default("nested")
1338 .dictionary_default("dict")
1339 .offer(
1340 OfferBuilder::protocol()
1341 .name("foo")
1342 .target_name("A")
1343 .source(OfferSource::Self_)
1344 .target(OfferTarget::Capability("dict".parse().unwrap())),
1345 )
1346 .offer(
1347 OfferBuilder::protocol()
1348 .name("bar")
1349 .target_name("B")
1350 .source(OfferSource::Self_)
1351 .target(OfferTarget::Capability("nested".parse().unwrap())),
1352 )
1353 .offer(
1354 OfferBuilder::dictionary()
1355 .name("nested")
1356 .source(OfferSource::Self_)
1357 .target(OfferTarget::Capability("dict".parse().unwrap())),
1358 )
1359 .offer(
1360 OfferBuilder::dictionary()
1361 .name("dict")
1362 .source(OfferSource::Self_)
1363 .target_static_child("leaf"),
1364 )
1365 .child_default("leaf")
1366 .build(),
1367 ),
1368 (
1369 "leaf",
1370 ComponentDeclBuilder::new()
1371 .use_(
1372 UseBuilder::protocol()
1373 .name("A")
1374 .from_dictionary("dict")
1375 .availability(Availability::Optional),
1376 )
1377 .use_(
1378 UseBuilder::protocol()
1379 .name("B")
1380 .from_dictionary("dict/nested")
1381 .availability(Availability::Optional),
1382 )
1383 .build(),
1384 ),
1385 ];
1386
1387 let test = T::new("root", components).build().await;
1388 test.check_use(
1389 "leaf".try_into().unwrap(),
1390 CheckUse::Protocol {
1391 path: "/svc/A".parse().unwrap(),
1392 expected_res: ExpectedResult::Ok,
1393 },
1394 )
1395 .await;
1396 test.check_use(
1397 "leaf".try_into().unwrap(),
1398 CheckUse::Protocol {
1399 path: "/svc/B".parse().unwrap(),
1400 expected_res: ExpectedResult::Ok,
1401 },
1402 )
1403 .await;
1404 }
1405
1406 pub async fn test_use_from_dictionary_availability_invalid(&self) {
1407 let components = vec![
1412 (
1413 "root",
1414 ComponentDeclBuilder::new()
1415 .protocol_default("foo")
1416 .protocol_default("bar")
1417 .protocol_default("qux")
1418 .dictionary_default("required_dict")
1419 .dictionary_default("optional_dict")
1420 .dictionary_default("nested")
1421 .dictionary_default("dict_with_optional_nested")
1422 .offer(
1423 OfferBuilder::protocol()
1424 .name("foo")
1425 .target_name("A")
1426 .source(OfferSource::Self_)
1427 .target(OfferTarget::Capability("required_dict".parse().unwrap()))
1428 .availability(Availability::Optional),
1429 )
1430 .offer(
1431 OfferBuilder::protocol()
1432 .name("bar")
1433 .target_name("B")
1434 .source(OfferSource::Self_)
1435 .target(OfferTarget::Capability("optional_dict".parse().unwrap())),
1436 )
1437 .offer(
1438 OfferBuilder::protocol()
1439 .name("qux")
1440 .target_name("C")
1441 .source(OfferSource::Self_)
1442 .target(OfferTarget::Capability("nested".parse().unwrap())),
1443 )
1444 .offer(
1445 OfferBuilder::dictionary()
1446 .name("nested")
1447 .source(OfferSource::Self_)
1448 .target(OfferTarget::Capability(
1449 "dict_with_optional_nested".parse().unwrap(),
1450 ))
1451 .availability(Availability::Optional),
1452 )
1453 .offer(
1454 OfferBuilder::dictionary()
1455 .name("required_dict")
1456 .source(OfferSource::Self_)
1457 .target_static_child("leaf"),
1458 )
1459 .offer(
1460 OfferBuilder::dictionary()
1461 .name("optional_dict")
1462 .source(OfferSource::Self_)
1463 .target_static_child("leaf")
1464 .availability(Availability::Optional),
1465 )
1466 .offer(
1467 OfferBuilder::dictionary()
1468 .name("dict_with_optional_nested")
1469 .source(OfferSource::Self_)
1470 .target_static_child("leaf"),
1471 )
1472 .child_default("leaf")
1473 .build(),
1474 ),
1475 (
1476 "leaf",
1477 ComponentDeclBuilder::new()
1478 .use_(UseBuilder::protocol().name("A").from_dictionary("required_dict"))
1479 .use_(UseBuilder::protocol().name("B").from_dictionary("optional_dict"))
1480 .use_(
1481 UseBuilder::protocol()
1482 .name("C")
1483 .from_dictionary("dict_with_optional_nested/nested"),
1484 )
1485 .build(),
1486 ),
1487 ];
1488
1489 let test = T::new("root", components).build().await;
1490 test.check_use(
1491 "leaf".try_into().unwrap(),
1492 CheckUse::Protocol {
1493 path: "/svc/A".parse().unwrap(),
1494 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1495 },
1496 )
1497 .await;
1498 test.check_use(
1499 "leaf".try_into().unwrap(),
1500 CheckUse::Protocol {
1501 path: "/svc/B".parse().unwrap(),
1502 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1503 },
1504 )
1505 .await;
1506 test.check_use(
1507 "leaf".try_into().unwrap(),
1508 CheckUse::Protocol {
1509 path: "/svc/C".parse().unwrap(),
1510 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1511 },
1512 )
1513 .await;
1514 }
1515
1516 pub async fn test_offer_from_dictionary_availability_attenuated(&self) {
1517 let components = vec![
1521 (
1522 "root",
1523 ComponentDeclBuilder::new()
1524 .protocol_default("foo")
1525 .protocol_default("bar")
1526 .dictionary_default("nested")
1527 .dictionary_default("dict")
1528 .offer(
1529 OfferBuilder::protocol()
1530 .name("foo")
1531 .target_name("A")
1532 .source(OfferSource::Self_)
1533 .target(OfferTarget::Capability("dict".parse().unwrap())),
1534 )
1535 .offer(
1536 OfferBuilder::protocol()
1537 .name("bar")
1538 .target_name("B")
1539 .source(OfferSource::Self_)
1540 .target(OfferTarget::Capability("nested".parse().unwrap())),
1541 )
1542 .offer(
1543 OfferBuilder::dictionary()
1544 .name("nested")
1545 .source(OfferSource::Self_)
1546 .target(OfferTarget::Capability("dict".parse().unwrap())),
1547 )
1548 .offer(
1549 OfferBuilder::protocol()
1550 .name("A")
1551 .source(OfferSource::Self_)
1552 .target_static_child("leaf")
1553 .from_dictionary("dict"),
1554 )
1555 .offer(
1556 OfferBuilder::protocol()
1557 .name("B")
1558 .source(OfferSource::Self_)
1559 .target_static_child("leaf")
1560 .from_dictionary("dict/nested"),
1561 )
1562 .child_default("leaf")
1563 .build(),
1564 ),
1565 (
1566 "leaf",
1567 ComponentDeclBuilder::new()
1568 .use_(UseBuilder::protocol().name("A").availability(Availability::Optional))
1569 .use_(UseBuilder::protocol().name("B").availability(Availability::Optional))
1570 .build(),
1571 ),
1572 ];
1573
1574 let test = T::new("root", components).build().await;
1575 test.check_use(
1576 "leaf".try_into().unwrap(),
1577 CheckUse::Protocol {
1578 path: "/svc/A".parse().unwrap(),
1579 expected_res: ExpectedResult::Ok,
1580 },
1581 )
1582 .await;
1583 test.check_use(
1584 "leaf".try_into().unwrap(),
1585 CheckUse::Protocol {
1586 path: "/svc/B".parse().unwrap(),
1587 expected_res: ExpectedResult::Ok,
1588 },
1589 )
1590 .await;
1591 }
1592
1593 pub async fn test_offer_from_dictionary_availability_invalid(&self) {
1594 let components = vec![
1599 (
1600 "root",
1601 ComponentDeclBuilder::new()
1602 .protocol_default("foo")
1603 .protocol_default("bar")
1604 .protocol_default("qux")
1605 .dictionary_default("required_dict")
1606 .dictionary_default("optional_dict")
1607 .dictionary_default("nested")
1608 .dictionary_default("dict_with_optional_nested")
1609 .offer(
1610 OfferBuilder::protocol()
1611 .name("foo")
1612 .target_name("A")
1613 .source(OfferSource::Self_)
1614 .target(OfferTarget::Capability("required_dict".parse().unwrap()))
1615 .availability(Availability::Optional),
1616 )
1617 .offer(
1618 OfferBuilder::protocol()
1619 .name("bar")
1620 .target_name("B")
1621 .source(OfferSource::Self_)
1622 .target(OfferTarget::Capability("optional_dict".parse().unwrap())),
1623 )
1624 .offer(
1625 OfferBuilder::protocol()
1626 .name("qux")
1627 .target_name("C")
1628 .source(OfferSource::Self_)
1629 .target(OfferTarget::Capability("nested".parse().unwrap())),
1630 )
1631 .offer(
1632 OfferBuilder::dictionary()
1633 .name("nested")
1634 .source(OfferSource::Self_)
1635 .target(OfferTarget::Capability(
1636 "dict_with_optional_nested".parse().unwrap(),
1637 ))
1638 .availability(Availability::Optional),
1639 )
1640 .offer(
1641 OfferBuilder::dictionary()
1642 .name("required_dict")
1643 .source(OfferSource::Self_)
1644 .target_static_child("mid"),
1645 )
1646 .offer(
1647 OfferBuilder::dictionary()
1648 .name("optional_dict")
1649 .source(OfferSource::Self_)
1650 .target_static_child("mid")
1651 .availability(Availability::Optional),
1652 )
1653 .offer(
1654 OfferBuilder::dictionary()
1655 .name("dict_with_optional_nested")
1656 .source(OfferSource::Self_)
1657 .target_static_child("mid"),
1658 )
1659 .child_default("mid")
1660 .build(),
1661 ),
1662 (
1663 "mid",
1664 ComponentDeclBuilder::new()
1665 .offer(
1666 OfferBuilder::protocol()
1667 .name("A")
1668 .source(OfferSource::Parent)
1669 .target_static_child("leaf")
1670 .from_dictionary("required_dict"),
1671 )
1672 .offer(
1673 OfferBuilder::protocol()
1674 .name("B")
1675 .source(OfferSource::Parent)
1676 .target_static_child("leaf")
1677 .from_dictionary("optional_dict"),
1678 )
1679 .offer(
1680 OfferBuilder::protocol()
1681 .name("C")
1682 .source(OfferSource::Parent)
1683 .target_static_child("leaf")
1684 .from_dictionary("dict_with_optional_nested/nested"),
1685 )
1686 .child_default("leaf")
1687 .build(),
1688 ),
1689 (
1690 "leaf",
1691 ComponentDeclBuilder::new()
1692 .use_(UseBuilder::protocol().name("A"))
1693 .use_(UseBuilder::protocol().name("B"))
1694 .use_(UseBuilder::protocol().name("C"))
1695 .build(),
1696 ),
1697 ];
1698
1699 let test = T::new("root", components).build().await;
1700 test.check_use(
1701 "mid/leaf".try_into().unwrap(),
1702 CheckUse::Protocol {
1703 path: "/svc/A".parse().unwrap(),
1704 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1705 },
1706 )
1707 .await;
1708 test.check_use(
1709 "mid/leaf".try_into().unwrap(),
1710 CheckUse::Protocol {
1711 path: "/svc/B".parse().unwrap(),
1712 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1713 },
1714 )
1715 .await;
1716 test.check_use(
1717 "mid/leaf".try_into().unwrap(),
1718 CheckUse::Protocol {
1719 path: "/svc/C".parse().unwrap(),
1720 expected_res: ExpectedResult::Err(Status::NOT_FOUND),
1721 },
1722 )
1723 .await;
1724 }
1725
1726 pub async fn test_expose_from_dictionary_availability_attenuated(&self) {
1727 let components = vec![
1731 (
1732 "root",
1733 ComponentDeclBuilder::new()
1734 .use_(
1735 UseBuilder::protocol()
1736 .source_static_child("leaf")
1737 .name("A")
1738 .availability(Availability::Optional),
1739 )
1740 .use_(
1741 UseBuilder::protocol()
1742 .source_static_child("leaf")
1743 .name("B")
1744 .availability(Availability::Optional),
1745 )
1746 .child_default("leaf")
1747 .build(),
1748 ),
1749 (
1750 "leaf",
1751 ComponentDeclBuilder::new()
1752 .protocol_default("foo")
1753 .protocol_default("bar")
1754 .dictionary_default("nested")
1755 .dictionary_default("dict")
1756 .offer(
1757 OfferBuilder::protocol()
1758 .name("foo")
1759 .target_name("A")
1760 .source(OfferSource::Self_)
1761 .target(OfferTarget::Capability("dict".parse().unwrap())),
1762 )
1763 .offer(
1764 OfferBuilder::protocol()
1765 .name("bar")
1766 .target_name("B")
1767 .source(OfferSource::Self_)
1768 .target(OfferTarget::Capability("nested".parse().unwrap())),
1769 )
1770 .offer(
1771 OfferBuilder::dictionary()
1772 .name("nested")
1773 .source(OfferSource::Self_)
1774 .target(OfferTarget::Capability("dict".parse().unwrap())),
1775 )
1776 .expose(
1777 ExposeBuilder::protocol()
1778 .name("A")
1779 .from_dictionary("dict")
1780 .source(ExposeSource::Self_),
1781 )
1782 .expose(
1783 ExposeBuilder::protocol()
1784 .name("B")
1785 .from_dictionary("dict/nested")
1786 .source(ExposeSource::Self_),
1787 )
1788 .build(),
1789 ),
1790 ];
1791
1792 let test = T::new("root", components).build().await;
1793 test.check_use(
1794 ".".try_into().unwrap(),
1795 CheckUse::Protocol {
1796 path: "/svc/A".parse().unwrap(),
1797 expected_res: ExpectedResult::Ok,
1798 },
1799 )
1800 .await;
1801 test.check_use(
1802 ".".try_into().unwrap(),
1803 CheckUse::Protocol {
1804 path: "/svc/B".parse().unwrap(),
1805 expected_res: ExpectedResult::Ok,
1806 },
1807 )
1808 .await;
1809 }
1810
1811 pub async fn test_expose_from_dictionary_availability_invalid(&self) {
1812 let components = vec![
1817 (
1818 "root",
1819 ComponentDeclBuilder::new()
1820 .use_(UseBuilder::protocol().source_static_child("mid").name("A"))
1821 .use_(UseBuilder::protocol().source_static_child("mid").name("B"))
1822 .use_(UseBuilder::protocol().source_static_child("mid").name("C"))
1823 .child_default("mid")
1824 .build(),
1825 ),
1826 (
1827 "mid",
1828 ComponentDeclBuilder::new()
1829 .expose(
1830 ExposeBuilder::protocol()
1831 .name("A")
1832 .from_dictionary("required_dict")
1833 .source_static_child("leaf"),
1834 )
1835 .expose(
1836 ExposeBuilder::protocol()
1837 .name("B")
1838 .from_dictionary("optional_dict")
1839 .source_static_child("leaf"),
1840 )
1841 .expose(
1842 ExposeBuilder::protocol()
1843 .name("C")
1844 .from_dictionary("dict_with_optional_nested/nested")
1845 .source_static_child("leaf"),
1846 )
1847 .child_default("leaf")
1848 .build(),
1849 ),
1850 (
1851 "leaf",
1852 ComponentDeclBuilder::new()
1853 .protocol_default("foo")
1854 .protocol_default("bar")
1855 .protocol_default("qux")
1856 .dictionary_default("required_dict")
1857 .dictionary_default("optional_dict")
1858 .dictionary_default("nested")
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 routing::capability_source::CapabilitySource::Component(
1985 routing::capability_source::ComponentSource {
1986 capability:
1987 routing::capability_source::ComponentCapability::Runner(RunnerDecl {
1988 name, ..
1989 }),
1990 moniker,
1991 },
1992 ) => {
1993 assert_eq!(name, "foo");
1994 assert_eq!(moniker, Moniker::root());
1995 }
1996 _ => panic!("unexpected source: {:?}", source),
1997 }
1998 }
1999
2000 pub async fn test_offer_runner_from_dictionary(&self) {
2001 let components = vec![
2002 (
2003 "root",
2004 ComponentDeclBuilder::new()
2005 .runner_default("foo")
2006 .dictionary_default("dict")
2007 .offer(
2008 OfferBuilder::runner()
2009 .name("foo")
2010 .target_name("bar")
2011 .source(OfferSource::Self_)
2012 .target(OfferTarget::Capability("dict".parse().unwrap())),
2013 )
2014 .offer(
2015 OfferBuilder::dictionary()
2016 .name("dict")
2017 .source(OfferSource::Self_)
2018 .target_static_child("mid"),
2019 )
2020 .child_default("mid")
2021 .build(),
2022 ),
2023 (
2024 "mid",
2025 ComponentDeclBuilder::new()
2026 .offer(
2027 OfferBuilder::runner()
2028 .name("bar")
2029 .target_name("baz")
2030 .from_dictionary("dict")
2031 .source(OfferSource::Parent)
2032 .target_static_child("leaf"),
2033 )
2034 .child_default("leaf")
2035 .build(),
2036 ),
2037 (
2038 "leaf",
2039 ComponentDeclBuilder::new_empty_component()
2040 .use_(UseBuilder::runner().name("baz"))
2041 .build(),
2042 ),
2043 ];
2044
2045 let test = T::new("root", components).build().await;
2046 let leaf_component = test
2047 .look_up_instance(&["mid", "leaf"].try_into().unwrap())
2048 .await
2049 .expect("leaf instance");
2050 let source = debug_route_sandbox_path(
2051 &leaf_component,
2052 &UseDecl::Runner(UseRunnerDecl {
2053 source: UseSource::Parent,
2054 source_name: "baz".parse().unwrap(),
2055 source_dictionary: Default::default(),
2056 }),
2057 )
2058 .await
2059 .expect("failed to route runner");
2060
2061 match source {
2062 routing::capability_source::CapabilitySource::Component(
2063 routing::capability_source::ComponentSource {
2064 capability:
2065 routing::capability_source::ComponentCapability::Runner(RunnerDecl {
2066 name, ..
2067 }),
2068 moniker,
2069 },
2070 ) => {
2071 assert_eq!(name, "foo");
2072 assert_eq!(moniker, Moniker::root());
2073 }
2074 _ => panic!("unexpected source: {:?}", source),
2075 }
2076 }
2077
2078 pub async fn test_offer_directory_from_dictionary(&self) {
2079 let use_decl =
2080 UseBuilder::directory().name("baz").rights(fio::R_STAR_DIR).path("/foo").build();
2081 let components = vec![
2082 (
2083 "root",
2084 ComponentDeclBuilder::new()
2085 .capability(
2086 CapabilityBuilder::directory()
2087 .name("foo")
2088 .rights(fio::R_STAR_DIR)
2089 .path("/foo"),
2090 )
2091 .dictionary_default("dict")
2092 .offer(
2093 OfferBuilder::directory()
2094 .name("foo")
2095 .target_name("bar")
2096 .source(OfferSource::Self_)
2097 .target(OfferTarget::Capability("dict".parse().unwrap())),
2098 )
2099 .offer(
2100 OfferBuilder::dictionary()
2101 .name("dict")
2102 .source(OfferSource::Self_)
2103 .target_static_child("mid"),
2104 )
2105 .child_default("mid")
2106 .build(),
2107 ),
2108 (
2109 "mid",
2110 ComponentDeclBuilder::new()
2111 .offer(
2112 OfferBuilder::directory()
2113 .name("bar")
2114 .target_name("baz")
2115 .from_dictionary("dict")
2116 .source(OfferSource::Parent)
2117 .target_static_child("leaf"),
2118 )
2119 .child_default("leaf")
2120 .build(),
2121 ),
2122 ("leaf", ComponentDeclBuilder::new().use_(use_decl.clone()).build()),
2123 ];
2124
2125 let test = T::new("root", components).build().await;
2126 let leaf_component = test
2127 .look_up_instance(&["mid", "leaf"].try_into().unwrap())
2128 .await
2129 .expect("leaf instance");
2130
2131 let source = debug_route_sandbox_path(&leaf_component, &use_decl)
2132 .await
2133 .expect("failed to route resolver");
2134
2135 match source {
2136 routing::capability_source::CapabilitySource::StorageBackingDirectory(
2137 routing::capability_source::StorageBackingDirectorySource {
2138 capability:
2139 routing::capability_source::ComponentCapability::Directory(DirectoryDecl {
2140 name,
2141 ..
2142 }),
2143 moniker,
2144 ..
2145 },
2146 ) => {
2147 assert_eq!(name, "foo");
2148 assert_eq!(moniker, Moniker::root());
2149 }
2150 _ => panic!("unexpected source: {:?}", source),
2151 }
2152 }
2153
2154 pub async fn test_use_config_from_dictionary(&self) {
2155 let components = vec![
2156 (
2157 "root",
2158 ComponentDeclBuilder::new()
2159 .capability(CapabilityBuilder::config().name("foo").value(10_i32.into()))
2160 .dictionary_default("dict")
2161 .offer(
2162 OfferBuilder::config()
2163 .name("foo")
2164 .target_name("bar")
2165 .source(OfferSource::Self_)
2166 .target(OfferTarget::Capability("dict".parse().unwrap())),
2167 )
2168 .offer(
2169 OfferBuilder::dictionary()
2170 .name("dict")
2171 .source(OfferSource::Self_)
2172 .target_static_child("leaf"),
2173 )
2174 .child_default("leaf")
2175 .build(),
2176 ),
2177 (
2178 "leaf",
2179 ComponentDeclBuilder::new()
2180 .use_(
2181 UseBuilder::config()
2182 .name("bar")
2183 .config_type(ConfigValueType::Int32)
2184 .from_dictionary("dict"),
2185 )
2186 .build(),
2187 ),
2188 ];
2189
2190 let test = T::new("root", components).build().await;
2191 let leaf_component =
2192 test.look_up_instance(&["leaf"].try_into().unwrap()).await.expect("leaf instance");
2193 let source = debug_route_sandbox_path(
2194 &leaf_component,
2195 &UseDecl::Config(UseConfigurationDecl {
2196 source: UseSource::Parent,
2197 source_name: "bar".parse().unwrap(),
2198 target_name: "bar".parse().unwrap(),
2199 availability: Availability::Required,
2200 type_: ConfigValueType::Int32,
2201 default: None,
2202 source_dictionary: "dict".parse().unwrap(),
2203 }),
2204 )
2205 .await
2206 .expect("failed to route config");
2207
2208 match source {
2209 routing::capability_source::CapabilitySource::Component(
2210 routing::capability_source::ComponentSource {
2211 capability: routing::capability_source::ComponentCapability::Config(_),
2212 moniker,
2213 },
2214 ) => {
2215 assert_eq!(moniker, moniker::Moniker::root());
2216 }
2217 _ => panic!("unexpected source: {:?}", source),
2218 }
2219 }
2220
2221 pub async fn test_offer_config_from_dictionary(&self) {
2222 let components = vec![
2223 (
2224 "root",
2225 ComponentDeclBuilder::new()
2226 .capability(CapabilityBuilder::config().name("foo").value(10_i32.into()))
2227 .dictionary_default("dict")
2228 .offer(
2229 OfferBuilder::config()
2230 .name("foo")
2231 .target_name("bar")
2232 .source(OfferSource::Self_)
2233 .target(OfferTarget::Capability("dict".parse().unwrap())),
2234 )
2235 .offer(
2236 OfferBuilder::dictionary()
2237 .name("dict")
2238 .source(OfferSource::Self_)
2239 .target_static_child("mid"),
2240 )
2241 .child_default("mid")
2242 .build(),
2243 ),
2244 (
2245 "mid",
2246 ComponentDeclBuilder::new()
2247 .offer(
2248 OfferBuilder::config()
2249 .name("bar")
2250 .target_name("baz")
2251 .from_dictionary("dict")
2252 .source(OfferSource::Parent)
2253 .target_static_child("leaf"),
2254 )
2255 .child_default("leaf")
2256 .build(),
2257 ),
2258 (
2259 "leaf",
2260 ComponentDeclBuilder::new()
2261 .use_(UseBuilder::config().name("baz").config_type(ConfigValueType::Int32))
2262 .build(),
2263 ),
2264 ];
2265
2266 let test = T::new("root", components).build().await;
2267 let leaf_component = test
2268 .look_up_instance(&["mid", "leaf"].try_into().unwrap())
2269 .await
2270 .expect("leaf instance");
2271 let source = debug_route_sandbox_path(
2272 &leaf_component,
2273 &UseDecl::Config(UseConfigurationDecl {
2274 source: UseSource::Parent,
2275 source_name: "baz".parse().unwrap(),
2276 target_name: "baz".parse().unwrap(),
2277 availability: Availability::Required,
2278 type_: ConfigValueType::Int32,
2279 default: None,
2280 source_dictionary: Default::default(),
2281 }),
2282 )
2283 .await
2284 .expect("failed to route config");
2285
2286 match source {
2287 routing::capability_source::CapabilitySource::Component(
2288 routing::capability_source::ComponentSource {
2289 capability: routing::capability_source::ComponentCapability::Config(_),
2290 moniker,
2291 },
2292 ) => {
2293 assert_eq!(moniker, moniker::Moniker::root());
2294 }
2295 _ => panic!("unexpected source: {:?}", source),
2296 }
2297 }
2298}