fidl_handle_tests/
socket.rs

1// Copyright 2020 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
5use 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}