1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h"
18
19 #include <gtest/gtest.h>
20
21 #include "l2cap/internal/ilink_mock.h"
22 #include "l2cap/internal/scheduler_mock.h"
23 #include "l2cap/l2cap_packets.h"
24 #include "packet/raw_builder.h"
25
26 namespace bluetooth {
27 namespace l2cap {
28 namespace internal {
29 namespace {
30
CreateSdu(std::vector<uint8_t> payload)31 std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) {
32 auto raw_builder = std::make_unique<packet::RawBuilder>();
33 raw_builder->AddOctets(payload);
34 return raw_builder;
35 }
36
GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet)37 PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
38 auto bytes = std::make_shared<std::vector<uint8_t>>();
39 BitInserter i(*bytes);
40 bytes->reserve(packet->size());
41 packet->Serialize(i);
42 return packet::PacketView<packet::kLittleEndian>(bytes);
43 }
44
sync_handler(os::Handler * handler)45 void sync_handler(os::Handler* handler) {
46 std::promise<void> promise;
47 auto future = promise.get_future();
48 handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
49 auto status = future.wait_for(std::chrono::milliseconds(300));
50 EXPECT_EQ(status, std::future_status::ready);
51 }
52
53 class ErtmDataControllerTest : public ::testing::Test {
54 protected:
SetUp()55 void SetUp() override {
56 thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
57 user_handler_ = new os::Handler(thread_);
58 queue_handler_ = new os::Handler(thread_);
59 }
60
TearDown()61 void TearDown() override {
62 queue_handler_->Clear();
63 user_handler_->Clear();
64 delete queue_handler_;
65 delete user_handler_;
66 delete thread_;
67 }
68
69 os::Thread* thread_ = nullptr;
70 os::Handler* user_handler_ = nullptr;
71 os::Handler* queue_handler_ = nullptr;
72 };
73
TEST_F(ErtmDataControllerTest,transmit_no_fcs)74 TEST_F(ErtmDataControllerTest, transmit_no_fcs) {
75 common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
76 testing::MockScheduler scheduler;
77 testing::MockILink link;
78 ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
79 EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
80 controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
81 auto next_packet = controller.GetNextPacket();
82 EXPECT_NE(next_packet, nullptr);
83 auto view = GetPacketView(std::move(next_packet));
84 auto pdu_view = BasicFrameView::Create(view);
85 EXPECT_TRUE(pdu_view.IsValid());
86 auto standard_view = StandardFrameView::Create(pdu_view);
87 EXPECT_TRUE(standard_view.IsValid());
88 auto i_frame_view = EnhancedInformationFrameView::Create(standard_view);
89 EXPECT_TRUE(i_frame_view.IsValid());
90 auto payload = i_frame_view.GetPayload();
91 std::string data = std::string(payload.begin(), payload.end());
92 EXPECT_EQ(data, "abcd");
93 EXPECT_EQ(i_frame_view.GetTxSeq(), 0);
94 EXPECT_EQ(i_frame_view.GetReqSeq(), 0);
95 }
96
TEST_F(ErtmDataControllerTest,receive_no_fcs)97 TEST_F(ErtmDataControllerTest, receive_no_fcs) {
98 common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
99 testing::MockScheduler scheduler;
100 testing::MockILink link;
101 ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
102 auto segment = CreateSdu({'a', 'b', 'c', 'd'});
103 auto builder = EnhancedInformationFrameBuilder::Create(1, 0, Final::NOT_SET, 0,
104 SegmentationAndReassembly::UNSEGMENTED, std::move(segment));
105 auto base_view = GetPacketView(std::move(builder));
106 controller.OnPdu(base_view);
107 sync_handler(queue_handler_);
108 auto payload = channel_queue.GetUpEnd()->TryDequeue();
109 EXPECT_NE(payload, nullptr);
110 std::string data = std::string(payload->begin(), payload->end());
111 EXPECT_EQ(data, "abcd");
112 }
113
TEST_F(ErtmDataControllerTest,reassemble_valid_sdu)114 TEST_F(ErtmDataControllerTest, reassemble_valid_sdu) {
115 common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
116 testing::MockScheduler scheduler;
117 testing::MockILink link;
118 ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
119 auto segment1 = CreateSdu({'a'});
120 auto segment2 = CreateSdu({'b', 'c'});
121 auto segment3 = CreateSdu({'d', 'e', 'f'});
122 auto builder1 = EnhancedInformationStartFrameBuilder::Create(1, 0, Final::NOT_SET, 0, 6, std::move(segment1));
123 auto base_view = GetPacketView(std::move(builder1));
124 controller.OnPdu(base_view);
125 auto builder2 = EnhancedInformationFrameBuilder::Create(1, 1, Final::NOT_SET, 0,
126 SegmentationAndReassembly::CONTINUATION, std::move(segment2));
127 base_view = GetPacketView(std::move(builder2));
128 controller.OnPdu(base_view);
129 auto builder3 = EnhancedInformationFrameBuilder::Create(1, 2, Final::NOT_SET, 0, SegmentationAndReassembly::END,
130 std::move(segment3));
131 base_view = GetPacketView(std::move(builder3));
132 controller.OnPdu(base_view);
133 sync_handler(queue_handler_);
134 auto payload = channel_queue.GetUpEnd()->TryDequeue();
135 EXPECT_NE(payload, nullptr);
136 std::string data = std::string(payload->begin(), payload->end());
137 EXPECT_EQ(data, "abcdef");
138 }
139
TEST_F(ErtmDataControllerTest,reassemble_invalid_sdu_size_in_start_frame_will_disconnect)140 TEST_F(ErtmDataControllerTest, reassemble_invalid_sdu_size_in_start_frame_will_disconnect) {
141 common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
142 testing::MockScheduler scheduler;
143 testing::MockILink link;
144 ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
145 auto segment1 = CreateSdu({'a'});
146 auto segment2 = CreateSdu({'b', 'c'});
147 auto segment3 = CreateSdu({'d', 'e', 'f'});
148 auto builder1 = EnhancedInformationStartFrameBuilder::Create(1, 0, Final::NOT_SET, 0, 10, std::move(segment1));
149 auto base_view = GetPacketView(std::move(builder1));
150 controller.OnPdu(base_view);
151 auto builder2 = EnhancedInformationFrameBuilder::Create(1, 1, Final::NOT_SET, 0,
152 SegmentationAndReassembly::CONTINUATION, std::move(segment2));
153 base_view = GetPacketView(std::move(builder2));
154 controller.OnPdu(base_view);
155 auto builder3 = EnhancedInformationFrameBuilder::Create(1, 2, Final::NOT_SET, 0, SegmentationAndReassembly::END,
156 std::move(segment3));
157 base_view = GetPacketView(std::move(builder3));
158 EXPECT_CALL(link, SendDisconnectionRequest(1, 1));
159 controller.OnPdu(base_view);
160 sync_handler(queue_handler_);
161 auto payload = channel_queue.GetUpEnd()->TryDequeue();
162 EXPECT_EQ(payload, nullptr);
163 }
164
TEST_F(ErtmDataControllerTest,transmit_with_fcs)165 TEST_F(ErtmDataControllerTest, transmit_with_fcs) {
166 common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
167 testing::MockScheduler scheduler;
168 testing::MockILink link;
169 ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
170 controller.EnableFcs(true);
171 EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
172 controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
173 auto next_packet = controller.GetNextPacket();
174 EXPECT_NE(next_packet, nullptr);
175 auto view = GetPacketView(std::move(next_packet));
176 auto pdu_view = BasicFrameWithFcsView::Create(view);
177 EXPECT_TRUE(pdu_view.IsValid());
178 auto standard_view = StandardFrameWithFcsView::Create(pdu_view);
179 EXPECT_TRUE(standard_view.IsValid());
180 auto i_frame_view = EnhancedInformationFrameWithFcsView::Create(standard_view);
181 EXPECT_TRUE(i_frame_view.IsValid());
182 auto payload = i_frame_view.GetPayload();
183 std::string data = std::string(payload.begin(), payload.end());
184 EXPECT_EQ(data, "abcd");
185 EXPECT_EQ(i_frame_view.GetTxSeq(), 0);
186 EXPECT_EQ(i_frame_view.GetReqSeq(), 0);
187 }
188
TEST_F(ErtmDataControllerTest,receive_packet_with_fcs)189 TEST_F(ErtmDataControllerTest, receive_packet_with_fcs) {
190 common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
191 testing::MockScheduler scheduler;
192 testing::MockILink link;
193 ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
194 controller.EnableFcs(true);
195 auto segment = CreateSdu({'a', 'b', 'c', 'd'});
196 auto builder = EnhancedInformationFrameWithFcsBuilder::Create(
197 1, 0, Final::NOT_SET, 0, SegmentationAndReassembly::UNSEGMENTED, std::move(segment));
198 auto base_view = GetPacketView(std::move(builder));
199 controller.OnPdu(base_view);
200 sync_handler(queue_handler_);
201 auto payload = channel_queue.GetUpEnd()->TryDequeue();
202 EXPECT_NE(payload, nullptr);
203 std::string data = std::string(payload->begin(), payload->end());
204 EXPECT_EQ(data, "abcd");
205 }
206
207 } // namespace
208 } // namespace internal
209 } // namespace l2cap
210 } // namespace bluetooth
211