// Copyright 2018 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 "garnet/drivers/bluetooth/lib/common/slab_allocator.h"
#include "garnet/drivers/bluetooth/lib/l2cap/fake_channel_test.h"
#include "garnet/drivers/bluetooth/lib/l2cap/fake_layer.h"
#include "garnet/drivers/bluetooth/lib/rfcomm/channel_manager.h"

namespace btlib {
namespace rfcomm {
namespace {

constexpr l2cap::ChannelId kL2CAPChannelId1 = 0x0040;
constexpr l2cap::ChannelId kL2CAPChannelId2 = 0x0041;
constexpr hci::ConnectionHandle kHandle1 = 1;

void DoNothingWithChannel(fbl::RefPtr<Channel> channel,
                          ServerChannel server_channel) {}

class RFCOMM_ChannelManagerTest : public l2cap::testing::FakeChannelTest {
 public:
  RFCOMM_ChannelManagerTest() : channel_manager_(nullptr) {}
  ~RFCOMM_ChannelManagerTest() override = default;

 protected:
  // Captures the state of the fake remote peer.
  struct PeerState {
    // Whether this peer supports credit-based flow. This bool also indicates
    // whether the session with this peer will have credit-based flow turned on;
    // our RFCOMM implementation will always turn on credit-based flow if the
    // peer supports it.
    bool credit_based_flow;
    Role role;
  };

  void SetUp() override {
    l2cap_ = l2cap::testing::FakeLayer::Create();
    FXL_DCHECK(l2cap_);

    l2cap_->Initialize();
    l2cap_->AddACLConnection(kHandle1, hci::Connection::Role::kMaster,
                             [] { FXL_LOG(WARNING) << "Unimplemented"; },
                             dispatcher());
    // Any new L2CAP channels (incoming our outgoing) opened by our
    // ChannelManager will be captured and stored in |handle_to_fake_channel_|.
    // Subsequently, all channels will have listeners attached to them, and any
    // frames sent from our RFCOMM sessions will be put into the queues in
    // |handle_to_incoming_frames_|.
    l2cap_->set_channel_callback(
        [this](fbl::RefPtr<l2cap::testing::FakeChannel> l2cap_channel) {
          FXL_DCHECK(l2cap_channel);
          auto handle = l2cap_channel->link_handle();
          handle_to_fake_channel_.emplace(handle, l2cap_channel);
          l2cap_channel->SetSendCallback(
              [this, handle](auto sdu) {
                if (handle_to_incoming_frames_.find(handle) ==
                    handle_to_incoming_frames_.end()) {
                  handle_to_incoming_frames_.emplace(
                      handle,
                      std::queue<std::unique_ptr<const common::ByteBuffer>>());
                }
                handle_to_incoming_frames_[handle].push(std::move(sdu));
              },
              dispatcher());
        });

    channel_manager_ = ChannelManager::Create(l2cap_.get());
    FXL_DCHECK(channel_manager_);
  }

  void TearDown() override {
    channel_manager_.release();
    l2cap_.reset();
    handle_to_peer_state_.clear();
    handle_to_fake_channel_.clear();
    handle_to_incoming_frames_.clear();
  }

  // Emplace a new PeerState for a new fake peer. Should be called for each fake
  // peer which a test is emulating. The returned PeerState should then be
  // updated throughout the test (e.g. the multiplexer state should change when
  // the multiplexer starts up).
  PeerState& AddFakePeerState(hci::ConnectionHandle handle, PeerState state) {
    FXL_DCHECK(handle_to_peer_state_.find(handle) ==
               handle_to_peer_state_.end());
    handle_to_peer_state_.emplace(handle, std::move(state));
    return handle_to_peer_state_[handle];
  }

  fbl::RefPtr<l2cap::testing::FakeChannel> GetFakeChannel(
      hci::ConnectionHandle handle) {
    FXL_DCHECK(handle_to_fake_channel_.find(handle) !=
               handle_to_fake_channel_.end());
    return handle_to_fake_channel_[handle];
  }

