// Copyright 2020 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/interrogator.h"

#include <lib/async/default.h>

#include "src/connectivity/bluetooth/core/bt-host/common/test_helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/peer_cache.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/util.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/controller_test.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/fake_peer.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/mock_controller.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/test_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/error.h"

namespace bt::gap {

constexpr hci_spec::ConnectionHandle kConnectionHandle = 0x0BAA;
const DeviceAddress kTestDevAddr(DeviceAddress::Type::kBREDR, {1});

class TestInterrogator final : public Interrogator {
 public:
  // Reuse constructor
  using Interrogator::Interrogator;
  ~TestInterrogator() override = default;

  using InterrogationRefPtr = Interrogator::InterrogationRefPtr;

  void set_send_commands_cb(fit::function<void(InterrogationRefPtr)> cb) {
    send_commands_cb_ = std::move(cb);
  }

  // Make command methods public for testing:

  using Interrogator::ReadRemoteVersionInformation;

 private:
  // Interrogator overrides:

  void SendCommands(InterrogationRefPtr interrogation) override {
    if (send_commands_cb_) {
      send_commands_cb_(std::move(interrogation));
    }
  }

  fit::function<void(InterrogationRefPtr)> send_commands_cb_;
};

using InterrogationRefPtr = TestInterrogator::InterrogationRefPtr;

using TestingBase = bt::testing::ControllerTest<bt::testing::MockController>;
class InterrogatorTest : public TestingBase {
 public:
  InterrogatorTest() = default;
  ~InterrogatorTest() override = default;

  void SetUp() override {
    TestingBase::SetUp();

    peer_cache_ = std::make_unique<PeerCache>();
    interrogator_ = std::make_unique<TestInterrogator>(peer_cache_.get(), transport()->WeakPtr());

    StartTestDevice();
  }

  void TearDown() override {
    RunLoopUntilIdle();
    test_device()->Stop();
    interrogator_ = nullptr;
    peer_cache_ = nullptr;
    TestingBase::TearDown();
  }

 protected:
  PeerCache* peer_cache() const { return peer_cache_.get(); }

  TestInterrogator* interrogator() const { return interrogator_.get(); }

  void DeleteInterrogator() { interrogator_.reset(); }

 private:
  std::unique_ptr<PeerCache> peer_cache_;
  std::unique_ptr<TestInterrogator> interrogator_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(InterrogatorTest);
};

using GAP_InterrogatorTest = InterrogatorTest;

TEST_F(InterrogatorTest, DroppingInterrogationRefCompletesInterrogation) {
  std::optional<InterrogationRefPtr> ref;
  interrogator()->set_send_commands_cb([&ref](InterrogationRefPtr r) { ref = std::move(r); });

  auto* peer = peer_cache()->NewPeer(kTestDevAddr, /*connectable=*/true);

  ASSERT_FALSE(ref.has_value());

  std::optional<hci::Result<>> result;
  interrogator()->Start(peer->identifier(), kConnectionHandle,
                        [&](hci::Result<> status) { result = status; });

  ASSERT_TRUE(ref.has_value());
  EXPECT_FALSE(result.has_value());

  // Dropping ref should call result callback with success status.
  ref.reset();

  ASSERT_TRUE(result.has_value());
  EXPECT_EQ(fitx::ok(), *result);
}

TEST_F(InterrogatorTest,
       DestroyingInterrogatorBeforeReadRemoteVersionInformationCompleteCallbackCalledDoesNotCrash) {
  std::optional<InterrogationRefPtr> ref;
  interrogator()->set_send_commands_cb([this, &ref](InterrogationRefPtr r) {
    ref = std::move(r);
    EXPECT_CMD_PACKET_OUT(test_device(), testing::ReadRemoteVersionInfoPacket(kConnectionHandle));
    interrogator()->ReadRemoteVersionInformation(*ref);
  });

  auto* peer = peer_cache()->NewPeer(kTestDevAddr, /*connectable=*/true);

  ASSERT_FALSE(ref.has_value());

  std::optional<hci::Result<>> result;
  interrogator()->Start(peer->identifier(), kConnectionHandle,
                        [&](hci::Result<> status) { result = status; });

  ASSERT_TRUE(ref.has_value());
  EXPECT_FALSE(result.has_value());

  DeleteInterrogator();

  // The result callback should be called synchronously.
  EXPECT_TRUE(result.has_value());
  EXPECT_EQ(result.value(), ToResult(HostError::kCanceled));

  test_device()->SendCommandChannelPacket(
      testing::ReadRemoteVersionInfoCompletePacket(kConnectionHandle));

  // Process command complete callback.
  RunLoopUntilIdle();
}

TEST_F(InterrogatorTest, Cancel) {
  std::optional<InterrogationRefPtr> ref;
  interrogator()->set_send_commands_cb([this, &ref](InterrogationRefPtr r) {
    ref = std::move(r);
    EXPECT_CMD_PACKET_OUT(test_device(), testing::ReadRemoteVersionInfoPacket(kConnectionHandle));
    interrogator()->ReadRemoteVersionInformation(*ref);
  });

  auto* peer = peer_cache()->NewPeer(kTestDevAddr, /*connectable=*/true);

  ASSERT_FALSE(ref.has_value());

  std::optional<hci::Result<>> result;
  interrogator()->Start(peer->identifier(), kConnectionHandle,
                        [&](hci::Result<> status) { result = status; });

  ASSERT_TRUE(ref.has_value());
  EXPECT_FALSE(result.has_value());

  interrogator()->Cancel(peer->identifier());

  // The result callback should be called synchronously.
  EXPECT_TRUE(result.has_value());
  EXPECT_EQ(result.value(), ToResult(HostError::kCanceled));

  // Events after Cancel() should be ignored.
  test_device()->SendCommandChannelPacket(
      testing::ReadRemoteVersionInfoCompletePacket(kConnectionHandle));

  // Process command complete callback.
  RunLoopUntilIdle();
  EXPECT_EQ(result.value(), ToResult(HostError::kCanceled));
}

}  // namespace bt::gap
