Skip to main content

routing_test_helpers/
dictionary.rs

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