//
//  Copyright (C) 2016 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#include <base/macros.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "service/adapter.h"
#include "service/hal/fake_bluetooth_gatt_interface.h"
#include "service/low_energy_advertiser.h"
#include "stack/include/bt_types.h"
#include "stack/include/hcidefs.h"
#include "test/mock_adapter.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::Exactly;
using ::testing::Invoke;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::Matcher;
using status_cb = base::Callback<void(uint8_t)>;
using reg_cb =
    base::Callback<void(uint8_t /* advertiser_id */, uint8_t /* status */)>;

namespace bluetooth {
namespace {

class MockAdvertiserHandler : public BleAdvertiserInterface {
 public:
  MockAdvertiserHandler() {}
  ~MockAdvertiserHandler() override = default;

  MOCK_METHOD1(RegisterAdvertiser, void(IdStatusCallback));
  MOCK_METHOD1(Unregister, void(uint8_t));
  MOCK_METHOD2(GetOwnAddress, void(uint8_t, GetAddressCallback));
  MOCK_METHOD3(SetParameters,
               void(uint8_t, AdvertiseParameters, ParametersCallback));
  MOCK_METHOD4(SetData, void(int, bool, std::vector<uint8_t>, StatusCallback));
  MOCK_METHOD6(Enable, void(uint8_t, bool, StatusCallback, uint16_t, uint8_t,
                            StatusCallback));
  MOCK_METHOD7(StartAdvertising,
               void(uint8_t advertiser_id, StatusCallback cb,
                    AdvertiseParameters, std::vector<uint8_t>,
                    std::vector<uint8_t>, int, StatusCallback));
  MOCK_METHOD9(StartAdvertisingSet,
               void(IdTxPowerStatusCallback cb, AdvertiseParameters params,
                    std::vector<uint8_t> advertise_data,
                    std::vector<uint8_t> scan_response_data,
                    PeriodicAdvertisingParameters periodic_params,
                    std::vector<uint8_t> periodic_data, uint16_t duration,
                    uint8_t maxExtAdvEvents, IdStatusCallback timeout_cb));
  MOCK_METHOD3(SetPeriodicAdvertisingParameters,
               void(int, PeriodicAdvertisingParameters, StatusCallback));
  MOCK_METHOD3(SetPeriodicAdvertisingData,
               void(int, std::vector<uint8_t>, StatusCallback));
  MOCK_METHOD3(SetPeriodicAdvertisingEnable, void(int, bool, StatusCallback));

 private:
  DISALLOW_COPY_AND_ASSIGN(MockAdvertiserHandler);
};

class LowEnergyAdvertiserTest : public ::testing::Test {
 public:
  LowEnergyAdvertiserTest() = default;
  ~LowEnergyAdvertiserTest() override = default;

  void SetUp() override {
    // Only set |mock_handler_| if a test hasn't set it.
    if (!mock_handler_) mock_handler_.reset(new MockAdvertiserHandler());
    hal::BluetoothGattInterface::InitializeForTesting(
        new hal::FakeBluetoothGattInterface(
            std::static_pointer_cast<BleAdvertiserInterface>(mock_handler_),
            nullptr, nullptr, nullptr));
    ble_advertiser_factory_.reset(new LowEnergyAdvertiserFactory());
  }

  void TearDown() override {
    ble_advertiser_factory_.reset();
    hal::BluetoothGattInterface::CleanUp();
  }

 protected:
  std::shared_ptr<MockAdvertiserHandler> mock_handler_;
  std::unique_ptr<LowEnergyAdvertiserFactory> ble_advertiser_factory_;

 private:
  DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiserTest);
};

// Used for tests that operate on a pre-registered advertiser.
class LowEnergyAdvertiserPostRegisterTest : public LowEnergyAdvertiserTest {
 public:
  LowEnergyAdvertiserPostRegisterTest() : next_client_id_(0) {}
  ~LowEnergyAdvertiserPostRegisterTest() override = default;

  void SetUp() override {
    LowEnergyAdvertiserTest::SetUp();
    auto callback = [&](std::unique_ptr<LowEnergyAdvertiser> advertiser) {
      le_advertiser_ = std::move(advertiser);
    };
    RegisterTestAdvertiser(callback);
  }

  void TearDown() override {
    EXPECT_CALL(*mock_handler_, Enable(_, false, _, _, _, _)).Times(1);
    EXPECT_CALL(*mock_handler_, Unregister(_)).Times(1);
    le_advertiser_.reset();
    LowEnergyAdvertiserTest::TearDown();
  }

