bt_fidl_mocks/
gatt.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::expect::{expect_call, Status};
6use anyhow::Error;
7use fidl_fuchsia_bluetooth::Uuid as FidlUuid;
8use fidl_fuchsia_bluetooth_gatt::{
9    self as gatt, ReadByTypeResult, RemoteServiceMarker, RemoteServiceProxy, RemoteServiceRequest,
10    RemoteServiceRequestStream,
11};
12use fuchsia_bluetooth::types::Uuid;
13use zx::MonotonicDuration;
14
15/// Provides a simple mock implementation of `fuchsia.bluetooth.gatt.RemoteService`.
16pub struct RemoteServiceMock {
17    stream: RemoteServiceRequestStream,
18    timeout: MonotonicDuration,
19}
20
21impl RemoteServiceMock {
22    pub fn new(
23        timeout: MonotonicDuration,
24    ) -> Result<(RemoteServiceProxy, RemoteServiceMock), Error> {
25        let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<RemoteServiceMarker>();
26        Ok((proxy, RemoteServiceMock { stream, timeout }))
27    }
28
29    /// Wait until a Read By Type message is received with the given `uuid`. `result` will be sent
30    /// in response to the matching FIDL request.
31    pub async fn expect_read_by_type(
32        &mut self,
33        expected_uuid: Uuid,
34        result: Result<&[ReadByTypeResult], gatt::Error>,
35    ) -> Result<(), Error> {
36        let expected_uuid: FidlUuid = expected_uuid.into();
37        expect_call(&mut self.stream, self.timeout, move |req| {
38            if let RemoteServiceRequest::ReadByType { uuid, responder } = req {
39                if uuid == expected_uuid {
40                    responder.send(result)?;
41                    Ok(Status::Satisfied(()))
42                } else {
43                    // Send error to unexpected request.
44                    responder.send(Err(fidl_fuchsia_bluetooth_gatt::Error::Failure))?;
45                    Ok(Status::Pending)
46                }
47            } else {
48                Ok(Status::Pending)
49            }
50        })
51        .await
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::timeout_duration;
59    use futures::join;
60
61    #[fuchsia_async::run_until_stalled(test)]
62    async fn test_expect_read_by_type() {
63        let (proxy, mut mock) =
64            RemoteServiceMock::new(timeout_duration()).expect("failed to create mock");
65        let uuid = Uuid::new16(0x180d);
66        let result = Ok(&[][..]);
67
68        let fidl_uuid: FidlUuid = uuid.clone().into();
69        let read_by_type = proxy.read_by_type(&fidl_uuid);
70        let expect = mock.expect_read_by_type(uuid, result);
71
72        let (read_by_type_result, expect_result) = join!(read_by_type, expect);
73        let _ = read_by_type_result.expect("read by type request failed");
74        let _ = expect_result.expect("expectation not satisfied");
75    }
76}