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/le_credit_based_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   return std::make_unique<packet::RawBuilder>(std::move(payload));
33 }
34 
GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet)35 PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
36   auto bytes = std::make_shared<std::vector<uint8_t>>();
37   BitInserter i(*bytes);
38   bytes->reserve(packet->size());
39   packet->Serialize(i);
40   return packet::PacketView<packet::kLittleEndian>(bytes);
41 }
42 
sync_handler(os::Handler * handler)43 void sync_handler(os::Handler* handler) {
44   std::promise<void> promise;
45   auto future = promise.get_future();
46   handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
47   auto status = future.wait_for(std::chrono::milliseconds(300));
48   EXPECT_EQ(status, std::future_status::ready);
49 }
50 
51 class LeCreditBasedDataControllerTest : public ::testing::Test {
52  protected:
SetUp()53   void SetUp() override {
54     thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
55     user_handler_ = new os::Handler(thread_);
56     queue_handler_ = new os::Handler(thread_);
57   }
58 
TearDown()59   void TearDown() override {
60     queue_handler_->Clear();
61     user_handler_->Clear();
62     delete queue_handler_;
63     delete user_handler_;
64     delete thread_;
65   }
66 
67   os::Thread* thread_ = nullptr;
68   os::Handler* user_handler_ = nullptr;
69   os::Handler* queue_handler_ = nullptr;
70 };
71 
TEST_F(LeCreditBasedDataControllerTest,transmit_unsegmented)72 TEST_F(LeCreditBasedDataControllerTest, transmit_unsegmented) {
73   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
74   testing::MockScheduler scheduler;
75   testing::MockILink link;
76   LeCreditBasedDataController controller{&link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
77   controller.OnCredit(10);
78   EXPECT_CALL(scheduler, OnPacketsReady(0x41, 1));
79   controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
80   auto next_packet = controller.GetNextPacket();
81   EXPECT_NE(next_packet, nullptr);
82   auto view = GetPacketView(std::move(next_packet));
83   auto pdu_view = BasicFrameView::Create(view);
84   EXPECT_TRUE(pdu_view.IsValid());
85   auto first_le_info_view = FirstLeInformationFrameView::Create(pdu_view);
86   EXPECT_TRUE(first_le_info_view.IsValid());
87   auto payload = first_le_info_view.GetPayload();
88   std::string data = std::string(payload.begin(), payload.end());
89   EXPECT_EQ(data, "abcd");
90 }
91 
TEST_F(LeCreditBasedDataControllerTest,transmit_segmented)92 TEST_F(LeCreditBasedDataControllerTest, transmit_segmented) {
93   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
94   testing::MockScheduler scheduler;
95   testing::MockILink link;
96   LeCreditBasedDataController controller{&link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
97   controller.OnCredit(10);
98   controller.SetMps(4);
99   EXPECT_CALL(scheduler, OnPacketsReady(0x41, 2));
100   // Should be divided into 'ab', and 'cd'
101   controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
102   auto next_packet = controller.GetNextPacket();
103   EXPECT_NE(next_packet, nullptr);
104   auto view = GetPacketView(std::move(next_packet));
105   auto pdu_view = BasicFrameView::Create(view);
106   EXPECT_TRUE(pdu_view.IsValid());
107   auto first_le_info_view = FirstLeInformationFrameView::Create(pdu_view);
108   EXPECT_TRUE(first_le_info_view.IsValid());
109   auto payload = first_le_info_view.GetPayload();
110   std::string data = std::string(payload.begin(), payload.end());
111   EXPECT_EQ(data, "ab");
112   EXPECT_EQ(first_le_info_view.GetL2capSduLength(), 4);
113 
114   next_packet = controller.GetNextPacket();
115   EXPECT_NE(next_packet, nullptr);
116   view = GetPacketView(std::move(next_packet));
117   pdu_view = BasicFrameView::Create(view);
118   EXPECT_TRUE(pdu_view.IsValid());
119   payload = pdu_view.GetPayload();
120   data = std::string(payload.begin(), payload.end());
121   EXPECT_EQ(data, "cd");
122 }
123 
TEST_F(LeCreditBasedDataControllerTest,receive_unsegmented)124 TEST_F(LeCreditBasedDataControllerTest, receive_unsegmented) {
125   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
126   testing::MockScheduler scheduler;
127   testing::MockILink link;
128   LeCreditBasedDataController controller{&link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
129   controller.OnCredit(10);
130   auto segment = CreateSdu({'a', 'b', 'c', 'd'});
131   auto builder = FirstLeInformationFrameBuilder::Create(0x41, 4, std::move(segment));
132   auto base_view = GetPacketView(std::move(builder));
133   controller.OnPdu(base_view);
134   sync_handler(queue_handler_);
135   auto payload = channel_queue.GetUpEnd()->TryDequeue();
136   EXPECT_NE(payload, nullptr);
137   std::string data = std::string(payload->begin(), payload->end());
138   EXPECT_EQ(data, "abcd");
139 }
140 
TEST_F(LeCreditBasedDataControllerTest,receive_segmented)141 TEST_F(LeCreditBasedDataControllerTest, receive_segmented) {
142   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
143   testing::MockScheduler scheduler;
144   testing::MockILink link;
145   LeCreditBasedDataController controller{&link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
146   controller.OnCredit(10);
147   auto segment1 = CreateSdu({'a', 'b', 'c', 'd'});
148   auto builder1 = FirstLeInformationFrameBuilder::Create(0x41, 7, std::move(segment1));
149   auto base_view = GetPacketView(std::move(builder1));
150   controller.OnPdu(base_view);
151   auto segment2 = CreateSdu({'e', 'f', 'g'});
152   auto builder2 = BasicFrameBuilder::Create(0x41, std::move(segment2));
153   base_view = GetPacketView(std::move(builder2));
154   EXPECT_CALL(link, SendLeCredit(0x41, 1));
155   controller.OnPdu(base_view);
156   sync_handler(queue_handler_);
157   auto payload = channel_queue.GetUpEnd()->TryDequeue();
158   EXPECT_NE(payload, nullptr);
159   std::string data = std::string(payload->begin(), payload->end());
160   EXPECT_EQ(data, "abcdefg");
161 }
162 
TEST_F(LeCreditBasedDataControllerTest,receive_segmented_with_wrong_sdu_length)163 TEST_F(LeCreditBasedDataControllerTest, receive_segmented_with_wrong_sdu_length) {
164   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
165   testing::MockScheduler scheduler;
166   testing::MockILink link;
167   LeCreditBasedDataController controller{&link, 0x41, 0x41, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
168   controller.OnCredit(10);
169   auto segment1 = CreateSdu({'a', 'b', 'c', 'd'});
170   auto builder1 = FirstLeInformationFrameBuilder::Create(0x41, 5, std::move(segment1));
171   auto base_view = GetPacketView(std::move(builder1));
172   controller.OnPdu(base_view);
173   auto segment2 = CreateSdu({'e', 'f', 'g'});
174   auto builder2 = BasicFrameBuilder::Create(0x41, std::move(segment2));
175   base_view = GetPacketView(std::move(builder2));
176   controller.OnPdu(base_view);
177   sync_handler(queue_handler_);
178   auto payload = channel_queue.GetUpEnd()->TryDequeue();
179   EXPECT_EQ(payload, nullptr);
180 }
181 
182 }  // namespace
183 }  // namespace internal
184 }  // namespace l2cap
185 }  // namespace bluetooth
186