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