10f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
20f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  Copyright (C) 2015 Google, Inc.
30f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
40f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  Licensed under the Apache License, Version 2.0 (the "License");
50f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  you may not use this file except in compliance with the License.
60f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  You may obtain a copy of the License at:
70f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
80f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  http://www.apache.org/licenses/LICENSE-2.0
90f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  Unless required by applicable law or agreed to in writing, software
110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  distributed under the License is distributed on an "AS IS" BASIS,
120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  See the License for the specific language governing permissions and
140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  limitations under the License.
150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <gmock/gmock.h>
180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <gtest/gtest.h>
190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
20234138e2606dd7a54fbcc540643511abc0a3598dArman Uguray#include "service/common/bluetooth/util/address_helper.h"
210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "service/gatt_server.h"
220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "service/hal/fake_bluetooth_gatt_interface.h"
23df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray#include "service/hal/gatt_helpers.h"
240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
250f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayusing ::testing::_;
260f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayusing ::testing::Return;
270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace bluetooth {
290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace {
300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
310f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayclass MockGattHandler
320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    : public hal::FakeBluetoothGattInterface::TestServerHandler {
330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray public:
340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  MockGattHandler() = default;
350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ~MockGattHandler() override = default;
360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  MOCK_METHOD1(RegisterServer, bt_status_t(bt_uuid_t*));
380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  MOCK_METHOD1(UnregisterServer, bt_status_t(int));
3978a44cdb25616892087af2c92abd382878c2ccb4Arman Uguray  MOCK_METHOD3(AddService, bt_status_t(int, btgatt_srvc_id_t*, int));
4091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  MOCK_METHOD5(AddCharacteristic, bt_status_t(int, int, bt_uuid_t*, int, int));
41d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  MOCK_METHOD4(AddDescriptor, bt_status_t(int, int, bt_uuid_t*, int));
4278a44cdb25616892087af2c92abd382878c2ccb4Arman Uguray  MOCK_METHOD3(StartService, bt_status_t(int, int, int));
4378a44cdb25616892087af2c92abd382878c2ccb4Arman Uguray  MOCK_METHOD2(DeleteService, bt_status_t(int, int));
44cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  MOCK_METHOD6(SendIndication, bt_status_t(int, int, int, int, int, char*));
45b10f96fa25266b69d0d31af166e93afe14134be7Arman Uguray  MOCK_METHOD4(SendResponse, bt_status_t(int, int, int, btgatt_response_t*));
460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray private:
480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  DISALLOW_COPY_AND_ASSIGN(MockGattHandler);
490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray};
500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
51514bf6087093375351784b287cb29c5f4603273cArman Ugurayclass TestDelegate : public GattServer::Delegate {
52514bf6087093375351784b287cb29c5f4603273cArman Uguray public:
53514bf6087093375351784b287cb29c5f4603273cArman Uguray  TestDelegate() = default;
54514bf6087093375351784b287cb29c5f4603273cArman Uguray  ~TestDelegate() override = default;
55514bf6087093375351784b287cb29c5f4603273cArman Uguray
56514bf6087093375351784b287cb29c5f4603273cArman Uguray  struct RequestData {
574ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    RequestData() : id(-1), offset(-1), is_long(false), is_prep(false),
584ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray                    need_rsp(false), is_exec(false), count(0) {}
59514bf6087093375351784b287cb29c5f4603273cArman Uguray    ~RequestData() = default;
60514bf6087093375351784b287cb29c5f4603273cArman Uguray
61514bf6087093375351784b287cb29c5f4603273cArman Uguray    std::string device_address;
62514bf6087093375351784b287cb29c5f4603273cArman Uguray    int id;
63514bf6087093375351784b287cb29c5f4603273cArman Uguray    int offset;
64514bf6087093375351784b287cb29c5f4603273cArman Uguray    bool is_long;
654ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    bool is_prep;
664ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    bool need_rsp;
674ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    bool is_exec;
68514bf6087093375351784b287cb29c5f4603273cArman Uguray    GattIdentifier gatt_id;
69514bf6087093375351784b287cb29c5f4603273cArman Uguray    int count;
704ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    std::vector<uint8_t> write_value;
71514bf6087093375351784b287cb29c5f4603273cArman Uguray  };
72514bf6087093375351784b287cb29c5f4603273cArman Uguray
73514bf6087093375351784b287cb29c5f4603273cArman Uguray  void OnCharacteristicReadRequest(
74514bf6087093375351784b287cb29c5f4603273cArman Uguray      GattServer* gatt_server,
75514bf6087093375351784b287cb29c5f4603273cArman Uguray      const std::string& device_address,
76514bf6087093375351784b287cb29c5f4603273cArman Uguray      int request_id, int offset, bool is_long,
77514bf6087093375351784b287cb29c5f4603273cArman Uguray      const bluetooth::GattIdentifier& characteristic_id) override {
78514bf6087093375351784b287cb29c5f4603273cArman Uguray    ASSERT_TRUE(gatt_server);
794ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_read_req_.device_address = device_address;
804ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_read_req_.id = request_id;
814ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_read_req_.offset = offset;
824ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_read_req_.is_long = is_long;
834ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_read_req_.gatt_id = characteristic_id;
844ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_read_req_.count++;
85514bf6087093375351784b287cb29c5f4603273cArman Uguray  }
86514bf6087093375351784b287cb29c5f4603273cArman Uguray
87514bf6087093375351784b287cb29c5f4603273cArman Uguray  void OnDescriptorReadRequest(
88514bf6087093375351784b287cb29c5f4603273cArman Uguray      GattServer* gatt_server,
89514bf6087093375351784b287cb29c5f4603273cArman Uguray      const std::string& device_address,
90514bf6087093375351784b287cb29c5f4603273cArman Uguray      int request_id, int offset, bool is_long,
91514bf6087093375351784b287cb29c5f4603273cArman Uguray      const bluetooth::GattIdentifier& descriptor_id) override {
92514bf6087093375351784b287cb29c5f4603273cArman Uguray    ASSERT_TRUE(gatt_server);
934ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_read_req_.device_address = device_address;
944ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_read_req_.id = request_id;
954ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_read_req_.offset = offset;
964ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_read_req_.is_long = is_long;
974ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_read_req_.gatt_id = descriptor_id;
984ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_read_req_.count++;
99514bf6087093375351784b287cb29c5f4603273cArman Uguray  }
100514bf6087093375351784b287cb29c5f4603273cArman Uguray
1014ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  void OnCharacteristicWriteRequest(
1024ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GattServer* gatt_server,
1034ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const std::string& device_address,
1044ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      int request_id, int offset, bool is_prepare_write, bool need_response,
1054ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const std::vector<uint8_t>& value,
1064ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const bluetooth::GattIdentifier& characteristic_id) override {
1074ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    ASSERT_TRUE(gatt_server);
1084ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.device_address = device_address;
1094ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.id = request_id;
1104ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.offset = offset;
1114ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.is_prep = is_prepare_write;
1124ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.need_rsp = need_response;
1134ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.gatt_id = characteristic_id;
1144ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.count++;
1154ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    char_write_req_.write_value = value;
1164ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  }
1174ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
1184ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  void OnDescriptorWriteRequest(
1194ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GattServer* gatt_server,
1204ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const std::string& device_address,
1214ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      int request_id, int offset, bool is_prepare_write, bool need_response,
1224ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const std::vector<uint8_t>& value,
1234ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const bluetooth::GattIdentifier& descriptor_id) override {
1244ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    ASSERT_TRUE(gatt_server);
1254ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.device_address = device_address;
1264ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.id = request_id;
1274ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.offset = offset;
1284ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.is_prep = is_prepare_write;
1294ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.need_rsp = need_response;
1304ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.gatt_id = descriptor_id;
1314ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.count++;
1324ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    desc_write_req_.write_value = value;
1334ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  }
1344ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
1354ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  void OnExecuteWriteRequest(
1364ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GattServer* gatt_server,
1374ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      const std::string& device_address,
1384ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      int request_id, bool is_execute) override {
1394ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    ASSERT_TRUE(gatt_server);
1404ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    exec_req_.device_address = device_address;
1414ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    exec_req_.id = request_id;
1424ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    exec_req_.is_exec = is_execute;
1434ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray    exec_req_.count++;
1444ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  }
1454ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
1464ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const RequestData& char_read_req() const { return char_read_req_; }
1474ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const RequestData& desc_read_req() const { return desc_read_req_; }
1484ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const RequestData& char_write_req() const { return char_write_req_; }
1494ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const RequestData& desc_write_req() const { return desc_write_req_; }
150514bf6087093375351784b287cb29c5f4603273cArman Uguray
151514bf6087093375351784b287cb29c5f4603273cArman Uguray private:
1524ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  RequestData char_read_req_;
1534ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  RequestData desc_read_req_;
1544ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  RequestData char_write_req_;
1554ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  RequestData desc_write_req_;
1564ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  RequestData exec_req_;
157514bf6087093375351784b287cb29c5f4603273cArman Uguray};
158514bf6087093375351784b287cb29c5f4603273cArman Uguray
1590f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayclass GattServerTest : public ::testing::Test {
1600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray public:
1610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  GattServerTest() = default;
1620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ~GattServerTest() override = default;
1630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  void SetUp() override {
1650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    mock_handler_.reset(new MockGattHandler());
1660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    fake_hal_gatt_iface_ = new hal::FakeBluetoothGattInterface(
1670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray        nullptr,
1680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray        std::static_pointer_cast<
1690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray            hal::FakeBluetoothGattInterface::TestServerHandler>(mock_handler_));
1700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    hal::BluetoothGattInterface::InitializeForTesting(fake_hal_gatt_iface_);
1720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    factory_.reset(new GattServerFactory());
1730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
1740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  void TearDown() override {
1760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    factory_.reset();
1770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    hal::BluetoothGattInterface::CleanUp();
1780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
1790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray protected:
1810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  hal::FakeBluetoothGattInterface* fake_hal_gatt_iface_;
1820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::shared_ptr<MockGattHandler> mock_handler_;
1830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_ptr<GattServerFactory> factory_;
1840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray private:
1860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  DISALLOW_COPY_AND_ASSIGN(GattServerTest);
1870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray};
1880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
189df0b2714553cabc735222ce18a5f018c5a5fa138Arman Ugurayconst int kDefaultServerId = 4;
190df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
191df0b2714553cabc735222ce18a5f018c5a5fa138Arman Ugurayclass GattServerPostRegisterTest : public GattServerTest {
192df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray public:
193df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  GattServerPostRegisterTest() = default;
194df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  ~GattServerPostRegisterTest() override = default;
195df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
196df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  void SetUp() override {
197df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    GattServerTest::SetUp();
198df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    UUID uuid = UUID::GetRandom();
199df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    auto callback = [&](BLEStatus status, const UUID& in_uuid,
200bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray                        std::unique_ptr<BluetoothInstance> in_client) {
201df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      CHECK(in_uuid == uuid);
202df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      CHECK(in_client.get());
203df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      CHECK(status == BLE_STATUS_SUCCESS);
204df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
205df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      gatt_server_ = std::unique_ptr<GattServer>(
206df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray          static_cast<GattServer*>(in_client.release()));
207df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    };
208df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
209df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    EXPECT_CALL(*mock_handler_, RegisterServer(_))
210df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        .Times(1)
211df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        .WillOnce(Return(BT_STATUS_SUCCESS));
212df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
213bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray    factory_->RegisterInstance(uuid, callback);
214df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
215df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    bt_uuid_t hal_uuid = uuid.GetBlueDroid();
216df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    fake_hal_gatt_iface_->NotifyRegisterServerCallback(
217df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        BT_STATUS_SUCCESS,
218df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        kDefaultServerId,
219df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        hal_uuid);
220df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  }
221df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
222df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  void TearDown() override {
223df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    EXPECT_CALL(*mock_handler_, UnregisterServer(_))
224df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        .Times(1)
225df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray        .WillOnce(Return(BT_STATUS_SUCCESS));
226df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    gatt_server_ = nullptr;
227df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    GattServerTest::TearDown();
228df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  }
229df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
230514bf6087093375351784b287cb29c5f4603273cArman Uguray  void SetUpTestService() {
231514bf6087093375351784b287cb29c5f4603273cArman Uguray    EXPECT_CALL(*mock_handler_, AddService(_, _, _))
232514bf6087093375351784b287cb29c5f4603273cArman Uguray        .Times(1)
233514bf6087093375351784b287cb29c5f4603273cArman Uguray        .WillOnce(Return(BT_STATUS_SUCCESS));
234514bf6087093375351784b287cb29c5f4603273cArman Uguray    EXPECT_CALL(*mock_handler_, AddCharacteristic(_, _, _, _, _))
235514bf6087093375351784b287cb29c5f4603273cArman Uguray        .Times(1)
236514bf6087093375351784b287cb29c5f4603273cArman Uguray        .WillOnce(Return(BT_STATUS_SUCCESS));
237514bf6087093375351784b287cb29c5f4603273cArman Uguray    EXPECT_CALL(*mock_handler_, AddDescriptor(_, _, _, _))
238514bf6087093375351784b287cb29c5f4603273cArman Uguray        .Times(1)
239514bf6087093375351784b287cb29c5f4603273cArman Uguray        .WillOnce(Return(BT_STATUS_SUCCESS));
240514bf6087093375351784b287cb29c5f4603273cArman Uguray    EXPECT_CALL(*mock_handler_, StartService(_, _, _))
241514bf6087093375351784b287cb29c5f4603273cArman Uguray        .Times(1)
242514bf6087093375351784b287cb29c5f4603273cArman Uguray        .WillOnce(Return(BT_STATUS_SUCCESS));
243514bf6087093375351784b287cb29c5f4603273cArman Uguray
244514bf6087093375351784b287cb29c5f4603273cArman Uguray    UUID uuid0 = UUID::GetRandom();
245514bf6087093375351784b287cb29c5f4603273cArman Uguray    UUID uuid1 = UUID::GetRandom();
246514bf6087093375351784b287cb29c5f4603273cArman Uguray    UUID uuid2 = UUID::GetRandom();
247514bf6087093375351784b287cb29c5f4603273cArman Uguray
248514bf6087093375351784b287cb29c5f4603273cArman Uguray    bool register_success = false;
249514bf6087093375351784b287cb29c5f4603273cArman Uguray
250514bf6087093375351784b287cb29c5f4603273cArman Uguray    // Doesn't matter what the permissions/properties are since this is all
251514bf6087093375351784b287cb29c5f4603273cArman Uguray    // fake.
252514bf6087093375351784b287cb29c5f4603273cArman Uguray    test_service_id_ = *gatt_server_->BeginServiceDeclaration(uuid0, true);
253514bf6087093375351784b287cb29c5f4603273cArman Uguray    test_char_id_ = *gatt_server_->AddCharacteristic(uuid1, 0, 0);
254514bf6087093375351784b287cb29c5f4603273cArman Uguray    test_desc_id_ = *gatt_server_->AddDescriptor(uuid2, 0);
255514bf6087093375351784b287cb29c5f4603273cArman Uguray    ASSERT_TRUE(gatt_server_->EndServiceDeclaration([&](
256514bf6087093375351784b287cb29c5f4603273cArman Uguray        BLEStatus status, const GattIdentifier& gatt_id) {
257514bf6087093375351784b287cb29c5f4603273cArman Uguray      ASSERT_EQ(BLE_STATUS_SUCCESS, status);
258514bf6087093375351784b287cb29c5f4603273cArman Uguray      ASSERT_TRUE(gatt_id == test_service_id_);
259514bf6087093375351784b287cb29c5f4603273cArman Uguray      register_success = true;
260514bf6087093375351784b287cb29c5f4603273cArman Uguray    }));
261514bf6087093375351784b287cb29c5f4603273cArman Uguray
262514bf6087093375351784b287cb29c5f4603273cArman Uguray    btgatt_srvc_id_t hal_srvc_id;
263514bf6087093375351784b287cb29c5f4603273cArman Uguray    hal::GetHALServiceId(test_service_id_, &hal_srvc_id);
264514bf6087093375351784b287cb29c5f4603273cArman Uguray    bt_uuid_t hal_uuid1 = uuid1.GetBlueDroid();
265514bf6087093375351784b287cb29c5f4603273cArman Uguray    bt_uuid_t hal_uuid2 = uuid2.GetBlueDroid();
266514bf6087093375351784b287cb29c5f4603273cArman Uguray
267514bf6087093375351784b287cb29c5f4603273cArman Uguray    srvc_handle_ = 0x0001;
268514bf6087093375351784b287cb29c5f4603273cArman Uguray    char_handle_ = 0x0003;
269514bf6087093375351784b287cb29c5f4603273cArman Uguray    desc_handle_ = 0x0004;
270514bf6087093375351784b287cb29c5f4603273cArman Uguray
271514bf6087093375351784b287cb29c5f4603273cArman Uguray    fake_hal_gatt_iface_->NotifyServiceAddedCallback(
272514bf6087093375351784b287cb29c5f4603273cArman Uguray        BT_STATUS_SUCCESS, kDefaultServerId, hal_srvc_id, srvc_handle_);
273514bf6087093375351784b287cb29c5f4603273cArman Uguray    fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
274514bf6087093375351784b287cb29c5f4603273cArman Uguray        BT_STATUS_SUCCESS, kDefaultServerId, hal_uuid1,
275514bf6087093375351784b287cb29c5f4603273cArman Uguray        srvc_handle_, char_handle_);
276514bf6087093375351784b287cb29c5f4603273cArman Uguray    fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
277514bf6087093375351784b287cb29c5f4603273cArman Uguray        BT_STATUS_SUCCESS, kDefaultServerId, hal_uuid2,
278514bf6087093375351784b287cb29c5f4603273cArman Uguray        srvc_handle_, desc_handle_);
279514bf6087093375351784b287cb29c5f4603273cArman Uguray    fake_hal_gatt_iface_->NotifyServiceStartedCallback(
280514bf6087093375351784b287cb29c5f4603273cArman Uguray        BT_STATUS_SUCCESS, kDefaultServerId, srvc_handle_);
281514bf6087093375351784b287cb29c5f4603273cArman Uguray
282514bf6087093375351784b287cb29c5f4603273cArman Uguray    testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
283514bf6087093375351784b287cb29c5f4603273cArman Uguray
284514bf6087093375351784b287cb29c5f4603273cArman Uguray    ASSERT_TRUE(register_success);
285514bf6087093375351784b287cb29c5f4603273cArman Uguray  }
286514bf6087093375351784b287cb29c5f4603273cArman Uguray
287df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray protected:
288df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  std::unique_ptr<GattServer> gatt_server_;
289df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
290514bf6087093375351784b287cb29c5f4603273cArman Uguray  GattIdentifier test_service_id_;
291514bf6087093375351784b287cb29c5f4603273cArman Uguray  GattIdentifier test_char_id_;
292514bf6087093375351784b287cb29c5f4603273cArman Uguray  GattIdentifier test_desc_id_;
293514bf6087093375351784b287cb29c5f4603273cArman Uguray  int srvc_handle_;
294514bf6087093375351784b287cb29c5f4603273cArman Uguray  int char_handle_;
295514bf6087093375351784b287cb29c5f4603273cArman Uguray  int desc_handle_;
296514bf6087093375351784b287cb29c5f4603273cArman Uguray
297df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray private:
298df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  DISALLOW_COPY_AND_ASSIGN(GattServerPostRegisterTest);
299df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray};
300df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
3010f2d4897046f037a9f181f47f3d349a9dd646478Arman UgurayTEST_F(GattServerTest, RegisterServer) {
3020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_CALL(*mock_handler_, RegisterServer(_))
3030f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .Times(2)
3040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .WillOnce(Return(BT_STATUS_FAIL))
3050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
3060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // These will be asynchronously populate with a result when the callback
3080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // executes.
3090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  BLEStatus status = BLE_STATUS_SUCCESS;
3100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  UUID cb_uuid;
3110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_ptr<GattServer> server;
3120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int callback_count = 0;
3130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  auto callback = [&](BLEStatus in_status, const UUID& uuid,
315bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray                      std::unique_ptr<BluetoothInstance> in_server) {
3160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    status = in_status;
3170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    cb_uuid = uuid;
3180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    server = std::unique_ptr<GattServer>(
3190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray        static_cast<GattServer*>(in_server.release()));
3200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    callback_count++;
3210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  };
3220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  UUID uuid0 = UUID::GetRandom();
3240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // HAL returns failure.
326bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_FALSE(factory_->RegisterInstance(uuid0, callback));
3270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(0, callback_count);
3280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // HAL returns success.
330bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_TRUE(factory_->RegisterInstance(uuid0, callback));
3310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(0, callback_count);
3320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Calling twice with the same UUID should fail with no additional calls into
3340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // the stack.
335bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_FALSE(factory_->RegisterInstance(uuid0, callback));
3360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
3380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Call with a different UUID while one is pending.
3400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  UUID uuid1 = UUID::GetRandom();
3410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_CALL(*mock_handler_, RegisterServer(_))
3420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .Times(1)
3430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
344bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_TRUE(factory_->RegisterInstance(uuid1, callback));
3450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Trigger callback with an unknown UUID. This should get ignored.
3470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  UUID uuid2 = UUID::GetRandom();
3480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_uuid_t hal_uuid = uuid2.GetBlueDroid();
3490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  fake_hal_gatt_iface_->NotifyRegisterServerCallback(0, 0, hal_uuid);
3500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(0, callback_count);
3510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // |uuid0| succeeds.
3530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int server_if0 = 2;  // Pick something that's not 0.
3540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  hal_uuid = uuid0.GetBlueDroid();
3550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  fake_hal_gatt_iface_->NotifyRegisterServerCallback(
3560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      BT_STATUS_SUCCESS, server_if0, hal_uuid);
3570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(1, callback_count);
3590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ASSERT_TRUE(server.get() != nullptr);  // Assert to terminate in case of error
3600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(BLE_STATUS_SUCCESS, status);
361bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_EQ(server_if0, server->GetInstanceId());
3620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(uuid0, server->GetAppIdentifier());
3630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(uuid0, cb_uuid);
3640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // The server should unregister itself when deleted.
3660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_CALL(*mock_handler_, UnregisterServer(server_if0))
3670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .Times(1)
3680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
3690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  server.reset();
3700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
3720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // |uuid1| fails.
3740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int server_if1 = 3;
3750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  hal_uuid = uuid1.GetBlueDroid();
3760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  fake_hal_gatt_iface_->NotifyRegisterServerCallback(
3770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      BT_STATUS_FAIL, server_if1, hal_uuid);
3780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(2, callback_count);
3800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ASSERT_TRUE(server.get() == nullptr);  // Assert to terminate in case of error
3810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(BLE_STATUS_FAILURE, status);
3820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  EXPECT_EQ(uuid1, cb_uuid);
3830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
385df0b2714553cabc735222ce18a5f018c5a5fa138Arman UgurayTEST_F(GattServerPostRegisterTest, SimpleServiceTest) {
386df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Setup a service callback.
387df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  GattIdentifier cb_id;
388df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  BLEStatus cb_status = BLE_STATUS_SUCCESS;
389df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  int cb_count = 0;
390df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
391df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    cb_id = in_id;
392df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    cb_status = in_status;
393df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    cb_count++;
394df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  };
395df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
396df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Service declaration not started.
397df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_FALSE(gatt_server_->EndServiceDeclaration(callback));
398df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
399df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  const UUID uuid = UUID::GetRandom();
400df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  auto service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
401df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(service_id != nullptr);
402df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(service_id->IsService());
403df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
404df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Already started.
405df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_FALSE(gatt_server_->BeginServiceDeclaration(uuid, false));
406df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
407df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Callback is NULL.
408df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_FALSE(
409df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      gatt_server_->EndServiceDeclaration(GattServer::ResultCallback()));
410df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
411df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // We should get a call for a service with one handle.
412bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_CALL(*mock_handler_, AddService(gatt_server_->GetInstanceId(), _, 1))
413df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .Times(2)
414df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillOnce(Return(BT_STATUS_FAIL))
415df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
416df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
417df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Stack returns failure. This will cause the entire service declaration to
418df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // end and needs to be restarted.
419df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_FALSE(gatt_server_->EndServiceDeclaration(callback));
420df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
421df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
422df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(service_id != nullptr);
423df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(service_id->IsService());
424df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
425df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Stack returns success.
426df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
427df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
428df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // EndServiceDeclaration already in progress.
429df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_FALSE(gatt_server_->EndServiceDeclaration(callback));
430df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
431df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(0, cb_count);
432df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
433df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  btgatt_srvc_id_t hal_id;
434df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
435df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  int srvc_handle = 0x0001;
436df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
437df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report success for AddService but for wrong server. Should be ignored.
438df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
439df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId + 1, hal_id, srvc_handle);
440df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(0, cb_count);
441df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
442df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report success for AddService.
443df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_CALL(*mock_handler_, StartService(kDefaultServerId, srvc_handle, _))
444df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .Times(1)
445df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
446df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
447df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
448df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
449df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(0, cb_count);
450df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
451df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report success for StartService but for wrong server. Should be ignored.
452df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceStartedCallback(
453df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId + 1, srvc_handle);
454df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(0, cb_count);
455df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
456df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report success for StartService.
457df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceStartedCallback(
458df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, srvc_handle);
459df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(1, cb_count);
460df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(BLE_STATUS_SUCCESS, cb_status);
461df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
462df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
463df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Start new service declaration with same UUID. We should get a different ID.
464df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  auto service_id1 = gatt_server_->BeginServiceDeclaration(uuid, true);
465df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(service_id1 != nullptr);
466df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(service_id1->IsService());
467df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(*service_id != *service_id1);
468df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray}
469df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
470df0b2714553cabc735222ce18a5f018c5a5fa138Arman UgurayTEST_F(GattServerPostRegisterTest, AddServiceFailures) {
471df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Setup a service callback.
472df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  GattIdentifier cb_id;
473df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  BLEStatus cb_status = BLE_STATUS_SUCCESS;
474df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  int cb_count = 0;
475df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
476df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    cb_id = in_id;
477df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    cb_status = in_status;
478df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray    cb_count++;
479df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  };
480df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
481df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  const UUID uuid = UUID::GetRandom();
482df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  auto service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
483df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  btgatt_srvc_id_t hal_id;
484df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
485df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  int srvc_handle = 0x0001;
486df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
487bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_CALL(*mock_handler_, AddService(gatt_server_->GetInstanceId(), _, 1))
488df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .Times(3)
489df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
490df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
491df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
492df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report failure for AddService.
493df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
494df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_FAIL, kDefaultServerId, hal_id, srvc_handle);
495df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(1, cb_count);
496df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
497df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
498df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
499df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Restart. We should get the same ID back.
500df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  auto service_id1 = gatt_server_->BeginServiceDeclaration(uuid, true);
501df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(*service_id1 == *service_id);
502df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
503df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
504df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report success for AddService but return failure from StartService.
505bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray  EXPECT_CALL(*mock_handler_, StartService(gatt_server_->GetInstanceId(), 1, _))
506df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .Times(2)
507df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillOnce(Return(BT_STATUS_FAIL))
508df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
509df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
510df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
511df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
512df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(2, cb_count);
513df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
514df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
515df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
516df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Restart.
517df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
518df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
519df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
520df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report success for AddService, return success from StartService.
521df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
522df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
523df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(2, cb_count);
524df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
525df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  // Report failure for StartService. Added service data should get deleted.
526df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_CALL(*mock_handler_,
527bb18c41ffa0370d4eb0c4a15904b114355606466Arman Uguray              DeleteService(gatt_server_->GetInstanceId(), srvc_handle))
528df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .Times(1)
529df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
530df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  fake_hal_gatt_iface_->NotifyServiceStartedCallback(
531df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray      BT_STATUS_FAIL, kDefaultServerId, srvc_handle);
532df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_EQ(3, cb_count);
533df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
534df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
535df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray}
536df0b2714553cabc735222ce18a5f018c5a5fa138Arman Uguray
53791613743c9db02dbe05d93d2afa163b78068d054Arman UgurayTEST_F(GattServerPostRegisterTest, AddCharacteristic) {
53891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Just pick some values.
53991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  const int props = bluetooth::kCharacteristicPropertyRead |
54091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      bluetooth::kCharacteristicPropertyNotify;
54191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  const int perms = kAttributePermissionReadEncrypted;
54291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  const UUID char_uuid = UUID::GetRandom();
54391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  bt_uuid_t hal_char_uuid = char_uuid.GetBlueDroid();
54491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
54591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Declaration not started.
54691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(nullptr, gatt_server_->AddCharacteristic(char_uuid, props, perms));
54791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
54891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Start a service declaration.
54991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  const UUID service_uuid = UUID::GetRandom();
55091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  auto service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
55191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(service_id != nullptr);
55291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  btgatt_srvc_id_t hal_id;
55391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
55491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
55591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Add two characteristics with the same UUID.
55691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  auto char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
55791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  auto char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
55891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
55991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(char_id0 != nullptr);
56091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(char_id1 != nullptr);
56191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(char_id0 != char_id1);
56291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(char_id0->IsCharacteristic());
56391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(char_id1->IsCharacteristic());
56491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(*char_id0->GetOwningServiceId() == *service_id);
56591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(*char_id1->GetOwningServiceId() == *service_id);
56691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
56791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Expect calls for 5 handles in total as we have 2 characteristics.
56891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_CALL(*mock_handler_, AddService(kDefaultServerId, _, 5))
56991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
57091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
57191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  GattIdentifier cb_id;
57291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  BLEStatus cb_status;
57391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  int cb_count = 0;
57491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
57591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray    cb_id = in_id;
57691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray    cb_status = in_status;
57791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray    cb_count++;
57891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  };
57991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
58091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  int srvc_handle = 0x0001;
58191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  int char_handle0 = 0x0002;
58291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  int char_handle1 = 0x0004;
58391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
58491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
585d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Cannot add any more characteristics while EndServiceDeclaration is in
586d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // progress.
587d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(nullptr, gatt_server_->AddCharacteristic(char_uuid, props, perms));
588d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
58991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_CALL(*mock_handler_, AddCharacteristic(_, _, _, _, _))
59091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .Times(8)
59191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_FAIL))      // char_id0 - try 1
59291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 2
59391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 3
59491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_FAIL))      // char_id1 - try 3
59591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 4
59691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id1 - try 4
59791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 5
59891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));  // char_id1 - try 5
59991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
60091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // First AddCharacteristic call will fail.
60191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
60291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
60391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(1, cb_count);
60491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
60591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
60691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
60791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Restart. (try 2)
60891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
60991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
61091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
61191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
61291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
61391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
61491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
61591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
61691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(1, cb_count);
61791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
61891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Report failure for pending AddCharacteristic.
61991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
62091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_FAIL, kDefaultServerId, hal_char_uuid,
62191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      srvc_handle, char_handle0);
62291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(2, cb_count);
62391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
62491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
62591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
62691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Restart. (try 3)
62791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
62891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
62991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
63091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
63191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
63291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
63391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
63491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
63591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(2, cb_count);
63691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
63791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Report success for pending AddCharacteristic we should receive a call for
63891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // the second characteristic which will fail.
63991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
64091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
64191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      srvc_handle, char_handle0);
64291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(3, cb_count);
64391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
64491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
64591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
64691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Restart. (try 4)
64791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
64891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
64991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
65091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
65191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
65291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
65391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
65491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
65591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(3, cb_count);
65691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
65791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Report success for pending AddCharacteristic. Second characteristic call
65891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // will start normally. We shouldn't receive any new callback.
65991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
66091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
66191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      srvc_handle, char_handle0);
66291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(3, cb_count);
66391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
66491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Report failure for pending AddCharacteristic call for second
66591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // characteristic.
66691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
66791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_FAIL, kDefaultServerId, hal_char_uuid,
66891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      srvc_handle, char_handle1);
66991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(4, cb_count);
67091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
67191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(cb_id == *service_id);
67291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
67391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Restart. (try 5)
67491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
67591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
67691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
67791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
67891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
67991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
68091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
68191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
68291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(4, cb_count);
68391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
68491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Report success for pending AddCharacteristic. Second characteristic call
68591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // will start normally. We shouldn't receive any new callback.
68691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
68791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
68891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      srvc_handle, char_handle0);
68991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(4, cb_count);
69091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
69191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // Report success for pending AddCharacteristic call for second
69291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // characteristic. We shouldn't receive any new callback but we'll get a call
69391613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  // to StartService.
69491613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_CALL(*mock_handler_, StartService(kDefaultServerId, srvc_handle, _))
69591613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .Times(1)
69691613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
69791613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
69891613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
69991613743c9db02dbe05d93d2afa163b78068d054Arman Uguray      srvc_handle, char_handle1);
70091613743c9db02dbe05d93d2afa163b78068d054Arman Uguray  EXPECT_EQ(4, cb_count);
70191613743c9db02dbe05d93d2afa163b78068d054Arman Uguray}
70291613743c9db02dbe05d93d2afa163b78068d054Arman Uguray
703d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman UgurayTEST_F(GattServerPostRegisterTest, AddDescriptor) {
704d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Set up some values for UUIDs, permissions, and properties.
705d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  const UUID service_uuid = UUID::GetRandom();
706d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  const UUID char_uuid0 = UUID::GetRandom();
707d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  const UUID char_uuid1 = UUID::GetRandom();
708d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  const UUID desc_uuid = UUID::GetRandom();
709d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  bt_uuid_t hal_char_uuid0 = char_uuid0.GetBlueDroid();
710d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  bt_uuid_t hal_char_uuid1 = char_uuid1.GetBlueDroid();
711d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  bt_uuid_t hal_desc_uuid = desc_uuid.GetBlueDroid();
712d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  const int props = bluetooth::kCharacteristicPropertyRead |
713d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      bluetooth::kCharacteristicPropertyNotify;
714d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  const int perms = kAttributePermissionReadEncrypted;
715d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
716d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Service declaration not started.
717d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(nullptr, gatt_server_->AddDescriptor(desc_uuid, perms));
718d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
719d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Start a service declaration.
720d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  auto service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
721d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  btgatt_srvc_id_t hal_id;
722d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
723d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
724d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // No characteristic was inserted.
725d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(nullptr, gatt_server_->AddDescriptor(desc_uuid, perms));
726d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
727d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Add two characeristics.
728d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  auto char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
729d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  auto char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
730d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
731d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Add a descriptor.
732d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  auto desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
733d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_NE(nullptr, desc_id);
734d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(desc_id->IsDescriptor());
735d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(*desc_id->GetOwningCharacteristicId() == *char_id1);
736d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(*desc_id->GetOwningServiceId() == *service_id);
737d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
738d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Add a second descriptor with the same UUID.
739d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  auto desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
740d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_NE(nullptr, desc_id1);
741d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(*desc_id1 != *desc_id);
742d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(desc_id1->IsDescriptor());
743d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(*desc_id1->GetOwningCharacteristicId() == *char_id1);
744d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(*desc_id1->GetOwningServiceId() == *service_id);
745d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
746d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Expect calls for 7 handles.
747d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_CALL(*mock_handler_, AddService(kDefaultServerId, _, 7))
748d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
749d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_CALL(*mock_handler_, AddCharacteristic(_, _, _, _, _))
750d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
751d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
752d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  GattIdentifier cb_id;
753d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  BLEStatus cb_status;
754d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  int cb_count = 0;
755d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
756d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray    cb_id = in_id;
757d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray    cb_status = in_status;
758d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray    cb_count++;
759d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  };
760d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
761d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  int srvc_handle = 0x0001;
762d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  int char_handle0 = 0x0002;
763d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  int char_handle1 = 0x0004;
764d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  int desc_handle0 = 0x0005;
765d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  int desc_handle1 = 0x0006;
766d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
767d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
768d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
769d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Cannot add any more descriptors while EndServiceDeclaration is in progress.
770d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(nullptr, gatt_server_->AddDescriptor(desc_uuid, perms));
771d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
772d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
773d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
774d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
775d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
776d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_CALL(*mock_handler_, AddDescriptor(_, _, _, _))
777d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .Times(8)
778d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_FAIL))      // desc_id0 - try 1
779d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 2
780d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 3
781d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_FAIL))      // desc_id1 - try 3
782d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 4
783d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id1 - try 4
784d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 5
785d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));  // desc_id1 - try 5
786d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
787d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Notify success for both characteristics. First descriptor call will fail.
788d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
789d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
790d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle0);
791d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
792d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
793d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
794d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle1);
795d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(1, cb_count);
796d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
797d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(cb_id == *service_id);
798d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
799d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Restart (try 2)
800d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  cb_count = 0;
801d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
802d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
803d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
804d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
805d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
806d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id);
807d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
808d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id1);
809d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
810d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
811d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
812d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
813d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
814d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
815d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
816d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle0);
817d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
818d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
819d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
820d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle1);
821d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
822d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
823d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Notify failure for first descriptor.
824d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
825d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_FAIL, kDefaultServerId, hal_desc_uuid,
826d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, desc_handle0);
827d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(1, cb_count);
828d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
829d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(cb_id == *service_id);
830d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
831d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Restart (try 3)
832d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  cb_count = 0;
833d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
834d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
835d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
836d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
837d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
838d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id);
839d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
840d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id1);
841d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
842d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
843d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
844d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
845d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
846d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
847d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
848d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle0);
849d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
850d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
851d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
852d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle1);
853d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
854d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
855d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Notify success for first descriptor; the second descriptor will fail
856d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // immediately.
857d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
858d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
859d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, desc_handle0);
860d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(1, cb_count);
861d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
862d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(cb_id == *service_id);
863d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
864d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Restart (try 4)
865d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  cb_count = 0;
866d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
867d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
868d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
869d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
870d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
871d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id);
872d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
873d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id1);
874d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
875d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
876d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
877d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
878d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
879d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
880d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
881d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle0);
882d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
883d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
884d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
885d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle1);
886d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
887d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
888d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Notify success for first first descriptor and failure for second
889d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // descriptor.
890d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
891d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
892d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, desc_handle0);
893d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
894d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
895d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
896d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_FAIL, kDefaultServerId, hal_desc_uuid,
897d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, desc_handle1);
898d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(1, cb_count);
899d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
900d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(cb_id == *service_id);
901d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
902d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Restart (try 5)
903d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  cb_count = 0;
904d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
905d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  hal::GetHALServiceId(*service_id, &hal_id);
906d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
907d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
908d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
909d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id);
910d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
911d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  ASSERT_NE(nullptr, desc_id1);
912d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
913d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
914d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
915d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
916d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
917d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
918d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
919d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle0);
920d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
921d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
922d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
923d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, char_handle1);
924d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
925d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
926d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // Notify success for both descriptors.
927d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
928d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
929d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, desc_handle0);
930d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
931d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
932d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  // The second descriptor callback should trigger the end routine.
933d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_CALL(*mock_handler_, StartService(kDefaultServerId, srvc_handle, _))
934d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .Times(1)
935d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
936d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
937d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
938d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray      srvc_handle, desc_handle1);
939d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray  EXPECT_EQ(0, cb_count);
940d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray}
941d9b0552a7f75737b5c8c60cb87f892b1b9323acfArman Uguray
942514bf6087093375351784b287cb29c5f4603273cArman UgurayTEST_F(GattServerPostRegisterTest, RequestRead) {
943514bf6087093375351784b287cb29c5f4603273cArman Uguray  SetUpTestService();
944514bf6087093375351784b287cb29c5f4603273cArman Uguray
945514bf6087093375351784b287cb29c5f4603273cArman Uguray  TestDelegate test_delegate;
946514bf6087093375351784b287cb29c5f4603273cArman Uguray  gatt_server_->SetDelegate(&test_delegate);
947514bf6087093375351784b287cb29c5f4603273cArman Uguray
948514bf6087093375351784b287cb29c5f4603273cArman Uguray  const std::vector<uint8_t> kTestValue = { 0x01, 0x02, 0x03 };
949514bf6087093375351784b287cb29c5f4603273cArman Uguray  const std::vector<uint8_t> kTestValueTooLarge(BTGATT_MAX_ATTR_LEN + 1, 0);
950514bf6087093375351784b287cb29c5f4603273cArman Uguray  const std::string kTestAddress0 = "01:23:45:67:89:AB";
951514bf6087093375351784b287cb29c5f4603273cArman Uguray  const std::string kTestAddress1 = "CD:EF:01:23:45:67";
952514bf6087093375351784b287cb29c5f4603273cArman Uguray  const int kReqId0 = 0;
953514bf6087093375351784b287cb29c5f4603273cArman Uguray  const int kReqId1 = 1;
954514bf6087093375351784b287cb29c5f4603273cArman Uguray  const int kConnId0 = 1;
955514bf6087093375351784b287cb29c5f4603273cArman Uguray
956514bf6087093375351784b287cb29c5f4603273cArman Uguray  // No pending request.
957514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
958514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId0,
959514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
960514bf6087093375351784b287cb29c5f4603273cArman Uguray
961514bf6087093375351784b287cb29c5f4603273cArman Uguray  bt_bdaddr_t hal_addr0, hal_addr1;
962514bf6087093375351784b287cb29c5f4603273cArman Uguray  ASSERT_TRUE(util::BdAddrFromString(kTestAddress0, &hal_addr0));
963514bf6087093375351784b287cb29c5f4603273cArman Uguray  ASSERT_TRUE(util::BdAddrFromString(kTestAddress1, &hal_addr1));
964514bf6087093375351784b287cb29c5f4603273cArman Uguray
965514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Send a connection callback. The GattServer should store the connection
966514bf6087093375351784b287cb29c5f4603273cArman Uguray  // information and be able to process the incoming read requests for this
967514bf6087093375351784b287cb29c5f4603273cArman Uguray  // connection.
968514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyServerConnectionCallback(
969514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kDefaultServerId, true, hal_addr0);
970514bf6087093375351784b287cb29c5f4603273cArman Uguray
971514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Unknown connection ID shouldn't trigger anything.
972514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
973514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0 + 1, kReqId0, hal_addr0, char_handle_, 0, false);
9744ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_read_req().count);
9754ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_read_req().count);
976514bf6087093375351784b287cb29c5f4603273cArman Uguray
977514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Unknown device address shouldn't trigger anything.
978514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
979514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kReqId0, hal_addr1, char_handle_, 0, false);
9804ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_read_req().count);
9814ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_read_req().count);
982514bf6087093375351784b287cb29c5f4603273cArman Uguray
983514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Unknown attribute handle shouldn't trigger anything.
984514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
985514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_ + 50, 0, false);
9864ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_read_req().count);
9874ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_read_req().count);
988514bf6087093375351784b287cb29c5f4603273cArman Uguray
989514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Characteristic and descriptor handles should trigger correct callbacks.
990514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
991514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_, 0, false);
9924ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.char_read_req().count);
9934ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kTestAddress0, test_delegate.char_read_req().device_address);
9944ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kReqId0, test_delegate.char_read_req().id);
9954ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_read_req().offset);
9964ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(test_delegate.char_read_req().is_long);
9974ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(test_char_id_ == test_delegate.char_read_req().gatt_id);
9984ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_read_req().count);
999514bf6087093375351784b287cb29c5f4603273cArman Uguray
1000514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
1001514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kReqId1, hal_addr0, desc_handle_, 2, true);
10024ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.char_read_req().count);
10034ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.desc_read_req().count);
10044ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kTestAddress0, test_delegate.desc_read_req().device_address);
10054ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kReqId1, test_delegate.desc_read_req().id);
10064ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(2, test_delegate.desc_read_req().offset);
10074ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(test_delegate.desc_read_req().is_long);
10084ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(test_desc_id_ == test_delegate.desc_read_req().gatt_id);
1009514bf6087093375351784b287cb29c5f4603273cArman Uguray
1010514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Callback with a pending request ID will be ignored.
1011514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
1012514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_, 0, false);
1013514bf6087093375351784b287cb29c5f4603273cArman Uguray  fake_hal_gatt_iface_->NotifyRequestReadCallback(
1014514bf6087093375351784b287cb29c5f4603273cArman Uguray      kConnId0, kReqId1, hal_addr0, char_handle_, 0, false);
10154ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.char_read_req().count);
10164ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.desc_read_req().count);
1017514bf6087093375351784b287cb29c5f4603273cArman Uguray
1018514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Send response for wrong device address.
1019514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
1020514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress1, kReqId0,
1021514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
1022514bf6087093375351784b287cb29c5f4603273cArman Uguray
1023514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Send response for a value that's too large.
1024514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
1025514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId0,
1026514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValueTooLarge));
1027514bf6087093375351784b287cb29c5f4603273cArman Uguray
1028514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_CALL(*mock_handler_, SendResponse(kConnId0, kReqId0,
1029514bf6087093375351784b287cb29c5f4603273cArman Uguray                                           BT_STATUS_SUCCESS, _))
1030514bf6087093375351784b287cb29c5f4603273cArman Uguray      .Times(2)
1031514bf6087093375351784b287cb29c5f4603273cArman Uguray      .WillOnce(Return(BT_STATUS_FAIL))
1032514bf6087093375351784b287cb29c5f4603273cArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
1033514bf6087093375351784b287cb29c5f4603273cArman Uguray
1034514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Stack call fails.
1035514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
1036514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId0,
1037514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
1038514bf6087093375351784b287cb29c5f4603273cArman Uguray
1039514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Successful send response for characteristic.
1040514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_TRUE(gatt_server_->SendResponse(
1041514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId0,
1042514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
1043514bf6087093375351784b287cb29c5f4603273cArman Uguray
1044514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Characteristic request ID no longer pending.
1045514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
1046514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId0,
1047514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
1048514bf6087093375351784b287cb29c5f4603273cArman Uguray
1049514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_CALL(*mock_handler_, SendResponse(kConnId0, kReqId1,
1050514bf6087093375351784b287cb29c5f4603273cArman Uguray                                           BT_STATUS_SUCCESS, _))
1051514bf6087093375351784b287cb29c5f4603273cArman Uguray      .Times(1)
1052514bf6087093375351784b287cb29c5f4603273cArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
1053514bf6087093375351784b287cb29c5f4603273cArman Uguray
1054514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Successful send response for descriptor.
1055514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_TRUE(gatt_server_->SendResponse(
1056514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId1,
1057514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
1058514bf6087093375351784b287cb29c5f4603273cArman Uguray
1059514bf6087093375351784b287cb29c5f4603273cArman Uguray  // Descriptor request ID no longer pending.
1060514bf6087093375351784b287cb29c5f4603273cArman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
1061514bf6087093375351784b287cb29c5f4603273cArman Uguray      kTestAddress0, kReqId1,
1062514bf6087093375351784b287cb29c5f4603273cArman Uguray      GATT_ERROR_NONE, 0, kTestValue));
1063514bf6087093375351784b287cb29c5f4603273cArman Uguray
1064514bf6087093375351784b287cb29c5f4603273cArman Uguray  gatt_server_->SetDelegate(nullptr);
1065514bf6087093375351784b287cb29c5f4603273cArman Uguray}
1066514bf6087093375351784b287cb29c5f4603273cArman Uguray
10674ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman UgurayTEST_F(GattServerPostRegisterTest, RequestWrite) {
10684ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  SetUpTestService();
10694ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
10704ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  TestDelegate test_delegate;
10714ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  gatt_server_->SetDelegate(&test_delegate);
10724ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
10734ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const std::vector<uint8_t> kTestValue = { 0x01, 0x02, 0x03 };
10744ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const std::string kTestAddress0 = "01:23:45:67:89:AB";
10754ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const std::string kTestAddress1 = "CD:EF:01:23:45:67";
10764ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const int kReqId0 = 0;
10774ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const int kReqId1 = 1;
10784ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  const int kConnId0 = 1;
10794ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
10804ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // No pending request.
10814ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
10824ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId0,
10834ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
10844ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
10854ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  bt_bdaddr_t hal_addr0, hal_addr1;
10864ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  ASSERT_TRUE(util::BdAddrFromString(kTestAddress0, &hal_addr0));
10874ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  ASSERT_TRUE(util::BdAddrFromString(kTestAddress1, &hal_addr1));
10884ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
10894ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Send a connection callback. The GattServer should store the connection
10904ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // information and be able to process the incoming read requests for this
10914ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // connection.
10924ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyServerConnectionCallback(
10934ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kDefaultServerId, true, hal_addr0);
10944ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
10954ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Unknown connection ID shouldn't trigger anything.
10964ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
10974ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0 + 1, kReqId0, hal_addr0, char_handle_, 0,
10984ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
10994ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_write_req().count);
11004ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_write_req().count);
11014ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11024ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Unknown device address shouldn't trigger anything.
11034ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11044ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId0, hal_addr1, char_handle_, 0,
11054ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
11064ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_write_req().count);
11074ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_write_req().count);
11084ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11094ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Unknown attribute handle shouldn't trigger anything.
11104ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11114ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_ + 50, 0,
11124ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
11134ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_write_req().count);
11144ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_write_req().count);
11154ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11164ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Characteristic and descriptor handles should trigger correct callbacks.
11174ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11184ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_, 0,
11194ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
11204ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.char_write_req().count);
11214ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kTestAddress0, test_delegate.char_write_req().device_address);
11224ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kReqId0, test_delegate.char_write_req().id);
11234ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.char_write_req().offset);
11244ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(true, test_delegate.char_write_req().need_rsp);
11254ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(false, test_delegate.char_write_req().is_exec);
11264ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kTestValue, test_delegate.char_write_req().write_value);
11274ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(test_char_id_ == test_delegate.char_write_req().gatt_id);
11284ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(0, test_delegate.desc_write_req().count);
11294ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11304ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11314ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId1, hal_addr0, desc_handle_, 2,
11324ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
11334ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.char_write_req().count);
11344ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.desc_write_req().count);
11354ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kTestAddress0, test_delegate.desc_write_req().device_address);
11364ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kReqId1, test_delegate.desc_write_req().id);
11374ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(2, test_delegate.desc_write_req().offset);
11384ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(true, test_delegate.desc_write_req().need_rsp);
11394ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(false, test_delegate.desc_write_req().is_exec);
11404ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(kTestValue, test_delegate.desc_write_req().write_value);
11414ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(test_desc_id_ == test_delegate.desc_write_req().gatt_id);
11424ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11434ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Callback with a pending request ID will be ignored.
11444ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11454ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_, 0,
11464ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
11474ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11484ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId1, hal_addr0, char_handle_, 0,
11494ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), true, false, (uint8_t *)kTestValue.data());
11504ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.char_write_req().count);
11514ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(1, test_delegate.desc_write_req().count);
11524ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11534ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Send response for wrong device address.
11544ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
11554ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress1, kReqId0,
11564ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
11574ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11584ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_CALL(*mock_handler_, SendResponse(kConnId0, kReqId0,
11594ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray                                           BT_STATUS_SUCCESS, _))
11604ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      .Times(2)
11614ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      .WillOnce(Return(BT_STATUS_FAIL))
11624ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
11634ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11644ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Stack call fails.
11654ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
11664ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId0,
11674ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
11684ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11694ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Successful send response for characteristic.
11704ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(gatt_server_->SendResponse(
11714ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId0,
11724ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
11734ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11744ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Characteristic request ID no longer pending.
11754ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
11764ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId0,
11774ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
11784ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11794ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_CALL(*mock_handler_, SendResponse(kConnId0, kReqId1,
11804ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray                                           BT_STATUS_SUCCESS, _))
11814ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      .Times(1)
11824ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
11834ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11844ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Successful send response for descriptor.
11854ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_TRUE(gatt_server_->SendResponse(
11864ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId1,
11874ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
11884ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11894ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // Descriptor request ID no longer pending.
11904ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
11914ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId1,
11924ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
11934ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
11944ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  // SendResponse should fail for a "Write Without Response".
11954ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
11964ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kConnId0, kReqId0, hal_addr0, char_handle_, 0,
11974ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestValue.size(), false, false, (uint8_t *)kTestValue.data());
11984ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_EQ(false, test_delegate.char_write_req().need_rsp);
11994ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  EXPECT_FALSE(gatt_server_->SendResponse(
12004ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      kTestAddress0, kReqId0,
12014ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray      GATT_ERROR_NONE, 0, kTestValue));
12024ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
12034ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray  gatt_server_->SetDelegate(nullptr);
12044ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray}
12054ebcbd9ede4006500c3ead0685befe0a8e4aadc2Arman Uguray
1206cd644e3c54a4321b7626b52531c59f88e24e87beArman UgurayTEST_F(GattServerPostRegisterTest, SendNotification) {
1207cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  SetUpTestService();
1208cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1209cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  const std::string kTestAddress0 = "01:23:45:67:89:AB";
1210cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  const std::string kTestAddress1 = "cd:ef:01:23:45:67";
1211cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  const std::string kInvalidAddress = "thingamajig blabbidyboop";
1212cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  const int kConnId0 = 0;
1213cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  const int kConnId1 = 1;
1214cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  std::vector<uint8_t> value;
1215cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  bt_bdaddr_t hal_addr0;
1216cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  ASSERT_TRUE(util::BdAddrFromString(kTestAddress0, &hal_addr0));
1217cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1218cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Set up two connections with the same address.
1219cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyServerConnectionCallback(
1220cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId0, kDefaultServerId, true, hal_addr0);
1221cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyServerConnectionCallback(
1222cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId1, kDefaultServerId, true, hal_addr0);
1223cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1224cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Set up a test callback.
1225cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  GATTError gatt_error;
1226cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  int callback_count = 0;
1227cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  auto callback = [&](GATTError in_error) {
1228cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray    gatt_error = in_error;
1229cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray    callback_count++;
1230cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  };
1231cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1232cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Bad device address.
1233cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_FALSE(gatt_server_->SendNotification(
1234cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kInvalidAddress,
1235cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      test_char_id_, false, value, callback));
1236cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1237cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Bad connection.
1238cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_FALSE(gatt_server_->SendNotification(
1239cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kTestAddress1,
1240cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      test_char_id_, false, value, callback));
1241cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1242cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // We should get a HAL call for each connection for this address. The calls
1243cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // fail.
1244cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1245cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId0,
1246cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 0, nullptr))
1247cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1248cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_FAIL));
1249cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1250cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId1,
1251cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 0, nullptr))
1252cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1253cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_FAIL));
1254cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_FALSE(gatt_server_->SendNotification(
1255cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kTestAddress0,
1256cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      test_char_id_, false, value, callback));
1257cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1258cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // One of the calls succeeds.
1259cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1260cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId0,
1261cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 0, nullptr))
1262cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1263cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
1264cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1265cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId1,
1266cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 0, nullptr))
1267cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1268cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_FAIL));
1269cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_TRUE(gatt_server_->SendNotification(
1270cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kTestAddress0,
1271cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      test_char_id_, false, value, callback));
1272cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1273cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // One of the connections is already pending so there should be only one call.
1274cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // This one we send with confirm=true.
1275cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1276cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId1,
1277cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 1, nullptr))
1278cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1279cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
1280cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_TRUE(gatt_server_->SendNotification(
1281cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kTestAddress0,
1282cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      test_char_id_, true, value, callback));
1283cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1284cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Calls are already pending.
1285cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_FALSE(gatt_server_->SendNotification(
1286cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kTestAddress0, test_char_id_, true, value, callback));
1287cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1288cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Trigger one confirmation callback. We should get calls for two callbacks
1289cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // since we have two separate calls pending.
1290cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyIndicationSentCallback(
1291cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId0, BT_STATUS_SUCCESS);
1292cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyIndicationSentCallback(
1293cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId1, BT_STATUS_SUCCESS);
1294cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_EQ(2, callback_count);
1295cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_EQ(GATT_ERROR_NONE, gatt_error);
1296cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1297cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  callback_count = 0;
1298cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1299cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Restart. Both calls succeed now.
1300cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1301cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId0,
1302cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 0, nullptr))
1303cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1304cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
1305cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_CALL(*mock_handler_,
1306cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray              SendIndication(kDefaultServerId, char_handle_, kConnId1,
1307cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray                             value.size(), 0, nullptr))
1308cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .Times(1)
1309cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      .WillOnce(Return(BT_STATUS_SUCCESS));
1310cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_TRUE(gatt_server_->SendNotification(
1311cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kTestAddress0,
1312cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      test_char_id_, false, value, callback));
1313cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1314cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Trigger one confirmation callback. The callback we passed should still be
1315cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // pending. The first callback is for the wrong connection ID.
1316cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyIndicationSentCallback(
1317cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId0 + 50, BT_STATUS_FAIL);
1318cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyIndicationSentCallback(
1319cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId0, BT_STATUS_SUCCESS);
1320cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_EQ(0, callback_count);
1321cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1322cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // This should be ignored since |kConnId0| was already processed.
1323cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyIndicationSentCallback(
1324cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId0, BT_STATUS_SUCCESS);
1325cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_EQ(0, callback_count);
1326cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
1327cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // Run the callback with failure. Since the previous callback reported
1328cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  // success, we should report success.
1329cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  fake_hal_gatt_iface_->NotifyIndicationSentCallback(
1330cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray      kConnId1, BT_STATUS_SUCCESS);
1331cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_EQ(1, callback_count);
1332cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray  EXPECT_EQ(GATT_ERROR_NONE, gatt_error);
1333cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray}
1334cd644e3c54a4321b7626b52531c59f88e24e87beArman Uguray
13350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace
13360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace bluetooth
1337