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 // TODO(b/369381361) Enfore -Wmissing-prototypes
30 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
31 
32 typedef void(tBTIF_CBACK)(uint16_t event, char* p_param);
33 typedef void(tBTIF_COPY_CBACK)(uint16_t event, char* p_dest, const char* p_src);
34 
35 // NOTE: Local re-implementation of functions to avoid thread context switching
36 static bool sStackRunning;
get_stack_is_running(void)37 bool get_stack_is_running(void) { return sStackRunning; }
38 static stack_manager_t sStackManager = {
39         nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, get_stack_is_running};
stack_manager_get_interface()40 const stack_manager_t* stack_manager_get_interface() { return &sStackManager; }
do_in_jni_thread(base::OnceClosure task)41 bt_status_t do_in_jni_thread(base::OnceClosure task) {
42   std::move(task).Run();
43   return BT_STATUS_SUCCESS;
44 }
is_on_jni_thread()45 bool is_on_jni_thread() { return true; }
46 
47 enum ResultType { NOT_SET = 0, UNKNOWN, UUID1_ADDR1, UUID1_ADDR2, UUID2_ADDR1, UUID2_ADDR2 };
48 
49 static ResultType sResult;
50 
51 class BtifProfileQueueTest : public ::testing::Test {
52 public:
53   static const uint16_t kTestUuid1 = 0x9527;
54   static const uint16_t kTestUuid2 = 0x819F;
55   static const RawAddress kTestAddr1;
56   static const RawAddress kTestAddr2;
57 
58 protected:
SetUp()59   void SetUp() override {
60     sStackRunning = true;
61     sResult = NOT_SET;
62   }
TearDown()63   void TearDown() override { btif_queue_release(); }
64 };
65 
66 const RawAddress BtifProfileQueueTest::kTestAddr1{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
67 const RawAddress BtifProfileQueueTest::kTestAddr2{{0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56}};
68 
test_connect_cb(RawAddress * bda,uint16_t uuid)69 static bt_status_t test_connect_cb(RawAddress* bda, uint16_t uuid) {
70   sResult = UNKNOWN;
71   if (*bda == BtifProfileQueueTest::kTestAddr1) {
72     if (uuid == BtifProfileQueueTest::kTestUuid1) {
73       sResult = UUID1_ADDR1;
74     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
75       sResult = UUID2_ADDR1;
76     }
77   } else if (*bda == BtifProfileQueueTest::kTestAddr2) {
78     if (uuid == BtifProfileQueueTest::kTestUuid1) {
79       sResult = UUID1_ADDR2;
80     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
81       sResult = UUID2_ADDR2;
82     }
83   }
84   return BT_STATUS_SUCCESS;
85 }
86 
TEST_F(BtifProfileQueueTest,test_connect)87 TEST_F(BtifProfileQueueTest, test_connect) {
88   sResult = NOT_SET;
89   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
90   EXPECT_EQ(sResult, UUID1_ADDR1);
91 }
92 
test_connect_cb_fail(RawAddress * bda,uint16_t uuid)93 static bt_status_t test_connect_cb_fail(RawAddress* bda, uint16_t uuid) {
94   sResult = UNKNOWN;
95   if (*bda == BtifProfileQueueTest::kTestAddr1) {
96     if (uuid == BtifProfileQueueTest::kTestUuid1) {
97       sResult = UUID1_ADDR1;
98     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
99       sResult = UUID2_ADDR1;
100     }
101   } else if (*bda == BtifProfileQueueTest::kTestAddr2) {
102     if (uuid == BtifProfileQueueTest::kTestUuid1) {
103       sResult = UUID1_ADDR2;
104     } else if (uuid == BtifProfileQueueTest::kTestUuid2) {
105       sResult = UUID2_ADDR2;
106     }
107   }
108   return BT_STATUS_BUSY;
109 }
110 
TEST_F(BtifProfileQueueTest,test_connect_fail_still_can_advance_the_queue)111 TEST_F(BtifProfileQueueTest, test_connect_fail_still_can_advance_the_queue) {
112   sResult = NOT_SET;
113   // First connect-message for UUID1-ADDR1 is executed, but does not be removed
114   // from connect-queue yet.
115   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
116   EXPECT_EQ(sResult, UUID1_ADDR1);
117   sResult = NOT_SET;
118   // Second connect-message for UUID2-ADDR1 be pushed into connect-queue, but is
119   // not executed
120   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb_fail);
121   EXPECT_EQ(sResult, NOT_SET);
122   // Third connect-message for UUID1-ADDR2 be pushed into connect-queue, but is
123   // not executed
124   btif_queue_connect(kTestUuid1, &kTestAddr2, test_connect_cb_fail);
125   EXPECT_EQ(sResult, NOT_SET);
126   // Fourth connect-message for UUID2-ADDR2 be pushed into connect-queue, but is
127   // not executed
128   btif_queue_connect(kTestUuid2, &kTestAddr2, test_connect_cb_fail);
129   EXPECT_EQ(sResult, NOT_SET);
130   // removed First connect-message from connect-queue, check it can advance to
131   // subsequent connect-message.
132   btif_queue_advance();
133   EXPECT_EQ(sResult, UUID2_ADDR2);
134 }
135 
TEST_F(BtifProfileQueueTest,test_connect_same_uuid_do_not_repeat)136 TEST_F(BtifProfileQueueTest, test_connect_same_uuid_do_not_repeat) {
137   sResult = NOT_SET;
138   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
139   EXPECT_EQ(sResult, UUID1_ADDR1);
140   // Second connection request on the same UUID do not repeat
141   sResult = NOT_SET;
142   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
143   EXPECT_EQ(sResult, NOT_SET);
144   // Not even after we advance the queue
145   sResult = NOT_SET;
146   btif_queue_advance();
147   btif_queue_connect_next();
148   EXPECT_EQ(sResult, NOT_SET);
149 }
150 
TEST_F(BtifProfileQueueTest,test_multiple_connects)151 TEST_F(BtifProfileQueueTest, test_multiple_connects) {
152   // First item is executed
153   sResult = NOT_SET;
154   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
155   EXPECT_EQ(sResult, UUID1_ADDR1);
156   // Second item with advance is executed
157   sResult = NOT_SET;
158   btif_queue_advance();
159   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
160   EXPECT_EQ(sResult, UUID2_ADDR1);
161 }
162 
TEST_F(BtifProfileQueueTest,test_multiple_connects_without_advance)163 TEST_F(BtifProfileQueueTest, test_multiple_connects_without_advance) {
164   // First item is executed
165   sResult = NOT_SET;
166   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
167   EXPECT_EQ(sResult, UUID1_ADDR1);
168   // Second item without advance is not executed
169   sResult = NOT_SET;
170   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
171   EXPECT_EQ(sResult, NOT_SET);
172   // Third item for same UUID1, but different address ADDR2
173   sResult = NOT_SET;
174   btif_queue_connect(kTestUuid1, &kTestAddr2, test_connect_cb);
175   EXPECT_EQ(sResult, NOT_SET);
176   // Fourth item for same UUID2, but different address ADDR2
177   sResult = NOT_SET;
178   btif_queue_connect(kTestUuid2, &kTestAddr2, test_connect_cb);
179   EXPECT_EQ(sResult, NOT_SET);
180   // Connect next doesn't work
181   sResult = NOT_SET;
182   btif_queue_connect_next();
183   EXPECT_EQ(sResult, NOT_SET);
184   // Advance moves queue to execute second item
185   sResult = NOT_SET;
186   btif_queue_advance();
187   EXPECT_EQ(sResult, UUID2_ADDR1);
188   // Advance moves queue to execute third item
189   sResult = NOT_SET;
190   btif_queue_advance();
191   EXPECT_EQ(sResult, UUID1_ADDR2);
192   // Advance moves queue to execute fourth item
193   sResult = NOT_SET;
194   btif_queue_advance();
195   EXPECT_EQ(sResult, UUID2_ADDR2);
196 }
197 
TEST_F(BtifProfileQueueTest,test_cleanup_first_allow_second)198 TEST_F(BtifProfileQueueTest, test_cleanup_first_allow_second) {
199   // First item is executed
200   sResult = NOT_SET;
201   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
202   EXPECT_EQ(sResult, UUID1_ADDR1);
203   // Second item without advance is not executed
204   sResult = NOT_SET;
205   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
206   EXPECT_EQ(sResult, NOT_SET);
207   // Connect next doesn't work
208   sResult = NOT_SET;
209   btif_queue_connect_next();
210   EXPECT_EQ(sResult, NOT_SET);
211   // Cleanup UUID1 allows the next profile connection to be executed
212   sResult = NOT_SET;
213   btif_queue_cleanup(kTestUuid1);
214   btif_queue_connect_next();
215   EXPECT_EQ(sResult, UUID2_ADDR1);
216 }
217 
TEST_F(BtifProfileQueueTest,test_cleanup_both)218 TEST_F(BtifProfileQueueTest, test_cleanup_both) {
219   // First item is executed
220   sResult = NOT_SET;
221   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
222   EXPECT_EQ(sResult, UUID1_ADDR1);
223   // Second item without advance is not executed
224   sResult = NOT_SET;
225   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
226   EXPECT_EQ(sResult, NOT_SET);
227   // Connect next doesn't work
228   sResult = NOT_SET;
229   btif_queue_connect_next();
230   EXPECT_EQ(sResult, NOT_SET);
231   // Cleanup both leaves nothing to execute
232   sResult = NOT_SET;
233   btif_queue_cleanup(kTestUuid1);
234   btif_queue_cleanup(kTestUuid2);
235   btif_queue_connect_next();
236   EXPECT_EQ(sResult, NOT_SET);
237 }
238 
TEST_F(BtifProfileQueueTest,test_cleanup_both_reverse_order)239 TEST_F(BtifProfileQueueTest, test_cleanup_both_reverse_order) {
240   // First item is executed
241   sResult = NOT_SET;
242   btif_queue_connect(kTestUuid1, &kTestAddr1, test_connect_cb);
243   EXPECT_EQ(sResult, UUID1_ADDR1);
244   // Second item without advance is not executed
245   sResult = NOT_SET;
246   btif_queue_connect(kTestUuid2, &kTestAddr1, test_connect_cb);
247   EXPECT_EQ(sResult, NOT_SET);
248   // Connect next doesn't work
249   sResult = NOT_SET;
250   btif_queue_connect_next();
251   EXPECT_EQ(sResult, NOT_SET);
252   // Cleanup both in reverse order leaves nothing to execute
253   sResult = NOT_SET;
254   btif_queue_cleanup(kTestUuid2);
255   btif_queue_cleanup(kTestUuid1);
256   btif_queue_connect_next();
257   EXPECT_EQ(sResult, NOT_SET);
258 }
259