1// Copyright 2021 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.
45//! This mod defines the building blocks for receiving inbound communication from external
6//! interfaces, such as FIDL. It also includes common implementations for working with
7//! `Jobs` for incoming requests.
89/// The [fidl] mod enables defining components that provide inbound communication over FIDL.
10pub mod fidl;
1112pub(crate) mod request;
13pub(crate) mod watch;
1415/// [Scoped] is a simple wrapper that can be used to overcome issues with using types outside this
16/// crate in traits that are defined outside as well. For example, the [From] trait requires that
17/// genericized type be defined within the crate. The extract method can be used to retrieve the
18/// contained data.
19pub(crate) struct Scoped<T>(pub T);
2021pub(crate) mod registration {
22use super::fidl;
23use crate::base::Dependency;
24use crate::job::source::Seeder;
25use fuchsia_component::server::{ServiceFsDir, ServiceObjLocal};
26use std::collections::HashSet;
2728/// [Registrar] defines the medium over which communication occurs. Each entry includes a
29 /// closure that takes a specific set of inputs necessary to bring up that particular
30 /// communication.
31pub enum Registrar {
32 Fidl(fidl::Register),
33/// This value is reserved for testing purposes.
34#[cfg(test)]
35Test(Box<dyn FnOnce()>),
36#[cfg(test)]
37TestWithSeeder(Box<dyn FnOnce(&Seeder)>),
38 }
3940impl Registrar {
41/// Brings up the communication by supplying the subset of needed inputs to the particular
42 /// [Registrar].
43pub fn register(
44self,
45 job_seeder: &Seeder,
46 service_dir: &mut ServiceFsDir<'_, ServiceObjLocal<'_, ()>>,
47 ) {
48match self {
49 Registrar::Fidl(register_fn) => {
50 register_fn(job_seeder, service_dir);
51 }
52#[cfg(test)]
53Registrar::Test(register_fn) => {
54 register_fn();
55 }
56#[cfg(test)]
57Registrar::TestWithSeeder(register_fn) => {
58 register_fn(job_seeder);
59 }
60 }
61 }
62 }
6364/// [Registrant] brings up an inbound interface in the service.
65pub struct Registrant {
66/// The name of the interface being registered.
67interface: String,
68/// The [Registrar] responsible for bringing up the interface.
69registrar: Registrar,
70/// A list of [Dependencies](Dependency) the registrant relies on being present in order to
71 /// function.
72dependencies: HashSet<Dependency>,
73 }
7475impl Registrant {
76pub(crate) fn new(
77 interface: String,
78 registrar: Registrar,
79 dependencies: HashSet<Dependency>,
80 ) -> Registrant {
81 Registrant { interface, registrar, dependencies }
82 }
8384pub(crate) fn get_dependencies(&self) -> &HashSet<Dependency> {
85&self.dependencies
86 }
8788pub(crate) fn get_interface(&self) -> &String {
89&self.interface
90 }
9192pub(crate) fn register(
93self,
94 job_seeder: &Seeder,
95 service_dir: &mut ServiceFsDir<'_, ServiceObjLocal<'_, ()>>,
96 ) {
97self.registrar.register(job_seeder, service_dir);
98 }
99 }
100}
101102#[cfg(test)]
103mod tests {
104use super::registration::{Registrant, Registrar};
105use crate::base::{Dependency, Entity, SettingType};
106use crate::job::source::Seeder;
107use crate::message::base::MessengerType;
108use crate::service;
109use assert_matches::assert_matches;
110use fuchsia_component::server::ServiceFs;
111112#[fuchsia::test(allow_stalls = false)]
113async fn test_registration() {
114let (tx, rx) = futures::channel::oneshot::channel::<()>();
115let dependency = Dependency::Entity(Entity::Handler(SettingType::Unknown));
116let registrant = Registrant::new(
117"Registrar::Test".to_string(),
118 Registrar::Test(Box::new(move || {
119assert!(tx.send(()).is_ok());
120 })),
121 [dependency].into(),
122 );
123124let mut fs = ServiceFs::new_local();
125126// Verify added dependency.
127assert!(registrant.get_dependencies().contains(&dependency));
128129let delegate = service::MessageHub::create_hub();
130let job_manager_signature = delegate
131 .create(MessengerType::Unbound)
132 .await
133.expect("messenger should be created")
134 .0
135.get_signature();
136let job_seeder = Seeder::new(&delegate, job_manager_signature).await;
137138// Register and consume Registrant.
139registrant.register(&job_seeder, &mut fs.root_dir());
140141// Verify registration occurred.
142assert_matches!(rx.await, Ok(()));
143 }
144}