  void ExpectFrame(hci::ConnectionHandle handle, FrameType type, DLCI dlci) {
    auto queue_it = handle_to_incoming_frames_.find(handle);
    EXPECT_FALSE(handle_to_incoming_frames_.end() == queue_it);

    EXPECT_FALSE(handle_to_peer_state_.find(handle) ==
                 handle_to_peer_state_.end());
    const PeerState& state = handle_to_peer_state_[handle];

    auto frame = Frame::Parse(state.credit_based_flow, OppositeRole(state.role),
                              queue_it->second.front()->view());
    queue_it->second.pop();
    EXPECT_TRUE(frame);
    EXPECT_EQ(type, static_cast<FrameType>(frame->control()));
    EXPECT_EQ(dlci, frame->dlci());
  }

  void ReceiveFrame(hci::ConnectionHandle handle,
                    std::unique_ptr<Frame> frame) {
    auto channel = GetFakeChannel(handle);

    auto buffer = common::NewSlabBuffer(frame->written_size());
    frame->Write(buffer->mutable_view());
    channel->Receive(buffer->view());
  }

  // Makes the asynchronous channel-getting process synchronous, for the
  // purposes of writing clean tests. This function will imitiate (to
  // |channel_manager_|) an RFCOMM peer, and will send frames to handle
  // multiplexer startup, optional parameter negotiation, and finally, channel
  // opening.
  //
  // If this is the first channel which will be opened on this handle,
  // the state of the peer should first be set in |handle_to_peer_state_|.
  // These state variables will then be used during the session startup
  // procedure which will ensue.
  fbl::RefPtr<Channel> OpenOutgoingChannel(hci::ConnectionHandle handle,
                                           ServerChannel server_channel);

  // The fake remote peer represented by |handle| attempts to open
  // |server_channel|. If no session exists, this function will handle session
  // startup, multiplexer startup, and parameter negotiation.
  void OpenIncomingChannel(hci::ConnectionHandle handle,
                           ServerChannel server_channel);

  std::unique_ptr<ChannelManager> channel_manager_;

  fbl::RefPtr<l2cap::testing::FakeLayer> l2cap_;

  std::unordered_map<hci::ConnectionHandle,
                     std::queue<std::unique_ptr<const common::ByteBuffer>>>
      handle_to_incoming_frames_;

  // Maps remote peers (represented as connection handles) to the L2CAP channel
  // (actually a FakeChannel) over which the corresponding RFCOMM session
  // communicates with that peer.
  std::unordered_map<hci::ConnectionHandle,
                     fbl::RefPtr<l2cap::testing::FakeChannel>>
      handle_to_fake_channel_;