  void RegisterTestAdvertiser(
      const std::function<void(std::unique_ptr<LowEnergyAdvertiser> advertiser)>
          callback) {
    UUID uuid = UUID::GetRandom();
    auto api_callback = [&](BLEStatus status, const UUID& in_uuid,
                            std::unique_ptr<BluetoothInstance> in_client) {
      CHECK(in_uuid == uuid);
      CHECK(in_client.get());
      CHECK(status == BLE_STATUS_SUCCESS);

      callback(std::unique_ptr<LowEnergyAdvertiser>(
          static_cast<LowEnergyAdvertiser*>(in_client.release())));
    };

    reg_cb reg_adv_cb;
    EXPECT_CALL(*mock_handler_, RegisterAdvertiser(_))
        .Times(1)
        .WillOnce(SaveArg<0>(&reg_adv_cb));

    ble_advertiser_factory_->RegisterInstance(uuid, api_callback);

    reg_adv_cb.Run(next_client_id_++, BT_STATUS_SUCCESS);
    ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
  }

  void StartAdvertising() {
    ASSERT_FALSE(le_advertiser_->IsAdvertisingStarted());
    ASSERT_FALSE(le_advertiser_->IsStartingAdvertising());
    ASSERT_FALSE(le_advertiser_->IsStoppingAdvertising());

    status_cb start_advertising_cb;
    EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
        .Times(1)
        .WillOnce(SaveArg<1>(&start_advertising_cb));
    status_cb set_data_cb;

    AdvertiseSettings settings;
    AdvertiseData adv, scan_rsp;
    ASSERT_TRUE(le_advertiser_->StartAdvertising(
        settings, adv, scan_rsp, LowEnergyAdvertiser::StatusCallback()));
    ASSERT_TRUE(le_advertiser_->IsStartingAdvertising());

    start_advertising_cb.Run(BT_STATUS_SUCCESS);

    ASSERT_TRUE(le_advertiser_->IsAdvertisingStarted());
    ASSERT_FALSE(le_advertiser_->IsStartingAdvertising());
    ASSERT_FALSE(le_advertiser_->IsStoppingAdvertising());
  }

  void AdvertiseDataTestHelper(AdvertiseData data,
                               std::function<void(BLEStatus)> callback,
                               status_cb* set_data_cb) {
    AdvertiseSettings settings;

    LOG_ASSERT(set_data_cb) << "set_data_cb must be set";

    EXPECT_TRUE(le_advertiser_->StartAdvertising(settings, data,
                                                 AdvertiseData(), callback));

    set_data_cb->Run(BT_STATUS_SUCCESS);

    status_cb disable_cb;
    EXPECT_CALL(*mock_handler_, Enable(_, false, _, _, _, _))
        .Times(1)
        .WillOnce(SaveArg<2>(&disable_cb));

    EXPECT_TRUE(
        le_advertiser_->StopAdvertising(LowEnergyAdvertiser::StatusCallback()));
    disable_cb.Run(BT_STATUS_SUCCESS);
  }

 protected:
  std::unique_ptr<LowEnergyAdvertiser> le_advertiser_;

 private:
  int next_client_id_;

  DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiserPostRegisterTest);
};

