bt_fidl_mocks/
sys.rs

1// Copyright 2021 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::expect::{expect_call, Status};
6use anyhow::Error;
7use fidl_fuchsia_bluetooth::PeerId;
8use fidl_fuchsia_bluetooth_sys::{
9    AccessMarker, AccessProxy, AccessRequest, AccessRequestStream, Error as AccessError,
10    InputCapability, OutputCapability, PairingDelegateProxy, PairingMarker, PairingOptions,
11    PairingProxy, PairingRequest, PairingRequestStream,
12};
13use zx::MonotonicDuration;
14
15/// Provides a simple mock implementation of `fuchsia.bluetooth.sys.Pairing`.
16pub struct PairingMock {
17    stream: PairingRequestStream,
18    timeout: MonotonicDuration,
19}
20
21impl PairingMock {
22    pub fn new(timeout: MonotonicDuration) -> Result<(PairingProxy, PairingMock), Error> {
23        let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<PairingMarker>();
24        Ok((proxy, PairingMock { stream, timeout }))
25    }
26
27    pub async fn expect_set_pairing_delegate(
28        &mut self,
29        expected_input_cap: InputCapability,
30        expected_output_cap: OutputCapability,
31    ) -> Result<PairingDelegateProxy, Error> {
32        expect_call(&mut self.stream, self.timeout, move |req| match req {
33            PairingRequest::SetPairingDelegate { input, output, delegate, control_handle: _ }
34                if input == expected_input_cap && output == expected_output_cap =>
35            {
36                Ok(Status::Satisfied(delegate.into_proxy()))
37            }
38            _ => Ok(Status::Pending),
39        })
40        .await
41    }
42}
43
44/// Provides a simple mock implementation of `fuchsia.bluetooth.sys.Access`.
45pub struct AccessMock {
46    stream: AccessRequestStream,
47    timeout: MonotonicDuration,
48}
49
50impl AccessMock {
51    pub fn new(timeout: MonotonicDuration) -> Result<(AccessProxy, AccessMock), Error> {
52        let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<AccessMarker>();
53        Ok((proxy, AccessMock { stream, timeout }))
54    }
55
56    pub async fn expect_disconnect(
57        &mut self,
58        expected_peer_id: PeerId,
59        result: Result<(), AccessError>,
60    ) -> Result<(), Error> {
61        expect_call(&mut self.stream, self.timeout, move |req| match req {
62            AccessRequest::Disconnect { id, responder } if id == expected_peer_id => {
63                responder.send(result)?;
64                Ok(Status::Satisfied(()))
65            }
66            _ => Ok(Status::Pending),
67        })
68        .await
69    }
70
71    pub async fn expect_forget(
72        &mut self,
73        expected_peer_id: PeerId,
74        result: Result<(), AccessError>,
75    ) -> Result<(), Error> {
76        expect_call(&mut self.stream, self.timeout, move |req| match req {
77            AccessRequest::Forget { id, responder } if id == expected_peer_id => {
78                responder.send(result)?;
79                Ok(Status::Satisfied(()))
80            }
81            _ => Ok(Status::Pending),
82        })
83        .await
84    }
85
86    pub async fn expect_pair(
87        &mut self,
88        expected_peer_id: PeerId,
89        expected_options: PairingOptions,
90        result: Result<(), AccessError>,
91    ) -> Result<(), Error> {
92        expect_call(&mut self.stream, self.timeout, move |req| match req {
93            AccessRequest::Pair { id, options, responder }
94                if id == expected_peer_id && options == expected_options =>
95            {
96                responder.send(result)?;
97                Ok(Status::Satisfied(()))
98            }
99            _ => Ok(Status::Pending),
100        })
101        .await
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use crate::timeout_duration;
109    use fidl_fuchsia_bluetooth_sys::PairingDelegateMarker;
110    use futures::join;
111
112    #[fuchsia_async::run_until_stalled(test)]
113    async fn test_expect_disconnect() {
114        let (proxy, mut mock) = AccessMock::new(timeout_duration()).expect("failed to create mock");
115        let peer_id = PeerId { value: 1 };
116
117        let disconnect = proxy.disconnect(&peer_id);
118        let expect = mock.expect_disconnect(peer_id, Ok(()));
119
120        let (disconnect_result, expect_result) = join!(disconnect, expect);
121        let _ = disconnect_result.expect("disconnect request failed");
122        let _ = expect_result.expect("expectation not satisfied");
123    }
124
125    #[fuchsia_async::run_until_stalled(test)]
126    async fn test_expect_forget() {
127        let (proxy, mut mock) = AccessMock::new(timeout_duration()).expect("failed to create mock");
128        let peer_id = PeerId { value: 1 };
129
130        let forget = proxy.forget(&peer_id);
131        let expect = mock.expect_forget(peer_id, Ok(()));
132
133        let (forget_result, expect_result) = join!(forget, expect);
134        let _ = forget_result.expect("forget request failed");
135        let _ = expect_result.expect("expectation not satisifed");
136    }
137
138    #[fuchsia_async::run_until_stalled(test)]
139    async fn test_expect_set_pairing_delegate() {
140        let (proxy, mut mock) =
141            PairingMock::new(timeout_duration()).expect("failed to create mock");
142
143        let input_cap = InputCapability::None;
144        let output_cap = OutputCapability::Display;
145        let (pairing_delegate_client, _pairing_delegate_server) =
146            fidl::endpoints::create_endpoints::<PairingDelegateMarker>();
147
148        let pair_set_result =
149            proxy.set_pairing_delegate(input_cap, output_cap, pairing_delegate_client);
150        let expect_result = mock.expect_set_pairing_delegate(input_cap, output_cap).await;
151
152        let _ = pair_set_result.expect("set_pairing_delegate request failed");
153        let _ = expect_result.expect("expectation not satisifed");
154    }
155}