  // Holds the state of the fake peers. Tests must manually update this
  // information as needed; for example, if a test mimics mux startup manually,
  // it must change its role accordingly, otherwise utility functions like
  // ExpectFrame() will not parse frames correctly.
  std::unordered_map<hci::ConnectionHandle, PeerState> handle_to_peer_state_;
};

fbl::RefPtr<Channel> RFCOMM_ChannelManagerTest::OpenOutgoingChannel(
    hci::ConnectionHandle handle, ServerChannel server_channel) {
  FXL_DCHECK(handle_to_peer_state_.find(handle) != handle_to_peer_state_.end())
      << "No peer state for handle " << handle;
  PeerState& state = handle_to_peer_state_[handle];

  fbl::RefPtr<Channel> return_channel = nullptr;
  channel_manager_->OpenRemoteChannel(
      handle, server_channel,
      [&return_channel](auto channel, auto server_channel) {
        return_channel = channel;
      },
      dispatcher());
  RunLoopUntilIdle();

  // If the fake L2CAP channel doesn't exist yet, we need to trigger its
  // creation with TriggerOutboundChannel.
  if (handle_to_fake_channel_.find(handle) == handle_to_fake_channel_.end()) {
    l2cap_->TriggerOutboundChannel(handle, l2cap::kRFCOMM, kL2CAPChannelId1,
                                   kL2CAPChannelId2);
    RunLoopUntilIdle();
  }

  EXPECT_FALSE(handle_to_incoming_frames_.find(handle) ==
               handle_to_incoming_frames_.end());
  auto& queue = handle_to_incoming_frames_[handle];

  EXPECT_FALSE(queue.empty());
  auto frame =
      Frame::Parse(state.credit_based_flow, state.role, queue.front()->view());

  queue.pop();
  FXL_DCHECK(frame);

  // If we received a mux startup request, respond to it.
  if (static_cast<FrameType>(frame->control()) ==
          FrameType::kSetAsynchronousBalancedMode &&
      frame->dlci() == kMuxControlDLCI) {
    ReceiveFrame(handle, std::make_unique<UnnumberedAcknowledgementResponse>(
                             state.role, kMuxControlDLCI));

    state.role = Role::kResponder;

    RunLoopUntilIdle();

    // Expect that another frame has arrived.
    EXPECT_FALSE(queue.empty());
    frame = Frame::Parse(state.credit_based_flow, state.role,
                         queue.front()->view());
    queue.pop();
  }

  // If we received a parameter negotiation request, respond to it.
  if (static_cast<FrameType>(frame->control()) ==
          FrameType::kUnnumberedInfoHeaderCheck &&
      frame->dlci() == kMuxControlDLCI) {
    auto pn_command_mux_command =
        static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand();
    EXPECT_EQ(MuxCommandType::kDLCParameterNegotiation,
              pn_command_mux_command->command_type());
    EXPECT_EQ(CommandResponse::kCommand,
              pn_command_mux_command->command_response());

    auto pn_command = std::unique_ptr<DLCParameterNegotiationCommand>(
        static_cast<DLCParameterNegotiationCommand*>(
            pn_command_mux_command.release()));

    // For now, just send back the same parameters (making sure to send the
    // correct credit-based flow response based on our credit-based flow
    // setting).
    ParameterNegotiationParams params = pn_command->params();
    params.credit_based_flow_handshake =
        state.credit_based_flow ? CreditBasedFlowHandshake::kSupportedResponse
                                : CreditBasedFlowHandshake::kUnsupported;
    ReceiveFrame(handle, std::make_unique<MuxCommandFrame>(
                             state.role, state.credit_based_flow,
                             std::make_unique<DLCParameterNegotiationCommand>(
                                 CommandResponse::kResponse, params)));

    RunLoopUntilIdle();

    // Expect that another frame has arrived.
    EXPECT_FALSE(queue.empty());
    frame = Frame::Parse(state.credit_based_flow, state.role,
                         queue.front()->view());
    queue.pop();
  }

  EXPECT_EQ(FrameType::kSetAsynchronousBalancedMode,
            FrameType(frame->control()));
  DLCI dlci = ServerChannelToDLCI(server_channel, state.role);
  EXPECT_EQ(dlci, frame->dlci());

  ReceiveFrame(handle, std::make_unique<UnnumberedAcknowledgementResponse>(
                           state.role, dlci));

  RunLoopUntilIdle();

  EXPECT_TRUE(return_channel);

  return return_channel;
}

void RFCOMM_ChannelManagerTest::OpenIncomingChannel(
    hci::ConnectionHandle handle, ServerChannel server_channel) {
  FXL_DCHECK(handle_to_peer_state_.find(handle) != handle_to_peer_state_.end())
      << "Please set peer state for handle " << handle
      << " before attempting to open a channel on this handle";

  PeerState& state = handle_to_peer_state_[handle];

  if (handle_to_fake_channel_.find(handle) == handle_to_fake_channel_.end()) {
    l2cap_->TriggerInboundChannel(handle, l2cap::kRFCOMM, kL2CAPChannelId1,
                                  kL2CAPChannelId2);
    RunLoopUntilIdle();

    // If channel didn't exist, then we need to do mux startup and parameter
    // negotiation.
    auto l2cap_channel = GetFakeChannel(handle);

    ReceiveFrame(handle, std::make_unique<SetAsynchronousBalancedModeCommand>(
                             Role::kUnassigned, kMuxControlDLCI));
    RunLoopUntilIdle();
    ExpectFrame(handle, FrameType::kUnnumberedAcknowledgement, kMuxControlDLCI);
    state.role = Role::kInitiator;

    DLCI dlci = ServerChannelToDLCI(server_channel, OppositeRole(state.role));

    // Send parameter negotiation
    ParameterNegotiationParams params;
    params.dlci = dlci;
    params.credit_based_flow_handshake =
        CreditBasedFlowHandshake::kSupportedRequest;
    params.priority = 61;
    params.maximum_frame_size =
        l2cap_channel->rx_mtu() < l2cap_channel->tx_mtu()
            ? l2cap_channel->rx_mtu()
            : l2cap_channel->tx_mtu();
    params.initial_credits = kMaxInitialCredits;
    ReceiveFrame(handle, std::make_unique<MuxCommandFrame>(
                             state.role, state.credit_based_flow,
                             std::make_unique<DLCParameterNegotiationCommand>(
                                 CommandResponse::kCommand, params)));
    RunLoopUntilIdle();

    // Expect parameter negotiation response
    EXPECT_TRUE(handle_to_incoming_frames_[handle].size());
    auto frame =
        Frame::Parse(state.credit_based_flow, state.role,
                     handle_to_incoming_frames_[handle].front()->view());
    handle_to_incoming_frames_[handle].pop();
    EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
              static_cast<FrameType>(frame->control()));
    EXPECT_EQ(kMuxControlDLCI, frame->dlci());
    auto mux_command =
        static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand();
    EXPECT_EQ(MuxCommandType::kDLCParameterNegotiation,
              mux_command->command_type());
    EXPECT_EQ(CommandResponse::kResponse, mux_command->command_response());
  }

