1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
pub mod component_controller;
use {
async_trait::async_trait, fidl::endpoints::ServerEnd, fidl::prelude::*,
fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_runner as fcrunner,
fuchsia_async as fasync, futures::stream::StreamExt, thiserror::Error, tracing::warn,
};
#[async_trait]
pub trait Runner: Sync + Send {
#[must_use]
async fn start(
&self,
start_info: fcrunner::ComponentStartInfo,
server_end: ServerEnd<fcrunner::ComponentControllerMarker>,
);
}
pub struct NullRunner {}
#[async_trait]
impl Runner for NullRunner {
async fn start(
&self,
_start_info: fcrunner::ComponentStartInfo,
server_end: ServerEnd<fcrunner::ComponentControllerMarker>,
) {
spawn_null_controller_server(
server_end
.into_stream()
.expect("NullRunner failed to convert server channel into request stream"),
);
}
}
fn spawn_null_controller_server(mut request_stream: fcrunner::ComponentControllerRequestStream) {
fasync::Task::spawn(async move {
if let Some(Ok(request)) = request_stream.next().await {
match request {
fcrunner::ComponentControllerRequest::Stop { control_handle }
| fcrunner::ComponentControllerRequest::Kill { control_handle } => {
control_handle.shutdown();
}
}
}
})
.detach();
}
#[derive(Debug, Clone, Error)]
pub struct RemoteRunnerError(pub fcomponent::Error);
impl std::fmt::Display for RemoteRunnerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use std::fmt::Debug;
self.0.fmt(f)
}
}
impl std::convert::From<fcomponent::Error> for RemoteRunnerError {
fn from(error: fcomponent::Error) -> RemoteRunnerError {
RemoteRunnerError(error)
}
}
pub struct RemoteRunner {
client: fcrunner::ComponentRunnerProxy,
}
impl RemoteRunner {
pub fn new(client: fcrunner::ComponentRunnerProxy) -> RemoteRunner {
RemoteRunner { client }
}
}
#[async_trait]
impl Runner for RemoteRunner {
async fn start(
&self,
start_info: fcrunner::ComponentStartInfo,
server_end: ServerEnd<fcrunner::ComponentControllerMarker>,
) {
let resolved_url = runner::get_resolved_url(&start_info).unwrap_or(String::new());
if let Err(e) = self.client.start(start_info, server_end) {
warn!(url=%resolved_url, error=%e, "Failed to call runner to start component");
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use fidl::endpoints::{self, Proxy};
#[fuchsia::test]
async fn test_null_runner() {
let null_runner = NullRunner {};
let (client, server) = endpoints::create_endpoints::<fcrunner::ComponentControllerMarker>();
null_runner
.start(
fcrunner::ComponentStartInfo {
resolved_url: None,
program: None,
ns: None,
outgoing_dir: None,
runtime_dir: None,
..fcrunner::ComponentStartInfo::EMPTY
},
server,
)
.await;
let proxy = client.into_proxy().expect("failed converting to proxy");
proxy.stop().expect("failed to send message to null runner");
proxy.on_closed().await.expect("failed waiting for channel to close");
}
}