1 /*
2 * Copyright 2024 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 <gtest/gtest.h>
18
19 #include <memory>
20
21 #include "bta/jv/bta_jv_int.h"
22 #include "bta_jv_api.h"
23 #include "osi/include/allocator.h"
24 #include "stack/include/sdp_status.h"
25 #include "test/common/mock_functions.h"
26 #include "test/fake/fake_osi.h"
27 #include "test/mock/mock_stack_sdp_legacy_api.h"
28 #include "types/bluetooth/uuid.h"
29 #include "types/raw_address.h"
30
31 namespace {
32 const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
33 const RawAddress kRawAddress2 =
34 RawAddress({0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc});
35 const bluetooth::Uuid kUuid = bluetooth::Uuid::From16Bit(0x1234);
36 const bluetooth::Uuid kUuid2 = bluetooth::Uuid::From16Bit(0x789a);
37
38 constexpr uint32_t kSlotId = 0x1234568;
39 constexpr uint8_t kScn = 123;
40
41 } // namespace
42
43 namespace bluetooth::legacy::testing {
44
45 void bta_jv_start_discovery_cback(uint32_t rfcomm_slot_id,
46 const RawAddress& bd_addr,
47 tSDP_RESULT result);
48
49 } // namespace bluetooth::legacy::testing
50
51 class FakeSdp {
52 public:
FakeSdp()53 FakeSdp() {
54 test::mock::stack_sdp_legacy::api_ = {
55 .service = {
56 .SDP_InitDiscoveryDb = [](tSDP_DISCOVERY_DB*, uint32_t, uint16_t,
57 const bluetooth::Uuid*, uint16_t,
58 const uint16_t*) -> bool { return true; },
59 .SDP_CancelServiceSearch = nullptr,
60 .SDP_ServiceSearchRequest = nullptr,
61 .SDP_ServiceSearchAttributeRequest = nullptr,
62 .SDP_ServiceSearchAttributeRequest2 =
63 [](const RawAddress& /* p_bd_addr */,
64 tSDP_DISCOVERY_DB* /* p_db */,
65 base::RepeatingCallback<
66 tSDP_DISC_CMPL_CB> /* complete_callback */) {
67 return true;
68 },
69 },
70 .db =
71 {
72 .SDP_FindServiceInDb = nullptr,
73 .SDP_FindServiceUUIDInDb =
74 [](const tSDP_DISCOVERY_DB* /* p_db */,
75 const bluetooth::Uuid& /* uuid */,
76 tSDP_DISC_REC* /* p_start_rec */) -> tSDP_DISC_REC* {
77 return nullptr;
78 },
79 .SDP_FindServiceInDb_128bit = nullptr,
80 },
81 .record =
82 {
83 .SDP_FindAttributeInRec = nullptr,
84 .SDP_FindServiceUUIDInRec_128bit = nullptr,
85 .SDP_FindProtocolListElemInRec =
86 [](const tSDP_DISC_REC* /* p_rec */,
87 uint16_t /* layer_uuid */,
88 tSDP_PROTOCOL_ELEM* /* p_elem */) -> bool {
89 return false;
90 },
91 .SDP_FindProfileVersionInRec = nullptr,
92 .SDP_FindServiceUUIDInRec = nullptr,
93 },
94 .handle =
95 {
96 .SDP_CreateRecord = nullptr,
97 .SDP_DeleteRecord = nullptr,
98 .SDP_AddAttribute = nullptr,
99 .SDP_AddSequence = nullptr,
100 .SDP_AddUuidSequence = nullptr,
101 .SDP_AddProtocolList = nullptr,
102 .SDP_AddAdditionProtoLists = nullptr,
103 .SDP_AddProfileDescriptorList = nullptr,
104 .SDP_AddLanguageBaseAttrIDList = nullptr,
105 .SDP_AddServiceClassIdList = nullptr,
106 },
107 .device_id =
108 {
109 .SDP_SetLocalDiRecord = nullptr,
110 .SDP_DiDiscover = nullptr,
111 .SDP_GetNumDiRecords = nullptr,
112 .SDP_GetDiRecord = nullptr,
113 },
114 };
115 }
116
~FakeSdp()117 ~FakeSdp() { test::mock::stack_sdp_legacy::api_ = {}; }
118 };
119
120 class BtaJvMockAndFakeTest : public ::testing::Test {
121 protected:
SetUp()122 void SetUp() override {
123 reset_mock_function_count_map();
124 fake_osi_ = std::make_unique<test::fake::FakeOsi>();
125 fake_sdp_ = std::make_unique<FakeSdp>();
126 }
127
TearDown()128 void TearDown() override {}
129
130 std::unique_ptr<test::fake::FakeOsi> fake_osi_;
131 std::unique_ptr<FakeSdp> fake_sdp_;
132 };
133
134 class BtaJvTest : public BtaJvMockAndFakeTest {
135 protected:
SetUp()136 void SetUp() override {
137 BtaJvMockAndFakeTest::SetUp();
138 bta_jv_cb.sdp_cb = {};
139 }
140
TearDown()141 void TearDown() override {
142 bta_jv_cb.sdp_cb = {};
143 BtaJvMockAndFakeTest::TearDown();
144 }
145 };
146
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__no_callback)147 TEST_F(BtaJvTest, bta_jv_start_discovery_cback__no_callback) {
148 bta_jv_enable(nullptr);
149 bluetooth::legacy::testing::bta_jv_start_discovery_cback(
150 0x12345678, kRawAddress, SDP_SUCCESS);
151 }
152
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__with_callback_success_no_record)153 TEST_F(BtaJvTest,
154 bta_jv_start_discovery_cback__with_callback_success_no_record) {
155 // Ensure that there was an sdp active
156 bta_jv_cb.sdp_cb = {
157 .sdp_active = true,
158 .bd_addr = kRawAddress,
159 .uuid = kUuid,
160 };
161 bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
162 switch (event) {
163 case BTA_JV_DISCOVERY_COMP_EVT:
164 ASSERT_EQ(p_data->disc_comp.status, tBTA_JV_STATUS::FAILURE);
165 ASSERT_EQ(kSlotId, id);
166 break;
167
168 case BTA_JV_ENABLE_EVT:
169 ASSERT_EQ(p_data->disc_comp.status, tBTA_JV_STATUS::SUCCESS);
170 ASSERT_EQ(0U, id);
171 break;
172
173 default:
174 FAIL();
175 }
176 });
177 bluetooth::legacy::testing::bta_jv_start_discovery_cback(kSlotId, kRawAddress,
178 SDP_SUCCESS);
179 }
180
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__with_callback_success_with_record)181 TEST_F(BtaJvTest,
182 bta_jv_start_discovery_cback__with_callback_success_with_record) {
183 static tSDP_DISC_REC sdp_disc_rec = {
184 .p_first_attr = nullptr,
185 .p_next_rec = nullptr,
186 .time_read = 1,
187 .remote_bd_addr = RawAddress::kAny,
188 };
189
190 test::mock::stack_sdp_legacy::api_.db.SDP_FindServiceUUIDInDb =
191 [](const tSDP_DISCOVERY_DB* /* p_db */, const bluetooth::Uuid& /* uuid */,
192 tSDP_DISC_REC* /* p_start_rec */) -> tSDP_DISC_REC* {
193 return &sdp_disc_rec;
194 };
195
196 test::mock::stack_sdp_legacy::api_.record.SDP_FindProtocolListElemInRec =
197 [](const tSDP_DISC_REC* /* p_rec */, uint16_t /* layer_uuid */,
198 tSDP_PROTOCOL_ELEM* p_elem) -> bool {
199 p_elem->params[0] = (uint16_t)kScn;
200 return true;
201 };
202
203 // Ensure that there was an sdp active
204 bta_jv_cb.sdp_cb = {
205 .sdp_active = true,
206 .bd_addr = kRawAddress,
207 .uuid = kUuid,
208 };
209 bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
210 switch (event) {
211 case BTA_JV_DISCOVERY_COMP_EVT:
212 ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
213 ASSERT_EQ(kScn, p_data->disc_comp.scn);
214 ASSERT_EQ(kSlotId, id);
215 break;
216
217 case BTA_JV_ENABLE_EVT:
218 ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
219 ASSERT_EQ(0U, id);
220 break;
221
222 default:
223 FAIL();
224 }
225 });
226 bluetooth::legacy::testing::bta_jv_start_discovery_cback(kSlotId, kRawAddress,
227 SDP_SUCCESS);
228 }
229
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__with_callback_failure)230 TEST_F(BtaJvTest, bta_jv_start_discovery_cback__with_callback_failure) {
231 tSDP_RESULT result = SDP_CONN_FAILED;
232
233 // Ensure that there was an sdp active
234 bta_jv_cb.sdp_cb = {
235 .sdp_active = true,
236 .bd_addr = kRawAddress,
237 .uuid = kUuid,
238 };
239 bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
240 switch (event) {
241 case BTA_JV_DISCOVERY_COMP_EVT:
242 ASSERT_EQ(tBTA_JV_STATUS::FAILURE, p_data->disc_comp.status);
243 ASSERT_EQ(kSlotId, id);
244 break;
245
246 case BTA_JV_ENABLE_EVT:
247 ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
248 ASSERT_EQ(0U, id);
249 break;
250
251 default:
252 FAIL();
253 }
254 });
255 bluetooth::legacy::testing::bta_jv_start_discovery_cback(kSlotId, kRawAddress,
256 result);
257 }
258
TEST_F(BtaJvTest,bta_jv_start_discovery__idle)259 TEST_F(BtaJvTest, bta_jv_start_discovery__idle) {
260 bluetooth::Uuid uuid_list[1] = {
261 kUuid,
262 };
263 uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));
264
265 bta_jv_start_discovery(kRawAddress, num_uuid, uuid_list, kSlotId);
266
267 ASSERT_EQ(true, bta_jv_cb.sdp_cb.sdp_active);
268 ASSERT_EQ(kRawAddress, bta_jv_cb.sdp_cb.bd_addr);
269 ASSERT_EQ(kUuid, bta_jv_cb.sdp_cb.uuid);
270 }
271
TEST_F(BtaJvTest,bta_jv_start_discovery__idle_failed_to_start)272 TEST_F(BtaJvTest, bta_jv_start_discovery__idle_failed_to_start) {
273 bluetooth::Uuid uuid_list[1] = {
274 kUuid,
275 };
276 uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));
277
278 test::mock::stack_sdp_legacy::api_.service
279 .SDP_ServiceSearchAttributeRequest2 =
280 [](const RawAddress& /* p_bd_addr */, tSDP_DISCOVERY_DB* /* p_db */,
281 base::RepeatingCallback<tSDP_DISC_CMPL_CB> /* complete_callback */) {
282 return false;
283 };
284
285 bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
286 switch (event) {
287 case BTA_JV_DISCOVERY_COMP_EVT:
288 ASSERT_EQ(tBTA_JV_STATUS::FAILURE, p_data->disc_comp.status);
289 ASSERT_EQ(kSlotId, id);
290 break;
291
292 case BTA_JV_ENABLE_EVT:
293 ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
294 ASSERT_EQ(0U, id);
295 break;
296
297 default:
298 FAIL();
299 }
300 });
301 bta_jv_start_discovery(kRawAddress2, num_uuid, uuid_list, kSlotId);
302
303 ASSERT_EQ(false, bta_jv_cb.sdp_cb.sdp_active);
304 ASSERT_EQ(RawAddress::kEmpty, bta_jv_cb.sdp_cb.bd_addr);
305 ASSERT_EQ(bluetooth::Uuid::kEmpty, bta_jv_cb.sdp_cb.uuid);
306 }
307
TEST_F(BtaJvTest,bta_jv_start_discovery__already_active)308 TEST_F(BtaJvTest, bta_jv_start_discovery__already_active) {
309 bta_jv_cb.sdp_cb = {
310 .sdp_active = true,
311 .bd_addr = kRawAddress,
312 .uuid = kUuid,
313 };
314
315 bluetooth::Uuid uuid_list[1] = {
316 kUuid2,
317 };
318 uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));
319
320 bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
321 switch (event) {
322 case BTA_JV_DISCOVERY_COMP_EVT:
323 ASSERT_EQ(tBTA_JV_STATUS::BUSY, p_data->disc_comp.status);
324 ASSERT_EQ(kSlotId, id);
325 break;
326
327 case BTA_JV_ENABLE_EVT:
328 ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
329 ASSERT_EQ(0U, id);
330 break;
331
332 default:
333 FAIL();
334 }
335 });
336 bta_jv_start_discovery(kRawAddress2, num_uuid, uuid_list, kSlotId);
337
338 ASSERT_EQ(true, bta_jv_cb.sdp_cb.sdp_active);
339 ASSERT_EQ(kRawAddress, bta_jv_cb.sdp_cb.bd_addr);
340 ASSERT_EQ(kUuid, bta_jv_cb.sdp_cb.uuid);
341 }
342