  // Otherwise, a session must already exist with this remote peer. We can
  // furthermore assume that a channel must be open, and thus that the
  // multiplexer has also been started, and parameter negotiation is complete.

  DLCI dlci = ServerChannelToDLCI(server_channel, OppositeRole(state.role));

  // Send SABM.
  ReceiveFrame(handle, std::make_unique<SetAsynchronousBalancedModeCommand>(
                           state.role, dlci));
  RunLoopUntilIdle();

  // Expect UA response.
  ExpectFrame(handle, FrameType::kUnnumberedAcknowledgement, dlci);
}
// Expect that registration of an L2CAP channel with the Channel Manager results
// in the L2CAP channel's eventual activation.
TEST_F(RFCOMM_ChannelManagerTest, RegisterL2CAPChannel) {
  ChannelOptions l2cap_channel_options(kL2CAPChannelId1);
  auto l2cap_channel = CreateFakeChannel(l2cap_channel_options);
  EXPECT_TRUE(channel_manager_->RegisterL2CAPChannel(l2cap_channel));
  EXPECT_TRUE(l2cap_channel->activated());
}

// Test that command timeouts during multiplexer startup result in the session
// being closed down.
TEST_F(RFCOMM_ChannelManagerTest, MuxStartupAndParamNegotiation_Timeout) {
  AddFakePeerState(kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  channel_manager_->OpenRemoteChannel(kHandle1, kMinServerChannel,
                                      &DoNothingWithChannel, dispatcher());
  l2cap_->TriggerOutboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                 kL2CAPChannelId2);
  RunLoopUntilIdle();

  auto channel = GetFakeChannel(kHandle1);

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Do nothing
  RunLoopFor(zx::min(5));

  // Expect closedown after timeout
  EXPECT_FALSE(channel->activated());
}

// Test successful multiplexer startup (resulting role: responder).
TEST_F(RFCOMM_ChannelManagerTest, MuxStartupAndParamNegotiation_Responder) {
  AddFakePeerState(kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  l2cap_->TriggerInboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                kL2CAPChannelId2);
  RunLoopUntilIdle();

  // Receive a multiplexer startup frame on the session
  ReceiveFrame(kHandle1, std::make_unique<SetAsynchronousBalancedModeCommand>(
                             Role::kUnassigned, kMuxControlDLCI));
  RunLoopUntilIdle();

  ExpectFrame(kHandle1, FrameType::kUnnumberedAcknowledgement, kMuxControlDLCI);
}

// Test successful multiplexer startup (resulting role: initiator)
TEST_F(RFCOMM_ChannelManagerTest, MuxStartupAndParamNegotiation_Initiator) {
  auto& state = AddFakePeerState(
      kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  bool channel_received = false;
  fbl::RefPtr<Channel> channel;
  channel_manager_->OpenRemoteChannel(
      kHandle1, kMinServerChannel,
      [&channel, &channel_received](auto ch, auto server_channel) {
        channel_received = true;
        channel = ch;
      },
      dispatcher());
  l2cap_->TriggerOutboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                 kL2CAPChannelId2);
  RunLoopUntilIdle();

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Receive a UA on the session
  ReceiveFrame(kHandle1, std::make_unique<UnnumberedAcknowledgementResponse>(
                             Role::kUnassigned, kMuxControlDLCI));
  RunLoopUntilIdle();

  state.role = Role::kResponder;
  DLCI dlci = ServerChannelToDLCI(kMinServerChannel, state.role);

  {
    // Expect a PN command from the session
    auto queue_it = handle_to_incoming_frames_.find(kHandle1);
    EXPECT_FALSE(queue_it == handle_to_incoming_frames_.end());
    EXPECT_EQ(1ul, queue_it->second.size());
    auto frame = Frame::Parse(true, OppositeRole(state.role),
                              queue_it->second.front()->view());
    queue_it->second.pop();
    EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
              static_cast<FrameType>(frame->control()));
    auto mux_command =
        static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand();
    EXPECT_EQ(MuxCommandType::kDLCParameterNegotiation,
              mux_command->command_type());

    auto params =
        static_cast<DLCParameterNegotiationCommand*>(mux_command.get())
            ->params();
    EXPECT_EQ(dlci, params.dlci);
    params.credit_based_flow_handshake =
        CreditBasedFlowHandshake::kSupportedResponse;

    // Receive PN response
    ReceiveFrame(kHandle1, std::make_unique<MuxCommandFrame>(
                               state.role, true,
                               std::make_unique<DLCParameterNegotiationCommand>(
                                   CommandResponse::kResponse, params)));
    RunLoopUntilIdle();
  }

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode, dlci);
  ReceiveFrame(kHandle1, std::make_unique<UnnumberedAcknowledgementResponse>(
                             state.role, dlci));
  RunLoopUntilIdle();

