unmanaged_element/
unmanaged_element.rs
1use anyhow::{anyhow, Result};
6use {fidl_fuchsia_power_broker as fbroker, power_broker_client as pbclient};
7
8pub struct UnmanagedElement {
9 pub context: pbclient::PowerElementContext,
10}
11
12impl UnmanagedElement {
13 pub async fn add(
14 topology: &fbroker::TopologyProxy,
15 name: &str,
16 valid_levels: &[fbroker::PowerLevel],
17 initial_current_level: &fbroker::PowerLevel,
18 ) -> Result<Self> {
19 let context = pbclient::PowerElementContext::builder(topology, name, valid_levels)
21 .initial_current_level(*initial_current_level)
22 .register_dependency_tokens(false) .build()
24 .await?;
25
26 Ok(Self { context })
27 }
28
29 pub async fn set_level(&self, new_current_level: &fbroker::PowerLevel) -> Result<()> {
30 self.context.current_level.update(*new_current_level).await?.map_err(|e| anyhow!("{e:?}"))
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37 use anyhow::Context;
38 use fidl::endpoints::create_proxy_and_stream;
39 use fuchsia_async as fasync;
40 use futures::channel::mpsc;
41 use futures::prelude::*;
42
43 struct FakePowerBroker {
44 element_schema_sender: mpsc::UnboundedSender<fbroker::ElementSchema>,
46 }
47
48 impl FakePowerBroker {
49 async fn run(&self, stream: fbroker::TopologyRequestStream) -> Result<()> {
50 stream
51 .map(|request| request.context("failed request"))
52 .try_for_each(|request| async {
53 match request {
54 fbroker::TopologyRequest::AddElement { payload, responder } => {
55 self.element_schema_sender
56 .unbounded_send(payload)
57 .expect("forwarding element schema");
58 responder.send(Ok(())).context("send failed")
59 }
60 _ => unreachable!(),
61 }
62 })
63 .await
64 }
65 }
66
67 struct FakeCurrentLevel {
68 power_level_sender: mpsc::UnboundedSender<fbroker::PowerLevel>,
70 }
71
72 impl FakeCurrentLevel {
73 async fn run(&self, stream: fbroker::CurrentLevelRequestStream) -> Result<()> {
74 stream
75 .map(|request| request.context("failed request"))
76 .try_for_each(|request| async {
77 match request {
78 fbroker::CurrentLevelRequest::Update { current_level, responder } => {
79 self.power_level_sender
80 .unbounded_send(current_level)
81 .expect("intercepting power level update");
82 responder.send(Ok(())).context("send failed")
83 }
84 _ => unreachable!(),
85 }
86 })
87 .await
88 }
89 }
90
91 #[fasync::run_until_stalled(test)]
92 async fn test_add_to_power_topology_sends_correct_schema() -> Result<()> {
93 let (topology, topology_stream) = create_proxy_and_stream::<fbroker::TopologyMarker>();
95 let (element_schema_sender, mut element_schema_receiver) =
96 mpsc::unbounded::<fbroker::ElementSchema>();
97 fasync::Task::local(async move {
98 let power_broker = FakePowerBroker { element_schema_sender };
99 power_broker.run(topology_stream).await.expect("topology server teardown");
100 })
101 .detach();
102
103 let element_name = "unmanaged-element";
105 let valid_levels = &pbclient::BINARY_POWER_LEVELS;
106 let initial_level = &pbclient::BINARY_POWER_LEVELS[0]; let _ = UnmanagedElement::add(&topology, element_name, valid_levels, initial_level).await?;
108
109 let schema = element_schema_receiver.next().await.expect("server AddElement call");
111 assert_eq!(schema.element_name, Some(element_name.to_string()));
112 assert_eq!(schema.valid_levels, Some(valid_levels.to_vec()));
113 assert_eq!(schema.initial_current_level, Some(*initial_level));
114 assert_eq!(schema.dependencies, Some(vec![]));
115 Ok(())
116 }
117
118 #[fasync::run_until_stalled(test)]
119 async fn test_set_level_changes_topology_current_level() -> Result<()> {
120 let (topology, topology_stream) = create_proxy_and_stream::<fbroker::TopologyMarker>();
122 let (element_schema_sender, mut element_schema_receiver) =
123 mpsc::unbounded::<fbroker::ElementSchema>();
124 fasync::Task::local(async move {
125 let power_broker = FakePowerBroker { element_schema_sender };
126 power_broker.run(topology_stream).await.expect("topology server teardown");
127 })
128 .detach();
129
130 let element_name = "unmanaged-element";
132 let valid_levels = &pbclient::BINARY_POWER_LEVELS;
133 let initial_level = &pbclient::BINARY_POWER_LEVELS[0]; let element =
135 UnmanagedElement::add(&topology, element_name, valid_levels, initial_level).await?;
136 let schema = element_schema_receiver.next().await.expect("server AddElement call");
137
138 let (power_level_sender, mut power_level_receiver) =
140 mpsc::unbounded::<fbroker::PowerLevel>();
141 fasync::Task::local(async move {
142 let current_level = FakeCurrentLevel { power_level_sender };
143 assert!(schema.level_control_channels.is_some());
144 let stream = schema.level_control_channels.unwrap().current.into_stream();
145 current_level.run(stream).await.expect("current level server teardown");
146 })
147 .detach();
148
149 element.set_level(&pbclient::BINARY_POWER_LEVELS[1]).await?;
150 assert_eq!(power_level_receiver.next().await, Some(pbclient::BINARY_POWER_LEVELS[1]));
151
152 element.set_level(&pbclient::BINARY_POWER_LEVELS[0]).await?;
153 assert_eq!(power_level_receiver.next().await, Some(pbclient::BINARY_POWER_LEVELS[0]));
154
155 Ok(())
156 }
157}