• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{
2     gatt::server::att_database::AttDatabase,
3     packets::{
4         AttChild, AttErrorResponseBuilder, AttOpcode, AttWriteRequestView, AttWriteResponseBuilder,
5     },
6 };
7 
handle_write_request<T: AttDatabase>( request: AttWriteRequestView<'_>, db: &T, ) -> AttChild8 pub async fn handle_write_request<T: AttDatabase>(
9     request: AttWriteRequestView<'_>,
10     db: &T,
11 ) -> AttChild {
12     let handle = request.get_handle().into();
13     match db.write_attribute(handle, request.get_value()).await {
14         Ok(()) => AttWriteResponseBuilder {}.into(),
15         Err(error_code) => AttErrorResponseBuilder {
16             opcode_in_error: AttOpcode::WRITE_REQUEST,
17             handle_in_error: handle.into(),
18             error_code,
19         }
20         .into(),
21     }
22 }
23 
24 #[cfg(test)]
25 mod test {
26     use super::*;
27 
28     use tokio_test::block_on;
29 
30     use crate::{
31         core::uuid::Uuid,
32         gatt::{
33             ids::AttHandle,
34             server::{
35                 att_database::{AttAttribute, AttDatabase},
36                 gatt_database::AttPermissions,
37                 test::test_att_db::TestAttDatabase,
38             },
39         },
40         packets::{
41             AttAttributeDataChild, AttChild, AttErrorCode, AttErrorResponseBuilder,
42             AttWriteRequestBuilder, AttWriteResponseBuilder,
43         },
44         utils::packet::{build_att_data, build_view_or_crash},
45     };
46 
47     #[test]
test_successful_write()48     fn test_successful_write() {
49         // arrange: db with one writable attribute
50         let db = TestAttDatabase::new(vec![(
51             AttAttribute {
52                 handle: AttHandle(1),
53                 type_: Uuid::new(0x1234),
54                 permissions: AttPermissions::READABLE | AttPermissions::WRITABLE_WITH_RESPONSE,
55             },
56             vec![],
57         )]);
58         let data = AttAttributeDataChild::RawData([1, 2].into());
59 
60         // act: write to the attribute
61         let att_view = build_view_or_crash(AttWriteRequestBuilder {
62             handle: AttHandle(1).into(),
63             value: build_att_data(data.clone()),
64         });
65         let resp = block_on(handle_write_request(att_view.view(), &db));
66 
67         // assert: that the write succeeded
68         assert_eq!(resp, AttChild::from(AttWriteResponseBuilder {}));
69         assert_eq!(block_on(db.read_attribute(AttHandle(1))).unwrap(), data);
70     }
71 
72     #[test]
test_failed_write()73     fn test_failed_write() {
74         // arrange: db with no writable attributes
75         let db = TestAttDatabase::new(vec![(
76             AttAttribute {
77                 handle: AttHandle(1),
78                 type_: Uuid::new(0x1234),
79                 permissions: AttPermissions::READABLE,
80             },
81             vec![],
82         )]);
83         // act: write to the attribute
84         let att_view = build_view_or_crash(AttWriteRequestBuilder {
85             handle: AttHandle(1).into(),
86             value: build_att_data(AttAttributeDataChild::RawData([1, 2].into())),
87         });
88         let resp = block_on(handle_write_request(att_view.view(), &db));
89 
90         // assert: that the write failed
91         assert_eq!(
92             resp,
93             AttChild::from(AttErrorResponseBuilder {
94                 opcode_in_error: AttOpcode::WRITE_REQUEST,
95                 handle_in_error: AttHandle(1).into(),
96                 error_code: AttErrorCode::WRITE_NOT_PERMITTED
97             })
98         );
99     }
100 }
101