fidl_handle_tests/
socket.rs
1use crate::LoggingFixture;
6use async_trait::async_trait;
7use futures::channel::oneshot;
8use futures::future::join;
9use futures::lock::Mutex;
10use futures::prelude::*;
11
12fn reverse<T>(value: (T, T)) -> (T, T) {
13 (value.1, value.0)
14}
15
16#[async_trait]
17pub trait Fixture: LoggingFixture {
18 async fn create_handles(&self, opt: fidl::SocketOpts) -> (fidl::Socket, fidl::Socket);
19}
20
21#[derive(Clone, Copy, PartialEq)]
22enum AfterSend {
23 RemainOpen,
24 CloseSender,
25}
26
27async fn send_bytes(
28 fixture: &Mutex<impl Fixture + 'static>,
29 sockets: (fidl::Socket, fidl::Socket),
30 out: &'static [u8],
31 after_send: AfterSend,
32) {
33 let mut tx = fidl::AsyncSocket::from_socket(sockets.0);
34 let mut rx = fidl::AsyncSocket::from_socket(sockets.1);
35 fixture.lock().await.log(&format!("# send bytes from {:?} to {:?}: {:?}", tx, rx, out));
36 let expect = out.to_vec();
37 let (tx_done, rx_done) = oneshot::channel();
38 join(
39 async move {
40 tx.write_all(out).await.unwrap();
41 match after_send {
42 AfterSend::RemainOpen => {
43 fixture.lock().await.log(&format!("# waiting for done"));
44 rx_done.await.unwrap()
45 }
46 AfterSend::CloseSender => drop(tx),
47 }
48 },
49 async move {
50 let mut in_bytes = Vec::new();
51 let mut buf = [0u8; 1];
52 while in_bytes.len() != out.len() {
53 rx.read_exact(&mut buf).await.unwrap();
54 in_bytes.push(buf[0]);
55 }
56 assert_eq!(in_bytes, expect);
57 let _ = tx_done.send(());
58 },
59 )
60 .await;
61}
62
63pub async fn run(fixture: impl Fixture + 'static) {
64 let fixture = &Mutex::new(fixture);
65 fixture.lock().await.log("# send bytes a->b remaining open");
66 let sockets = fixture.lock().await.create_handles(fidl::SocketOpts::STREAM).await;
67 send_bytes(&fixture, sockets, &[1, 2, 3], AfterSend::RemainOpen).await;
68 fixture.lock().await.log("# send bytes b->a remaining open");
69 let sockets = reverse(fixture.lock().await.create_handles(fidl::SocketOpts::STREAM).await);
70 send_bytes(&fixture, sockets, &[7, 8, 9], AfterSend::RemainOpen).await;
71 fixture.lock().await.log("# send bytes a->b then close");
72 let sockets = fixture.lock().await.create_handles(fidl::SocketOpts::STREAM).await;
73 send_bytes(&fixture, sockets, &[1, 2, 3], AfterSend::CloseSender).await;
74 fixture.lock().await.log("# send bytes b->a then close");
75 let sockets = reverse(fixture.lock().await.create_handles(fidl::SocketOpts::STREAM).await);
76 send_bytes(&fixture, sockets, &[7, 8, 9], AfterSend::CloseSender).await;
77}
78
79#[cfg(test)]
80mod test {
81 use super::*;
82
83 struct FidlFixture;
84
85 #[async_trait]
86 impl Fixture for FidlFixture {
87 async fn create_handles(&self, opts: fidl::SocketOpts) -> (fidl::Socket, fidl::Socket) {
88 match opts {
89 fidl::SocketOpts::STREAM => fidl::Socket::create_stream(),
90 fidl::SocketOpts::DATAGRAM => fidl::Socket::create_datagram(),
91
92 #[cfg(target_os = "fuchsia")]
93 _ => panic!("unsupported socket options"),
94 }
95 }
96 }
97
98 impl LoggingFixture for FidlFixture {
99 fn log(&mut self, msg: &str) {
100 println!("{}", msg);
101 }
102 }
103
104 #[fuchsia_async::run_singlethreaded(test)]
105 async fn tests() {
106 run(FidlFixture).await
107 }
108}