  EXPECT_TRUE(channel_received);
  EXPECT_TRUE(channel);
}

// Test multiplexer startup conflict procedure (resulting role: initiator).
TEST_F(RFCOMM_ChannelManagerTest,
       MuxStartupAndParamNegotiation_Conflict_BecomeInitiator) {
  auto& state = AddFakePeerState(
      kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  bool channel_received = false;
  fbl::RefPtr<Channel> channel;
  channel_manager_->OpenRemoteChannel(
      kHandle1, kMinServerChannel,
      [&channel, &channel_received](auto ch, auto server_channel) {
        channel_received = true;
        channel = ch;
      },
      dispatcher());
  l2cap_->TriggerOutboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                 kL2CAPChannelId2);
  RunLoopUntilIdle();

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Receive a conflicting SABM on the session
  ReceiveFrame(kHandle1, std::make_unique<SetAsynchronousBalancedModeCommand>(
                             state.role, kMuxControlDLCI));
  RunLoopUntilIdle();

  ExpectFrame(kHandle1, FrameType::kDisconnectedMode, kMuxControlDLCI);

  // Wait and expect a SABM
  RunLoopFor(zx::sec(5));
  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Receive a UA on the session
  ReceiveFrame(kHandle1, std::make_unique<UnnumberedAcknowledgementResponse>(
                             state.role, kMuxControlDLCI));
  RunLoopUntilIdle();

  state.role = Role::kResponder;
  DLCI dlci = ServerChannelToDLCI(kMinServerChannel, state.role);

  {
    // Expect a PN command from the session
    auto queue_it = handle_to_incoming_frames_.find(kHandle1);
    EXPECT_FALSE(queue_it == handle_to_incoming_frames_.end());
    EXPECT_EQ(1ul, queue_it->second.size());
    auto frame = Frame::Parse(true, OppositeRole(state.role),
                              queue_it->second.front()->view());
    queue_it->second.pop();
    EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
              static_cast<FrameType>(frame->control()));
    auto mux_command =
        static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand();
    EXPECT_EQ(MuxCommandType::kDLCParameterNegotiation,
              mux_command->command_type());

    auto params =
        static_cast<DLCParameterNegotiationCommand*>(mux_command.get())
            ->params();
    EXPECT_EQ(dlci, params.dlci);
    params.credit_based_flow_handshake =
        CreditBasedFlowHandshake::kSupportedResponse;

    // Receive PN response
    ReceiveFrame(kHandle1, std::make_unique<MuxCommandFrame>(
                               state.role, true,
                               std::make_unique<DLCParameterNegotiationCommand>(
                                   CommandResponse::kResponse, params)));
    RunLoopUntilIdle();
  }

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode, dlci);
  ReceiveFrame(kHandle1, std::make_unique<UnnumberedAcknowledgementResponse>(
                             state.role, dlci));
  RunLoopUntilIdle();

  EXPECT_TRUE(channel_received);
  EXPECT_TRUE(channel);
}

