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