1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/l2cap/mock_channel_test.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
18
19 namespace bt::l2cap::testing {
20
Transaction(const ByteBuffer & expected,const std::vector<const ByteBuffer * > & replies,ExpectationMetadata meta)21 MockChannelTest::Transaction::Transaction(
22 const ByteBuffer& expected,
23 const std::vector<const ByteBuffer*>& replies,
24 ExpectationMetadata meta)
25 : expected_({DynamicByteBuffer(expected), meta}) {
26 for (const ByteBuffer* buffer : replies) {
27 replies_.push(DynamicByteBuffer(*buffer));
28 }
29 }
30
Match(const ByteBuffer & packet)31 bool MockChannelTest::Transaction::Match(const ByteBuffer& packet) {
32 return ContainersEqual(expected_.data, packet);
33 }
34
TearDown()35 void MockChannelTest::TearDown() {
36 while (!transactions_.empty()) {
37 Transaction& transaction = transactions_.front();
38 ExpectationMetadata meta = transaction.expected().meta;
39 ADD_FAILURE_AT(meta.file, meta.line)
40 << "Didn't receive expected outbound packet (" << meta.expectation
41 << ") {" << ByteContainerToString(transaction.expected().data) << "}";
42 transactions_.pop();
43 }
44 }
45
QueueTransaction(const ByteBuffer & expected,const std::vector<const ByteBuffer * > & replies,ExpectationMetadata meta)46 void MockChannelTest::QueueTransaction(
47 const ByteBuffer& expected,
48 const std::vector<const ByteBuffer*>& replies,
49 ExpectationMetadata meta) {
50 transactions_.emplace(expected, replies, meta);
51 }
52
CreateFakeChannel(const ChannelOptions & options)53 FakeChannel::WeakPtr MockChannelTest::CreateFakeChannel(
54 const ChannelOptions& options) {
55 fake_chan_ = std::make_unique<FakeChannel>(
56 options.id,
57 options.remote_id,
58 options.conn_handle,
59 options.link_type,
60 ChannelInfo::MakeBasicMode(options.mtu, options.mtu));
61 fake_chan_->SetSendCallback(
62 fit::bind_member<&MockChannelTest::OnPacketSent>(this));
63 return fake_chan_->AsWeakPtr();
64 }
65
OnPacketSent(std::unique_ptr<ByteBuffer> packet)66 void MockChannelTest::OnPacketSent(std::unique_ptr<ByteBuffer> packet) {
67 if (packet_callback_) {
68 packet_callback_(*packet);
69 }
70
71 ASSERT_FALSE(transactions_.empty()) << "Received unexpected packet: { "
72 << ByteContainerToString(*packet) << "}";
73
74 Transaction expected = std::move(transactions_.front());
75 transactions_.pop();
76 if (!expected.Match(packet->view())) {
77 auto meta = expected.expected().meta;
78 GTEST_FAIL_AT(meta.file, meta.line)
79 << "Expected packet (" << meta.expectation << ")";
80 }
81
82 while (!expected.replies().empty()) {
83 auto reply = std::move(expected.replies().front());
84 expected.replies().pop();
85 // Post tasks to simulate real inbound packets, which are asynchronous.
86 (void)heap_dispatcher().Post(
87 [this, reply = std::move(reply)](pw::async::Context /*ctx*/,
88 pw::Status status) {
89 if (status.ok()) {
90 fake_chan_->Receive(reply);
91 }
92 });
93 }
94 }
95
96 } // namespace bt::l2cap::testing
97