TEST_F(LowEnergyAdvertiserTest, RegisterInstance) {
  // These will be asynchronously populated with a result when the callback
  // executes.
  BLEStatus status = BLE_STATUS_SUCCESS;
  UUID cb_uuid;
  std::unique_ptr<LowEnergyAdvertiser> advertiser;
  int callback_count = 0;

  auto callback = [&](BLEStatus in_status, const UUID& uuid,
                      std::unique_ptr<BluetoothInstance> in_client) {
    status = in_status;
    cb_uuid = uuid;
    advertiser = std::unique_ptr<LowEnergyAdvertiser>(
        static_cast<LowEnergyAdvertiser*>(in_client.release()));
    callback_count++;
  };

  UUID uuid0 = UUID::GetRandom();

  reg_cb reg_adv1_cb;
  EXPECT_CALL(*mock_handler_, RegisterAdvertiser(_))
      .Times(1)
      .WillOnce(SaveArg<0>(&reg_adv1_cb));

  // Success.
  EXPECT_TRUE(ble_advertiser_factory_->RegisterInstance(uuid0, callback));
  EXPECT_EQ(0, callback_count);

  // Calling twice with the same UUID should fail with no additional call into
  // the stack.
  EXPECT_FALSE(ble_advertiser_factory_->RegisterInstance(uuid0, callback));

  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // Call with a different UUID while one is pending.
  UUID uuid1 = UUID::GetRandom();
  reg_cb reg_adv2_cb;
  EXPECT_CALL(*mock_handler_, RegisterAdvertiser(_))
      .Times(1)
      .WillOnce(SaveArg<0>(&reg_adv2_cb));
  EXPECT_TRUE(ble_advertiser_factory_->RegisterInstance(uuid1, callback));

  // |uuid0| succeeds.
  int client_if0 = 2;  // Pick something that's not 0.
  reg_adv1_cb.Run(client_if0, BT_STATUS_SUCCESS);

  EXPECT_EQ(1, callback_count);
  ASSERT_TRUE(advertiser.get() !=
              nullptr);  // Assert to terminate in case of error
  EXPECT_EQ(BLE_STATUS_SUCCESS, status);
  EXPECT_EQ(client_if0, advertiser->GetInstanceId());
  EXPECT_EQ(uuid0, advertiser->GetAppIdentifier());
  EXPECT_EQ(uuid0, cb_uuid);

  // The advertiser should unregister itself when deleted.
  EXPECT_CALL(*mock_handler_, Enable(client_if0, false, _, _, _, _)).Times(1);
  EXPECT_CALL(*mock_handler_, Unregister(client_if0)).Times(1);
  advertiser.reset();
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // |uuid1| fails.
  uint8_t client_if1 = 10;
  reg_adv2_cb.Run(client_if1, BT_STATUS_FAIL);

  EXPECT_EQ(2, callback_count);
  ASSERT_TRUE(advertiser.get() ==
              nullptr);  // Assert to terminate in case of error
  EXPECT_EQ(BLE_STATUS_FAILURE, status);
  EXPECT_EQ(uuid1, cb_uuid);
}

TEST_F(LowEnergyAdvertiserPostRegisterTest, StartAdvertisingBasic) {
  EXPECT_FALSE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());

  // Use default advertising settings and data.
  AdvertiseSettings settings;
  AdvertiseData adv_data, scan_rsp;
  int callback_count = 0;
  BLEStatus last_status = BLE_STATUS_FAILURE;
  auto callback = [&](BLEStatus status) {
    last_status = status;
    callback_count++;
  };

  status_cb start_advertising_cb;
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(2)
      .WillRepeatedly(SaveArg<1>(&start_advertising_cb));

  // Stack call returns success.
  EXPECT_TRUE(
      le_advertiser_->StartAdvertising(settings, adv_data, scan_rsp, callback));

  EXPECT_FALSE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_TRUE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(0, callback_count);

  // Already starting.
  EXPECT_FALSE(
      le_advertiser_->StartAdvertising(settings, adv_data, scan_rsp, callback));

  // Notify failure.
  start_advertising_cb.Run(BT_STATUS_FAIL);

  EXPECT_FALSE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(1, callback_count);
  EXPECT_EQ(BLE_STATUS_FAILURE, last_status);

  // Try again.
  EXPECT_TRUE(
      le_advertiser_->StartAdvertising(settings, adv_data, scan_rsp, callback));
  EXPECT_FALSE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_TRUE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(1, callback_count);

  start_advertising_cb.Run(BT_STATUS_SUCCESS);

  EXPECT_TRUE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(2, callback_count);
  EXPECT_EQ(BLE_STATUS_SUCCESS, last_status);

  // Already started.
  EXPECT_FALSE(
      le_advertiser_->StartAdvertising(settings, adv_data, scan_rsp, callback));
}

TEST_F(LowEnergyAdvertiserPostRegisterTest, StopAdvertisingBasic) {
  AdvertiseSettings settings;

  // Not enabled.
  EXPECT_FALSE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(
      le_advertiser_->StopAdvertising(LowEnergyAdvertiser::StatusCallback()));

  // Start advertising for testing.
  StartAdvertising();

  int callback_count = 0;
  BLEStatus last_status = BLE_STATUS_FAILURE;
  auto callback = [&](BLEStatus status) {
    last_status = status;
    callback_count++;
  };

  status_cb enable_cb;
  EXPECT_CALL(*mock_handler_, Enable(_, false, _, _, _, _))
      .Times(2)
      .WillRepeatedly(SaveArg<2>(&enable_cb));

  // Stack returns success.
  EXPECT_TRUE(le_advertiser_->StopAdvertising(callback));
  EXPECT_TRUE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_TRUE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(0, callback_count);

  // Already disabling.
  EXPECT_FALSE(le_advertiser_->StopAdvertising(callback));
  EXPECT_TRUE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_TRUE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(0, callback_count);

  // Notify failure.
  enable_cb.Run(BT_STATUS_FAIL);
  EXPECT_TRUE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(1, callback_count);
  EXPECT_EQ(BLE_STATUS_FAILURE, last_status);

  // Try again.
  EXPECT_TRUE(le_advertiser_->StopAdvertising(callback));
  EXPECT_TRUE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_TRUE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(1, callback_count);

  // Notify success.
  enable_cb.Run(BT_STATUS_SUCCESS);
  EXPECT_FALSE(le_advertiser_->IsAdvertisingStarted());
  EXPECT_FALSE(le_advertiser_->IsStartingAdvertising());
  EXPECT_FALSE(le_advertiser_->IsStoppingAdvertising());
  EXPECT_EQ(2, callback_count);
  EXPECT_EQ(BLE_STATUS_SUCCESS, last_status);

  // Already stopped.
  EXPECT_FALSE(le_advertiser_->StopAdvertising(callback));
}