// Test multiplexer startup conflict procedure (resulting role: responder).
TEST_F(RFCOMM_ChannelManagerTest,
       MuxStartupAndParamNegotiation_Conflict_BecomeResponder) {
  auto& state = AddFakePeerState(
      kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  bool channel_delivered = false;
  channel_manager_->OpenRemoteChannel(
      kHandle1, kMinServerChannel,
      [&channel_delivered](auto channel, auto server_channel) {
        channel_delivered = true;
      },
      dispatcher());
  l2cap_->TriggerOutboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                 kL2CAPChannelId2);
  RunLoopUntilIdle();

  // Expect initial mux-opening SABM
  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Receive a conflicting SABM on the session
  state.role = Role::kNegotiating;
  ReceiveFrame(kHandle1, std::make_unique<SetAsynchronousBalancedModeCommand>(
                             state.role, kMuxControlDLCI));
  RunLoopUntilIdle();

  // Expect a DM frame from the session
  ExpectFrame(kHandle1, FrameType::kDisconnectedMode, kMuxControlDLCI);

  // Immediately receive another SABM on the session
  ReceiveFrame(kHandle1, std::make_unique<SetAsynchronousBalancedModeCommand>(
                             state.role, kMuxControlDLCI));
  RunLoopUntilIdle();

  // Expect UA
  ExpectFrame(kHandle1, FrameType::kUnnumberedAcknowledgement, kMuxControlDLCI);
  state.role = Role::kInitiator;

  {
    // Expect a PN command from the session
    EXPECT_FALSE(handle_to_incoming_frames_.find(kHandle1) ==
                 handle_to_incoming_frames_.end());
    auto& queue = handle_to_incoming_frames_[kHandle1];
    EXPECT_EQ(1ul, queue.size());
    auto frame = Frame::Parse(state.credit_based_flow, OppositeRole(state.role),
                              queue.front()->view());
    queue.pop();
    EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
              static_cast<FrameType>(frame->control()));
    DLCI dlci = ServerChannelToDLCI(kMinServerChannel, state.role);
    auto mux_command =
        static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand();
    EXPECT_EQ(MuxCommandType::kDLCParameterNegotiation,
              mux_command->command_type());

    auto params =
        static_cast<DLCParameterNegotiationCommand*>(mux_command.get())
            ->params();
    EXPECT_EQ(dlci, params.dlci);
    params.credit_based_flow_handshake =
        CreditBasedFlowHandshake::kSupportedResponse;

    // Receive PN response
    ReceiveFrame(kHandle1, std::make_unique<MuxCommandFrame>(
                               state.role, true,
                               std::make_unique<DLCParameterNegotiationCommand>(
                                   CommandResponse::kResponse, params)));
    RunLoopUntilIdle();
  }

  // EXPECT_TRUE(channel_received);
  // EXPECT_FALSE(channel);
}

