// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/connectivity/bluetooth/core/bt-host/gap/low_energy_advertising_manager.h"

#include <fbl/macros.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>

#include <map>

#include "lib/gtest/test_loop_fixture.h"
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/fake_connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/fake_local_address_delegate.h"

namespace bt {
namespace gap {
namespace {

constexpr size_t kDefaultMaxAds = 1;
constexpr size_t kDefaultMaxAdSize = 23;
constexpr size_t kDefaultFakeAdSize = 20;
constexpr zx::duration kTestInterval = zx::sec(1);

const DeviceAddress kRandomAddress(DeviceAddress::Type::kLERandom,
                                   "00:11:22:33:44:55");

struct AdvertisementStatus {
  AdvertisingData data;
  AdvertisingData scan_rsp;
  bool anonymous;
  zx::duration interval;
  hci::LowEnergyAdvertiser::ConnectionCallback connect_cb;
};

// LowEnergyAdvertiser for testing purposes:
//  - Reports max_ads supported
//  - Reports mas_ad_size supported
//  - Actually just accepts all ads and stores them in ad_store
class FakeLowEnergyAdvertiser final : public hci::LowEnergyAdvertiser {
 public:
  FakeLowEnergyAdvertiser(
      size_t max_ads, size_t max_ad_size,
      std::map<DeviceAddress, AdvertisementStatus>* ad_store)
      : max_ads_(max_ads), max_ad_size_(max_ad_size), ads_(ad_store) {
    ZX_ASSERT(ads_);
  }

  ~FakeLowEnergyAdvertiser() override = default;

  size_t GetSizeLimit() override { return max_ad_size_; }

  size_t GetMaxAdvertisements() const override { return max_ads_; }

  bool AllowsRandomAddressChange() const override { return true; }

  void StartAdvertising(const DeviceAddress& address, const ByteBuffer& data,
                        const ByteBuffer& scan_rsp,
                        ConnectionCallback connect_callback,
                        zx::duration interval, bool anonymous,
                        AdvertisingStatusCallback callback) override {
    if (!pending_error_) {
      callback(zx::duration(), pending_error_);
      pending_error_ = hci::Status();
      return;
    }
    if (data.size() > max_ad_size_) {
      callback(zx::duration(), hci::Status(HostError::kInvalidParameters));
      return;
    }
    if (scan_rsp.size() > max_ad_size_) {
      callback(zx::duration(), hci::Status(HostError::kInvalidParameters));
      return;
    }
    AdvertisementStatus new_status;
    AdvertisingData::FromBytes(data, &new_status.data);
    AdvertisingData::FromBytes(scan_rsp, &new_status.scan_rsp);
    new_status.connect_cb = std::move(connect_callback);
    new_status.interval = interval;
    new_status.anonymous = anonymous;
    ads_->emplace(address, std::move(new_status));
    callback(interval, hci::Status());
  }

  bool StopAdvertising(const DeviceAddress& address) override {
    ads_->erase(address);
    return true;
  }

  void OnIncomingConnection(
      hci::ConnectionHandle handle, hci::Connection::Role role,
      const DeviceAddress& peer_address,
      const hci::LEConnectionParameters& conn_params) override {
    // Right now, we call the first callback, because we can't call any other
    // ones.
    // TODO(jamuraa): make this send it to the correct callback once we can
    // determine which one that is.
    const auto& cb = ads_->begin()->second.connect_cb;
    if (cb) {
      cb(std::make_unique<hci::testing::FakeConnection>(
          handle, hci::Connection::LinkType::kLE, role, ads_->begin()->first,
          peer_address));
    }
  }

  // Sets this faker up to send an error back from the next StartAdvertising
  // call. Set to success to disable a previously called error.
  void ErrorOnNext(hci::Status error_status) { pending_error_ = error_status; }

 private:
  size_t max_ads_, max_ad_size_;
  std::map<DeviceAddress, AdvertisementStatus>* ads_;
  hci::Status pending_error_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeLowEnergyAdvertiser);
};

using TestingBase = ::gtest::TestLoopFixture;

class GAP_LowEnergyAdvertisingManagerTest : public TestingBase {
 public:
  GAP_LowEnergyAdvertisingManagerTest() = default;
  ~GAP_LowEnergyAdvertisingManagerTest() override = default;

 protected:
  void SetUp() override {
    fake_address_delegate_.set_local_address(kRandomAddress);
    MakeFakeAdvertiser();
    MakeAdvertisingManager();
  }

