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