fdf_component/testing/
node.rs1use anyhow::Result;
8use fidl::endpoints::ServerEnd;
9use fuchsia_sync::Mutex;
10use futures::TryStreamExt;
11use std::collections::HashMap;
12use std::sync::{Arc, Weak};
13use {
14 fidl_fuchsia_device_fs as fdf_devfs, fidl_fuchsia_driver_framework as fdf_fidl,
15 fuchsia_async as fasync, zx,
16};
17
18pub type NodeId = usize;
20
21struct TestNode {
23 id: NodeId,
24 context: Weak<NodeManager>,
25 name: String,
26 children: HashMap<String, NodeId>,
27 properties: Vec<fdf_fidl::NodeProperty2>,
28 parent: Option<NodeId>,
29 devfs_connector_client: Option<fdf_devfs::ConnectorProxy>,
30 scope: fasync::Scope,
31}
32
33impl TestNode {
34 fn serve_node(&self, server_end: ServerEnd<fdf_fidl::NodeMarker>) {
35 let mut stream = server_end.into_stream();
36 let node_id = self.id;
37 let context = self.context.clone();
38 self.scope.spawn(async move {
39 while let Some(request) = stream.try_next().await.unwrap() {
40 if let fdf_fidl::NodeRequest::AddChild { args, controller, node, responder } =
41 request
42 {
43 let name = args.name.as_ref().unwrap();
44 let _ = context.upgrade().expect("manager").new_node(
45 name,
46 Some(node_id),
47 args.properties2,
48 Some(controller),
49 node,
50 args.devfs_args,
51 );
52
53 let _ = responder.send(Ok(()));
54 }
55 }
56
57 context.upgrade().expect("manager").remove_node(&node_id);
58 });
59 }
60
61 fn serve_controller(&self, server_end: ServerEnd<fdf_fidl::NodeControllerMarker>) {
62 let mut stream = server_end.into_stream();
63 let node_id = self.id;
64 let context = self.context.clone();
65 self.scope.spawn(async move {
66 while let Some(request) = stream.try_next().await.unwrap() {
67 match request {
68 fdf_fidl::NodeControllerRequest::Remove { control_handle: _ } => {
69 context.upgrade().expect("manager").remove_node(&node_id);
70 }
71 fdf_fidl::NodeControllerRequest::RequestBind { payload: _, responder } => {
72 let _ = responder.send(Ok(()));
73 }
74 _ => (),
75 }
76 }
77 });
78 }
79}
80
81pub(crate) struct NodeManager {
82 nodes: Mutex<HashMap<NodeId, TestNode>>,
83 next_id: Mutex<NodeId>,
84}
85
86pub struct NodeHandle {
88 manager: Weak<NodeManager>,
89 id: NodeId,
90}
91
92impl NodeHandle {
93 pub(crate) fn new(manager: Weak<NodeManager>, id: NodeId) -> Self {
94 Self { manager, id }
95 }
96
97 pub fn name(&self) -> String {
99 self.manager.upgrade().expect("manager").name(&self.id)
100 }
101
102 pub fn children(&self) -> HashMap<String, NodeHandle> {
104 self.manager
105 .upgrade()
106 .expect("manager")
107 .children(&self.id)
108 .into_iter()
109 .map(|(n, id)| (n, NodeHandle::new(self.manager.clone(), id)))
110 .collect()
111 }
112
113 pub fn properties(&self) -> Vec<fdf_fidl::NodeProperty2> {
115 self.manager.upgrade().expect("manager").properties(&self.id)
116 }
117
118 pub fn parent(&self) -> Option<NodeHandle> {
120 self.manager
121 .upgrade()
122 .expect("manager")
123 .parent(&self.id)
124 .map(|id| NodeHandle::new(self.manager.clone(), id))
125 }
126
127 pub async fn connect_to_device(&self) -> Result<zx::Channel, anyhow::Error> {
129 self.manager.upgrade().expect("manager").connect_to_device(self.id).await
130 }
131}
132
133impl NodeManager {
134 pub(crate) fn new() -> Arc<Self> {
135 Arc::new(Self { nodes: Mutex::new(HashMap::new()), next_id: Mutex::new(0) })
136 }
137
138 pub(crate) fn create_root_node(
139 self: &Arc<Self>,
140 node: ServerEnd<fdf_fidl::NodeMarker>,
141 ) -> NodeId {
142 self.new_node("root", None, None, None, Some(node), None)
143 }
144
145 fn new_node(
146 self: &Arc<Self>,
147 name: &str,
148 parent: Option<NodeId>,
149 properties: Option<Vec<fdf_fidl::NodeProperty2>>,
150 controller: Option<ServerEnd<fdf_fidl::NodeControllerMarker>>,
151 node: Option<ServerEnd<fdf_fidl::NodeMarker>>,
152 devfs_args: Option<fdf_fidl::DevfsAddArgs>,
153 ) -> NodeId {
154 let mut next_id = self.next_id.lock();
155 let child_id = *next_id;
156 *next_id += 1;
157 drop(next_id);
158
159 let devfs_connector_client = {
160 if let Some(fdf_fidl::DevfsAddArgs { connector: Some(client), .. }) = devfs_args {
161 Some(client.into_proxy())
162 } else {
163 None
164 }
165 };
166
167 let child_node = TestNode {
168 id: child_id,
169 context: Arc::downgrade(self),
170 name: name.to_string(),
171 children: HashMap::new(),
172 properties: properties.unwrap_or_default(),
173 parent,
174 devfs_connector_client,
175 scope: fasync::Scope::new(),
176 };
177
178 if let Some(parent_id) = parent {
179 let mut nodes = self.nodes.lock();
180 nodes.get_mut(&parent_id).expect("parent").children.insert(name.to_string(), child_id);
181 log::info!("adding child {name} to parent {parent_id}");
182 }
183
184 if let Some(controller) = controller {
185 child_node.serve_controller(controller);
186 }
187
188 if let Some(node) = node {
189 child_node.serve_node(node);
190 }
191
192 self.nodes.lock().insert(child_id, child_node);
193 child_id
194 }
195
196 async fn connect_to_device(&self, node_id: NodeId) -> Result<zx::Channel, anyhow::Error> {
197 let (client_end, server_end) = zx::Channel::create();
198 let nodes = self.nodes.lock();
199 let node = nodes.get(&node_id).expect("node");
200 if let Some(connector) = node.devfs_connector_client.as_ref() {
201 connector.connect(server_end).unwrap();
202 Ok(client_end)
203 } else {
204 Err(anyhow::anyhow!("Devfs connector not found"))
205 }
206 }
207
208 fn children(self: &Arc<Self>, node_id: &NodeId) -> HashMap<String, NodeId> {
209 let nodes = self.nodes.lock();
210 nodes.get(node_id).expect("node").children.clone()
211 }
212
213 fn parent(&self, node_id: &NodeId) -> Option<NodeId> {
214 let nodes = self.nodes.lock();
215 nodes.get(node_id).expect("node").parent
216 }
217
218 fn name(&self, node_id: &NodeId) -> String {
219 let nodes = self.nodes.lock();
220 nodes.get(node_id).expect("node").name.clone()
221 }
222
223 fn properties(&self, node_id: &NodeId) -> Vec<fdf_fidl::NodeProperty2> {
224 let nodes = self.nodes.lock();
225 nodes.get(node_id).expect("node").properties.clone()
226 }
227
228 fn remove_node(self: &Arc<Self>, node_id: &NodeId) {
229 let children = self.children(node_id);
230 for child_id in children.values() {
231 self.remove_node(child_id);
232 }
233
234 if let Some(parent_id) = self.parent(node_id) {
235 let name = self.name(node_id);
236 let mut nodes = self.nodes.lock();
237 nodes.get_mut(&parent_id).expect("parent").children.remove(&name);
238 }
239
240 self.nodes.lock().remove(node_id);
241 }
242}