  void TearDown() override {
    adv_mgr_ = nullptr;
    advertiser_ = nullptr;
  }

  // Makes some fake advertising data of a specific |packed_size|
  AdvertisingData CreateFakeAdvertisingData(
      size_t packed_size = kDefaultFakeAdSize) {
    AdvertisingData result;
    auto buffer = CreateStaticByteBuffer(0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
                                         0x06, 0x07, 0x08);
    size_t bytes_left = packed_size;
    while (bytes_left > 0) {
      // Each field to take 10 bytes total, unless the next header (4 bytes)
      // won't fit. In which case we add enough bytes to finish up.
      size_t data_bytes = bytes_left < 14 ? (bytes_left - 4) : 6;
      result.SetManufacturerData(0xb000 + bytes_left,
                                 buffer.view(0, data_bytes));
      bytes_left = packed_size - result.CalculateBlockSize();
    }
    return result;
  }

  LowEnergyAdvertisingManager::AdvertisingStatusCallback GetErrorCallback() {
    return [this](AdvertisementId ad_id, hci::Status status) {
      EXPECT_EQ(kInvalidAdvertisementId, ad_id);
      EXPECT_FALSE(status);
      last_status_ = status;
    };
  }

  LowEnergyAdvertisingManager::AdvertisingStatusCallback GetSuccessCallback() {
    return [this](AdvertisementId ad_id, hci::Status status) {
      last_ad_id_ = ad_id;
      EXPECT_NE(kInvalidAdvertisementId, ad_id);
      EXPECT_TRUE(status);
      last_status_ = status;
    };
  }

  void MakeFakeAdvertiser(size_t max_ads = kDefaultMaxAds,
                          size_t max_ad_size = kDefaultMaxAdSize) {
    advertiser_ = std::make_unique<FakeLowEnergyAdvertiser>(
        max_ads, max_ad_size, &ad_store_);
  }

  void MakeAdvertisingManager() {
    adv_mgr_ = std::make_unique<LowEnergyAdvertisingManager>(
        advertiser(), &fake_address_delegate_);
  }

  LowEnergyAdvertisingManager* adv_mgr() const { return adv_mgr_.get(); }
  const std::map<DeviceAddress, AdvertisementStatus>& ad_store() {
    return ad_store_;
  }
  AdvertisementId last_ad_id() const { return last_ad_id_; }

  // Returns and clears the last callback status. This resets the state to
  // detect another callback.
  const std::optional<hci::Status> MoveLastStatus() {
    return std::move(last_status_);
  }

  FakeLowEnergyAdvertiser* advertiser() const { return advertiser_.get(); }

 private:
  hci::FakeLocalAddressDelegate fake_address_delegate_;

  std::map<DeviceAddress, AdvertisementStatus> ad_store_;
  AdvertisementId last_ad_id_;
  std::optional<hci::Status> last_status_;
  std::unique_ptr<FakeLowEnergyAdvertiser> advertiser_;
  std::unique_ptr<LowEnergyAdvertisingManager> adv_mgr_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(GAP_LowEnergyAdvertisingManagerTest);
};

// Tests:
//  - When the advertiser succeeds, the callback is called with the success
TEST_F(GAP_LowEnergyAdvertisingManagerTest, Success) {
  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp;  // Empty scan response

  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, nullptr, kTestInterval,
                              false /* anonymous */, GetSuccessCallback());

  RunLoopUntilIdle();

  EXPECT_TRUE(MoveLastStatus());
  ASSERT_EQ(1u, ad_store().size());

  // Verify that the advertiser uses the requested local address.
  EXPECT_EQ(kRandomAddress, ad_store().begin()->first);
}

TEST_F(GAP_LowEnergyAdvertisingManagerTest, DataSize) {
  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp;  // Empty scan response

  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, nullptr, kTestInterval,
                              false /* anonymous */, GetSuccessCallback());

  RunLoopUntilIdle();

  fake_ad = CreateFakeAdvertisingData(kDefaultMaxAdSize + 1);

  EXPECT_TRUE(MoveLastStatus());
  EXPECT_EQ(1u, ad_store().size());

  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, nullptr, kTestInterval,
                              false /* anonymous */, GetErrorCallback());

  RunLoopUntilIdle();

  EXPECT_TRUE(MoveLastStatus());
  EXPECT_EQ(1u, ad_store().size());
}

