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
use {
anyhow::Error,
argh::FromArgs,
fidl_fuchsia_kernel::{CounterMarker, CounterProxy},
fidl_fuchsia_mem::Buffer,
fuchsia_component::{client::connect_to_protocol, server::ServiceFs},
fuchsia_zircon as zx,
futures::prelude::*,
std::sync::Arc,
tracing::*,
};
pub const PROGRAM_NAME: &str = "kcounter";
#[derive(FromArgs, Debug, PartialEq)]
#[argh(subcommand, name = "kcounter")]
pub struct CommandLine {}
async fn publish_kcounter_inspect(
kcounter: CounterProxy,
inspector: &fuchsia_inspect::Inspector,
) -> Result<(), Error> {
let (status, Buffer { vmo, size: _ }) = kcounter.get_inspect_vmo().await?;
let () = zx::ok(status)?;
let vmo = Arc::new(vmo);
inspector.root().record_lazy_values("kcounter", move || {
let kcounter = kcounter.clone();
let vmo = vmo.clone();
async move {
let status = kcounter.update_inspect_vmo().await?;
let () = zx::ok(status)?;
Ok(fuchsia_inspect::Inspector::new(
fuchsia_inspect::InspectorConfig::default().no_op().vmo(vmo),
))
}
.boxed()
});
Ok(())
}
pub async fn main() -> Result<(), Error> {
let mut fs = ServiceFs::new();
fs.take_and_serve_directory_handle()?;
let inspector = fuchsia_inspect::component::inspector();
inspect_runtime::serve(inspector, &mut fs)?;
publish_kcounter_inspect(connect_to_protocol::<CounterMarker>()?, inspector).await?;
info!("Serving");
fs.collect::<()>().await;
info!("Exiting");
Ok(())
}
#[cfg(test)]
mod tests {
use {
super::*, fidl_fuchsia_kernel::CounterRequest, fuchsia_async as fasync, std::sync::Mutex,
};
#[fasync::run_until_stalled(test)]
async fn test_kcounter_proxy() -> Result<(), Error> {
let (proxy, mut stream) =
fidl::endpoints::create_proxy_and_stream::<CounterMarker>().unwrap();
let counter = Arc::new(Mutex::new((0, 0)));
let counter_in_server = counter.clone();
let _task = fasync::Task::local(async move {
while let Some(req) = stream.next().await {
let mut counter = counter_in_server.lock().unwrap();
match req {
Ok(CounterRequest::GetInspectVmo { responder }) => {
(*counter).0 += 1;
let vmo = zx::Vmo::create(0).unwrap();
responder
.send(zx::Status::OK.into_raw(), &mut Buffer { vmo, size: 0 })
.expect("Failed to respond to GetInspectVmo");
}
Ok(CounterRequest::UpdateInspectVmo { responder }) => {
(*counter).1 += 1;
responder
.send(zx::Status::OK.into_raw())
.expect("Failed to respond to UpdateInspectVmo");
}
Err(e) => {
assert!(false, "Server error: {}", e);
}
};
}
});
let inspector = fuchsia_inspect::Inspector::default();
publish_kcounter_inspect(proxy, &inspector).await?;
{
let counter = counter.lock().unwrap();
assert_eq!((*counter).0, 1, "Incorrect call(s) to GetInspectVmo");
assert_eq!((*counter).1, 0, "Incorrect call(s) to UpdateInspectVmo");
};
fuchsia_inspect::reader::read(&inspector).await?;
{
let counter = counter.lock().unwrap();
assert_eq!((*counter).0, 1, "Incorrect call(s) to GetInspectVmo");
assert_eq!((*counter).1, 1, "Incorrect call(s) to UpdateInspectVmo");
};
fuchsia_inspect::reader::read(&inspector).await?;
{
let counter = counter.lock().unwrap();
assert_eq!((*counter).0, 1, "Incorrect call(s) to GetInspectVmo");
assert_eq!((*counter).1, 2, "Incorrect call(s) to UpdateInspectVmo");
};
Ok(())
}
}