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