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