// 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.

#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TESTING_FAKE_CONTROLLER_TEST_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TESTING_FAKE_CONTROLLER_TEST_H_

#include <lib/async/cpp/task.h>
#include <zircon/assert.h>

#include <memory>

#include <fbl/macros.h>

#include "lib/gtest/test_loop_fixture.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/acl_data_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/acl_data_packet.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/device_wrapper.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/transport.h"

namespace bt {
namespace testing {

class FakeControllerBase;

// FakeControllerTest is a test harness intended for tests that rely on HCI
// transactions. It is templated on FakeControllerType which must derive from
// FakeControllerBase and must be able to send and receive HCI packets over
// Zircon channels, acting as the controller endpoint of HCI.
//
// The testing library provides two such types:
//
//   - TestController (test_controller.h): Routes HCI packets directly to the
//     test harness. It allows tests to setup expectations based on the receipt
//     of HCI packets.
//
//   - FakeController (fake_controller.h): Emulates a Bluetooth controller. This
//     can respond to HCI commands the way a real controller would (albeit in a
//     contrived fashion), emulate discovery and connection events, etc.
template <class FakeControllerType>
class FakeControllerTest : public ::gtest::TestLoopFixture {
 public:
  // Default data buffer information used by ACLDataChannel.
  static constexpr size_t kDefaultMaxDataPacketLength = 1024;
  static constexpr size_t kDefaultMaxPacketCount = 5;

  FakeControllerTest() = default;
  virtual ~FakeControllerTest() = default;

 protected:
  // TestBase overrides:
  void SetUp() override {
    transport_ = hci::Transport::Create(FakeControllerTest<FakeControllerType>::SetUpTestDevice());
    transport_->Initialize(dispatcher());
  }

  void TearDown() override {
    if (!transport_)
      return;

    if (transport_->IsInitialized()) {
      transport_->ShutDown();
    }

    RunLoopUntilIdle();

    transport_ = nullptr;
    test_device_ = nullptr;
  }

  // Directly initializes the ACL data channel and wires up its data rx
  // callback. It is OK to override the data rx callback after this is called.
  //
  // If data buffer information isn't provided, the ACLDataChannel will be
  // initialized with shared BR/EDR/LE buffers using the constants declared
  // above.
  bool InitializeACLDataChannel(const hci::DataBufferInfo& bredr_buffer_info = hci::DataBufferInfo(
                                    kDefaultMaxDataPacketLength, kDefaultMaxPacketCount),
                                const hci::DataBufferInfo& le_buffer_info = hci::DataBufferInfo()) {
    if (!transport_->InitializeACLDataChannel(bredr_buffer_info, le_buffer_info)) {
      return false;
    }

    transport_->acl_data_channel()->SetDataRxHandler(
        std::bind(&FakeControllerTest<FakeControllerType>::OnDataReceived, this,
                  std::placeholders::_1),
        dispatcher());

    return true;
  }

  // Sets a callback which will be invoked when we receive packets from the test
  // controller. |callback| will be posted on the test loop, thus no locking is
  // necessary within the callback.
  //
  // InitializeACLDataChannel() must be called once and its data rx handler must
  // not be overridden by tests for |callback| to work.
  void set_data_received_callback(hci::ACLPacketHandler callback) {
    data_received_callback_ = std::move(callback);
  }

  fxl::RefPtr<hci::Transport> transport() const { return transport_; }
  hci::CommandChannel* cmd_channel() const { return transport_->command_channel(); }
  hci::ACLDataChannel* acl_data_channel() const { return transport_->acl_data_channel(); }

  // Deletes |test_device_| and resets the pointer.
  void DeleteTestDevice() { test_device_ = nullptr; }

  // Getters for internal fields frequently used by tests.
  FakeControllerType* test_device() const { return test_device_.get(); }
  zx::channel test_cmd_chan() { return std::move(cmd1_); }
  zx::channel test_acl_chan() { return std::move(acl1_); }

  // Starts processing data on the control and ACL data channels.
  void StartTestDevice() {
    test_device()->StartCmdChannel(test_cmd_chan());
    test_device()->StartAclChannel(test_acl_chan());
  }

 private:
  // Channels to be moved to the tests
  zx::channel cmd1_;
  zx::channel acl1_;

  // Initializes |test_device_| and returns the DeviceWrapper endpoint which can
  // be passed to classes that are under test.
  std::unique_ptr<hci::DeviceWrapper> SetUpTestDevice() {
    zx::channel cmd0;
    zx::channel acl0;

    zx_status_t status = zx::channel::create(0, &cmd0, &cmd1_);
    ZX_DEBUG_ASSERT(ZX_OK == status);

    status = zx::channel::create(0, &acl0, &acl1_);
    ZX_DEBUG_ASSERT(ZX_OK == status);

    auto hci_dev = std::make_unique<hci::DummyDeviceWrapper>(std::move(cmd0), std::move(acl0));
    test_device_ = std::make_unique<FakeControllerType>();

    return hci_dev;
  }

  void OnDataReceived(hci::ACLDataPacketPtr data_packet) {
    // Accessing |data_received_callback_| is racy but unlikely to cause issues
    // in unit tests. NOTE(armansito): Famous last words?
    if (!data_received_callback_)
      return;

    async::PostTask(dispatcher(), [this, packet = std::move(data_packet)]() mutable {
      data_received_callback_(std::move(packet));
    });
  }

  std::unique_ptr<FakeControllerType> test_device_;
  fxl::RefPtr<hci::Transport> transport_;
  hci::ACLPacketHandler data_received_callback_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeControllerTest);
  static_assert(std::is_base_of<FakeControllerBase, FakeControllerType>::value,
                "TestBase must be used with a derivative of FakeControllerBase");
};

}  // namespace testing
}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TESTING_FAKE_CONTROLLER_TEST_H_
