1 //! Mocked implementation of GattDatastore for use in test
2 
3 use crate::{
4     gatt::{
5         callbacks::{GattWriteRequestType, RawGattDatastore, TransactionDecision},
6         ffi::AttributeBackingType,
7         ids::{AttHandle, TransportIndex},
8     },
9     packets::att::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 RawGattDatastore into a channel of MockRawDatastoreEvents
19 pub struct MockRawDatastore(mpsc::UnboundedSender<MockRawDatastoreEvents>);
20 
21 impl MockRawDatastore {
22     /// Constructor. Returns self and the RX side of the associated channel.
new() -> (Self, UnboundedReceiver<MockRawDatastoreEvents>)23     pub fn new() -> (Self, UnboundedReceiver<MockRawDatastoreEvents>) {
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 MockRawDatastoreEvents {
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         u32,
39         oneshot::Sender<Result<Vec<u8>, AttErrorCode>>,
40     ),
41     /// A characteristic was written to on a given handle. The oneshot is used
42     /// to return whether the write succeeded.
43     Write(
44         TransportIndex,
45         AttHandle,
46         AttributeBackingType,
47         GattWriteRequestType,
48         Vec<u8>,
49         oneshot::Sender<Result<(), AttErrorCode>>,
50     ),
51     /// A characteristic was written to on a given handle, where the response was disregarded.
52     WriteNoResponse(TransportIndex, AttHandle, AttributeBackingType, Vec<u8>),
53     /// The prepared writes have been committed / aborted. The oneshot is used
54     /// to return whether this operation succeeded.
55     Execute(TransportIndex, TransactionDecision, oneshot::Sender<Result<(), AttErrorCode>>),
56 }
57 
58 #[async_trait(?Send)]
59 impl RawGattDatastore for MockRawDatastore {
read( &self, tcb_idx: TransportIndex, handle: AttHandle, offset: u32, attr_type: AttributeBackingType, ) -> Result<Vec<u8>, AttErrorCode>60     async fn read(
61         &self,
62         tcb_idx: TransportIndex,
63         handle: AttHandle,
64         offset: u32,
65         attr_type: AttributeBackingType,
66     ) -> Result<Vec<u8>, AttErrorCode> {
67         let (tx, rx) = oneshot::channel();
68         self.0.send(MockRawDatastoreEvents::Read(tcb_idx, handle, attr_type, offset, tx)).unwrap();
69         let resp = rx.await.unwrap();
70         info!("sending {resp:?} down from upper tester");
71         resp
72     }
73 
write( &self, tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, data: &[u8], ) -> Result<(), AttErrorCode>74     async fn write(
75         &self,
76         tcb_idx: TransportIndex,
77         handle: AttHandle,
78         attr_type: AttributeBackingType,
79         write_type: GattWriteRequestType,
80         data: &[u8],
81     ) -> Result<(), AttErrorCode> {
82         let (tx, rx) = oneshot::channel();
83         self.0
84             .send(MockRawDatastoreEvents::Write(
85                 tcb_idx,
86                 handle,
87                 attr_type,
88                 write_type,
89                 data.to_vec(),
90                 tx,
91             ))
92             .unwrap();
93         rx.await.unwrap()
94     }
95 
write_no_response( &self, tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: &[u8], )96     fn write_no_response(
97         &self,
98         tcb_idx: TransportIndex,
99         handle: AttHandle,
100         attr_type: AttributeBackingType,
101         data: &[u8],
102     ) {
103         self.0
104             .send(MockRawDatastoreEvents::WriteNoResponse(
105                 tcb_idx,
106                 handle,
107                 attr_type,
108                 data.to_vec(),
109             ))
110             .unwrap();
111     }
112 
execute( &self, tcb_idx: TransportIndex, decision: TransactionDecision, ) -> Result<(), AttErrorCode>113     async fn execute(
114         &self,
115         tcb_idx: TransportIndex,
116         decision: TransactionDecision,
117     ) -> Result<(), AttErrorCode> {
118         let (tx, rx) = oneshot::channel();
119         self.0.send(MockRawDatastoreEvents::Execute(tcb_idx, decision, tx)).unwrap();
120         rx.await.unwrap()
121     }
122 }
123