1 /******************************************************************************
2  *
3  *  Copyright 2017 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #include "btif/include/btif_profile_queue.h"
19 
20 #include <base/functional/bind.h>
21 #include <base/functional/callback.h>
22 #include <base/location.h>
23 #include <gtest/gtest.h>
24 
25 #include "btif/include/stack_manager_t.h"
26 #include "types/bluetooth/uuid.h"
27 #include "types/raw_address.h"
28 
29 typedef void(tBTIF_CBACK)(uint16_t event, char* p_param);
30 typedef void(tBTIF_COPY_CBACK)(uint16_t event, char* p_dest, const char* p_src);
31 
32 // NOTE: Local re-implementation of functions to avoid thread context switching
33 static bool sStackRunning;
get_stack_is_running(void)34 bool get_stack_is_running(void) { return sStackRunning; }
35 static stack_manager_t sStackManager = {nullptr, nullptr, nullptr, nullptr,
36                                         get_stack_is_running};
stack_manager_get_interface()37 const stack_manager_t* stack_manager_get_interface() { return &sStackManager; }
do_in_jni_thread(base::OnceClosure task)38 bt_status_t do_in_jni_thread(base::OnceClosure task) {
39   std::move(task).Run();
40   return BT_STATUS_SUCCESS;
41 }
is_on_jni_thread()42 bool is_on_jni_thread() { return true; }
43 
44 enum ResultType {
45   NOT_SET = 0,
46   UNKNOWN,
47   UUID1_ADDR1,
48   UUID1_ADDR2,
49   UUID2_ADDR1,
50   UUID2_ADDR2
51 };
52 
53 static ResultType sResult;
54 
55 class BtifProfileQueueTest : public ::testing::Test {
56  public:
57   static const uint16_t kTestUuid1 = 0x9527;
58   static const uint16_t kTestUuid2 = 0x819F;
59   static const RawAddress kTestAddr1;
60   static const RawAddress kTestAddr2;
61 
62  protected:
SetUp()63   void SetUp() override {
64     sStackRunning = true;
65     sResult = NOT_SET;
66   };
TearDown()67   void TearDown() override { btif_queue_release(); };
68 };
69 
70 const RawAddress BtifProfileQueueTest::kTestAddr1{
71     {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
72 const RawAddress BtifProfileQueueTest::kTestAddr2{
73     {0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56}};
74 
test_connect_cb(RawAddress * bda,uint16_t uuid)75 static bt_status_t test_connect_cb(RawAddress* bda, uint16_t uuid) {
76   sResult = UNKNOWN;
77   if (*bda == BtifProfileQueueTest::kTestAddr1) {
78     if (uuid == BtifProfileQueueTest::kTestUuid1) {
79       sResult = UUID1_ADDR1;
80     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
81       sResult = UUID2_ADDR1;
82     }
83   } else if (*bda == BtifProfileQueueTest::kTestAddr2) {
84     if (uuid == BtifProfileQueueTest::kTestUuid1) {
85       sResult = UUID1_ADDR2;
86     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
87       sResult = UUID2_ADDR2;
88     }
89   }
90   return BT_STATUS_SUCCESS;
91 }
92 
TEST_F(BtifProfileQueueTest,test_connect)93 TEST_F(BtifProfileQueueTest, test_connect) {
94   sResult = NOT_SET;
95   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
96   EXPECT_EQ(sResult, UUID1_ADDR1);
97 }
98 
test_connect_cb_fail(RawAddress * bda,uint16_t uuid)99 static bt_status_t test_connect_cb_fail(RawAddress* bda, uint16_t uuid) {
100   sResult = UNKNOWN;
101   if (*bda == BtifProfileQueueTest::kTestAddr1) {
102     if (uuid == BtifProfileQueueTest::kTestUuid1) {
103       sResult = UUID1_ADDR1;
104     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
105       sResult = UUID2_ADDR1;
106     }
107   } else if (*bda == BtifProfileQueueTest::kTestAddr2) {
108     if (uuid == BtifProfileQueueTest::kTestUuid1) {
109       sResult = UUID1_ADDR2;
110     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
111       sResult = UUID2_ADDR2;
112     }
113   }
114   return BT_STATUS_BUSY;
115 }
116 
TEST_F(BtifProfileQueueTest,test_connect_fail_still_can_advance_the_queue)117 TEST_F(BtifProfileQueueTest, test_connect_fail_still_can_advance_the_queue) {
118   sResult = NOT_SET;
119   // First connect-message for UUID1-ADDR1 is executed, but does not be removed
120   // from connect-queue yet.
121   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
122   EXPECT_EQ(sResult, UUID1_ADDR1);
123   sResult = NOT_SET;
124   // Second connect-message for UUID2-ADDR1 be pushed into connect-queue, but is
125   // not executed
126   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb_fail);
127   EXPECT_EQ(sResult, NOT_SET);
128   // Third connect-message for UUID1-ADDR2 be pushed into connect-queue, but is
129   // not executed
130   btif_queue_connect(kTestUuid1, &kTestAddr2, test_connect_cb_fail);
131   EXPECT_EQ(sResult, NOT_SET);
132   // Fourth connect-message for UUID2-ADDR2 be pushed into connect-queue, but is
133   // not executed
134   btif_queue_connect(kTestUuid2, &kTestAddr2, test_connect_cb_fail);
135   EXPECT_EQ(sResult, NOT_SET);
136   // removed First connect-message from connect-queue, check it can advance to
137   // subsequent connect-message.
138   btif_queue_advance();
139   EXPECT_EQ(sResult, UUID2_ADDR2);
140 }
141 
TEST_F(BtifProfileQueueTest,test_connect_same_uuid_do_not_repeat)142 TEST_F(BtifProfileQueueTest, test_connect_same_uuid_do_not_repeat) {
143   sResult = NOT_SET;
144   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
145   EXPECT_EQ(sResult, UUID1_ADDR1);
146   // Second connection request on the same UUID do not repeat
147   sResult = NOT_SET;
148   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
149   EXPECT_EQ(sResult, NOT_SET);
150   // Not even after we advance the queue
151   sResult = NOT_SET;
152   btif_queue_advance();
153   btif_queue_connect_next();
154   EXPECT_EQ(sResult, NOT_SET);
155 }
156 
TEST_F(BtifProfileQueueTest,test_multiple_connects)157 TEST_F(BtifProfileQueueTest, test_multiple_connects) {
158   // First item is executed
159   sResult = NOT_SET;
160   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
161   EXPECT_EQ(sResult, UUID1_ADDR1);
162   // Second item with advance is executed
163   sResult = NOT_SET;
164   btif_queue_advance();
165   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
166   EXPECT_EQ(sResult, UUID2_ADDR1);
167 }
168 
TEST_F(BtifProfileQueueTest,test_multiple_connects_without_advance)169 TEST_F(BtifProfileQueueTest, test_multiple_connects_without_advance) {
170   // First item is executed
171   sResult = NOT_SET;
172   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
173   EXPECT_EQ(sResult, UUID1_ADDR1);
174   // Second item without advance is not executed
175   sResult = NOT_SET;
176   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
177   EXPECT_EQ(sResult, NOT_SET);
178   // Third item for same UUID1, but different address ADDR2
179   sResult = NOT_SET;
180   btif_queue_connect(kTestUuid1, &kTestAddr2, test_connect_cb);
181   EXPECT_EQ(sResult, NOT_SET);
182   // Fourth item for same UUID2, but different address ADDR2
183   sResult = NOT_SET;
184   btif_queue_connect(kTestUuid2, &kTestAddr2, test_connect_cb);
185   EXPECT_EQ(sResult, NOT_SET);
186   // Connect next doesn't work
187   sResult = NOT_SET;
188   btif_queue_connect_next();
189   EXPECT_EQ(sResult, NOT_SET);
190   // Advance moves queue to execute second item
191   sResult = NOT_SET;
192   btif_queue_advance();
193   EXPECT_EQ(sResult, UUID2_ADDR1);
194   // Advance moves queue to execute third item
195   sResult = NOT_SET;
196   btif_queue_advance();
197   EXPECT_EQ(sResult, UUID1_ADDR2);
198   // Advance moves queue to execute fourth item
199   sResult = NOT_SET;
200   btif_queue_advance();
201   EXPECT_EQ(sResult, UUID2_ADDR2);
202 }
203 
TEST_F(BtifProfileQueueTest,test_cleanup_first_allow_second)204 TEST_F(BtifProfileQueueTest, test_cleanup_first_allow_second) {
205   // First item is executed
206   sResult = NOT_SET;
207   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
208   EXPECT_EQ(sResult, UUID1_ADDR1);
209   // Second item without advance is not executed
210   sResult = NOT_SET;
211   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
212   EXPECT_EQ(sResult, NOT_SET);
213   // Connect next doesn't work
214   sResult = NOT_SET;
215   btif_queue_connect_next();
216   EXPECT_EQ(sResult, NOT_SET);
217   // Cleanup UUID1 allows the next profile connection to be executed
218   sResult = NOT_SET;
219   btif_queue_cleanup(kTestUuid1);
220   btif_queue_connect_next();
221   EXPECT_EQ(sResult, UUID2_ADDR1);
222 }
223 
TEST_F(BtifProfileQueueTest,test_cleanup_both)224 TEST_F(BtifProfileQueueTest, test_cleanup_both) {
225   // First item is executed
226   sResult = NOT_SET;
227   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
228   EXPECT_EQ(sResult, UUID1_ADDR1);
229   // Second item without advance is not executed
230   sResult = NOT_SET;
231   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
232   EXPECT_EQ(sResult, NOT_SET);
233   // Connect next doesn't work
234   sResult = NOT_SET;
235   btif_queue_connect_next();
236   EXPECT_EQ(sResult, NOT_SET);
237   // Cleanup both leaves nothing to execute
238   sResult = NOT_SET;
239   btif_queue_cleanup(kTestUuid1);
240   btif_queue_cleanup(kTestUuid2);
241   btif_queue_connect_next();
242   EXPECT_EQ(sResult, NOT_SET);
243 }
244 
TEST_F(BtifProfileQueueTest,test_cleanup_both_reverse_order)245 TEST_F(BtifProfileQueueTest, test_cleanup_both_reverse_order) {
246   // First item is executed
247   sResult = NOT_SET;
248   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
249   EXPECT_EQ(sResult, UUID1_ADDR1);
250   // Second item without advance is not executed
251   sResult = NOT_SET;
252   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
253   EXPECT_EQ(sResult, NOT_SET);
254   // Connect next doesn't work
255   sResult = NOT_SET;
256   btif_queue_connect_next();
257   EXPECT_EQ(sResult, NOT_SET);
258   // Cleanup both in reverse order leaves nothing to execute
259   sResult = NOT_SET;
260   btif_queue_cleanup(kTestUuid2);
261   btif_queue_cleanup(kTestUuid1);
262   btif_queue_connect_next();
263   EXPECT_EQ(sResult, NOT_SET);
264 }
265