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