Skip to main content

driver_tools/subcommands/list_composites/
mod.rs

1// Copyright 2022 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
5pub mod args;
6
7use anyhow::{Context, Result};
8use args::ListCompositesCommand;
9use flex_client::ProxyHasDomain;
10use flex_fuchsia_driver_development as fdd;
11use flex_fuchsia_driver_framework as fdf;
12use std::io::Write;
13
14pub async fn list_composites(
15    cmd: ListCompositesCommand,
16    writer: &mut dyn Write,
17    proxy: fdd::ManagerProxy,
18) -> Result<()> {
19    writeln!(
20        writer,
21        "WARNING: This command is deprecated. Use `ffx driver composite list` instead."
22    )?;
23
24    let (iterator, iterator_server) =
25        proxy.domain().create_proxy::<fdd::CompositeInfoIteratorMarker>();
26    proxy.get_composite_info(iterator_server).context("GetCompositeInfo() failed")?;
27
28    loop {
29        let composite_list =
30            iterator.get_next().await.context("CompositeInfoIterator GetNext() failed")?;
31
32        if composite_list.is_empty() {
33            break;
34        }
35
36        for composite_node in composite_list {
37            match composite_node.composite {
38                Some(fdd::CompositeInfo::Composite(info)) => {
39                    write_composite(
40                        writer,
41                        info,
42                        composite_node.parent_topological_paths.unwrap(),
43                        composite_node.topological_path,
44                        cmd.verbose,
45                    )?;
46                }
47                _ => {}
48            }
49        }
50    }
51
52    Ok(())
53}
54
55fn write_composite(
56    writer: &mut dyn Write,
57    composite: fdf::CompositeInfo,
58    parent_topological_paths: Vec<Option<String>>,
59    topological_path: Option<String>,
60    verbose: bool,
61) -> Result<()> {
62    let spec = composite.spec.unwrap_or_default();
63    let driver_match = composite.matched_driver.unwrap_or_default();
64    if !verbose {
65        writeln!(writer, "{}", spec.name.unwrap_or_else(|| "".to_string()))?;
66        return Ok(());
67    }
68
69    writeln!(writer, "{0: <9}: {1}", "Name", spec.name.unwrap_or_else(|| "".to_string()))?;
70    writeln!(
71        writer,
72        "{0: <9}: {1}",
73        "Driver",
74        driver_match
75            .composite_driver
76            .and_then(|composite_driver| composite_driver.driver_info)
77            .and_then(|driver_info| driver_info.url)
78            .unwrap_or_else(|| "N/A".to_string())
79    )?;
80    writeln!(
81        writer,
82        "{0: <9}: {1}",
83        "Device",
84        topological_path.unwrap_or_else(|| "N/A".to_string())
85    )?;
86
87    write_parent_nodes_info(
88        writer,
89        driver_match.primary_parent_index,
90        driver_match.parent_names.unwrap_or_default(),
91        parent_topological_paths,
92    )?;
93
94    writeln!(writer)?;
95    Ok(())
96}
97
98fn write_parent_nodes_info(
99    writer: &mut dyn Write,
100    primary_index: Option<u32>,
101    parent_names: Vec<String>,
102    parent_paths: Vec<Option<String>>,
103) -> Result<()> {
104    writeln!(writer, "{0: <9}: {1}", "Parents", parent_names.len())?;
105    for (i, parent_name) in parent_names.into_iter().enumerate() {
106        let primary_tag = if primary_index == Some(i as u32) { "(Primary)" } else { "" };
107        writeln!(writer, "{0: <1} {1} : {2} {3}", "Parent", i, parent_name, primary_tag)?;
108
109        writeln!(
110            writer,
111            "   {0: <1} : {1}",
112            "Device",
113            parent_paths[i].clone().unwrap_or_else(|| "Unbound".to_string())
114        )?;
115    }
116    Ok(())
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122    use std::io::Error;
123
124    pub struct TestWriteBuffer {
125        pub content: String,
126    }
127
128    impl Write for TestWriteBuffer {
129        fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
130            self.content.push_str(std::str::from_utf8(buf).unwrap());
131            Ok(buf.len())
132        }
133
134        fn flush(&mut self) -> Result<(), Error> {
135            Ok(())
136        }
137    }
138
139    #[fuchsia::test]
140    async fn test_composite_verbose() {
141        let test_composite = fdf::CompositeInfo {
142            spec: Some(fdf::CompositeNodeSpec {
143                name: Some("composite_dev".to_string()),
144                ..Default::default()
145            }),
146            matched_driver: Some(fdf::CompositeDriverMatch {
147                composite_driver: Some(fdf::CompositeDriverInfo {
148                    driver_info: Some(fdf::DriverInfo {
149                        url: Some("fuchsia-boot:///#meta/waxwing.cm".to_string()),
150                        ..Default::default()
151                    }),
152                    ..Default::default()
153                }),
154                parent_names: Some(vec!["sysmem".to_string(), "acpi".to_string()]),
155                primary_parent_index: Some(1),
156                ..Default::default()
157            }),
158            ..Default::default()
159        };
160
161        let mut test_write_buffer = TestWriteBuffer { content: "".to_string() };
162        writeln!(
163            &mut test_write_buffer,
164            "WARNING: This command is deprecated. Use `ffx driver composite list` instead."
165        )
166        .unwrap();
167        write_composite(
168            &mut test_write_buffer,
169            test_composite,
170            vec![Some("path/sysmem_dev".to_string()), Some("path/acpi_dev".to_string())],
171            Some("dev/sys/composite_dev".to_string()),
172            true,
173        )
174        .unwrap();
175        assert_eq!(
176            format!(
177                "WARNING: This command is deprecated. Use `ffx driver composite list` instead.\n{}",
178                include_str!("../../../tests/golden/list_composites_verbose")
179            ),
180            test_write_buffer.content
181        );
182    }
183
184    #[fuchsia::test]
185    async fn test_composite_verbose_empty_fields() {
186        let test_composite = fdf::CompositeInfo {
187            spec: Some(fdf::CompositeNodeSpec {
188                name: Some("composite_dev".to_string()),
189                ..Default::default()
190            }),
191            matched_driver: Some(fdf::CompositeDriverMatch {
192                composite_driver: Some(fdf::CompositeDriverInfo {
193                    composite_name: Some("composite_name".to_string()),
194                    driver_info: Some(fdf::DriverInfo {
195                        url: Some("fuchsia-boot:///#meta/waxwing.cm".to_string()),
196                        ..Default::default()
197                    }),
198                    ..Default::default()
199                }),
200                parent_names: Some(vec!["sysmem".to_string(), "acpi".to_string()]),
201                primary_parent_index: Some(1),
202                ..Default::default()
203            }),
204            ..Default::default()
205        };
206
207        let mut test_write_buffer = TestWriteBuffer { content: "".to_string() };
208        writeln!(
209            &mut test_write_buffer,
210            "WARNING: This command is deprecated. Use `ffx driver composite list` instead."
211        )
212        .unwrap();
213        write_composite(
214            &mut test_write_buffer,
215            test_composite,
216            vec![None, None],
217            Some("dev/sys/composite_dev".to_string()),
218            true,
219        )
220        .unwrap();
221        println!("{}", test_write_buffer.content);
222
223        assert_eq!(
224            format!(
225                "WARNING: This command is deprecated. Use `ffx driver composite list` instead.\n{}",
226                include_str!("../../../tests/golden/list_composites_verbose_empty_fields")
227            ),
228            test_write_buffer.content
229        );
230    }
231}