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/le_signaling_channel.h"
16
17 #include <pw_bytes/endian.h>
18
19 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel_test.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
21
22 namespace bt::l2cap::internal {
23 namespace {
24
25 constexpr hci_spec::ConnectionHandle kTestHandle = 0x0001;
26 constexpr uint8_t kTestCmdId = 1;
27
28 template <pw::bluetooth::emboss::ConnectionRole Role =
29 pw::bluetooth::emboss::ConnectionRole::CENTRAL>
30 class LESignalingChannelTestBase : public testing::FakeChannelTest {
31 public:
32 LESignalingChannelTestBase() = default;
33 ~LESignalingChannelTestBase() override = default;
34
35 protected:
SetUp()36 void SetUp() override {
37 ChannelOptions options(kLESignalingChannelId);
38 options.conn_handle = kTestHandle;
39
40 fake_sig_chan_ = CreateFakeChannel(options);
41 sig_ = std::make_unique<LESignalingChannel>(
42 fake_sig_chan_->GetWeakPtr(), Role, dispatcher());
43 }
44
TearDown()45 void TearDown() override { sig_ = nullptr; }
46
sig() const47 LESignalingChannel* sig() const { return sig_.get(); }
48
49 private:
50 std::unique_ptr<testing::FakeChannel> fake_sig_chan_;
51 std::unique_ptr<LESignalingChannel> sig_;
52
53 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LESignalingChannelTestBase);
54 };
55
56 using LESignalingChannelTest = LESignalingChannelTestBase<>;
57
58 using LESignalingChannelPeripheralTest = LESignalingChannelTestBase<
59 pw::bluetooth::emboss::ConnectionRole::PERIPHERAL>;
60
TEST_F(LESignalingChannelTest,IgnoreEmptyFrame)61 TEST_F(LESignalingChannelTest, IgnoreEmptyFrame) {
62 bool send_cb_called = false;
63 auto send_cb = [&send_cb_called](auto) { send_cb_called = true; };
64
65 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
66 fake_chan()->Receive(BufferView());
67
68 RunUntilIdle();
69 EXPECT_FALSE(send_cb_called);
70 }
71
TEST_F(LESignalingChannelTest,RejectMalformedTooLarge)72 TEST_F(LESignalingChannelTest, RejectMalformedTooLarge) {
73 // Command Reject packet.
74 // clang-format off
75 StaticByteBuffer expected(
76 // Command header
77 0x01, kTestCmdId, 0x02, 0x00,
78
79 // Reason (Command not understood)
80 0x00, 0x00);
81
82 // Header-encoded length is less than the otherwise-valid Connection Parameter
83 // Update packet's payload size.
84 StaticByteBuffer cmd_with_oversize_payload(
85 0x12, kTestCmdId, 0x07, 0x00,
86
87 // Valid connection parameters
88 0x06, 0x00,
89 0x80, 0x0C,
90 0xF3, 0x01,
91 0x80, 0x0C);
92 // clang-format on
93
94 EXPECT_TRUE(ReceiveAndExpect(cmd_with_oversize_payload, expected));
95 }
96
TEST_F(LESignalingChannelTest,RejectMalformedTooSmall)97 TEST_F(LESignalingChannelTest, RejectMalformedTooSmall) {
98 // Command Reject packet.
99 // clang-format off
100 StaticByteBuffer expected(
101 // Command header
102 0x01, kTestCmdId, 0x02, 0x00,
103
104 // Reason (Command not understood)
105 0x00, 0x00);
106
107 // Header-encoded length is more than the otherwise-valid Connection Parameter
108 // Update packet's payload size.
109 StaticByteBuffer cmd_with_undersize_payload(
110 0x12, kTestCmdId, 0x09, 0x00,
111
112 // Valid connection parameters
113 0x06, 0x00,
114 0x80, 0x0C,
115 0xF3, 0x01,
116 0x80, 0x0C);
117 // clang-format on
118
119 EXPECT_TRUE(ReceiveAndExpect(cmd_with_undersize_payload, expected));
120 }
121
TEST_F(LESignalingChannelTest,DefaultMTU)122 TEST_F(LESignalingChannelTest, DefaultMTU) {
123 constexpr size_t kCommandSize = kMinLEMTU + 1;
124
125 // The channel should start out with the minimum MTU as the default (23
126 // octets).
127 StaticByteBuffer<kCommandSize> cmd;
128
129 // Make sure that the packet is well formed (the command code does not
130 // matter).
131 MutableSignalingPacket packet(&cmd, kCommandSize - sizeof(CommandHeader));
132 packet.mutable_header()->id = kTestCmdId;
133 packet.mutable_header()->length = pw::bytes::ConvertOrderTo(
134 cpp20::endian::little, static_cast<uint16_t>(packet.payload_size()));
135
136 // Command Reject packet.
137 // clang-format off
138 StaticByteBuffer expected(
139 // Command header
140 0x01, kTestCmdId, 0x04, 0x00,
141
142 // Reason (Signaling MTU exceeded)
143 0x01, 0x00,
144
145 // The supported MTU (23)
146 0x17, 0x00);
147 // clang-format on
148
149 EXPECT_TRUE(ReceiveAndExpect(cmd, expected));
150 }
151
152 } // namespace
153 } // namespace bt::l2cap::internal
154