xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/gatt/gatt_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt.h"
16 
17 #include <pw_async/fake_dispatcher_fixture.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
20 #include "pw_bluetooth_sapphire/internal/host/att/error.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/host_error.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h"
23 #include "pw_bluetooth_sapphire/internal/host/gatt/fake_client.h"
24 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"
25 #include "pw_bluetooth_sapphire/internal/host/gatt/local_service_manager.h"
26 #include "pw_bluetooth_sapphire/internal/host/gatt/mock_server.h"
27 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel.h"
28 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
29 
30 namespace bt::gatt::internal {
31 namespace {
32 constexpr PeerId kPeerId0(0);
33 constexpr PeerId kPeerId1(1);
34 constexpr PeerId kPeerId(10);
35 constexpr UUID kTestServiceUuid0(uint16_t{0xbeef});
36 constexpr IdType kChrcId{13};
37 constexpr bt::UUID kChrcUuid(uint16_t{113u});
38 
39 // Factory function for tests of client-facing behavior that don't care about
40 // the server
CreateMockServer(PeerId peer_id,LocalServiceManager::WeakPtr local_services)41 std::unique_ptr<Server> CreateMockServer(
42     PeerId peer_id, LocalServiceManager::WeakPtr local_services) {
43   return std::make_unique<testing::MockServer>(peer_id,
44                                                std::move(local_services));
45 }
46 
47 class GattTest : public pw::async::test::FakeDispatcherFixture {
48  public:
49   GattTest() = default;
50   ~GattTest() override = default;
51 
52  protected:
53   struct ServiceWatcherData {
54     PeerId peer_id;
55     std::vector<att::Handle> removed;
56     ServiceList added;
57     ServiceList modified;
58   };
59 
SetUp()60   void SetUp() override {
61     auto client = std::make_unique<testing::FakeClient>(dispatcher());
62     fake_client_weak_ = client->AsFakeWeakPtr();
63     client_ = std::move(client);
64     gatt_ = GATT::Create();
65   }
66 
TearDown()67   void TearDown() override {
68     // Clear any previous expectations that are based on the ATT Write Request,
69     // so that write requests sent during RemoteService::ShutDown() are ignored.
70     fake_client()->set_write_request_callback({});
71     gatt_.reset();
72   }
73 
74   // Register an arbitrary service with a single characteristic of id |kChrcId|,
75   // e.g. for sending notifications. Returns the internal IdType of the
76   // registered service.
RegisterArbitraryService()77   IdType RegisterArbitraryService() {
78     auto svc = std::make_unique<Service>(/*primary=*/true, kTestServiceUuid0);
79     const att::AccessRequirements kReadPerm,
80         kWritePerm;  // Default is not allowed
81     // Allow "update" (i.e. indications / notifications) with no security
82     const att::AccessRequirements kUpdatePerm(/*encryption=*/false,
83                                               /*authentication=*/false,
84                                               /*authorization=*/false);
85     auto chrc = std::make_unique<Characteristic>(kChrcId,
86                                                  kChrcUuid,
87                                                  Property::kIndicate,
88                                                  /*extended_properties=*/0,
89                                                  kReadPerm,
90                                                  kWritePerm,
91                                                  kUpdatePerm);
92     svc->AddCharacteristic(std::move(chrc));
93 
94     std::optional<IdType> svc_id = std::nullopt;
95     auto id_cb = [&svc_id](IdType received_id) {
96       EXPECT_NE(kInvalidId, received_id);
97       svc_id = received_id;
98     };
99     gatt()->RegisterService(std::move(svc),
100                             std::move(id_cb),
101                             NopReadHandler,
102                             NopWriteHandler,
103                             NopCCCallback);
104     RunUntilIdle();
105     EXPECT_TRUE(svc_id.has_value());
106     return *svc_id;
107   }
108 
gatt() const109   GATT* gatt() const { return gatt_.get(); }
110 
fake_client() const111   testing::FakeClient::WeakPtr fake_client() const { return fake_client_weak_; }
take_client()112   std::unique_ptr<Client> take_client() { return std::move(client_); }
113 
114  private:
115   std::unique_ptr<GATT> gatt_;
116   std::unique_ptr<Client> client_;
117   testing::FakeClient::WeakPtr fake_client_weak_;
118 
119   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(GattTest);
120 };
121 
TEST_F(GattTest,RemoteServiceWatcherNotifiesAddedModifiedAndRemovedService)122 TEST_F(GattTest, RemoteServiceWatcherNotifiesAddedModifiedAndRemovedService) {
123   const att::Handle kGattSvcStartHandle(1);
124   const att::Handle kSvcChangedChrcHandle(2);
125   const att::Handle kSvcChangedChrcValueHandle(3);
126   const att::Handle kCCCDescriptorHandle(4);
127   const att::Handle kGattSvcEndHandle(kCCCDescriptorHandle);
128 
129   ServiceData gatt_svc(ServiceKind::PRIMARY,
130                        kGattSvcStartHandle,
131                        kGattSvcEndHandle,
132                        types::kGenericAttributeService);
133   CharacteristicData service_changed_chrc(Property::kIndicate,
134                                           std::nullopt,
135                                           kSvcChangedChrcHandle,
136                                           kSvcChangedChrcValueHandle,
137                                           types::kServiceChangedCharacteristic);
138   DescriptorData ccc_descriptor(kCCCDescriptorHandle,
139                                 types::kClientCharacteristicConfig);
140   fake_client()->set_services({gatt_svc});
141   fake_client()->set_characteristics({service_changed_chrc});
142   fake_client()->set_descriptors({ccc_descriptor});
143 
144   // Return success when a Service Changed Client Characteristic Config
145   // descriptor write is performed.
146   int write_request_count = 0;
147   fake_client()->set_write_request_callback(
148       [&](att::Handle handle, const auto&, auto status_callback) {
149         write_request_count++;
150         EXPECT_EQ(kCCCDescriptorHandle, handle);
151         status_callback(fit::ok());
152       });
153 
154   std::vector<ServiceWatcherData> svc_watcher_data;
155   gatt()->RegisterRemoteServiceWatcherForPeer(
156       kPeerId,
157       [&](std::vector<att::Handle> removed,
158           ServiceList added,
159           ServiceList modified) {
160         svc_watcher_data.push_back(
161             ServiceWatcherData{.peer_id = kPeerId,
162                                .removed = std::move(removed),
163                                .added = std::move(added),
164                                .modified = std::move(modified)});
165       });
166 
167   gatt()->AddConnection(kPeerId, take_client(), CreateMockServer);
168   RunUntilIdle();
169   EXPECT_EQ(write_request_count, 0);
170 
171   gatt()->InitializeClient(kPeerId, /*service_uuids=*/{});
172   RunUntilIdle();
173   EXPECT_EQ(write_request_count, 1);
174   ASSERT_EQ(1u, svc_watcher_data.size());
175   ASSERT_EQ(1u, svc_watcher_data[0].added.size());
176   EXPECT_EQ(kPeerId, svc_watcher_data[0].peer_id);
177   EXPECT_EQ(kGattSvcStartHandle, svc_watcher_data[0].added[0]->handle());
178 
179   // Add, modify, and remove a service.
180   const att::Handle kSvc1StartHandle(5);
181   const att::Handle kSvc1EndHandle(kSvc1StartHandle);
182 
183   // Add a test service to ensure that service discovery occurs after the
184   // Service Changed characteristic is configured.
185   ServiceData svc1(ServiceKind::PRIMARY,
186                    kSvc1StartHandle,
187                    kSvc1EndHandle,
188                    kTestServiceUuid0);
189   fake_client()->set_services({gatt_svc, svc1});
190 
191   // Send a notification that svc1 has been added.
192   StaticByteBuffer svc_changed_range_buffer(
193       LowerBits(kSvc1StartHandle),
194       UpperBits(kSvc1StartHandle),  // start handle of affected range
195       LowerBits(kSvc1EndHandle),
196       UpperBits(kSvc1EndHandle)  // end handle of affected range
197   );
198   fake_client()->SendNotification(/*indicate=*/true,
199                                   kSvcChangedChrcValueHandle,
200                                   svc_changed_range_buffer,
201                                   /*maybe_truncated=*/false);
202   RunUntilIdle();
203   ASSERT_EQ(2u, svc_watcher_data.size());
204   ASSERT_EQ(1u, svc_watcher_data[1].added.size());
205   EXPECT_EQ(0u, svc_watcher_data[1].removed.size());
206   EXPECT_EQ(0u, svc_watcher_data[1].modified.size());
207   EXPECT_EQ(kPeerId, svc_watcher_data[1].peer_id);
208   EXPECT_EQ(kSvc1StartHandle, svc_watcher_data[1].added[0]->handle());
209   bool original_service_removed = false;
210   svc_watcher_data[1].added[0]->AddRemovedHandler(
211       [&]() { original_service_removed = true; });
212 
213   // Send a notification that svc1 has been modified.
214   fake_client()->SendNotification(/*indicate=*/true,
215                                   kSvcChangedChrcValueHandle,
216                                   svc_changed_range_buffer,
217                                   /*maybe_truncated=*/false);
218   RunUntilIdle();
219   EXPECT_TRUE(original_service_removed);
220   ASSERT_EQ(3u, svc_watcher_data.size());
221   EXPECT_EQ(0u, svc_watcher_data[2].added.size());
222   EXPECT_EQ(0u, svc_watcher_data[2].removed.size());
223   ASSERT_EQ(1u, svc_watcher_data[2].modified.size());
224   EXPECT_EQ(kPeerId, svc_watcher_data[2].peer_id);
225   EXPECT_EQ(kSvc1StartHandle, svc_watcher_data[2].modified[0]->handle());
226   bool modified_service_removed = false;
227   svc_watcher_data[2].modified[0]->AddRemovedHandler(
228       [&]() { modified_service_removed = true; });
229 
230   // Remove the service.
231   fake_client()->set_services({gatt_svc});
232 
233   // Send a notification that svc1 has been removed.
234   fake_client()->SendNotification(/*indicate=*/true,
235                                   kSvcChangedChrcValueHandle,
236                                   svc_changed_range_buffer,
237                                   /*maybe_truncated=*/false);
238   RunUntilIdle();
239   EXPECT_TRUE(modified_service_removed);
240   ASSERT_EQ(4u, svc_watcher_data.size());
241   EXPECT_EQ(0u, svc_watcher_data[3].added.size());
242   ASSERT_EQ(1u, svc_watcher_data[3].removed.size());
243   EXPECT_EQ(0u, svc_watcher_data[3].modified.size());
244   EXPECT_EQ(kPeerId, svc_watcher_data[3].peer_id);
245   EXPECT_EQ(kSvc1StartHandle, svc_watcher_data[3].removed[0]);
246 }
247 
248 // Register 3 service watchers, 2 of which are for the same peer.  Then
249 // unregister 2 service watchers (one for each peer) and ensure only the third
250 // is called.
TEST_F(GattTest,MultipleRegisterRemoteServiceWatcherForPeers)251 TEST_F(GattTest, MultipleRegisterRemoteServiceWatcherForPeers) {
252   // Configure peer 0 with 1 service.
253   const att::Handle kSvcStartHandle0(42);
254   const att::Handle kSvcEndHandle0(kSvcStartHandle0);
255   ServiceData svc_data_0(ServiceKind::PRIMARY,
256                          kSvcStartHandle0,
257                          kSvcEndHandle0,
258                          kTestServiceUuid0);
259   auto client_0 = std::make_unique<testing::FakeClient>(dispatcher());
260   client_0->set_services({svc_data_0});
261 
262   gatt()->AddConnection(kPeerId0, std::move(client_0), CreateMockServer);
263 
264   std::vector<ServiceWatcherData> watcher_data_0;
265   GATT::RemoteServiceWatcherId id_0 =
266       gatt()->RegisterRemoteServiceWatcherForPeer(
267           kPeerId0,
268           [&](std::vector<att::Handle> removed,
269               ServiceList added,
270               ServiceList modified) {
271             watcher_data_0.push_back(
272                 ServiceWatcherData{.peer_id = kPeerId0,
273                                    .removed = std::move(removed),
274                                    .added = std::move(added),
275                                    .modified = std::move(modified)});
276           });
277 
278   // Configure peer 1 with gatt service.
279   const att::Handle kGattSvcStartHandle(1);
280   const att::Handle kSvcChangedChrcHandle(2);
281   const att::Handle kSvcChangedChrcValueHandle(3);
282   const att::Handle kCCCDescriptorHandle(4);
283   const att::Handle kGattSvcEndHandle(kCCCDescriptorHandle);
284   ServiceData gatt_svc(ServiceKind::PRIMARY,
285                        kGattSvcStartHandle,
286                        kGattSvcEndHandle,
287                        types::kGenericAttributeService);
288   CharacteristicData service_changed_chrc(Property::kIndicate,
289                                           std::nullopt,
290                                           kSvcChangedChrcHandle,
291                                           kSvcChangedChrcValueHandle,
292                                           types::kServiceChangedCharacteristic);
293   DescriptorData ccc_descriptor(kCCCDescriptorHandle,
294                                 types::kClientCharacteristicConfig);
295   auto client_1 = std::make_unique<testing::FakeClient>(dispatcher());
296   auto client_1_weak = client_1.get();
297   client_1->set_services({gatt_svc});
298   client_1->set_characteristics({service_changed_chrc});
299   client_1->set_descriptors({ccc_descriptor});
300 
301   // Return success when a Service Changed Client Characteristic Config
302   // descriptor write is performed.
303   client_1->set_write_request_callback(
304       [&](att::Handle, const auto&, auto status_callback) {
305         status_callback(fit::ok());
306       });
307 
308   gatt()->AddConnection(kPeerId1, std::move(client_1), CreateMockServer);
309 
310   // Register 2 watchers for kPeerId1.
311   std::vector<ServiceWatcherData> watcher_data_1;
312   GATT::RemoteServiceWatcherId id_1 =
313       gatt()->RegisterRemoteServiceWatcherForPeer(
314           kPeerId1,
315           [&](std::vector<att::Handle> removed,
316               ServiceList added,
317               ServiceList modified) {
318             watcher_data_1.push_back(
319                 ServiceWatcherData{.peer_id = kPeerId1,
320                                    .removed = std::move(removed),
321                                    .added = std::move(added),
322                                    .modified = std::move(modified)});
323           });
324   EXPECT_NE(id_0, id_1);
325 
326   std::vector<ServiceWatcherData> watcher_data_2;
327   gatt()->RegisterRemoteServiceWatcherForPeer(
328       kPeerId1,
329       [&](std::vector<att::Handle> removed,
330           ServiceList added,
331           ServiceList modified) {
332         watcher_data_2.push_back(
333             ServiceWatcherData{.peer_id = kPeerId1,
334                                .removed = std::move(removed),
335                                .added = std::move(added),
336                                .modified = std::move(modified)});
337       });
338 
339   // Service discovery should complete and all service watchers should be
340   // notified.
341   gatt()->InitializeClient(kPeerId0, /*service_uuids=*/{});
342   gatt()->InitializeClient(kPeerId1, /*service_uuids=*/{});
343   RunUntilIdle();
344   ASSERT_EQ(watcher_data_0.size(), 1u);
345   ASSERT_EQ(watcher_data_0[0].added.size(), 1u);
346   EXPECT_EQ(watcher_data_0[0].added[0]->handle(), kSvcStartHandle0);
347 
348   ASSERT_EQ(watcher_data_1.size(), 1u);
349   ASSERT_EQ(watcher_data_1[0].added.size(), 1u);
350   EXPECT_EQ(watcher_data_1[0].added[0]->handle(), kGattSvcStartHandle);
351 
352   ASSERT_EQ(watcher_data_2.size(), 1u);
353   ASSERT_EQ(watcher_data_2[0].added.size(), 1u);
354   EXPECT_EQ(watcher_data_2[0].added[0]->handle(), kGattSvcStartHandle);
355 
356   gatt()->UnregisterRemoteServiceWatcher(id_0);
357   gatt()->UnregisterRemoteServiceWatcher(id_1);
358 
359   const att::Handle kSvcStartHandle1(84);
360   const att::Handle kSvcEndHandle1(kSvcStartHandle1);
361   ServiceData svc_data_1(ServiceKind::PRIMARY,
362                          kSvcStartHandle1,
363                          kSvcEndHandle1,
364                          kTestServiceUuid0);
365   client_1_weak->set_services({gatt_svc, svc_data_1});
366 
367   // Send a notification that service kSvcStartHandle1 has been added.
368   StaticByteBuffer svc_changed_range_buffer(
369       LowerBits(kSvcStartHandle1),
370       UpperBits(kSvcStartHandle1),  // start handle of affected range
371       LowerBits(kSvcEndHandle1),
372       UpperBits(kSvcEndHandle1)  // end handle of affected range
373   );
374   client_1_weak->SendNotification(/*indicate=*/true,
375                                   kSvcChangedChrcValueHandle,
376                                   svc_changed_range_buffer,
377                                   /*maybe_truncated=*/false);
378   RunUntilIdle();
379   // Unregistered handlers should not be notified.
380   ASSERT_EQ(watcher_data_0.size(), 1u);
381   ASSERT_EQ(watcher_data_1.size(), 1u);
382 
383   // Still registered handler should be notified of added service.
384   ASSERT_EQ(watcher_data_2.size(), 2u);
385   ASSERT_EQ(watcher_data_2[1].added.size(), 1u);
386   EXPECT_EQ(watcher_data_2[1].added[0]->handle(), kSvcStartHandle1);
387 }
388 
TEST_F(GattTest,ServiceDiscoveryFailureShutsDownConnection)389 TEST_F(GattTest, ServiceDiscoveryFailureShutsDownConnection) {
390   testing::MockServer::WeakPtr mock_server;
391   auto mock_server_factory = [&](PeerId peer_id,
392                                  LocalServiceManager::WeakPtr local_services) {
393     auto unique_mock_server = std::make_unique<testing::MockServer>(
394         peer_id, std::move(local_services));
395     mock_server = unique_mock_server->AsMockWeakPtr();
396     return unique_mock_server;
397   };
398   fake_client()->set_discover_services_callback([](ServiceKind) {
399     return ToResult(att::ErrorCode::kRequestNotSupported);
400   });
401   gatt()->AddConnection(kPeerId, take_client(), std::move(mock_server_factory));
402   ASSERT_TRUE(mock_server.is_alive());
403   EXPECT_FALSE(mock_server->was_shut_down());
404   gatt()->InitializeClient(kPeerId, std::vector<UUID>{});
405   RunUntilIdle();
406   EXPECT_TRUE(mock_server->was_shut_down());
407 }
408 
TEST_F(GattTest,SendIndicationNoConnectionFails)409 TEST_F(GattTest, SendIndicationNoConnectionFails) {
410   att::Result<> res = fit::ok();
411   auto indicate_cb = [&res](att::Result<> cb_res) { res = cb_res; };
412   // Don't add the connection to GATT before trying to send an indication
413   gatt()->SendUpdate(/*service_id=*/1,
414                      /*chrc_id=*/2,
415                      PeerId{3},
416                      std::vector<uint8_t>{1},
417                      std::move(indicate_cb));
418   EXPECT_EQ(fit::failed(), res);
419 }
420 
421 class GattTestBoolParam : public GattTest,
422                           public ::testing::WithParamInterface<bool> {};
423 
TEST_P(GattTestBoolParam,SendIndicationReceiveResponse)424 TEST_P(GattTestBoolParam, SendIndicationReceiveResponse) {
425   testing::MockServer::WeakPtr mock_server;
426   auto mock_server_factory = [&](PeerId peer_id,
427                                  LocalServiceManager::WeakPtr local_services) {
428     auto unique_mock_server = std::make_unique<testing::MockServer>(
429         peer_id, std::move(local_services));
430     mock_server = unique_mock_server->AsMockWeakPtr();
431     return unique_mock_server;
432   };
433   gatt()->AddConnection(kPeerId, take_client(), std::move(mock_server_factory));
434   ASSERT_TRUE(mock_server.is_alive());
435 
436   // Configure how the mock server handles updates sent from the GATT object.
437   IndicationCallback mock_ind_cb = nullptr;
438   const std::vector<uint8_t> kIndicateVal{114};  // 114 is arbitrary
439   testing::UpdateHandler handler = [&](auto /*ignore*/,
440                                        auto /*ignore*/,
441                                        const ByteBuffer& bytes,
442                                        IndicationCallback ind_cb) {
443     EXPECT_EQ(kIndicateVal, bytes.ToVector());
444     mock_ind_cb = std::move(ind_cb);
445   };
446   mock_server->set_update_handler(std::move(handler));
447 
448   // Registering the service isn't strictly necessary as gatt::GATT itself is
449   // not responsible for checking that a service exists before sending an
450   // update, but it's a more realistic test.
451   IdType svc_id = RegisterArbitraryService();
452 
453   std::optional<att::Result<>> indicate_status;
454   auto indicate_cb = [&](att::Result<> status) { indicate_status = status; };
455   gatt()->SendUpdate(
456       svc_id, kChrcId, kPeerId, kIndicateVal, std::move(indicate_cb));
457   RunUntilIdle();
458   EXPECT_TRUE(mock_ind_cb);
459   EXPECT_FALSE(indicate_status.has_value());
460   if (GetParam()) {
461     mock_ind_cb(fit::ok());
462     ASSERT_TRUE(indicate_status.has_value());
463     EXPECT_TRUE(indicate_status->is_ok());
464   } else {
465     mock_ind_cb(ToResult(HostError::kTimedOut));
466     ASSERT_TRUE(indicate_status.has_value());
467     EXPECT_EQ(ToResult(HostError::kTimedOut), *indicate_status);
468   }
469 }
470 
471 INSTANTIATE_TEST_SUITE_P(GattTestBoolParamTests,
472                          GattTestBoolParam,
473                          ::testing::Bool());
474 
TEST_F(GattTest,NotifyConnectedPeersNoneConnectedDoesntCrash)475 TEST_F(GattTest, NotifyConnectedPeersNoneConnectedDoesntCrash) {
476   // Registering a service isn't strictly necessary, but makes for a more
477   // realistic test.
478   IdType svc_id = RegisterArbitraryService();
479 
480   const std::vector<uint8_t> kNotifyVal{12u};
481   gatt()->UpdateConnectedPeers(
482       svc_id, kChrcId, kNotifyVal, /*indicate_cb=*/nullptr);
483   RunUntilIdle();
484 }
485 
TEST_F(GattTest,NotifyConnectedPeerWithConnectionDoesntCrash)486 TEST_F(GattTest, NotifyConnectedPeerWithConnectionDoesntCrash) {
487   // Registering a service isn't strictly necessary, but makes for a more
488   // realistic test.
489   IdType svc_id = RegisterArbitraryService();
490 
491   testing::MockServer::WeakPtr mock_server;
492   auto mock_server_factory = [&](PeerId peer_id,
493                                  LocalServiceManager::WeakPtr local_services) {
494     auto unique_mock_server = std::make_unique<testing::MockServer>(
495         peer_id, std::move(local_services));
496     mock_server = unique_mock_server->AsMockWeakPtr();
497     return unique_mock_server;
498   };
499   gatt()->AddConnection(kPeerId, take_client(), std::move(mock_server_factory));
500   ASSERT_TRUE(mock_server.is_alive());
501 
502   // Configure how the mock server handles updates sent from the GATT object.
503   IndicationCallback mock_ind_cb = [](att::Result<>) {};  // no-op, but not-null
504   const std::vector<uint8_t> kNotifyVal{12u};
505   testing::UpdateHandler handler = [&](auto /*ignore*/,
506                                        auto /*ignore*/,
507                                        const ByteBuffer& bytes,
508                                        IndicationCallback ind_cb) {
509     EXPECT_EQ(kNotifyVal, bytes.ToVector());
510     mock_ind_cb = std::move(ind_cb);
511   };
512   mock_server->set_update_handler(std::move(handler));
513   gatt()->UpdateConnectedPeers(
514       svc_id, kChrcId, kNotifyVal, /*indicate_cb=*/nullptr);
515   RunUntilIdle();
516   EXPECT_EQ(nullptr, mock_ind_cb);
517 }
518 
TEST_F(GattTest,IndicateConnectedPeersNoneConnectedSucceeds)519 TEST_F(GattTest, IndicateConnectedPeersNoneConnectedSucceeds) {
520   // Registering a service isn't strictly necessary, but makes for a more
521   // realistic test.
522   IdType svc_id = RegisterArbitraryService();
523 
524   const std::vector<uint8_t> indicate_val{12u};
525   att::Result<> res = ToResult(att::ErrorCode::kAttributeNotFound);
526   auto indicate_cb = [&](att::Result<> cb_res) { res = cb_res; };
527   gatt()->UpdateConnectedPeers(
528       svc_id, kChrcId, indicate_val, std::move(indicate_cb));
529 
530   EXPECT_EQ(fit::ok(), res);
531 }
532 
533 struct PeerIdAndMtu {
534   PeerId peer_id;
535   uint16_t mtu;
536 };
TEST_F(GattTest,UpdateMtuListenersNotified)537 TEST_F(GattTest, UpdateMtuListenersNotified) {
538   // Add MTU listeners to GATT
539   std::optional<PeerIdAndMtu> listener_1_results;
540   auto listener_1 = [&](PeerId peer_id, uint16_t mtu) {
541     listener_1_results = PeerIdAndMtu{.peer_id = peer_id, .mtu = mtu};
542   };
543   std::optional<PeerIdAndMtu> listener_2_results;
544   auto listener_2 = [&](PeerId peer_id, uint16_t mtu) {
545     listener_2_results = PeerIdAndMtu{.peer_id = peer_id, .mtu = mtu};
546   };
547   gatt()->RegisterPeerMtuListener(std::move(listener_1));
548   GATT::PeerMtuListenerId listener_2_id =
549       gatt()->RegisterPeerMtuListener(std::move(listener_2));
550 
551   // Configure MTU
552   const uint16_t kExpectedMtu = att::kLEMinMTU + 1;
553   fake_client()->set_server_mtu(kExpectedMtu);
554 
555   // Add connection, initialize, and verify that MTU exchange succeeds
556   gatt()->AddConnection(kPeerId0, take_client(), CreateMockServer);
557   gatt()->InitializeClient(kPeerId0, {});
558   RunUntilIdle();
559 
560   ASSERT_TRUE(listener_1_results.has_value());
561   EXPECT_EQ(kPeerId0, listener_1_results->peer_id);
562   EXPECT_EQ(kExpectedMtu, listener_1_results->mtu);
563   ASSERT_TRUE(listener_2_results.has_value());
564   EXPECT_EQ(kPeerId0, listener_2_results->peer_id);
565   EXPECT_EQ(kExpectedMtu, listener_2_results->mtu);
566 
567   // After unregistering listener_2, only listener_1 should be notified for the
568   // next update
569   listener_1_results.reset();
570   listener_2_results.reset();
571   EXPECT_TRUE(gatt()->UnregisterPeerMtuListener(listener_2_id));
572   auto client_2 = std::make_unique<testing::FakeClient>(dispatcher());
573   const uint16_t kNewExpectedMtu = kExpectedMtu + 1;
574   client_2->set_server_mtu(kNewExpectedMtu);
575   gatt()->AddConnection(kPeerId1, std::move(client_2), CreateMockServer);
576   gatt()->InitializeClient(kPeerId1, {});
577   RunUntilIdle();
578 
579   ASSERT_TRUE(listener_1_results.has_value());
580   EXPECT_EQ(kPeerId1, listener_1_results->peer_id);
581   EXPECT_EQ(kNewExpectedMtu, listener_1_results->mtu);
582   EXPECT_FALSE(listener_2_results.has_value());
583 }
584 
TEST_F(GattTest,MtuExchangeServerNotSupportedListenersNotifiedDefaultMtu)585 TEST_F(GattTest, MtuExchangeServerNotSupportedListenersNotifiedDefaultMtu) {
586   // Add MTU listeners to GATT
587   std::optional<PeerIdAndMtu> listener_1_results;
588   auto listener_1 = [&](PeerId peer_id, uint16_t mtu) {
589     listener_1_results = PeerIdAndMtu{.peer_id = peer_id, .mtu = mtu};
590   };
591   std::optional<PeerIdAndMtu> listener_2_results;
592   auto listener_2 = [&](PeerId peer_id, uint16_t mtu) {
593     listener_2_results = PeerIdAndMtu{.peer_id = peer_id, .mtu = mtu};
594   };
595   gatt()->RegisterPeerMtuListener(std::move(listener_1));
596   gatt()->RegisterPeerMtuListener(std::move(listener_2));
597 
598   // It should be OK for the MTU exchange to fail with kRequestNotSupported, in
599   // which case we use the default LE MTU per v5.3 Vol. 3 Part G 4.3.1 (not the
600   // Server MTU)
601   fake_client()->set_server_mtu(att::kLEMinMTU + 5);
602   fake_client()->set_exchange_mtu_status(
603       ToResult(att::ErrorCode::kRequestNotSupported));
604   gatt()->AddConnection(kPeerId0, take_client(), CreateMockServer);
605   gatt()->InitializeClient(kPeerId0, {});
606   RunUntilIdle();
607 
608   ASSERT_TRUE(listener_1_results.has_value());
609   EXPECT_EQ(kPeerId0, listener_1_results->peer_id);
610   EXPECT_EQ(att::kLEMinMTU, listener_1_results->mtu);
611   ASSERT_TRUE(listener_2_results.has_value());
612   EXPECT_EQ(kPeerId0, listener_2_results->peer_id);
613   EXPECT_EQ(att::kLEMinMTU, listener_2_results->mtu);
614 }
615 
TEST_F(GattTest,MtuExchangeFailsListenersNotNotifiedConnectionShutdown)616 TEST_F(GattTest, MtuExchangeFailsListenersNotNotifiedConnectionShutdown) {
617   // Add MTU listener to GATT
618   bool listener_invoked = false;
619   auto listener = [&](PeerId /*ignore*/, uint16_t /*ignore*/) {
620     listener_invoked = true;
621   };
622   gatt()->RegisterPeerMtuListener(std::move(listener));
623 
624   // Configure MTU exchange to fail
625   fake_client()->set_exchange_mtu_status(ToResult(HostError::kFailed));
626 
627   // Track mock server
628   testing::MockServer::WeakPtr mock_server;
629   auto mock_server_factory = [&](PeerId peer_id,
630                                  LocalServiceManager::WeakPtr local_services) {
631     auto unique_mock_server = std::make_unique<testing::MockServer>(
632         peer_id, std::move(local_services));
633     mock_server = unique_mock_server->AsMockWeakPtr();
634     return unique_mock_server;
635   };
636 
637   // Add connection, initialize, and verify that MTU exchange failure causes
638   // connection shutdown.
639   gatt()->AddConnection(
640       kPeerId0, take_client(), std::move(mock_server_factory));
641   gatt()->InitializeClient(kPeerId0, {});
642   RunUntilIdle();
643   EXPECT_FALSE(listener_invoked);
644   ASSERT_TRUE(mock_server.is_alive());
645   EXPECT_TRUE(mock_server->was_shut_down());
646 }
647 
648 const std::vector<uint8_t> kIndicateVal{12u};
649 class GattIndicateMultipleConnectedPeersTest : public GattTest {
650  protected:
SetUp()651   void SetUp() override {
652     GattTest::SetUp();
653     // Registering a service isn't strictly necessary, but makes for a more
654     // realistic test.
655     svc_id_ = RegisterArbitraryService();
656 
657     // Add first connection
658     auto mock_server_factory_0 =
659         [&](PeerId peer_id, LocalServiceManager::WeakPtr local_services) {
660           auto unique_mock_server = std::make_unique<testing::MockServer>(
661               peer_id, std::move(local_services));
662           mock_server_0_ = unique_mock_server->AsMockWeakPtr();
663           return unique_mock_server;
664         };
665     gatt()->AddConnection(kPeerId0,
666                           std::make_unique<testing::FakeClient>(dispatcher()),
667                           std::move(mock_server_factory_0));
668     ASSERT_TRUE(mock_server_0_.is_alive());
669 
670     // Add second connection
671     auto mock_server_factory_1 =
672         [&](PeerId peer_id, LocalServiceManager::WeakPtr local_services) {
673           auto unique_mock_server = std::make_unique<testing::MockServer>(
674               peer_id, std::move(local_services));
675           mock_server_1_ = unique_mock_server->AsMockWeakPtr();
676           return unique_mock_server;
677         };
678     gatt()->AddConnection(kPeerId1,
679                           std::make_unique<testing::FakeClient>(dispatcher()),
680                           std::move(mock_server_factory_1));
681     ASSERT_TRUE(mock_server_1_.is_alive());
682 
683     // Configure how the mock servers handle updates from the GATT object.
684     testing::UpdateHandler handler_0 = [&](auto /*ignore*/,
685                                            auto /*ignore*/,
686                                            const ByteBuffer& bytes,
687                                            IndicationCallback ind_cb) {
688       EXPECT_EQ(kIndicateVal, bytes.ToVector());
689       indication_ack_cb_0_ = std::move(ind_cb);
690     };
691     mock_server_0_->set_update_handler(std::move(handler_0));
692 
693     testing::UpdateHandler handler_1 = [&](auto /*ignore*/,
694                                            auto /*ignore*/,
695                                            const ByteBuffer& bytes,
696                                            IndicationCallback ind_cb) {
697       EXPECT_EQ(kIndicateVal, bytes.ToVector());
698       indication_ack_cb_1_ = std::move(ind_cb);
699     };
700     mock_server_1_->set_update_handler(std::move(handler_1));
701   }
702 
703   IndicationCallback indication_ack_cb_0_;
704   IndicationCallback indication_ack_cb_1_;
705   IdType svc_id_;
706   testing::MockServer::WeakPtr mock_server_0_;
707   testing::MockServer::WeakPtr mock_server_1_;
708 };
709 
TEST_F(GattIndicateMultipleConnectedPeersTest,UpdateConnectedPeersWaitsTillAllCallbacksComplete)710 TEST_F(GattIndicateMultipleConnectedPeersTest,
711        UpdateConnectedPeersWaitsTillAllCallbacksComplete) {
712   // Send an indication.
713   att::Result<> res =
714       ToResult(att::ErrorCode::kInvalidPDU);  // arbitrary error code
715   IndicationCallback indication_cb = [&res](att::Result<> cb_res) {
716     res = cb_res;
717   };
718   gatt()->UpdateConnectedPeers(
719       svc_id_, kChrcId, kIndicateVal, indication_cb.share());
720   RunUntilIdle();
721   ASSERT_TRUE(indication_ack_cb_0_);
722   ASSERT_TRUE(indication_ack_cb_1_);
723 
724   // The UpdateConnectedPeers callback shouldn't resolved when the first
725   // indication is ACKed.
726   indication_ack_cb_0_(fit::ok());
727   RunUntilIdle();
728   EXPECT_EQ(ToResult(att::ErrorCode::kInvalidPDU), res);
729 
730   indication_ack_cb_1_(fit::ok());
731   RunUntilIdle();
732   EXPECT_EQ(fit::ok(), res);
733 }
734 
TEST_F(GattIndicateMultipleConnectedPeersTest,OneFailsNextSucceedsOnlyFailureNotified)735 TEST_F(GattIndicateMultipleConnectedPeersTest,
736        OneFailsNextSucceedsOnlyFailureNotified) {
737   std::optional<att::Result<>> res;
738   IndicationCallback indication_cb = [&res](att::Result<> cb_res) {
739     res = cb_res;
740   };
741   gatt()->UpdateConnectedPeers(
742       svc_id_, kChrcId, kIndicateVal, indication_cb.share());
743   RunUntilIdle();
744   EXPECT_EQ(std::nullopt, res);
745   ASSERT_TRUE(indication_ack_cb_0_);
746   ASSERT_TRUE(indication_ack_cb_1_);
747 
748   indication_ack_cb_0_(ToResult(att::ErrorCode::kRequestNotSupported));
749   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), res);
750 
751   // Acking the next indication should not cause the callback to be invoked
752   // again with success.
753   indication_ack_cb_1_(fit::ok());
754   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), res);
755 }
756 
757 }  // namespace
758 }  // namespace bt::gatt::internal
759