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