• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::{
10         AttAttributeDataChild, AttAttributeDataView, AttErrorCode, OwnedAttAttributeDataView,
11         Packet,
12     },
13 };
14 use async_trait::async_trait;
15 use log::info;
16 use tokio::sync::{
17     mpsc::{self, unbounded_channel, UnboundedReceiver},
18     oneshot,
19 };
20 
21 /// Routes calls to RawGattDatastore into a channel of MockRawDatastoreEvents
22 pub struct MockRawDatastore(mpsc::UnboundedSender<MockRawDatastoreEvents>);
23 
24 impl MockRawDatastore {
25     /// Constructor. Returns self and the RX side of the associated channel.
new() -> (Self, UnboundedReceiver<MockRawDatastoreEvents>)26     pub fn new() -> (Self, UnboundedReceiver<MockRawDatastoreEvents>) {
27         let (tx, rx) = unbounded_channel();
28         (Self(tx), rx)
29     }
30 }
31 
32 /// Events representing calls to GattDatastore
33 #[derive(Debug)]
34 pub enum MockRawDatastoreEvents {
35     /// A characteristic was read on a given handle. The oneshot is used to
36     /// return the value read.
37     Read(
38         TransportIndex,
39         AttHandle,
40         AttributeBackingType,
41         u32,
42         oneshot::Sender<Result<AttAttributeDataChild, AttErrorCode>>,
43     ),
44     /// A characteristic was written to on a given handle. The oneshot is used
45     /// to return whether the write succeeded.
46     Write(
47         TransportIndex,
48         AttHandle,
49         AttributeBackingType,
50         GattWriteRequestType,
51         OwnedAttAttributeDataView,
52         oneshot::Sender<Result<(), AttErrorCode>>,
53     ),
54     /// A characteristic was written to on a given handle, where the response was disregarded.
55     WriteNoResponse(TransportIndex, AttHandle, AttributeBackingType, OwnedAttAttributeDataView),
56     /// The prepared writes have been committed / aborted. The oneshot is used
57     /// to return whether this operation succeeded.
58     Execute(TransportIndex, TransactionDecision, oneshot::Sender<Result<(), AttErrorCode>>),
59 }
60 
61 #[async_trait(?Send)]
62 impl RawGattDatastore for MockRawDatastore {
read( &self, tcb_idx: TransportIndex, handle: AttHandle, offset: u32, attr_type: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode>63     async fn read(
64         &self,
65         tcb_idx: TransportIndex,
66         handle: AttHandle,
67         offset: u32,
68         attr_type: AttributeBackingType,
69     ) -> Result<AttAttributeDataChild, AttErrorCode> {
70         let (tx, rx) = oneshot::channel();
71         self.0.send(MockRawDatastoreEvents::Read(tcb_idx, handle, attr_type, offset, tx)).unwrap();
72         let resp = rx.await.unwrap();
73         info!("sending {resp:?} down from upper tester");
74         resp
75     }
76 
write( &self, tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, data: AttAttributeDataView<'_>, ) -> Result<(), AttErrorCode>77     async fn write(
78         &self,
79         tcb_idx: TransportIndex,
80         handle: AttHandle,
81         attr_type: AttributeBackingType,
82         write_type: GattWriteRequestType,
83         data: AttAttributeDataView<'_>,
84     ) -> Result<(), AttErrorCode> {
85         let (tx, rx) = oneshot::channel();
86         self.0
87             .send(MockRawDatastoreEvents::Write(
88                 tcb_idx,
89                 handle,
90                 attr_type,
91                 write_type,
92                 data.to_owned_packet(),
93                 tx,
94             ))
95             .unwrap();
96         rx.await.unwrap()
97     }
98 
write_no_response( &self, tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: AttAttributeDataView<'_>, )99     fn write_no_response(
100         &self,
101         tcb_idx: TransportIndex,
102         handle: AttHandle,
103         attr_type: AttributeBackingType,
104         data: AttAttributeDataView<'_>,
105     ) {
106         self.0
107             .send(MockRawDatastoreEvents::WriteNoResponse(
108                 tcb_idx,
109                 handle,
110                 attr_type,
111                 data.to_owned_packet(),
112             ))
113             .unwrap();
114     }
115 
execute( &self, tcb_idx: TransportIndex, decision: TransactionDecision, ) -> Result<(), AttErrorCode>116     async fn execute(
117         &self,
118         tcb_idx: TransportIndex,
119         decision: TransactionDecision,
120     ) -> Result<(), AttErrorCode> {
121         let (tx, rx) = oneshot::channel();
122         self.0.send(MockRawDatastoreEvents::Execute(tcb_idx, decision, tx)).unwrap();
123         rx.await.unwrap()
124     }
125 }
126