rust/bt-gatt: Support offset and truncation in FakePeerService read Test: cargo test Change-Id: Ia79c0d06484c0fa6c56f6388591f04abd9b9bc41 Reviewed-on: https://bluetooth-review.googlesource.com/c/bluetooth/+/3640
diff --git a/rust/bt-gatt/src/test_utils.rs b/rust/bt-gatt/src/test_utils.rs index 7f274f2..c31ffab 100644 --- a/rust/bt-gatt/src/test_utils.rs +++ b/rust/bt-gatt/src/test_utils.rs
@@ -107,16 +107,22 @@ fn read_characteristic<'a>( &self, handle: &Handle, - _offset: u16, + offset: u16, buf: &'a mut [u8], ) -> <FakeTypes as GattTypes>::ReadFut<'a> { let read_characteristics = &(*self.inner.lock()).characteristics; let Some((_, value)) = read_characteristics.get(handle) else { return ready(Err(Error::Gatt(GattError::InvalidHandle))); }; - let len = std::cmp::min(buf.len(), value.len()); - buf[..len].copy_from_slice(&value[..len]); - ready(Ok((len, false))) + let offset = offset as usize; + if offset > value.len() { + return ready(Err(Error::Gatt(GattError::InvalidOffset))); + } + let remaining = &value[offset..]; + let len = std::cmp::min(buf.len(), remaining.len()); + buf[..len].copy_from_slice(&remaining[..len]); + let truncated = remaining.len() > buf.len(); + ready(Ok((len, truncated))) } // For testing, should call `expect_characteristic_value` with the expected
diff --git a/rust/bt-gatt/src/tests.rs b/rust/bt-gatt/src/tests.rs index d8188e4..8b95ec1 100644 --- a/rust/bt-gatt/src/tests.rs +++ b/rust/bt-gatt/src/tests.rs
@@ -144,10 +144,46 @@ // Successfully reads the updated value. let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 0, &mut buf[..]); let polled = read_result.poll_unpin(&mut noop_cx); - assert_matches!(polled, Poll::Ready(Ok((len, _))) => { + assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => { assert_eq!(len, 4); - assert_eq!(buf[..len], vec![0,1,2,3]); + assert_eq!(buf[..len], vec![0, 1, 2, 3]); + assert!(!truncated); }); + + // Read with small buffer (buf.len() < value.len()) sets truncated = true + let mut small_buf = vec![0; 2]; + let mut read_result = + fake_peer_service.read_characteristic(&Handle(0x1), 0, &mut small_buf[..]); + let polled = read_result.poll_unpin(&mut noop_cx); + assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => { + assert_eq!(len, 2); + assert_eq!(small_buf[..len], vec![0, 1]); + assert!(truncated); + }); + + // Read with valid offset (offset = 2 < value.len()) + let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 2, &mut buf[..]); + let polled = read_result.poll_unpin(&mut noop_cx); + assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => { + assert_eq!(len, 2); + assert_eq!(buf[..len], vec![2, 3]); + assert!(!truncated); + }); + + // Read with offset equal to value length (offset = 4 == value.len()) returns 0 + // bytes read + let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 4, &mut buf[..]); + let polled = read_result.poll_unpin(&mut noop_cx); + assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => { + assert_eq!(len, 0); + assert!(!truncated); + }); + + // Read with offset too large (offset = 5 > value.len()) returns + // GattError::InvalidOffset + let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 5, &mut buf[..]); + let polled = read_result.poll_unpin(&mut noop_cx); + assert_matches!(polled, Poll::Ready(Err(Error::Gatt(GattError::InvalidOffset)))); } #[test]