// TODO(BT-742): Revise this test to use multiple advertising instances when
// multi-advertising is supported.
//  - Stopping one that is registered stops it in the advertiser
//    (and stops the right address)
//  - Stopping an advertisement that isn't registered retuns false
TEST_F(GAP_LowEnergyAdvertisingManagerTest, RegisterUnregister) {
  MakeFakeAdvertiser(2 /* ads available */);
  MakeAdvertisingManager();

  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp;  // Empty scan response

  EXPECT_FALSE(adv_mgr()->StopAdvertising(kInvalidAdvertisementId));

  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, nullptr, kTestInterval,
                              false /* anonymous */, GetSuccessCallback());

  RunLoopUntilIdle();

  EXPECT_TRUE(MoveLastStatus());
  EXPECT_EQ(1u, ad_store().size());

  EXPECT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
  EXPECT_TRUE(ad_store().empty());

  EXPECT_FALSE(adv_mgr()->StopAdvertising(last_ad_id()));
  EXPECT_TRUE(ad_store().empty());
}

//  - When the advertiser returns an error, we return an error
TEST_F(GAP_LowEnergyAdvertisingManagerTest, AdvertiserError) {
  advertiser()->ErrorOnNext(hci::Status(hci::kInvalidHCICommandParameters));
  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp;

  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, nullptr, kTestInterval,
                              false /* anonymous */, GetErrorCallback());

  RunLoopUntilIdle();

  EXPECT_TRUE(MoveLastStatus());
}

//  - It calls the connectable callback correctly when connected to
TEST_F(GAP_LowEnergyAdvertisingManagerTest, ConnectCallback) {
  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp;

  hci::ConnectionPtr link;
  AdvertisementId advertised_id = kInvalidAdvertisementId;

  auto connect_cb = [&](AdvertisementId connected_id,
                        hci::ConnectionPtr cb_link) {
    link = std::move(cb_link);
    EXPECT_EQ(advertised_id, connected_id);
  };
  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, connect_cb, kTestInterval,
                              false /* anonymous */, GetSuccessCallback());

  RunLoopUntilIdle();

  EXPECT_TRUE(MoveLastStatus());
  advertised_id = last_ad_id();

  DeviceAddress peer_address(DeviceAddress::Type::kLEPublic,
                             "03:02:01:01:02:03");
  advertiser()->OnIncomingConnection(1, hci::Connection::Role::kSlave,
                                     peer_address,
                                     hci::LEConnectionParameters());
  RunLoopUntilIdle();
  ASSERT_TRUE(link);

  // Make sure that the link has the correct local and peer addresses assigned.
  EXPECT_EQ(kRandomAddress, link->local_address());
  EXPECT_EQ(peer_address, link->peer_address());
}

//  - Error: Connectable and Anonymous at the same time
TEST_F(GAP_LowEnergyAdvertisingManagerTest, ConnectAdvertiseError) {
  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp;

  auto connect_cb = [this](AdvertisementId connected_id,
                           hci::ConnectionPtr conn) {};

  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, connect_cb, kTestInterval,
                              true /* anonymous */, GetErrorCallback());

  EXPECT_TRUE(MoveLastStatus());
}

//  - Passes the values for the data on. (anonymous, data, scan_rsp,
//  interval_ms)
TEST_F(GAP_LowEnergyAdvertisingManagerTest, SendsCorrectData) {
  AdvertisingData fake_ad = CreateFakeAdvertisingData();
  AdvertisingData scan_rsp = CreateFakeAdvertisingData(21 /* size of ad */);

  zx_duration_t random = 0;
  zx_cprng_draw(&random, sizeof(random));
  auto interval = zx::duration(random);
  adv_mgr()->StartAdvertising(fake_ad, scan_rsp, nullptr, interval,
                              false /* anonymous */, GetSuccessCallback());

  RunLoopUntilIdle();

  EXPECT_TRUE(MoveLastStatus());
  EXPECT_EQ(1u, ad_store().size());

  auto ad_status = &ad_store().begin()->second;

  EXPECT_EQ(fake_ad, ad_status->data);
  EXPECT_EQ(scan_rsp, ad_status->scan_rsp);
  EXPECT_EQ(false, ad_status->anonymous);
  EXPECT_EQ(nullptr, ad_status->connect_cb);
  EXPECT_EQ(interval, ad_status->interval);
}

}  // namespace
}  // namespace gap
}  // namespace bt
