1 //! Mocked implementation of GattDatastore for use in test
2 
3 use crate::{
4     gatt::{
5         callbacks::GattDatastore,
6         ffi::AttributeBackingType,
7         ids::{AttHandle, TransportIndex},
8     },
9     packets::AttErrorCode,
10 };
11 use async_trait::async_trait;
12 use log::info;
13 use tokio::sync::{
14     mpsc::{self, unbounded_channel, UnboundedReceiver},
15     oneshot,
16 };
17 
18 /// Routes calls to GattDatastore into a channel of MockDatastoreEvents
19 pub struct MockDatastore(mpsc::UnboundedSender<MockDatastoreEvents>);
20 
21 impl MockDatastore {
22     /// Constructor. Returns self and the RX side of the associated channel.
new() -> (Self, UnboundedReceiver<MockDatastoreEvents>)23     pub fn new() -> (Self, UnboundedReceiver<MockDatastoreEvents>) {
24         let (tx, rx) = unbounded_channel();
25         (Self(tx), rx)
26     }
27 }
28 
29 /// Events representing calls to GattDatastore
30 #[derive(Debug)]
31 pub enum MockDatastoreEvents {
32     /// A characteristic was read on a given handle. The oneshot is used to
33     /// return the value read.
34     Read(
35         TransportIndex,
36         AttHandle,
37         AttributeBackingType,
38         oneshot::Sender<Result<Vec<u8>, AttErrorCode>>,
39     ),
40     /// A characteristic was written to on a given handle. The oneshot is used
41     /// to return whether the write succeeded.
42     Write(
43         TransportIndex,
44         AttHandle,
45         AttributeBackingType,
46         Vec<u8>,
47         oneshot::Sender<Result<(), AttErrorCode>>,
48     ),
49 }
50 
51 #[async_trait(?Send)]
52 impl GattDatastore for MockDatastore {
read( &self, tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, ) -> Result<Vec<u8>, AttErrorCode>53     async fn read(
54         &self,
55         tcb_idx: TransportIndex,
56         handle: AttHandle,
57         attr_type: AttributeBackingType,
58     ) -> Result<Vec<u8>, AttErrorCode> {
59         let (tx, rx) = oneshot::channel();
60         self.0.send(MockDatastoreEvents::Read(tcb_idx, handle, attr_type, tx)).unwrap();
61         let resp = rx.await.unwrap();
62         info!("sending {resp:?} down from upper tester");
63         resp
64     }
65 
write( &self, tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: &[u8], ) -> Result<(), AttErrorCode>66     async fn write(
67         &self,
68         tcb_idx: TransportIndex,
69         handle: AttHandle,
70         attr_type: AttributeBackingType,
71         data: &[u8],
72     ) -> Result<(), AttErrorCode> {
73         let (tx, rx) = oneshot::channel();
74         self.0
75             .send(MockDatastoreEvents::Write(tcb_idx, handle, attr_type, data.to_vec(), tx))
76             .unwrap();
77         rx.await.unwrap()
78     }
79 }
80