blob: 2ad952adc3db3ef02577c91cda5795d84e845c1f [file] [log] [blame]
// 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.
#ifndef GARNET_DRIVERS_BLUETOOTH_LIB_L2CAP_FAKE_SIGNALING_CHANNEL_H_
#define GARNET_DRIVERS_BLUETOOTH_LIB_L2CAP_FAKE_SIGNALING_CHANNEL_H_
#include <lib/async/cpp/task.h>
#include <unordered_map>
#include <vector>
#include "garnet/drivers/bluetooth/lib/l2cap/signaling_channel.h"
namespace btlib {
namespace l2cap {
namespace internal {
namespace testing {
// Can be injected into internal L2CAP tests to drive fake interactions over the
// signaling channels with remote peers (in both directions). Expectations for
// inbound and outbound expected transactions are not synchronized.
class FakeSignalingChannel : public SignalingChannelInterface {
public:
// |dispatcher| is the test message loop's dispatcher
explicit FakeSignalingChannel(async_dispatcher_t* dispatcher);
~FakeSignalingChannel() override = default;
// SignalingChannelInterface overrides
bool SendRequest(CommandCode req_code, const common::ByteBuffer& payload,
ResponseHandler cb) override;
void ServeRequest(CommandCode req_code, RequestDelegate cb) override;
// Add an expected outbound request, which FakeSignalingChannel will respond
// to with a series of responses. The request's contents will be expected to
// match |req_code| and |req_payload|. The corresponding request handler will
// be expected to handle as many responses as are provided here for testing.
// |responses| should be a comma-delimited list of
// std::pair<Status rsp_status, common::BufferView rsp_payload>.
template <typename... Responses>
void AddOutbound(CommandCode req_code, common::BufferView req_payload,
Responses... responses) {
transactions_.push_back(Transaction{req_code, req_payload, {responses...}});
}
// Simulate reception of an inbound request with |req_code| and |req_payload|,
// then expect a corresponding outbound response with payload |rsp_payload|.
void ReceiveExpect(CommandCode req_code,
const common::ByteBuffer& req_payload,
const common::ByteBuffer& rsp_payload);
// Simulate reception of an inbound request with |req_code| and |req_payload|,
// then expect a matching rejection with the Not Understood reason.
void ReceiveExpectRejectNotUnderstood(CommandCode req_code,
const common::ByteBuffer& req_payload);
// Simulate reception of an inbound request with |req_code| and |req_payload|,
// then expect a matching rejection with the Invalid Channel ID reason and the
// rejected IDs |local_cid| and |remote_cid|.
void ReceiveExpectRejectInvalidChannelId(
CommandCode req_code, const common::ByteBuffer& req_payload,
ChannelId local_cid, ChannelId remote_cid);
private:
// Expected outbound request and response(s) that this fake send(s) back
struct Transaction {
CommandCode request_code;
common::BufferView req_payload;
std::vector<std::pair<Status, common::BufferView>> responses;
};
// Test a previously-registered request handler by simulating an inbound
// request of |req_code| and |req_payload|. The test will assert-fail if no
// handler had been registered with |ServeRequest|. |fake_responder| will be
// generated internally based on the kind of reply that the handler is
// expected to send and is passed to the handler-under-test. The test will
// fail if no reply at all is sent.
void ReceiveExpectInternal(CommandCode req_code,
const common::ByteBuffer& req_payload,
Responder* fake_responder);
// Test message loop dispatcher
async_dispatcher_t* const dispatcher_;
// Expected outbound transactions
std::vector<Transaction> transactions_;
// Index of current outbound transaction expected through SendRequest
size_t expected_transaction_index_ = 0UL;
// Registered inbound request delegates
std::unordered_map<CommandCode, RequestDelegate> request_handlers_;
};
} // namespace testing
} // namespace internal
} // namespace l2cap
} // namespace btlib
#endif // GARNET_DRIVERS_BLUETOOTH_LIB_L2CAP_FAKE_SIGNALING_CHANNEL_H_