// Tests whether sessions handle invalid max frame sizes correctly.
TEST_F(RFCOMM_ChannelManagerTest,
       MuxStartupAndParamNegotiation_BadPN_InvalidMaxFrameSize) {
  auto& state = AddFakePeerState(
      kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  bool channel_delivered = false;
  channel_manager_->OpenRemoteChannel(
      kHandle1, kMinServerChannel,
      [&channel_delivered](auto channel, auto server_channel) {
        channel_delivered = true;
      },
      dispatcher());
  l2cap_->TriggerOutboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                 kL2CAPChannelId2);
  RunLoopUntilIdle();

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Receive a UA on the session
  ReceiveFrame(kHandle1, std::make_unique<UnnumberedAcknowledgementResponse>(
                             state.role, kMuxControlDLCI));
  RunLoopUntilIdle();

  state.role = Role::kResponder;
  DLCI dlci = ServerChannelToDLCI(kMinServerChannel, state.role);

  {
    // Expect a PN command from the session
    EXPECT_FALSE(handle_to_incoming_frames_.find(kHandle1) ==
                 handle_to_incoming_frames_.end());
    auto& queue = handle_to_incoming_frames_[kHandle1];
    EXPECT_EQ(1ul, queue.size());
    auto frame = Frame::Parse(state.credit_based_flow, OppositeRole(state.role),
                              queue.front()->view());
    queue.pop();
    EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
              static_cast<FrameType>(frame->control()));
    DLCI dlci = ServerChannelToDLCI(kMinServerChannel, state.role);
    auto mux_command =
        static_cast<MuxCommandFrame*>(frame.get())->TakeMuxCommand();
    EXPECT_EQ(MuxCommandType::kDLCParameterNegotiation,
              mux_command->command_type());

    // Create invalid parameters.
    auto params =
        static_cast<DLCParameterNegotiationCommand*>(mux_command.get())
            ->params();
    EXPECT_EQ(dlci, params.dlci);
    params.credit_based_flow_handshake =
        CreditBasedFlowHandshake::kSupportedResponse;
    // Request a larger max frame size than what was proposed.
    params.maximum_frame_size += 1;

    // Receive PN response
    ReceiveFrame(kHandle1, std::make_unique<MuxCommandFrame>(
                               OppositeRole(state.role), true,
                               std::make_unique<DLCParameterNegotiationCommand>(
                                   CommandResponse::kResponse, params)));
    RunLoopUntilIdle();
  }

  ExpectFrame(kHandle1, FrameType::kDisconnect, dlci);
}

// A DM response to a mux SABM shouldn't crash (but shouldn't do anything else).
TEST_F(RFCOMM_ChannelManagerTest,
       MuxStartupAndParamNegotiation_RejectMuxStartup) {
  AddFakePeerState(kHandle1, PeerState{true /*credits*/, Role::kUnassigned});

  bool channel_delivered = false;
  channel_manager_->OpenRemoteChannel(
      kHandle1, kMinServerChannel,
      [&channel_delivered](auto channel, auto server_channel) {
        channel_delivered = true;
      },
      dispatcher());
  l2cap_->TriggerOutboundChannel(kHandle1, l2cap::kRFCOMM, kL2CAPChannelId1,
                                 kL2CAPChannelId2);
  RunLoopUntilIdle();

  ExpectFrame(kHandle1, FrameType::kSetAsynchronousBalancedMode,
              kMuxControlDLCI);

  // Receive a DM on the session
  ReceiveFrame(kHandle1, std::make_unique<DisconnectedModeResponse>(
                             Role::kUnassigned, kMuxControlDLCI));
  RunLoopUntilIdle();
}