TEST_F(LowEnergyAdvertiserPostRegisterTest, InvalidAdvertiseData) {
  const std::vector<uint8_t> data0{0x02, HCI_EIR_FLAGS_TYPE, 0x00};
  const std::vector<uint8_t> data1{0x04, HCI_EIR_MANUFACTURER_SPECIFIC_TYPE,
                                   0x01, 0x02, 0x00};
  AdvertiseData invalid_adv(data0);
  AdvertiseData valid_adv(data1);

  AdvertiseSettings settings;

  EXPECT_FALSE(le_advertiser_->StartAdvertising(
      settings, valid_adv, invalid_adv, LowEnergyAdvertiser::StatusCallback()));
  EXPECT_FALSE(le_advertiser_->StartAdvertising(
      settings, invalid_adv, valid_adv, LowEnergyAdvertiser::StatusCallback()));

  // Manufacturer data not correctly formatted according to spec. We let the
  // stack handle this case.
  const std::vector<uint8_t> data2{0x01, HCI_EIR_MANUFACTURER_SPECIFIC_TYPE};
  AdvertiseData invalid_mfc(data2);

  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _)).Times(1);
  EXPECT_TRUE(le_advertiser_->StartAdvertising(
      settings, invalid_mfc, valid_adv, LowEnergyAdvertiser::StatusCallback()));
}

