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/scheduler_fifo.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include "l2cap/internal/channel_impl_mock.h"
23 #include "l2cap/internal/data_controller_mock.h"
24 #include "l2cap/internal/data_pipeline_manager_mock.h"
25 #include "os/handler.h"
26 #include "os/mock_queue.h"
27 #include "os/thread.h"
28 #include "packet/raw_builder.h"
29 
30 namespace bluetooth {
31 namespace l2cap {
32 namespace internal {
33 namespace {
34 
35 using ::testing::_;
36 using ::testing::Return;
37 
CreateSdu(std::vector<uint8_t> payload)38 std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) {
39   auto raw_builder = std::make_unique<packet::RawBuilder>();
40   raw_builder->AddOctets(payload);
41   return raw_builder;
42 }
43 
GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet)44 PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
45   auto bytes = std::make_shared<std::vector<uint8_t>>();
46   BitInserter i(*bytes);
47   bytes->reserve(packet->size());
48   packet->Serialize(i);
49   return packet::PacketView<packet::kLittleEndian>(bytes);
50 }
51 
52 class MyDataController : public testing::MockDataController {
53  public:
GetNextPacket()54   std::unique_ptr<BasePacketBuilder> GetNextPacket() override {
55     auto next = std::move(next_packets.front());
56     next_packets.pop();
57     return next;
58   }
59 
60   std::queue<std::unique_ptr<BasePacketBuilder>> next_packets;
61 };
62 
63 class L2capSchedulerFifoTest : public ::testing::Test {
64  protected:
SetUp()65   void SetUp() override {
66     thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
67     queue_handler_ = new os::Handler(thread_);
68     mock_data_pipeline_manager_ = new testing::MockDataPipelineManager(queue_handler_, &queue_end_);
69     fifo_ = new Fifo(mock_data_pipeline_manager_, &queue_end_, queue_handler_);
70   }
71 
TearDown()72   void TearDown() override {
73     delete fifo_;
74     delete mock_data_pipeline_manager_;
75     queue_handler_->Clear();
76     delete queue_handler_;
77     delete thread_;
78   }
79 
80   os::Thread* thread_ = nullptr;
81   os::Handler* queue_handler_ = nullptr;
82   os::MockIQueueDequeue<Scheduler::LowerDequeue> dequeue_;
83   os::MockIQueueEnqueue<Scheduler::LowerEnqueue> enqueue_;
84   common::BidiQueueEnd<Scheduler::LowerEnqueue, Scheduler::LowerDequeue> queue_end_{&enqueue_, &dequeue_};
85   testing::MockDataPipelineManager* mock_data_pipeline_manager_ = nullptr;
86   MyDataController data_controller_1_;
87   MyDataController data_controller_2_;
88   Fifo* fifo_ = nullptr;
89 };
90 
TEST_F(L2capSchedulerFifoTest,send_packet)91 TEST_F(L2capSchedulerFifoTest, send_packet) {
92   auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'}));
93   data_controller_1_.next_packets.push(std::move(frame));
94   EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(_)).WillOnce(Return(&data_controller_1_));
95   EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(1));
96   fifo_->OnPacketsReady(1, 1);
97   enqueue_.run_enqueue();
98   auto&& packet = enqueue_.enqueued.front();
99   auto packet_view = GetPacketView(std::move(packet));
100   auto basic_frame_view = BasicFrameView::Create(packet_view);
101   ASSERT_TRUE(basic_frame_view.IsValid());
102   ASSERT_EQ(basic_frame_view.GetChannelId(), 1);
103   auto payload = basic_frame_view.GetPayload();
104   ASSERT_EQ(std::string(payload.begin(), payload.end()), "abc");
105   enqueue_.enqueued.pop();
106 }
107 
TEST_F(L2capSchedulerFifoTest,prioritize_channel)108 TEST_F(L2capSchedulerFifoTest, prioritize_channel) {
109   auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'}));
110   data_controller_1_.next_packets.push(std::move(frame));
111   frame = BasicFrameBuilder::Create(2, CreateSdu({'d', 'e', 'f'}));
112   data_controller_2_.next_packets.push(std::move(frame));
113 
114   EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(1)).WillRepeatedly(Return(&data_controller_1_));
115   EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(2)).WillRepeatedly(Return(&data_controller_2_));
116   EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(1));
117   EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(2));
118   fifo_->SetChannelTxPriority(1, true);
119   fifo_->OnPacketsReady(2, 1);
120   fifo_->OnPacketsReady(1, 1);
121   enqueue_.run_enqueue(2);
122   auto packet1 = std::move(enqueue_.enqueued.front());
123   auto packet_view = GetPacketView(std::move(packet1));
124   auto basic_frame_view = BasicFrameView::Create(packet_view);
125   ASSERT_TRUE(basic_frame_view.IsValid());
126   ASSERT_EQ(basic_frame_view.GetChannelId(), 1);
127   auto payload = basic_frame_view.GetPayload();
128   ASSERT_EQ(std::string(payload.begin(), payload.end()), "abc");
129   enqueue_.enqueued.pop();
130 
131   auto packet2 = std::move(enqueue_.enqueued.front());
132   packet_view = GetPacketView(std::move(packet2));
133   basic_frame_view = BasicFrameView::Create(packet_view);
134   ASSERT_TRUE(basic_frame_view.IsValid());
135   ASSERT_EQ(basic_frame_view.GetChannelId(), 2);
136   payload = basic_frame_view.GetPayload();
137   ASSERT_EQ(std::string(payload.begin(), payload.end()), "def");
138   enqueue_.enqueued.pop();
139 }
140 
TEST_F(L2capSchedulerFifoTest,remove_channel)141 TEST_F(L2capSchedulerFifoTest, remove_channel) {
142   auto frame = BasicFrameBuilder::Create(1, CreateSdu({'a', 'b', 'c'}));
143   data_controller_1_.next_packets.push(std::move(frame));
144   frame = BasicFrameBuilder::Create(2, CreateSdu({'d', 'e', 'f'}));
145   data_controller_2_.next_packets.push(std::move(frame));
146 
147   EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(1)).WillRepeatedly(Return(&data_controller_1_));
148   EXPECT_CALL(*mock_data_pipeline_manager_, GetDataController(2)).WillRepeatedly(Return(&data_controller_2_));
149   EXPECT_CALL(*mock_data_pipeline_manager_, OnPacketSent(2));
150   fifo_->OnPacketsReady(1, 1);
151   fifo_->OnPacketsReady(2, 1);
152   fifo_->RemoveChannel(1);
153   enqueue_.run_enqueue(1);
154   auto packet1 = std::move(enqueue_.enqueued.front());
155   auto packet_view = GetPacketView(std::move(packet1));
156   auto basic_frame_view = BasicFrameView::Create(packet_view);
157   ASSERT_TRUE(basic_frame_view.IsValid());
158   ASSERT_EQ(basic_frame_view.GetChannelId(), 2);
159   auto payload = basic_frame_view.GetPayload();
160   ASSERT_EQ(std::string(payload.begin(), payload.end()), "def");
161   enqueue_.enqueued.pop();
162 }
163 
164 }  // namespace
165 }  // namespace internal
166 }  // namespace l2cap
167 }  // namespace bluetooth
168