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/gtest_helpers.h"
18 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
19
20 namespace bt::l2cap::testing {
21
Transaction(const ByteBuffer & expected,const std::vector<const ByteBuffer * > & replies,ExpectationMetadata meta)22 MockChannelTest::Transaction::Transaction(
23 const ByteBuffer& expected,
24 const std::vector<const ByteBuffer*>& replies,
25 ExpectationMetadata meta)
26 : expected_({DynamicByteBuffer(expected), meta}) {
27 for (const ByteBuffer* buffer : replies) {
28 replies_.push(DynamicByteBuffer(*buffer));
29 }
30 }
31
Match(const ByteBuffer & packet)32 bool MockChannelTest::Transaction::Match(const ByteBuffer& packet) {
33 return ContainersEqual(expected_.data, packet);
34 }
35
TearDown()36 void MockChannelTest::TearDown() {
37 while (!transactions_.empty()) {
38 Transaction& transaction = transactions_.front();
39 ExpectationMetadata meta = transaction.expected().meta;
40 ADD_FAILURE_AT(meta.file, meta.line)
41 << "Didn't receive expected outbound packet (" << meta.expectation
42 << ") {" << ByteContainerToString(transaction.expected().data) << "}";
43 transactions_.pop();
44 }
45 }
46
QueueTransaction(const ByteBuffer & expected,const std::vector<const ByteBuffer * > & replies,ExpectationMetadata meta)47 void MockChannelTest::QueueTransaction(
48 const ByteBuffer& expected,
49 const std::vector<const ByteBuffer*>& replies,
50 ExpectationMetadata meta) {
51 transactions_.emplace(expected, replies, meta);
52 }
53
CreateFakeChannel(const ChannelOptions & options)54 FakeChannel::WeakPtr MockChannelTest::CreateFakeChannel(
55 const ChannelOptions& options) {
56 fake_chan_ = std::make_unique<FakeChannel>(
57 options.id,
58 options.remote_id,
59 options.conn_handle,
60 options.link_type,
61 ChannelInfo::MakeBasicMode(options.mtu, options.mtu));
62 fake_chan_->SetSendCallback(
63 fit::bind_member<&MockChannelTest::OnPacketSent>(this));
64 return fake_chan_->AsWeakPtr();
65 }
66
OnPacketSent(std::unique_ptr<ByteBuffer> packet)67 void MockChannelTest::OnPacketSent(std::unique_ptr<ByteBuffer> packet) {
68 if (packet_callback_) {
69 packet_callback_(*packet);
70 }
71
72 ASSERT_FALSE(transactions_.empty()) << "Received unexpected packet: { "
73 << ByteContainerToString(*packet) << "}";
74
75 Transaction expected = std::move(transactions_.front());
76 transactions_.pop();
77 if (!expected.Match(packet->view())) {
78 auto meta = expected.expected().meta;
79 GTEST_FAIL_AT(meta.file, meta.line)
80 << "Expected packet (" << meta.expectation << ")";
81 }
82
83 while (!expected.replies().empty()) {
84 auto reply = std::move(expected.replies().front());
85 expected.replies().pop();
86 // Post tasks to simulate real inbound packets, which are asynchronous.
87 (void)heap_dispatcher().Post(
88 [this, reply = std::move(reply)](pw::async::Context /*ctx*/,
89 pw::Status status) {
90 if (status.ok()) {
91 fake_chan_->Receive(reply);
92 }
93 });
94 }
95 }
96
97 } // namespace bt::l2cap::testing
98