TEST_F(LowEnergyAdvertiserPostRegisterTest, AdvertiseDataParsing) {
  const std::vector<uint8_t> kUUID16BitData{
      0x03, HCI_EIR_COMPLETE_16BITS_UUID_TYPE, 0xDE, 0xAD,
  };

  const std::vector<uint8_t> kUUID32BitData{
      0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE, 0xDE, 0xAD, 0x01, 0x02};

  const std::vector<uint8_t> kUUID128BitData{
      0x11, HCI_EIR_COMPLETE_128BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0x03, 0x04,
      0x05, 0x06,
      0x07, 0x08,
      0x09, 0x0A,
      0x0B, 0x0C,
      0x0D, 0x0E};

  const std::vector<uint8_t> kMultiUUIDData{
      0x11, HCI_EIR_COMPLETE_128BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0x03, 0x04,
      0x05, 0x06,
      0x07, 0x08,
      0x09, 0x0A,
      0x0B, 0x0C,
      0x0D, 0x0E,
      0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE,
      0xDE, 0xAD,
      0xBE, 0xEF};

  const std::vector<uint8_t> kServiceData16Bit{
      0x05, HCI_EIR_SERVICE_DATA_16BITS_UUID_TYPE, 0xDE, 0xAD, 0xBE, 0xEF};

  const std::vector<uint8_t> kServiceData32Bit{
      0x07, HCI_EIR_SERVICE_DATA_32BITS_UUID_TYPE, 0xDE, 0xAD, 0x01, 0x02, 0xBE,
      0xEF};

  const std::vector<uint8_t> kServiceData128Bit{
      0x13, HCI_EIR_SERVICE_DATA_128BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0x03, 0x04,
      0x05, 0x06,
      0x07, 0x08,
      0x09, 0x0A,
      0x0B, 0x0C,
      0x0D, 0x0E,
      0xBE, 0xEF};

  const std::vector<uint8_t> kMultiServiceData{
      0x13, HCI_EIR_SERVICE_DATA_128BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0x03, 0x04,
      0x05, 0x06,
      0xBE, 0xEF,
      0xDE, 0xAD,
      0x01, 0x02,
      0x03, 0x04,
      0x05, 0x06,
      0x05, HCI_EIR_SERVICE_DATA_16BITS_UUID_TYPE,
      0xDE, 0xAD,
      0xBE, 0xEF};

  const std::vector<uint8_t> kServiceUUIDMatch{
      0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0x07, HCI_EIR_SERVICE_DATA_32BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0xBE, 0xEF};

  const std::vector<uint8_t> kServiceUUIDMismatch{
      0x05, HCI_EIR_COMPLETE_32BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x01,
      0x07, HCI_EIR_SERVICE_DATA_32BITS_UUID_TYPE,
      0xDE, 0xAD,
      0x01, 0x02,
      0xBE, 0xEF};

  AdvertiseData uuid_16bit_adv(kUUID16BitData);
  AdvertiseData uuid_32bit_adv(kUUID32BitData);
  AdvertiseData uuid_128bit_adv(kUUID128BitData);
  AdvertiseData multi_uuid_adv(kMultiUUIDData);

  AdvertiseData service_16bit_adv(kServiceData16Bit);
  AdvertiseData service_32bit_adv(kServiceData32Bit);
  AdvertiseData service_128bit_adv(kServiceData128Bit);
  AdvertiseData multi_service_adv(kMultiServiceData);

  AdvertiseData service_uuid_match(kServiceUUIDMatch);
  AdvertiseData service_uuid_mismatch(kServiceUUIDMismatch);

  AdvertiseSettings settings;

  int callback_count = 0;
  BLEStatus last_status = BLE_STATUS_FAILURE;
  auto callback = [&](BLEStatus status) {
    last_status = status;
    callback_count++;
  };

  status_cb start_advertising_cb;
  // Multiple UUID test
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(multi_uuid_adv, callback, &start_advertising_cb);
  EXPECT_EQ(1, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // Multiple Service Data test
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(multi_service_adv, callback, &start_advertising_cb);
  EXPECT_EQ(2, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // 16bit uuid test, should succeed with correctly parsed uuid in little-endian
  // 128-bit format.
  const std::vector<uint8_t> uuid_16bit_canonical{
      0xFB, 0x34, 0x9b, 0x5F, 0x80, 0x00, 0x00, 0x80,
      0x00, 0x10, 0x00, 0x00, 0xDE, 0xAD, 0x00, 0x00};
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(uuid_16bit_adv, callback, &start_advertising_cb);
  EXPECT_EQ(3, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // 32bit uuid test, should succeed with correctly parsed uuid
  const std::vector<uint8_t> uuid_32bit_canonical{
      0xFB, 0x34, 0x9b, 0x5F, 0x80, 0x00, 0x00, 0x80,
      0x00, 0x10, 0x00, 0x00, 0xDE, 0xAD, 0x01, 0x02};
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(uuid_32bit_adv, callback, &start_advertising_cb);
  EXPECT_EQ(4, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // 128bit uuid test, should succeed with correctly parsed uuid
  const std::vector<uint8_t> uuid_128bit{0xDE, 0xAD, 0x01, 0x02, 0x03, 0x04,
                                         0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
                                         0x0B, 0x0C, 0x0D, 0x0E};
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(uuid_128bit_adv, callback, &start_advertising_cb);
  EXPECT_EQ(5, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  const std::vector<uint8_t> service_data{0xBE, 0xEF};

  // Service data with 16bit uuid included, should succeed with
  // uuid and service data parsed out
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(service_16bit_adv, callback, &start_advertising_cb);
  EXPECT_EQ(6, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // Service data with 32bit uuid included, should succeed with
  // uuid and service data parsed out
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(service_32bit_adv, callback, &start_advertising_cb);
  EXPECT_EQ(7, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // Service data with 128bit uuid included, should succeed with
  // uuid and service data parsed out
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(service_128bit_adv, callback, &start_advertising_cb);
  EXPECT_EQ(8, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // Service data and UUID where the UUID for both match, should succeed.
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(service_uuid_match, callback, &start_advertising_cb);
  EXPECT_EQ(9, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());

  // Service data and UUID where the UUID for dont match, should fail
  EXPECT_CALL(*mock_handler_, StartAdvertising(_, _, _, _, _, _, _))
      .Times(1)
      .WillOnce(SaveArg<1>(&start_advertising_cb));
  AdvertiseDataTestHelper(service_uuid_match, callback, &start_advertising_cb);
  EXPECT_EQ(10, callback_count);
  ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
}

MATCHER_P(BitEq, x, std::string(negation ? "isn't" : "is") +
                        " bitwise equal to " + ::testing::PrintToString(x)) {
  static_assert(sizeof(x) == sizeof(arg), "Size mismatch");
  return std::memcmp(&arg, &x, sizeof(x)) == 0;
}

}  // namespace
}  // namespace bluetooth
