xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/fuchsia/host/fidl/gatt2_server_server_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 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/fuchsia/host/fidl/gatt2_server_server.h"
16 
17 #include <fuchsia/bluetooth/gatt2/cpp/fidl_test_base.h>
18 #include <gmock/gmock.h>
19 #include <zircon/status.h>
20 
21 #include <algorithm>
22 #include <optional>
23 
24 #include "fuchsia/bluetooth/cpp/fidl.h"
25 #include "fuchsia/bluetooth/gatt2/cpp/fidl.h"
26 #include "lib/fidl/cpp/interface_handle.h"
27 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/fake_gatt_fixture.h"
28 #include "pw_unit_test/framework.h"
29 
30 namespace bthost {
31 namespace {
32 
33 namespace fbg = fuchsia::bluetooth::gatt2;
34 namespace fbt = fuchsia::bluetooth;
35 
36 const std::vector<uint8_t> kBuffer = {0x00, 0x01, 0x02};
37 
BuildSimpleCharacteristic(uint64_t handle)38 fbg::Characteristic BuildSimpleCharacteristic(uint64_t handle) {
39   fbg::Characteristic chrc;
40   fbg::Handle chrc_handle{handle};
41   chrc.set_handle(chrc_handle);
42   chrc.set_type(fbt::Uuid{{6}});
43   chrc.set_properties(fbg::CharacteristicPropertyBits::READ);
44   fbg::AttributePermissions permissions;
45   fbg::SecurityRequirements security;
46   security.set_encryption_required(true);
47   permissions.set_read(std::move(security));
48   chrc.set_permissions(std::move(permissions));
49   return chrc;
50 }
51 
BuildSimpleService(uint64_t svc_handle=1,bt::UInt128 svc_type={5},uint64_t chrc_handle=2)52 fbg::ServiceInfo BuildSimpleService(uint64_t svc_handle = 1,
53                                     bt::UInt128 svc_type = {5},
54                                     uint64_t chrc_handle = 2) {
55   fbg::ServiceInfo svc_info;
56   svc_info.set_handle(fbg::ServiceHandle{svc_handle});
57   svc_info.set_type(fbt::Uuid{svc_type});
58 
59   std::vector<fbg::Characteristic> chrcs;
60   chrcs.push_back(BuildSimpleCharacteristic(chrc_handle));
61   svc_info.set_characteristics(std::move(chrcs));
62 
63   return svc_info;
64 }
65 
66 class MockLocalService final : private ServerBase<fbg::LocalService> {
67  public:
68   using ReadValueFunction =
69       fit::function<void(fbt::PeerId, fbg::Handle, int32_t, ReadValueCallback)>;
70   using WriteValueFunction = fit::function<void(
71       fbg::LocalServiceWriteValueRequest, WriteValueCallback)>;
72   using CccFunction = fit::function<void(fbt::PeerId,
73                                          fbg::Handle,
74                                          bool,
75                                          bool,
76                                          CharacteristicConfigurationCallback)>;
77 
MockLocalService(fidl::InterfaceRequest<fbg::LocalService> request)78   MockLocalService(fidl::InterfaceRequest<fbg::LocalService> request)
79       : ServerBase<fbg::LocalService>(this, std::move(request)) {
80     set_error_handler([this](zx_status_t status) { error_ = status; });
81   }
82 
set_read_value_function(ReadValueFunction func)83   void set_read_value_function(ReadValueFunction func) {
84     read_value_func_ = std::move(func);
85   }
set_write_value_function(WriteValueFunction func)86   void set_write_value_function(WriteValueFunction func) {
87     write_value_func_ = std::move(func);
88   }
set_ccc_function(CccFunction func)89   void set_ccc_function(CccFunction func) { ccc_func_ = std::move(func); }
90 
credits() const91   int credits() const { return credits_; }
92 
credit_log() const93   const std::vector<uint8_t>& credit_log() const { return credits_log_; }
94 
NotifyValue(fbg::ValueChangedParameters update)95   void NotifyValue(fbg::ValueChangedParameters update) {
96     credits_--;
97     binding()->events().OnNotifyValue(std::move(update));
98   }
99 
IndicateValue(fbg::ValueChangedParameters update,zx::eventpair confirmation)100   void IndicateValue(fbg::ValueChangedParameters update,
101                      zx::eventpair confirmation) {
102     credits_--;
103     binding()->events().OnIndicateValue(std::move(update),
104                                         std::move(confirmation));
105   }
106 
error() const107   std::optional<zx_status_t> error() const { return error_; }
108 
109  private:
110   // fbg::LocalService overrides:
CharacteristicConfiguration(fbt::PeerId peer_id,fbg::Handle handle,bool notify,bool indicate,CharacteristicConfigurationCallback callback)111   void CharacteristicConfiguration(
112       fbt::PeerId peer_id,
113       fbg::Handle handle,
114       bool notify,
115       bool indicate,
116       CharacteristicConfigurationCallback callback) override {
117     if (ccc_func_) {
118       ccc_func_(peer_id, handle, notify, indicate, std::move((callback)));
119     }
120   }
ReadValue(fbt::PeerId peer_id,fbg::Handle handle,int32_t offset,ReadValueCallback callback)121   void ReadValue(fbt::PeerId peer_id,
122                  fbg::Handle handle,
123                  int32_t offset,
124                  ReadValueCallback callback) override {
125     if (read_value_func_) {
126       read_value_func_(peer_id, handle, offset, std::move(callback));
127     }
128   }
WriteValue(fbg::LocalServiceWriteValueRequest req,WriteValueCallback callback)129   void WriteValue(fbg::LocalServiceWriteValueRequest req,
130                   WriteValueCallback callback) override {
131     if (write_value_func_) {
132       write_value_func_(std::move(req), std::move(callback));
133     }
134   }
PeerUpdate(fbg::LocalServicePeerUpdateRequest req,PeerUpdateCallback callback)135   void PeerUpdate(fbg::LocalServicePeerUpdateRequest req,
136                   PeerUpdateCallback callback) override {}
ValueChangedCredit(uint8_t additional_credit)137   void ValueChangedCredit(uint8_t additional_credit) override {
138     credits_ += additional_credit;
139     credits_log_.push_back(additional_credit);
140   }
141 
142   ReadValueFunction read_value_func_;
143   WriteValueFunction write_value_func_;
144   CccFunction ccc_func_;
145   // Use signed integer because in tests it is possible to have negative
146   // credits.
147   int credits_ = fbg::INITIAL_VALUE_CHANGED_CREDITS;
148   std::vector<uint8_t> credits_log_;
149   std::optional<zx_status_t> error_;
150 };
151 
152 class Gatt2ServerServerTest : public bt::fidl::testing::FakeGattFixture {
153  public:
154   ~Gatt2ServerServerTest() override = default;
155 
Gatt2ServerServerTest()156   Gatt2ServerServerTest() {}
157 
SetUp()158   void SetUp() override {
159     // Create and connect to production GATT2 Server implementation
160     fidl::InterfaceHandle<fbg::Server> server_handle;
161     server_ = std::make_unique<Gatt2ServerServer>(gatt()->GetWeakPtr(),
162                                                   server_handle.NewRequest());
163     server_ptr_ = server_handle.Bind();
164   }
165 
TearDown()166   void TearDown() override {}
167 
168  protected:
server_ptr()169   fbg::ServerPtr& server_ptr() { return server_ptr_; }
170 
DestroyServer()171   void DestroyServer() { server_.reset(); }
172 
173  private:
174   // Proxy interface to the GATT2 Server implementation.
175   fbg::ServerPtr server_ptr_;
176   // Raw GATT2 Server implementation
177   std::unique_ptr<Gatt2ServerServer> server_;
178 };
179 
TEST_F(Gatt2ServerServerTest,PublishAndRemoveServiceWithTwoCharacteristicsSuccess)180 TEST_F(Gatt2ServerServerTest,
181        PublishAndRemoveServiceWithTwoCharacteristicsSuccess) {
182   fbg::ServiceInfo svc_info;
183   svc_info.set_handle(fbg::ServiceHandle{1});
184   bt::UInt128 svc_type = {5};
185   svc_info.set_type(fbt::Uuid{svc_type});
186 
187   std::vector<fbg::Characteristic> characteristics;
188   characteristics.push_back(BuildSimpleCharacteristic(/*handle=*/2));
189   characteristics.push_back(BuildSimpleCharacteristic(/*handle=*/3));
190   svc_info.set_characteristics(std::move(characteristics));
191 
192   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_0;
193   fidl::InterfaceRequest<fbg::LocalService> request =
194       local_service_handle_0.NewRequest();
195 
196   int cb_count = 0;
197   auto cb = [&](fbg::Server_PublishService_Result res) {
198     EXPECT_TRUE(res.is_response());
199     cb_count++;
200   };
201   server_ptr()->PublishService(
202       std::move(svc_info), std::move(local_service_handle_0), std::move(cb));
203   RunLoopUntilIdle();
204   EXPECT_EQ(cb_count, 1);
205   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
206   bt::gatt::Service* service =
207       fake_gatt()->local_services().begin()->second.service.get();
208   EXPECT_EQ(service->type(), svc_type);
209   EXPECT_TRUE(service->primary());
210   ASSERT_EQ(service->characteristics().size(), 2u);
211   EXPECT_EQ(service->characteristics()[0]->id(), 2u);
212   EXPECT_EQ(service->characteristics()[1]->id(), 3u);
213 
214   request.Close(ZX_ERR_PEER_CLOSED);
215   RunLoopUntilIdle();
216   EXPECT_EQ(fake_gatt()->local_services().size(), 0u);
217 }
218 
TEST_F(Gatt2ServerServerTest,DestroyingServerUnregistersService)219 TEST_F(Gatt2ServerServerTest, DestroyingServerUnregistersService) {
220   bt::UInt128 svc_type = {5};
221   fbg::ServiceInfo svc_info = BuildSimpleService(/*svc_handle=*/1, svc_type);
222 
223   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
224   fidl::InterfaceRequest<fbg::LocalService> request =
225       local_service_handle.NewRequest();
226 
227   int cb_count = 0;
228   auto cb = [&](fbg::Server_PublishService_Result res) {
229     EXPECT_TRUE(res.is_response());
230     cb_count++;
231   };
232   server_ptr()->PublishService(
233       std::move(svc_info), std::move(local_service_handle), std::move(cb));
234   RunLoopUntilIdle();
235   EXPECT_EQ(cb_count, 1);
236   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
237   EXPECT_EQ(
238       fake_gatt()->local_services().begin()->second.service->type().value(),
239       svc_type);
240   DestroyServer();
241   EXPECT_EQ(fake_gatt()->local_services().size(), 0u);
242 }
243 
TEST_F(Gatt2ServerServerTest,PublishServiceWithoutHandleFails)244 TEST_F(Gatt2ServerServerTest, PublishServiceWithoutHandleFails) {
245   fbg::ServiceInfo svc_info = BuildSimpleService();
246   svc_info.clear_handle();
247 
248   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
249   auto request = local_service_handle.NewRequest();
250 
251   int cb_count = 0;
252   auto cb = [&](fbg::Server_PublishService_Result res) {
253     ASSERT_TRUE(res.is_err());
254     EXPECT_EQ(res.err(), fbg::PublishServiceError::INVALID_SERVICE_HANDLE);
255     cb_count++;
256   };
257   server_ptr()->PublishService(
258       std::move(svc_info), std::move(local_service_handle), std::move(cb));
259   RunLoopUntilIdle();
260   EXPECT_EQ(cb_count, 1);
261   EXPECT_EQ(fake_gatt()->local_services().size(), 0u);
262 }
263 
TEST_F(Gatt2ServerServerTest,PublishServiceWithoutTypeFails)264 TEST_F(Gatt2ServerServerTest, PublishServiceWithoutTypeFails) {
265   fbg::ServiceInfo svc_info = BuildSimpleService();
266   svc_info.clear_type();
267 
268   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
269   auto request = local_service_handle.NewRequest();
270 
271   int cb_count = 0;
272   auto cb = [&](fbg::Server_PublishService_Result res) {
273     ASSERT_TRUE(res.is_err());
274     EXPECT_EQ(res.err(), fbg::PublishServiceError::INVALID_UUID);
275     cb_count++;
276   };
277   server_ptr()->PublishService(
278       std::move(svc_info), std::move(local_service_handle), std::move(cb));
279   RunLoopUntilIdle();
280   EXPECT_EQ(cb_count, 1);
281   EXPECT_EQ(fake_gatt()->local_services().size(), 0u);
282 }
283 
TEST_F(Gatt2ServerServerTest,PublishServiceWithoutCharacteristicsFails)284 TEST_F(Gatt2ServerServerTest, PublishServiceWithoutCharacteristicsFails) {
285   fbg::ServiceInfo svc_info = BuildSimpleService();
286   svc_info.clear_characteristics();
287 
288   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
289   auto request = local_service_handle.NewRequest();
290 
291   int cb_count = 0;
292   auto cb = [&](fbg::Server_PublishService_Result res) {
293     ASSERT_TRUE(res.is_err());
294     EXPECT_EQ(res.err(), fbg::PublishServiceError::INVALID_CHARACTERISTICS);
295     cb_count++;
296   };
297   server_ptr()->PublishService(
298       std::move(svc_info), std::move(local_service_handle), std::move(cb));
299   RunLoopUntilIdle();
300   EXPECT_EQ(cb_count, 1);
301   EXPECT_EQ(fake_gatt()->local_services().size(), 0u);
302 }
303 
TEST_F(Gatt2ServerServerTest,PublishServiceWithReusedHandleFails)304 TEST_F(Gatt2ServerServerTest, PublishServiceWithReusedHandleFails) {
305   fbg::ServiceInfo svc_info_0 = BuildSimpleService();
306 
307   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_0;
308   auto request_0 = local_service_handle_0.NewRequest();
309 
310   int cb_count_0 = 0;
311   auto cb_0 = [&](fbg::Server_PublishService_Result res) {
312     EXPECT_TRUE(res.is_response());
313     cb_count_0++;
314   };
315   server_ptr()->PublishService(std::move(svc_info_0),
316                                std::move(local_service_handle_0),
317                                std::move(cb_0));
318   RunLoopUntilIdle();
319   EXPECT_EQ(cb_count_0, 1);
320   EXPECT_EQ(fake_gatt()->local_services().size(), 1u);
321 
322   fbg::ServiceInfo svc_info_1 = BuildSimpleService();
323 
324   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_1;
325   auto request_1 = local_service_handle_1.NewRequest();
326 
327   int cb_count_1 = 0;
328   auto cb_1 = [&](fbg::Server_PublishService_Result res) {
329     ASSERT_TRUE(res.is_err());
330     EXPECT_EQ(res.err(), fbg::PublishServiceError::INVALID_SERVICE_HANDLE);
331     cb_count_1++;
332   };
333   server_ptr()->PublishService(std::move(svc_info_1),
334                                std::move(local_service_handle_1),
335                                std::move(cb_1));
336   RunLoopUntilIdle();
337   EXPECT_EQ(cb_count_1, 1);
338   EXPECT_EQ(fake_gatt()->local_services().size(), 1u);
339 }
340 
TEST_F(Gatt2ServerServerTest,PublishServiceWithReusedHandleAcrossTwoGattServersSuccceeds)341 TEST_F(Gatt2ServerServerTest,
342        PublishServiceWithReusedHandleAcrossTwoGattServersSuccceeds) {
343   // Both services are identical.
344   fbg::ServiceInfo svc_info_0 = BuildSimpleService();
345   fbg::ServiceInfo svc_info_1 = BuildSimpleService();
346 
347   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_0;
348   auto request_0 = local_service_handle_0.NewRequest();
349 
350   int cb_count_0 = 0;
351   auto cb_0 = [&](fbg::Server_PublishService_Result res) {
352     EXPECT_TRUE(res.is_response());
353     cb_count_0++;
354   };
355   server_ptr()->PublishService(std::move(svc_info_0),
356                                std::move(local_service_handle_0),
357                                std::move(cb_0));
358   RunLoopUntilIdle();
359   EXPECT_EQ(cb_count_0, 1);
360   EXPECT_EQ(fake_gatt()->local_services().size(), 1u);
361 
362   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_1;
363   auto request_1 = local_service_handle_1.NewRequest();
364 
365   int cb_count_1 = 0;
366   auto cb_1 = [&](fbg::Server_PublishService_Result res) {
367     EXPECT_TRUE(res.is_response());
368     cb_count_1++;
369   };
370 
371   // Create and connect to a second GATT Server implementation
372   fidl::InterfaceHandle<fbg::Server> server_handle_1;
373   auto server_1 = std::make_unique<Gatt2ServerServer>(
374       gatt()->GetWeakPtr(), server_handle_1.NewRequest());
375   fidl::InterfacePtr<fuchsia::bluetooth::gatt2::Server> server_ptr_1 =
376       server_handle_1.Bind();
377   // Publish an identical service.
378   server_ptr_1->PublishService(std::move(svc_info_1),
379                                std::move(local_service_handle_1),
380                                std::move(cb_1));
381   RunLoopUntilIdle();
382   EXPECT_EQ(cb_count_1, 1);
383   ASSERT_EQ(fake_gatt()->local_services().size(), 2u);
384 }
385 
TEST_F(Gatt2ServerServerTest,PublishTwoServicesSuccess)386 TEST_F(Gatt2ServerServerTest, PublishTwoServicesSuccess) {
387   bt::UInt128 svc_type_0 = {5};
388   fbg::ServiceInfo svc_info_0 =
389       BuildSimpleService(/*svc_handle=*/1, svc_type_0);
390 
391   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_0;
392   fidl::InterfaceRequest<fbg::LocalService> request_0 =
393       local_service_handle_0.NewRequest();
394 
395   int cb_count_0 = 0;
396   auto cb_0 = [&](fbg::Server_PublishService_Result res) {
397     EXPECT_TRUE(res.is_response());
398     cb_count_0++;
399   };
400   server_ptr()->PublishService(std::move(svc_info_0),
401                                std::move(local_service_handle_0),
402                                std::move(cb_0));
403   RunLoopUntilIdle();
404   EXPECT_EQ(cb_count_0, 1);
405   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
406   bt::gatt::Service* service =
407       fake_gatt()->local_services().begin()->second.service.get();
408   EXPECT_EQ(service->type(), svc_type_0);
409 
410   bt::UInt128 svc_type_1 = {6};
411   fbg::ServiceInfo svc_info_1 =
412       BuildSimpleService(/*svc_handle=*/9, svc_type_1);
413 
414   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_1;
415   fidl::InterfaceRequest<fbg::LocalService> request_1 =
416       local_service_handle_1.NewRequest();
417 
418   int cb_count_1 = 0;
419   auto cb_1 = [&](fbg::Server_PublishService_Result res) {
420     EXPECT_TRUE(res.is_response());
421     cb_count_1++;
422   };
423   server_ptr()->PublishService(std::move(svc_info_1),
424                                std::move(local_service_handle_1),
425                                std::move(cb_1));
426   RunLoopUntilIdle();
427   EXPECT_EQ(cb_count_1, 1);
428   ASSERT_EQ(fake_gatt()->local_services().size(), 2u);
429   auto svc_iter = fake_gatt()->local_services().begin();
430   EXPECT_EQ(svc_iter->second.service->type(), svc_type_0);
431   svc_iter++;
432   EXPECT_EQ(svc_iter->second.service->type(), svc_type_1);
433 
434   request_0.Close(ZX_ERR_PEER_CLOSED);
435   request_1.Close(ZX_ERR_PEER_CLOSED);
436   RunLoopUntilIdle();
437   EXPECT_EQ(fake_gatt()->local_services().size(), 0u);
438 }
439 
TEST_F(Gatt2ServerServerTest,PublishSecondaryService)440 TEST_F(Gatt2ServerServerTest, PublishSecondaryService) {
441   bt::UInt128 svc_type = {5};
442   fbg::ServiceInfo svc_info = BuildSimpleService(/*svc_handle=*/1, svc_type);
443   svc_info.set_kind(fbg::ServiceKind::SECONDARY);
444 
445   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
446   fidl::InterfaceRequest<fbg::LocalService> request =
447       local_service_handle.NewRequest();
448 
449   int cb_count = 0;
450   auto cb = [&](fbg::Server_PublishService_Result res) {
451     EXPECT_TRUE(res.is_response());
452     cb_count++;
453   };
454   server_ptr()->PublishService(
455       std::move(svc_info), std::move(local_service_handle), std::move(cb));
456   RunLoopUntilIdle();
457   EXPECT_EQ(cb_count, 1);
458   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
459   auto svc_iter = fake_gatt()->local_services().begin();
460   EXPECT_EQ(svc_iter->second.service->type(), svc_type);
461   EXPECT_FALSE(svc_iter->second.service->primary());
462 }
463 
TEST_F(Gatt2ServerServerTest,ReadSuccess)464 TEST_F(Gatt2ServerServerTest, ReadSuccess) {
465   uint64_t svc_handle = 1;
466   fbg::ServiceInfo svc_info;
467   svc_info.set_handle(fbg::ServiceHandle{svc_handle});
468   svc_info.set_type(fbt::Uuid{{5}});
469   fbg::Characteristic chrc;
470   fbg::Handle chrc_handle{2};
471   chrc.set_handle(chrc_handle);
472   chrc.set_type(fbt::Uuid{{0}});
473   chrc.set_properties(fbg::CharacteristicPropertyBits::READ);
474   chrc.set_permissions(fbg::AttributePermissions());
475   std::vector<fbg::Characteristic> chrcs;
476   chrcs.push_back(std::move(chrc));
477   svc_info.set_characteristics(std::move(chrcs));
478 
479   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
480   MockLocalService local_svc(local_service_handle.NewRequest());
481 
482   int cb_count = 0;
483   auto cb = [&](fbg::Server_PublishService_Result res) {
484     EXPECT_TRUE(res.is_response());
485     cb_count++;
486   };
487   server_ptr()->PublishService(
488       std::move(svc_info), std::move(local_service_handle), std::move(cb));
489   RunLoopUntilIdle();
490   EXPECT_EQ(cb_count, 1);
491   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
492   auto svc_iter = fake_gatt()->local_services().begin();
493   ASSERT_EQ(svc_iter->second.service->characteristics().size(), 1u);
494 
495   bt::gatt::IdType svc_id = svc_iter->first;
496   bt::gatt::IdType chrc_id =
497       svc_iter->second.service->characteristics()[0]->id();
498   bt::PeerId peer_id(99);
499 
500   int read_value_count = 0;
501   local_svc.set_read_value_function(
502       [&](fbt::PeerId cb_peer_id,
503           fbg::Handle handle,
504           int32_t offset,
505           fbg::LocalService::ReadValueCallback callback) {
506         read_value_count++;
507         EXPECT_EQ(peer_id.value(), cb_peer_id.value);
508         EXPECT_EQ(handle.value, chrc_handle.value);
509         EXPECT_EQ(offset, 3);
510         callback(fpromise::ok(kBuffer));
511       });
512 
513   int read_responder_count = 0;
514   auto read_responder = [&](fit::result<bt::att::ErrorCode> status,
515                             const bt::ByteBuffer& value) {
516     read_responder_count++;
517     EXPECT_TRUE(status.is_ok());
518     EXPECT_THAT(value, ::testing::ElementsAreArray(kBuffer));
519   };
520 
521   svc_iter->second.read_handler(
522       peer_id, svc_id, chrc_id, /*offset=*/3, read_responder);
523   RunLoopUntilIdle();
524   EXPECT_EQ(read_value_count, 1);
525   EXPECT_EQ(read_responder_count, 1);
526 }
527 
TEST_F(Gatt2ServerServerTest,ReadErrorResponse)528 TEST_F(Gatt2ServerServerTest, ReadErrorResponse) {
529   uint64_t svc_handle = 1;
530   fbg::ServiceInfo svc_info;
531   svc_info.set_handle(fbg::ServiceHandle{svc_handle});
532   svc_info.set_type(fbt::Uuid{{5}});
533   fbg::Characteristic chrc;
534   fbg::Handle chrc_handle{2};
535   chrc.set_handle(chrc_handle);
536   chrc.set_type(fbt::Uuid{{0}});
537   chrc.set_properties(fbg::CharacteristicPropertyBits::READ);
538   chrc.set_permissions(fbg::AttributePermissions());
539   std::vector<fbg::Characteristic> chrcs;
540   chrcs.push_back(std::move(chrc));
541   svc_info.set_characteristics(std::move(chrcs));
542 
543   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
544   MockLocalService local_svc(local_service_handle.NewRequest());
545 
546   int cb_count = 0;
547   auto cb = [&](fbg::Server_PublishService_Result res) {
548     EXPECT_TRUE(res.is_response());
549     cb_count++;
550   };
551   server_ptr()->PublishService(
552       std::move(svc_info), std::move(local_service_handle), std::move(cb));
553   RunLoopUntilIdle();
554   EXPECT_EQ(cb_count, 1);
555   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
556   auto svc_iter = fake_gatt()->local_services().begin();
557   ASSERT_EQ(svc_iter->second.service->characteristics().size(), 1u);
558 
559   bt::gatt::IdType svc_id = svc_iter->first;
560   bt::gatt::IdType chrc_id =
561       svc_iter->second.service->characteristics()[0]->id();
562 
563   int read_value_count = 0;
564   local_svc.set_read_value_function(
565       [&](fbt::PeerId cb_peer_id,
566           fbg::Handle handle,
567           int32_t offset,
568           fbg::LocalService::ReadValueCallback callback) {
569         read_value_count++;
570         callback(fpromise::error(fbg::Error::READ_NOT_PERMITTED));
571       });
572 
573   int read_responder_count = 0;
574   auto read_responder = [&](fit::result<bt::att::ErrorCode> status,
575                             const bt::ByteBuffer& value) {
576     read_responder_count++;
577     ASSERT_TRUE(status.is_error());
578     EXPECT_EQ(status.error_value(), bt::att::ErrorCode::kReadNotPermitted);
579     EXPECT_EQ(value.size(), 0u);
580   };
581 
582   svc_iter->second.read_handler(
583       bt::PeerId(42), svc_id, chrc_id, /*offset=*/0, read_responder);
584   RunLoopUntilIdle();
585   EXPECT_EQ(read_value_count, 1);
586   EXPECT_EQ(read_responder_count, 1);
587 }
588 
TEST_F(Gatt2ServerServerTest,WriteSuccess)589 TEST_F(Gatt2ServerServerTest, WriteSuccess) {
590   uint64_t svc_handle = 1;
591   fbg::ServiceInfo svc_info;
592   svc_info.set_handle(fbg::ServiceHandle{svc_handle});
593   svc_info.set_type(fbt::Uuid{{5}});
594   fbg::Characteristic chrc;
595   fbg::Handle chrc_handle{2};
596   chrc.set_handle(chrc_handle);
597   chrc.set_type(fbt::Uuid{{0}});
598   chrc.set_properties(fbg::CharacteristicPropertyBits::WRITE);
599   chrc.set_permissions(fbg::AttributePermissions());
600   std::vector<fbg::Characteristic> chrcs;
601   chrcs.push_back(std::move(chrc));
602   svc_info.set_characteristics(std::move(chrcs));
603 
604   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
605   MockLocalService local_svc(local_service_handle.NewRequest());
606 
607   int cb_count = 0;
608   auto cb = [&](fbg::Server_PublishService_Result res) {
609     EXPECT_TRUE(res.is_response());
610     cb_count++;
611   };
612   server_ptr()->PublishService(
613       std::move(svc_info), std::move(local_service_handle), std::move(cb));
614   RunLoopUntilIdle();
615   EXPECT_EQ(cb_count, 1);
616   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
617   auto svc_iter = fake_gatt()->local_services().begin();
618   ASSERT_EQ(svc_iter->second.service->characteristics().size(), 1u);
619 
620   bt::gatt::IdType svc_id = svc_iter->first;
621   bt::gatt::IdType chrc_id =
622       svc_iter->second.service->characteristics()[0]->id();
623   bt::PeerId peer_id(99);
624   bt::StaticByteBuffer value_buffer(0x00, 0x01, 0x02);
625 
626   int write_value_count = 0;
627   local_svc.set_write_value_function(
628       [&](fbg::LocalServiceWriteValueRequest req,
629           fbg::LocalService::WriteValueCallback cb) {
630         write_value_count++;
631         ASSERT_TRUE(req.has_peer_id());
632         EXPECT_EQ(req.peer_id().value, peer_id.value());
633         ASSERT_TRUE(req.has_handle());
634         EXPECT_EQ(req.handle().value, chrc_handle.value);
635         ASSERT_TRUE(req.has_offset());
636         EXPECT_EQ(req.offset(), 3u);
637         ASSERT_TRUE(req.has_value());
638         EXPECT_THAT(req.value(), ::testing::ElementsAreArray(value_buffer));
639         cb(fpromise::ok());
640       });
641   int write_responder_count = 0;
642   auto write_responder = [&](fit::result<bt::att::ErrorCode> status) {
643     write_responder_count++;
644     EXPECT_TRUE(status.is_ok());
645   };
646   svc_iter->second.write_handler(peer_id,
647                                  svc_id,
648                                  chrc_id,
649                                  /*offset=*/3,
650                                  value_buffer,
651                                  std::move(write_responder));
652   RunLoopUntilIdle();
653   EXPECT_EQ(write_value_count, 1);
654   EXPECT_EQ(write_responder_count, 1);
655 }
656 
TEST_F(Gatt2ServerServerTest,WriteError)657 TEST_F(Gatt2ServerServerTest, WriteError) {
658   uint64_t svc_handle = 1;
659   fbg::ServiceInfo svc_info;
660   svc_info.set_handle(fbg::ServiceHandle{svc_handle});
661   svc_info.set_type(fbt::Uuid{{5}});
662   fbg::Characteristic chrc;
663   fbg::Handle chrc_handle{2};
664   chrc.set_handle(chrc_handle);
665   chrc.set_type(fbt::Uuid{{0}});
666   chrc.set_properties(fbg::CharacteristicPropertyBits::WRITE);
667   chrc.set_permissions(fbg::AttributePermissions());
668   std::vector<fbg::Characteristic> chrcs;
669   chrcs.push_back(std::move(chrc));
670   svc_info.set_characteristics(std::move(chrcs));
671 
672   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
673   MockLocalService local_svc(local_service_handle.NewRequest());
674 
675   int cb_count = 0;
676   auto cb = [&](fbg::Server_PublishService_Result res) {
677     EXPECT_TRUE(res.is_response());
678     cb_count++;
679   };
680   server_ptr()->PublishService(
681       std::move(svc_info), std::move(local_service_handle), std::move(cb));
682   RunLoopUntilIdle();
683   EXPECT_EQ(cb_count, 1);
684   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
685   auto svc_iter = fake_gatt()->local_services().begin();
686   ASSERT_EQ(svc_iter->second.service->characteristics().size(), 1u);
687 
688   bt::gatt::IdType svc_id = svc_iter->first;
689   bt::gatt::IdType chrc_id =
690       svc_iter->second.service->characteristics()[0]->id();
691 
692   int write_value_count = 0;
693   local_svc.set_write_value_function(
694       [&](fbg::LocalServiceWriteValueRequest req,
695           fbg::LocalService::WriteValueCallback cb) {
696         write_value_count++;
697         cb(fpromise::error(fbg::Error::WRITE_NOT_PERMITTED));
698       });
699   int write_responder_count = 0;
700   auto write_responder = [&](fit::result<bt::att::ErrorCode> status) {
701     write_responder_count++;
702     ASSERT_TRUE(status.is_error());
703     EXPECT_EQ(status.error_value(), bt::att::ErrorCode::kWriteNotPermitted);
704   };
705   svc_iter->second.write_handler(bt::PeerId(4),
706                                  svc_id,
707                                  chrc_id,
708                                  /*offset=*/0,
709                                  bt::BufferView(),
710                                  std::move(write_responder));
711   RunLoopUntilIdle();
712   EXPECT_EQ(write_value_count, 1);
713   EXPECT_EQ(write_responder_count, 1);
714 }
715 
TEST_F(Gatt2ServerServerTest,ClientCharacteristicConfiguration)716 TEST_F(Gatt2ServerServerTest, ClientCharacteristicConfiguration) {
717   const uint64_t chrc_handle = 2;
718   fbg::ServiceInfo svc_info =
719       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
720 
721   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
722   MockLocalService local_svc = local_service_handle.NewRequest();
723 
724   int cb_count = 0;
725   auto cb = [&](fbg::Server_PublishService_Result res) {
726     EXPECT_TRUE(res.is_response());
727     cb_count++;
728   };
729   server_ptr()->PublishService(
730       std::move(svc_info), std::move(local_service_handle), std::move(cb));
731   RunLoopUntilIdle();
732   EXPECT_EQ(cb_count, 1);
733   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
734   auto svc_iter = fake_gatt()->local_services().begin();
735   bt::gatt::IdType svc_id = svc_iter->first;
736 
737   bt::PeerId peer_id(4);
738   int ccc_count = 0;
739   local_svc.set_ccc_function(
740       [&](fbt::PeerId cb_peer_id,
741           fbg::Handle handle,
742           bool notify,
743           bool indicate,
744           fbg::LocalService::CharacteristicConfigurationCallback cb) {
745         ccc_count++;
746         EXPECT_EQ(peer_id.value(), cb_peer_id.value);
747         EXPECT_EQ(handle.value, chrc_handle);
748         EXPECT_TRUE(notify);
749         EXPECT_FALSE(indicate);
750         cb();
751       });
752   svc_iter->second.ccc_callback(
753       svc_id, chrc_handle, peer_id, /*notify=*/true, /*indicate=*/false);
754   RunLoopUntilIdle();
755   EXPECT_EQ(ccc_count, 1);
756 }
757 
TEST_F(Gatt2ServerServerTest,IndicateAllPeers)758 TEST_F(Gatt2ServerServerTest, IndicateAllPeers) {
759   const uint64_t chrc_handle = 2;
760   fbg::ServiceInfo svc_info =
761       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
762 
763   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
764   MockLocalService local_svc = local_service_handle.NewRequest();
765 
766   int cb_count = 0;
767   auto cb = [&](fbg::Server_PublishService_Result res) {
768     EXPECT_TRUE(res.is_response());
769     cb_count++;
770   };
771   server_ptr()->PublishService(
772       std::move(svc_info), std::move(local_service_handle), std::move(cb));
773   RunLoopUntilIdle();
774   EXPECT_EQ(cb_count, 1);
775   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
776   auto svc_iter = fake_gatt()->local_services().begin();
777 
778   fbg::ValueChangedParameters params_0;
779   params_0.set_handle(fbg::Handle{chrc_handle});
780   std::vector<uint8_t> buffer = {0x00, 0x01, 0x02};
781   params_0.set_value(buffer);
782   zx::eventpair confirm_ours_0;
783   zx::eventpair confirm_theirs_0;
784   zx::eventpair::create(/*options=*/0, &confirm_ours_0, &confirm_theirs_0);
785   local_svc.IndicateValue(std::move(params_0), std::move(confirm_theirs_0));
786   RunLoopUntilIdle();
787   ASSERT_EQ(svc_iter->second.updates.size(), 1u);
788   EXPECT_EQ(svc_iter->second.updates[0].chrc_id, chrc_handle);
789   EXPECT_EQ(svc_iter->second.updates[0].value, buffer);
790 
791   // Eventpair should not be signalled until indicate_cb called.
792   zx_signals_t observed;
793   zx_status_t status =
794       confirm_ours_0.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
795                               /*deadline=*/zx::time(0),
796                               &observed);
797   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
798   EXPECT_EQ(observed, 0u);
799 
800   svc_iter->second.updates[0].indicate_cb(fit::ok());
801 
802   status =
803       confirm_ours_0.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
804                               /*deadline=*/zx::time(0),
805                               &observed);
806   ASSERT_EQ(status, ZX_OK);
807   // The eventpair should have been signaled before it was closed.
808   EXPECT_EQ(observed, ZX_EVENTPAIR_SIGNALED | ZX_EVENTPAIR_PEER_CLOSED);
809   observed = 0;
810 
811   // Also test with an empty peer_ids vector
812   fbg::ValueChangedParameters params_1;
813   params_1.set_peer_ids({});
814   params_1.set_handle(fbg::Handle{chrc_handle});
815   params_1.set_value(buffer);
816   zx::eventpair confirm_ours_1;
817   zx::eventpair confirm_theirs_1;
818   zx::eventpair::create(/*options=*/0, &confirm_ours_1, &confirm_theirs_1);
819   local_svc.IndicateValue(std::move(params_1), std::move(confirm_theirs_1));
820   RunLoopUntilIdle();
821   ASSERT_EQ(svc_iter->second.updates.size(), 2u);
822   status =
823       confirm_ours_1.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
824                               /*deadline=*/zx::time(0),
825                               &observed);
826   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
827   EXPECT_EQ(observed, 0u);
828 
829   svc_iter->second.updates[1].indicate_cb(fit::ok());
830 
831   status =
832       confirm_ours_1.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
833                               /*deadline=*/zx::time(0),
834                               &observed);
835   ASSERT_EQ(status, ZX_OK);
836   EXPECT_EQ(observed, ZX_EVENTPAIR_SIGNALED | ZX_EVENTPAIR_PEER_CLOSED);
837 }
838 
TEST_F(Gatt2ServerServerTest,IndicateAllPeersError)839 TEST_F(Gatt2ServerServerTest, IndicateAllPeersError) {
840   const uint64_t chrc_handle = 2;
841   fbg::ServiceInfo svc_info =
842       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
843 
844   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
845   MockLocalService local_svc = local_service_handle.NewRequest();
846 
847   int cb_count = 0;
848   auto cb = [&](fbg::Server_PublishService_Result res) {
849     EXPECT_TRUE(res.is_response());
850     cb_count++;
851   };
852   server_ptr()->PublishService(
853       std::move(svc_info), std::move(local_service_handle), std::move(cb));
854   RunLoopUntilIdle();
855   EXPECT_EQ(cb_count, 1);
856   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
857   auto svc_iter = fake_gatt()->local_services().begin();
858 
859   fbg::ValueChangedParameters params;
860   params.set_handle(fbg::Handle{chrc_handle});
861   std::vector<uint8_t> buffer = {0x00, 0x01, 0x02};
862   params.set_value(buffer);
863   zx::eventpair confirm_ours;
864   zx::eventpair confirm_theirs;
865   zx::eventpair::create(/*options=*/0, &confirm_ours, &confirm_theirs);
866   local_svc.IndicateValue(std::move(params), std::move(confirm_theirs));
867   RunLoopUntilIdle();
868   ASSERT_EQ(svc_iter->second.updates.size(), 1u);
869   EXPECT_EQ(svc_iter->second.updates[0].chrc_id, chrc_handle);
870   EXPECT_EQ(svc_iter->second.updates[0].value, buffer);
871 
872   // Eventpair should not be signalled until indicate_cb called.
873   zx_signals_t observed;
874   zx_status_t status =
875       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
876                             /*deadline=*/zx::time(0),
877                             &observed);
878   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
879   EXPECT_EQ(observed, 0u);
880 
881   svc_iter->second.updates[0].indicate_cb(
882       fit::error(bt::att::ErrorCode::kUnlikelyError));
883 
884   status =
885       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
886                             /*deadline=*/zx::time(0),
887                             &observed);
888   ASSERT_EQ(status, ZX_OK);
889   EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
890 }
891 
TEST_F(Gatt2ServerServerTest,IndicateValueChangedParametersMissingHandleClosesService)892 TEST_F(Gatt2ServerServerTest,
893        IndicateValueChangedParametersMissingHandleClosesService) {
894   const uint64_t chrc_handle = 2;
895   fbg::ServiceInfo svc_info =
896       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
897 
898   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
899   MockLocalService local_svc = local_service_handle.NewRequest();
900 
901   int cb_count = 0;
902   auto cb = [&](fbg::Server_PublishService_Result res) {
903     EXPECT_TRUE(res.is_response());
904     cb_count++;
905   };
906   server_ptr()->PublishService(
907       std::move(svc_info), std::move(local_service_handle), std::move(cb));
908   RunLoopUntilIdle();
909   EXPECT_EQ(cb_count, 1);
910   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
911   ASSERT_FALSE(local_svc.error());
912 
913   // No handle is set.
914   fbg::ValueChangedParameters params_0;
915   std::vector<uint8_t> buffer = {0x00, 0x01, 0x02};
916   params_0.set_value(buffer);
917   zx::eventpair confirm_ours_0;
918   zx::eventpair confirm_theirs_0;
919   zx::eventpair::create(/*options=*/0, &confirm_ours_0, &confirm_theirs_0);
920   local_svc.IndicateValue(std::move(params_0), std::move(confirm_theirs_0));
921   RunLoopUntilIdle();
922   ASSERT_TRUE(local_svc.error());
923   EXPECT_EQ(local_svc.error().value(), ZX_ERR_PEER_CLOSED);
924   EXPECT_TRUE(fake_gatt()->local_services().empty());
925   zx_signals_t observed;
926   zx_status_t status =
927       confirm_ours_0.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
928                               /*deadline=*/zx::time(0),
929                               &observed);
930   ASSERT_EQ(status, ZX_OK);
931   EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
932 }
933 
TEST_F(Gatt2ServerServerTest,IndicateValueChangedParametersMissingValueClosesService)934 TEST_F(Gatt2ServerServerTest,
935        IndicateValueChangedParametersMissingValueClosesService) {
936   const uint64_t chrc_handle = 2;
937   fbg::ServiceInfo svc_info =
938       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
939 
940   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
941   MockLocalService local_svc = local_service_handle.NewRequest();
942 
943   int cb_count = 0;
944   auto cb = [&](fbg::Server_PublishService_Result res) {
945     EXPECT_TRUE(res.is_response());
946     cb_count++;
947   };
948   server_ptr()->PublishService(
949       std::move(svc_info), std::move(local_service_handle), std::move(cb));
950   RunLoopUntilIdle();
951   EXPECT_EQ(cb_count, 1);
952   ASSERT_FALSE(local_svc.error());
953   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
954 
955   // No value is set.
956   fbg::ValueChangedParameters params_1;
957   params_1.set_handle(fbg::Handle{chrc_handle});
958   zx::eventpair confirm_ours_1;
959   zx::eventpair confirm_theirs_1;
960   zx::eventpair::create(/*options=*/0, &confirm_ours_1, &confirm_theirs_1);
961   local_svc.IndicateValue(std::move(params_1), std::move(confirm_theirs_1));
962   RunLoopUntilIdle();
963   ASSERT_TRUE(local_svc.error());
964   EXPECT_EQ(local_svc.error().value(), ZX_ERR_PEER_CLOSED);
965   EXPECT_TRUE(fake_gatt()->local_services().empty());
966   zx_signals_t observed;
967   zx_status_t status =
968       confirm_ours_1.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
969                               /*deadline=*/zx::time(0),
970                               &observed);
971   ASSERT_EQ(status, ZX_OK);
972   EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
973 }
974 
TEST_F(Gatt2ServerServerTest,Indicate2PeersSuccess)975 TEST_F(Gatt2ServerServerTest, Indicate2PeersSuccess) {
976   const uint64_t chrc_handle = 2;
977   fbg::ServiceInfo svc_info =
978       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
979 
980   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
981   MockLocalService local_svc = local_service_handle.NewRequest();
982 
983   int cb_count = 0;
984   auto cb = [&](fbg::Server_PublishService_Result res) {
985     EXPECT_TRUE(res.is_response());
986     cb_count++;
987   };
988   server_ptr()->PublishService(
989       std::move(svc_info), std::move(local_service_handle), std::move(cb));
990   RunLoopUntilIdle();
991   EXPECT_EQ(cb_count, 1);
992   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
993   auto svc_iter = fake_gatt()->local_services().begin();
994 
995   bt::PeerId peer_0(0);
996   bt::PeerId peer_1(1);
997   fbg::ValueChangedParameters params;
998   params.set_handle(fbg::Handle{chrc_handle});
999   std::vector<uint8_t> buffer = {0x00, 0x01, 0x02};
1000   params.set_value(buffer);
1001   params.set_peer_ids(
1002       {fbt::PeerId{peer_0.value()}, fbt::PeerId{peer_1.value()}});
1003   zx::eventpair confirm_ours;
1004   zx::eventpair confirm_theirs;
1005   zx::eventpair::create(/*options=*/0, &confirm_ours, &confirm_theirs);
1006   local_svc.IndicateValue(std::move(params), std::move(confirm_theirs));
1007   RunLoopUntilIdle();
1008   ASSERT_EQ(svc_iter->second.updates.size(), 2u);
1009   EXPECT_EQ(svc_iter->second.updates[0].chrc_id, chrc_handle);
1010   EXPECT_EQ(svc_iter->second.updates[0].value, buffer);
1011   EXPECT_THAT(svc_iter->second.updates[0].peer, ::testing::Optional(peer_0));
1012   EXPECT_EQ(svc_iter->second.updates[1].chrc_id, chrc_handle);
1013   EXPECT_EQ(svc_iter->second.updates[1].value, buffer);
1014   EXPECT_THAT(svc_iter->second.updates[1].peer, ::testing::Optional(peer_1));
1015 
1016   // Eventpair should not be signaled until indicate_cb called for both peers.
1017   zx_signals_t observed;
1018   zx_status_t status =
1019       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1020                             /*deadline=*/zx::time(0),
1021                             &observed);
1022   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
1023 
1024   svc_iter->second.updates[1].indicate_cb(fit::ok());
1025 
1026   status =
1027       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1028                             /*deadline=*/zx::time(0),
1029                             &observed);
1030   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
1031 
1032   svc_iter->second.updates[0].indicate_cb(fit::ok());
1033 
1034   status =
1035       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1036                             /*deadline=*/zx::time(0),
1037                             &observed);
1038   ASSERT_EQ(status, ZX_OK);
1039   EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED);
1040 }
1041 
TEST_F(Gatt2ServerServerTest,Indicate2PeersFirstOneFails)1042 TEST_F(Gatt2ServerServerTest, Indicate2PeersFirstOneFails) {
1043   const uint64_t chrc_handle = 2;
1044   fbg::ServiceInfo svc_info =
1045       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1046 
1047   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1048   MockLocalService local_svc = local_service_handle.NewRequest();
1049 
1050   int cb_count = 0;
1051   auto cb = [&](fbg::Server_PublishService_Result res) {
1052     EXPECT_TRUE(res.is_response());
1053     cb_count++;
1054   };
1055   server_ptr()->PublishService(
1056       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1057   RunLoopUntilIdle();
1058   EXPECT_EQ(cb_count, 1);
1059   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1060   auto svc_iter = fake_gatt()->local_services().begin();
1061 
1062   fbg::ValueChangedParameters params;
1063   params.set_handle(fbg::Handle{chrc_handle});
1064   params.set_value(kBuffer);
1065   params.set_peer_ids({fbt::PeerId{0}, fbt::PeerId{1}});
1066   zx::eventpair confirm_ours;
1067   zx::eventpair confirm_theirs;
1068   zx::eventpair::create(/*options=*/0, &confirm_ours, &confirm_theirs);
1069   local_svc.IndicateValue(std::move(params), std::move(confirm_theirs));
1070   RunLoopUntilIdle();
1071   ASSERT_EQ(svc_iter->second.updates.size(), 2u);
1072 
1073   zx_signals_t observed;
1074   zx_status_t status =
1075       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1076                             /*deadline=*/zx::time(0),
1077                             &observed);
1078   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
1079 
1080   svc_iter->second.updates[0].indicate_cb(
1081       fit::error(bt::att::ErrorCode::kUnlikelyError));
1082 
1083   status =
1084       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1085                             /*deadline=*/zx::time(0),
1086                             &observed);
1087   ASSERT_EQ(status, ZX_OK);
1088   EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
1089 
1090   svc_iter->second.updates[1].indicate_cb(fit::ok());
1091 }
1092 
TEST_F(Gatt2ServerServerTest,Indicate2PeersBothFail)1093 TEST_F(Gatt2ServerServerTest, Indicate2PeersBothFail) {
1094   const uint64_t chrc_handle = 2;
1095   fbg::ServiceInfo svc_info =
1096       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1097 
1098   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1099   MockLocalService local_svc = local_service_handle.NewRequest();
1100 
1101   int cb_count = 0;
1102   auto cb = [&](fbg::Server_PublishService_Result res) {
1103     EXPECT_TRUE(res.is_response());
1104     cb_count++;
1105   };
1106   server_ptr()->PublishService(
1107       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1108   RunLoopUntilIdle();
1109   EXPECT_EQ(cb_count, 1);
1110   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1111   auto svc_iter = fake_gatt()->local_services().begin();
1112 
1113   fbg::ValueChangedParameters params;
1114   params.set_handle(fbg::Handle{chrc_handle});
1115   params.set_value(kBuffer);
1116   params.set_peer_ids({fbt::PeerId{0}, fbt::PeerId{1}});
1117   zx::eventpair confirm_ours;
1118   zx::eventpair confirm_theirs;
1119   zx::eventpair::create(/*options=*/0, &confirm_ours, &confirm_theirs);
1120   local_svc.IndicateValue(std::move(params), std::move(confirm_theirs));
1121   RunLoopUntilIdle();
1122   ASSERT_EQ(svc_iter->second.updates.size(), 2u);
1123 
1124   zx_signals_t observed;
1125   zx_status_t status =
1126       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1127                             /*deadline=*/zx::time(0),
1128                             &observed);
1129   ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
1130 
1131   svc_iter->second.updates[1].indicate_cb(
1132       fit::error(bt::att::ErrorCode::kUnlikelyError));
1133 
1134   status =
1135       confirm_ours.wait_one(ZX_EVENTPAIR_PEER_CLOSED | ZX_EVENTPAIR_SIGNALED,
1136                             /*deadline=*/zx::time(0),
1137                             &observed);
1138   ASSERT_EQ(status, ZX_OK);
1139   EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
1140 
1141   svc_iter->second.updates[0].indicate_cb(
1142       fit::error(bt::att::ErrorCode::kUnlikelyError));
1143 }
1144 
TEST_F(Gatt2ServerServerTest,NotifyAllPeers)1145 TEST_F(Gatt2ServerServerTest, NotifyAllPeers) {
1146   const uint64_t chrc_handle = 2;
1147   fbg::ServiceInfo svc_info =
1148       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1149 
1150   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1151   MockLocalService local_svc = local_service_handle.NewRequest();
1152 
1153   int cb_count = 0;
1154   auto cb = [&](fbg::Server_PublishService_Result res) {
1155     EXPECT_TRUE(res.is_response());
1156     cb_count++;
1157   };
1158   server_ptr()->PublishService(
1159       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1160   RunLoopUntilIdle();
1161   EXPECT_EQ(cb_count, 1);
1162   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1163   auto svc_iter = fake_gatt()->local_services().begin();
1164 
1165   fbg::ValueChangedParameters params_0;
1166   params_0.set_handle(fbg::Handle{chrc_handle});
1167   params_0.set_value(kBuffer);
1168   local_svc.NotifyValue(std::move(params_0));
1169   RunLoopUntilIdle();
1170   ASSERT_EQ(svc_iter->second.updates.size(), 1u);
1171   EXPECT_EQ(svc_iter->second.updates[0].chrc_id, chrc_handle);
1172   EXPECT_EQ(svc_iter->second.updates[0].value, kBuffer);
1173   EXPECT_FALSE(svc_iter->second.updates[0].peer);
1174   EXPECT_FALSE(svc_iter->second.updates[0].indicate_cb);
1175 
1176   // Also test with an empty peer_ids vector
1177   fbg::ValueChangedParameters params_1;
1178   params_1.set_peer_ids({});
1179   params_1.set_handle(fbg::Handle{chrc_handle});
1180   params_1.set_value(kBuffer);
1181   local_svc.NotifyValue(std::move(params_1));
1182   RunLoopUntilIdle();
1183   ASSERT_EQ(svc_iter->second.updates.size(), 2u);
1184   EXPECT_EQ(svc_iter->second.updates[1].chrc_id, chrc_handle);
1185   EXPECT_EQ(svc_iter->second.updates[1].value, kBuffer);
1186   EXPECT_FALSE(svc_iter->second.updates[1].peer);
1187   EXPECT_FALSE(svc_iter->second.updates[1].indicate_cb);
1188 }
1189 
TEST_F(Gatt2ServerServerTest,NotifyTwoPeers)1190 TEST_F(Gatt2ServerServerTest, NotifyTwoPeers) {
1191   const uint64_t chrc_handle = 2;
1192   fbg::ServiceInfo svc_info =
1193       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1194 
1195   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1196   MockLocalService local_svc = local_service_handle.NewRequest();
1197 
1198   int cb_count = 0;
1199   auto cb = [&](fbg::Server_PublishService_Result res) {
1200     EXPECT_TRUE(res.is_response());
1201     cb_count++;
1202   };
1203   server_ptr()->PublishService(
1204       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1205   RunLoopUntilIdle();
1206   EXPECT_EQ(cb_count, 1);
1207   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1208   auto svc_iter = fake_gatt()->local_services().begin();
1209 
1210   fbg::ValueChangedParameters params_0;
1211   params_0.set_handle(fbg::Handle{chrc_handle});
1212   params_0.set_value(kBuffer);
1213   params_0.set_peer_ids({fbt::PeerId{0}, fbt::PeerId{1}});
1214   local_svc.NotifyValue(std::move(params_0));
1215   RunLoopUntilIdle();
1216   ASSERT_EQ(svc_iter->second.updates.size(), 2u);
1217   EXPECT_EQ(svc_iter->second.updates[0].chrc_id, chrc_handle);
1218   EXPECT_EQ(svc_iter->second.updates[0].value, kBuffer);
1219   EXPECT_THAT(svc_iter->second.updates[0].peer,
1220               ::testing::Optional(bt::PeerId(0)));
1221   EXPECT_FALSE(svc_iter->second.updates[0].indicate_cb);
1222   EXPECT_EQ(svc_iter->second.updates[1].chrc_id, chrc_handle);
1223   EXPECT_EQ(svc_iter->second.updates[1].value, kBuffer);
1224   EXPECT_THAT(svc_iter->second.updates[1].peer,
1225               ::testing::Optional(bt::PeerId(1)));
1226   EXPECT_FALSE(svc_iter->second.updates[1].indicate_cb);
1227 }
1228 
TEST_F(Gatt2ServerServerTest,NotifyInvalidParametersMissingHandleClosesService)1229 TEST_F(Gatt2ServerServerTest,
1230        NotifyInvalidParametersMissingHandleClosesService) {
1231   const uint64_t chrc_handle = 2;
1232   fbg::ServiceInfo svc_info =
1233       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1234 
1235   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1236   MockLocalService local_svc = local_service_handle.NewRequest();
1237 
1238   int cb_count = 0;
1239   auto cb = [&](fbg::Server_PublishService_Result res) {
1240     EXPECT_TRUE(res.is_response());
1241     cb_count++;
1242   };
1243   server_ptr()->PublishService(
1244       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1245   RunLoopUntilIdle();
1246   EXPECT_EQ(cb_count, 1);
1247   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1248   ASSERT_FALSE(local_svc.error());
1249 
1250   // Missing handle.
1251   fbg::ValueChangedParameters params_0;
1252   params_0.set_value(kBuffer);
1253   local_svc.NotifyValue(std::move(params_0));
1254   RunLoopUntilIdle();
1255   ASSERT_TRUE(local_svc.error());
1256   EXPECT_EQ(local_svc.error().value(), ZX_ERR_PEER_CLOSED);
1257   EXPECT_TRUE(fake_gatt()->local_services().empty());
1258 }
1259 
TEST_F(Gatt2ServerServerTest,NotifyInvalidParametersMissingValueClosesService)1260 TEST_F(Gatt2ServerServerTest,
1261        NotifyInvalidParametersMissingValueClosesService) {
1262   const uint64_t chrc_handle = 2;
1263   fbg::ServiceInfo svc_info =
1264       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1265 
1266   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1267   MockLocalService local_svc = local_service_handle.NewRequest();
1268 
1269   int cb_count = 0;
1270   auto cb = [&](fbg::Server_PublishService_Result res) {
1271     EXPECT_TRUE(res.is_response());
1272     cb_count++;
1273   };
1274   server_ptr()->PublishService(
1275       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1276   RunLoopUntilIdle();
1277   EXPECT_EQ(cb_count, 1);
1278   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1279   ASSERT_FALSE(local_svc.error());
1280 
1281   // Missing value.
1282   fbg::ValueChangedParameters params_1;
1283   params_1.set_handle(fbg::Handle{chrc_handle});
1284   local_svc.NotifyValue(std::move(params_1));
1285   RunLoopUntilIdle();
1286   ASSERT_TRUE(local_svc.error());
1287   EXPECT_EQ(local_svc.error().value(), ZX_ERR_PEER_CLOSED);
1288   EXPECT_TRUE(fake_gatt()->local_services().empty());
1289 }
1290 
TEST_F(Gatt2ServerServerTest,ValueChangedFlowControl)1291 TEST_F(Gatt2ServerServerTest, ValueChangedFlowControl) {
1292   const uint64_t chrc_handle = 2;
1293   fbg::ServiceInfo svc_info =
1294       BuildSimpleService(/*svc_handle=*/1, /*svc_type=*/{5}, chrc_handle);
1295 
1296   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1297   MockLocalService local_svc = local_service_handle.NewRequest();
1298 
1299   int cb_count = 0;
1300   auto cb = [&](fbg::Server_PublishService_Result res) {
1301     EXPECT_TRUE(res.is_response());
1302     cb_count++;
1303   };
1304   server_ptr()->PublishService(
1305       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1306   RunLoopUntilIdle();
1307   EXPECT_EQ(cb_count, 1);
1308   ASSERT_EQ(fake_gatt()->local_services().size(), 1u);
1309   auto svc_iter = fake_gatt()->local_services().begin();
1310 
1311   for (size_t i = 0; i < 3 * fbg::INITIAL_VALUE_CHANGED_CREDITS; i++) {
1312     fbg::ValueChangedParameters params;
1313     params.set_handle(fbg::Handle{chrc_handle});
1314     params.set_value(kBuffer);
1315     local_svc.NotifyValue(std::move(params));
1316   }
1317   RunLoopUntilIdle();
1318   ASSERT_EQ(svc_iter->second.updates.size(),
1319             3 * fbg::INITIAL_VALUE_CHANGED_CREDITS);
1320   EXPECT_GT(local_svc.credits(), 0);
1321   EXPECT_LE(local_svc.credits(),
1322             static_cast<int>(fbg::INITIAL_VALUE_CHANGED_CREDITS));
1323   EXPECT_GE(local_svc.credit_log().size(), 2u);
1324 
1325   for (size_t i = 0; i < 3 * fbg::INITIAL_VALUE_CHANGED_CREDITS; i++) {
1326     fbg::ValueChangedParameters params;
1327     params.set_handle(fbg::Handle{chrc_handle});
1328     params.set_value(kBuffer);
1329     zx::eventpair confirm_ours;
1330     zx::eventpair confirm_theirs;
1331     zx::eventpair::create(/*options=*/0, &confirm_ours, &confirm_theirs);
1332     local_svc.IndicateValue(std::move(params), std::move(confirm_theirs));
1333   }
1334   RunLoopUntilIdle();
1335   ASSERT_EQ(svc_iter->second.updates.size(),
1336             6 * fbg::INITIAL_VALUE_CHANGED_CREDITS);
1337   EXPECT_GT(local_svc.credits(), 0);
1338   EXPECT_LE(local_svc.credits(),
1339             static_cast<int>(fbg::INITIAL_VALUE_CHANGED_CREDITS));
1340   EXPECT_GE(local_svc.credit_log().size(), 5u);
1341 }
1342 
TEST_F(Gatt2ServerServerTest,PublishServiceWithInvalidCharacteristic)1343 TEST_F(Gatt2ServerServerTest, PublishServiceWithInvalidCharacteristic) {
1344   fbg::ServiceInfo svc_info;
1345   svc_info.set_handle(fbg::ServiceHandle{1});
1346   bt::UInt128 svc_type = {5};
1347   svc_info.set_type(fbt::Uuid{svc_type});
1348 
1349   fbg::Characteristic chrc_0;
1350   fbg::Handle chrc_handle_0{2};
1351   chrc_0.set_handle(chrc_handle_0);
1352 
1353   std::vector<fbg::Characteristic> characteristics;
1354   characteristics.push_back(std::move(chrc_0));
1355   svc_info.set_characteristics(std::move(characteristics));
1356 
1357   fidl::InterfaceHandle<fbg::LocalService> local_service_handle_0;
1358   fidl::InterfaceRequest<fbg::LocalService> request =
1359       local_service_handle_0.NewRequest();
1360 
1361   int cb_count = 0;
1362   auto cb = [&](fbg::Server_PublishService_Result res) {
1363     cb_count++;
1364     ASSERT_TRUE(res.is_err());
1365     EXPECT_EQ(res.err(), fbg::PublishServiceError::INVALID_CHARACTERISTICS);
1366   };
1367   server_ptr()->PublishService(
1368       std::move(svc_info), std::move(local_service_handle_0), std::move(cb));
1369   RunLoopUntilIdle();
1370   EXPECT_EQ(cb_count, 1);
1371   ASSERT_EQ(fake_gatt()->local_services().size(), 0u);
1372 }
1373 
TEST_F(Gatt2ServerServerTest,PublishServiceReturnsInvalidId)1374 TEST_F(Gatt2ServerServerTest, PublishServiceReturnsInvalidId) {
1375   bt::UInt128 svc_type = {5};
1376   fbg::ServiceInfo svc_info = BuildSimpleService(/*svc_handle=*/1, svc_type);
1377 
1378   fidl::InterfaceHandle<fbg::LocalService> local_service_handle;
1379   fidl::InterfaceRequest<fbg::LocalService> request =
1380       local_service_handle.NewRequest();
1381 
1382   int cb_count = 0;
1383   auto cb = [&](fbg::Server_PublishService_Result res) {
1384     cb_count++;
1385     ASSERT_TRUE(res.is_err());
1386     EXPECT_EQ(res.err(), fbg::PublishServiceError::UNLIKELY_ERROR);
1387   };
1388 
1389   fake_gatt()->set_register_service_fails(true);
1390   server_ptr()->PublishService(
1391       std::move(svc_info), std::move(local_service_handle), std::move(cb));
1392   RunLoopUntilIdle();
1393   EXPECT_EQ(cb_count, 1);
1394   ASSERT_EQ(fake_gatt()->local_services().size(), 0u);
1395 }
1396 
1397 }  // namespace
1398 }  // namespace bthost
1399