TEST_F(RFCOMM_ChannelManagerTest, OpenOutgoingChannel) {
  handle_to_peer_state_.emplace(kHandle1, PeerState{true, Role::kUnassigned});
  PeerState& state = handle_to_peer_state_[kHandle1];

  auto channel = OpenOutgoingChannel(kHandle1, kMinServerChannel);
  EXPECT_TRUE(channel);

  DLCI dlci = ServerChannelToDLCI(kMinServerChannel, state.role);

  common::ByteBufferPtr received_data;
  channel->Activate(
      [&received_data](auto data) { received_data = std::move(data); }, []() {},
      dispatcher());

  auto pattern = common::CreateStaticByteBuffer(1, 2, 3, 4);
  auto buffer = std::make_unique<common::DynamicByteBuffer>(pattern);
  channel->Send(std::move(buffer));
  RunLoopUntilIdle();

  auto frame =
      Frame::Parse(state.credit_based_flow, OppositeRole(state.role),
                   handle_to_incoming_frames_[kHandle1].front()->view());
  EXPECT_TRUE(frame);
  EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
            static_cast<FrameType>(frame->control()));
  EXPECT_EQ(dlci, frame->dlci());
  EXPECT_EQ(pattern,
            *static_cast<UserDataFrame*>(frame.get())->TakeInformation());

  buffer = std::make_unique<common::DynamicByteBuffer>(pattern);
  ReceiveFrame(kHandle1, std::make_unique<UserDataFrame>(
                             state.role, state.credit_based_flow, dlci,
                             std::move(buffer)));
  RunLoopUntilIdle();

  EXPECT_TRUE(received_data);
  EXPECT_EQ(pattern, *received_data);
}

TEST_F(RFCOMM_ChannelManagerTest, OpenIncomingChannel) {
  auto& state = AddFakePeerState(
      kHandle1, PeerState{true /* credit-based flow */, Role::kUnassigned});

  fbl::RefPtr<Channel> channel;
  auto server_channel = channel_manager_->AllocateLocalChannel(
      [&channel](auto received_channel, auto) { channel = received_channel; },
      dispatcher());

  OpenIncomingChannel(kHandle1, server_channel);
  RunLoopUntilIdle();
  EXPECT_TRUE(channel);

  DLCI dlci = ServerChannelToDLCI(server_channel, OppositeRole(state.role));

  common::ByteBufferPtr received_data;
  channel->Activate(
      [&received_data](auto data) { received_data = std::move(data); }, []() {},
      dispatcher());

  auto pattern = common::CreateStaticByteBuffer(1, 2, 3, 4);
  auto buffer = std::make_unique<common::DynamicByteBuffer>(pattern);
  channel->Send(std::move(buffer));
  RunLoopUntilIdle();

  auto frame =
      Frame::Parse(state.credit_based_flow, OppositeRole(state.role),
                   handle_to_incoming_frames_[kHandle1].front()->view());
  EXPECT_TRUE(frame);
  EXPECT_EQ(FrameType::kUnnumberedInfoHeaderCheck,
            static_cast<FrameType>(frame->control()));
  EXPECT_EQ(dlci, frame->dlci());
  EXPECT_EQ(pattern,
            *static_cast<UserDataFrame*>(frame.get())->TakeInformation());

  buffer = std::make_unique<common::DynamicByteBuffer>(pattern);
  ReceiveFrame(kHandle1, std::make_unique<UserDataFrame>(
                             state.role, state.credit_based_flow, dlci,
                             std::move(buffer)));
  RunLoopUntilIdle();

  EXPECT_TRUE(received_data);
  EXPECT_EQ(pattern, *received_data);
}

}  // namespace
}  // namespace rfcomm
}  // namespace btlib
