1 /*
2 * Copyright 2022 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 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <stdlib.h>
20
21 #include <cstddef>
22 #include <cstdint>
23
24 #include "include/macros.h"
25 #include "osi/include/allocator.h"
26 #include "stack/include/bt_uuid16.h"
27 #include "stack/include/sdp_api.h"
28 #include "stack/include/sdpdefs.h"
29 #include "stack/sdp/internal/sdp_api.h"
30 #include "stack/sdp/sdpint.h"
31 #include "test/fake/fake_osi.h"
32 #include "test/mock/mock_osi_allocator.h"
33 #include "test/mock/mock_stack_l2cap_interface.h"
34
35 #ifndef BT_DEFAULT_BUFFER_SIZE
36 #define BT_DEFAULT_BUFFER_SIZE (4096 + 16)
37 #endif
38
39 // TODO(b/369381361) Enfore -Wmissing-prototypes
40 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
41
42 using ::testing::_;
43 using ::testing::DoAll;
44 using ::testing::Invoke;
45 using ::testing::NotNull;
46 using ::testing::Pointee;
47 using ::testing::Return;
48 using ::testing::ReturnArg;
49 using ::testing::SaveArg;
50 using ::testing::SaveArgPointee;
51 using ::testing::StrEq;
52 using ::testing::StrictMock;
53 using ::testing::Test;
54
55 namespace {
56 constexpr uint8_t kSDP_MAX_CONNECTIONS = static_cast<uint8_t>(SDP_MAX_CONNECTIONS);
57
58 RawAddress addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
59 int L2CA_ConnectReqWithSecurity_cid = 42;
60 tSDP_DISCOVERY_DB* sdp_db = nullptr;
61
62 class StackSdpWithMocksTest : public ::testing::Test {
63 protected:
SetUp()64 void SetUp() override {
65 fake_osi_ = std::make_unique<test::fake::FakeOsi>();
66 bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_);
67
68 tL2CAP_APPL_INFO l2cap_callbacks{};
69 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _))
70 .WillOnce(DoAll(SaveArg<1>(&l2cap_callbacks), ::testing::ReturnArg<0>()));
71 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(_));
72 }
73
TearDown()74 void TearDown() override {
75 bluetooth::testing::stack::l2cap::reset_interface();
76 fake_osi_.reset();
77 }
78
79 bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
80 std::unique_ptr<test::fake::FakeOsi> fake_osi_;
81 };
82
83 class StackSdpInitTest : public StackSdpWithMocksTest {
84 protected:
SetUp()85 void SetUp() override {
86 StackSdpWithMocksTest::SetUp();
87 sdp_init();
88 sdp_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
89 }
90
TearDown()91 void TearDown() override {
92 osi_free(sdp_db);
93 sdp_free();
94 StackSdpWithMocksTest::TearDown();
95 }
96 };
97
98 } // namespace
99
TEST_F(StackSdpInitTest,nop)100 TEST_F(StackSdpInitTest, nop) {}
101
TEST_F(StackSdpInitTest,sdp_service_search_request)102 TEST_F(StackSdpInitTest, sdp_service_search_request) {
103 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
104 .WillOnce(Invoke([](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
105 uint16_t /* sec_level */) -> uint16_t {
106 return L2CA_ConnectReqWithSecurity_cid;
107 }));
108 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(_)).WillOnce(Return(true));
109
110 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DataWrite(_, _))
111 .WillOnce(Invoke([](uint16_t /* cid */, BT_HDR* p_data) -> tL2CAP_DW_RESULT {
112 osi_free_and_reset((void**)&p_data);
113 return tL2CAP_DW_RESULT::SUCCESS;
114 }));
115
116 ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
117 int cid = L2CA_ConnectReqWithSecurity_cid;
118 tCONN_CB* p_ccb = sdpu_find_ccb_by_cid(cid);
119 ASSERT_NE(p_ccb, nullptr);
120 ASSERT_EQ(p_ccb->con_state, tSDP_STATE::CONN_SETUP);
121
122 tL2CAP_CFG_INFO cfg;
123 sdp_cb.reg_info.pL2CA_ConfigCfm_Cb(p_ccb->connection_id, 0, &cfg);
124
125 ASSERT_EQ(p_ccb->con_state, tSDP_STATE::CONNECTED);
126
127 sdp_disconnect(p_ccb, tSDP_STATUS::SDP_SUCCESS);
128 sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb(p_ccb->connection_id, 0);
129
130 ASSERT_EQ(p_ccb->con_state, tSDP_STATE::IDLE);
131 }
132
find_ccb(uint16_t cid,tSDP_STATE state)133 tCONN_CB* find_ccb(uint16_t cid, tSDP_STATE state) {
134 uint16_t xx;
135 tCONN_CB* p_ccb;
136
137 // Look through each connection control block
138 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
139 if ((p_ccb->con_state == state) && (p_ccb->connection_id == cid)) {
140 return p_ccb;
141 }
142 }
143 return nullptr; // not found
144 }
145
TEST_F(StackSdpInitTest,sdp_service_search_request_queuing)146 TEST_F(StackSdpInitTest, sdp_service_search_request_queuing) {
147 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
148 .WillOnce(Invoke([](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
149 uint16_t /* sec_level */) -> uint16_t {
150 return L2CA_ConnectReqWithSecurity_cid;
151 }));
152 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DataWrite(_, _))
153 .WillRepeatedly(Invoke([](uint16_t /* cid */, BT_HDR* data) -> tL2CAP_DW_RESULT {
154 osi_free(data);
155 return tL2CAP_DW_RESULT::SUCCESS;
156 }));
157
158 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(_)).WillOnce(Return(true));
159
160 ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
161 const int cid = L2CA_ConnectReqWithSecurity_cid;
162 tCONN_CB* p_ccb1 = find_ccb(cid, tSDP_STATE::CONN_SETUP);
163 ASSERT_NE(p_ccb1, nullptr);
164 ASSERT_EQ(p_ccb1->con_state, tSDP_STATE::CONN_SETUP);
165
166 ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
167 tCONN_CB* p_ccb2 = find_ccb(cid, tSDP_STATE::CONN_PEND);
168 ASSERT_NE(p_ccb2, nullptr);
169 ASSERT_NE(p_ccb2, p_ccb1);
170 ASSERT_EQ(p_ccb2->con_state, tSDP_STATE::CONN_PEND);
171
172 tL2CAP_CFG_INFO cfg;
173 sdp_cb.reg_info.pL2CA_ConfigCfm_Cb(p_ccb1->connection_id, 0, &cfg);
174
175 ASSERT_EQ(p_ccb1->con_state, tSDP_STATE::CONNECTED);
176 ASSERT_EQ(p_ccb2->con_state, tSDP_STATE::CONN_PEND);
177
178 p_ccb1->disconnect_reason = tSDP_STATUS::SDP_SUCCESS;
179 sdp_disconnect(p_ccb1, tSDP_STATUS::SDP_SUCCESS);
180
181 ASSERT_EQ(p_ccb1->con_state, tSDP_STATE::IDLE);
182 ASSERT_EQ(p_ccb2->con_state, tSDP_STATE::CONNECTED);
183
184 sdp_disconnect(p_ccb2, tSDP_STATUS::SDP_SUCCESS);
185 sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb(p_ccb2->connection_id, 0);
186
187 ASSERT_EQ(p_ccb1->con_state, tSDP_STATE::IDLE);
188 ASSERT_EQ(p_ccb2->con_state, tSDP_STATE::IDLE);
189 }
190
sdp_callback(const RawAddress &,tSDP_RESULT result)191 void sdp_callback(const RawAddress& /* bd_addr */, tSDP_RESULT result) {
192 if (result == tSDP_STATUS::SDP_SUCCESS) {
193 ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
194 }
195 }
196
TEST_F(StackSdpInitTest,sdp_service_search_request_queuing_race_condition)197 TEST_F(StackSdpInitTest, sdp_service_search_request_queuing_race_condition) {
198 uint16_t cid = L2CA_ConnectReqWithSecurity_cid;
199 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
200 .WillRepeatedly(Invoke([&cid](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
201 uint16_t /* sec_level */) -> uint16_t { return cid++; }));
202 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(_)).WillRepeatedly(Return(true));
203
204 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DataWrite(_, _))
205 .WillOnce(Invoke([](uint16_t /* cid */, BT_HDR* p_data) -> tL2CAP_DW_RESULT {
206 osi_free_and_reset((void**)&p_data);
207 return tL2CAP_DW_RESULT::SUCCESS;
208 }));
209
210 // start first request
211 ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, sdp_callback));
212 const uint16_t cid1 = L2CA_ConnectReqWithSecurity_cid;
213 tCONN_CB* p_ccb1 = find_ccb(cid1, tSDP_STATE::CONN_SETUP);
214 ASSERT_NE(p_ccb1, nullptr);
215 ASSERT_EQ(p_ccb1->con_state, tSDP_STATE::CONN_SETUP);
216
217 tL2CAP_CFG_INFO cfg;
218 sdp_cb.reg_info.pL2CA_ConfigCfm_Cb(p_ccb1->connection_id, 0, &cfg);
219
220 ASSERT_EQ(p_ccb1->con_state, tSDP_STATE::CONNECTED);
221
222 sdp_disconnect(p_ccb1, tSDP_STATUS::SDP_SUCCESS);
223 sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb(p_ccb1->connection_id, 0);
224
225 const uint16_t cid2 = L2CA_ConnectReqWithSecurity_cid + 1;
226 ASSERT_NE(cid1, cid2); // The callback a queued a new request
227 tCONN_CB* p_ccb2 = find_ccb(cid2, tSDP_STATE::CONN_SETUP);
228 ASSERT_NE(p_ccb2, nullptr);
229 // If race condition, this will be stuck in PEND
230 ASSERT_EQ(p_ccb2->con_state, tSDP_STATE::CONN_SETUP);
231
232 sdp_disconnect(p_ccb2, tSDP_STATUS::SDP_SUCCESS);
233 }
234
TEST_F(StackSdpInitTest,sdp_disc_wait_text)235 TEST_F(StackSdpInitTest, sdp_disc_wait_text) {
236 std::vector<std::pair<tSDP_DISC_WAIT, std::string>> states = {
237 std::make_pair(SDP_DISC_WAIT_CONN, "SDP_DISC_WAIT_CONN"),
238 std::make_pair(SDP_DISC_WAIT_HANDLES, "SDP_DISC_WAIT_HANDLES"),
239 std::make_pair(SDP_DISC_WAIT_ATTR, "SDP_DISC_WAIT_ATTR"),
240 std::make_pair(SDP_DISC_WAIT_SEARCH_ATTR, "SDP_DISC_WAIT_SEARCH_ATTR"),
241 std::make_pair(SDP_DISC_WAIT_CANCEL, "SDP_DISC_WAIT_CANCEL"),
242 };
243 for (const auto& state : states) {
244 ASSERT_STREQ(state.second.c_str(), sdp_disc_wait_text(state.first).c_str());
245 }
246 auto unknown = base::StringPrintf("UNKNOWN[%d]", std::numeric_limits<uint8_t>::max());
247 ASSERT_STREQ(unknown.c_str(),
248 sdp_disc_wait_text(static_cast<tSDP_DISC_WAIT>(std::numeric_limits<uint8_t>::max()))
249 .c_str());
250 }
251
TEST_F(StackSdpInitTest,sdp_state_text)252 TEST_F(StackSdpInitTest, sdp_state_text) {
253 std::vector<std::pair<tSDP_STATE, std::string>> states = {
254 std::make_pair(tSDP_STATE::IDLE, "tSDP_STATE::IDLE(0x0)"),
255 std::make_pair(tSDP_STATE::CONN_SETUP, "tSDP_STATE::CONN_SETUP(0x1)"),
256 std::make_pair(tSDP_STATE::CFG_SETUP, "tSDP_STATE::CFG_SETUP(0x2)"),
257 std::make_pair(tSDP_STATE::CONNECTED, "tSDP_STATE::CONNECTED(0x3)"),
258 std::make_pair(tSDP_STATE::CONN_PEND, "tSDP_STATE::CONN_PEND(0x4)"),
259 };
260 for (const auto& state : states) {
261 ASSERT_STREQ(state.second.c_str(), sdp_state_text(state.first).c_str());
262 }
263 auto unknown = []() {
264 RETURN_UNKNOWN_TYPE_STRING(tSDP_STATE, std::numeric_limits<std::uint8_t>::max());
265 }();
266 ASSERT_STREQ(unknown.c_str(),
267 sdp_state_text(static_cast<tSDP_STATE>(std::numeric_limits<std::uint8_t>::max()))
268 .c_str());
269 }
270
TEST_F(StackSdpInitTest,sdp_flags_text)271 TEST_F(StackSdpInitTest, sdp_flags_text) {
272 std::vector<std::pair<tSDP_DISC_WAIT, std::string>> flags = {
273 std::make_pair(SDP_FLAGS_IS_ORIG, "SDP_FLAGS_IS_ORIG"),
274 std::make_pair(SDP_FLAGS_HIS_CFG_DONE, "SDP_FLAGS_HIS_CFG_DONE"),
275 std::make_pair(SDP_FLAGS_MY_CFG_DONE, "SDP_FLAGS_MY_CFG_DONE"),
276 };
277 for (const auto& flag : flags) {
278 ASSERT_STREQ(flag.second.c_str(), sdp_flags_text(flag.first).c_str());
279 }
280 auto unknown = base::StringPrintf("UNKNOWN[%hhu]", std::numeric_limits<uint8_t>::max());
281 ASSERT_STREQ(
282 unknown.c_str(),
283 sdp_flags_text(static_cast<tSDP_DISC_WAIT>(std::numeric_limits<uint8_t>::max())).c_str());
284 }
285
TEST_F(StackSdpInitTest,sdp_status_text)286 TEST_F(StackSdpInitTest, sdp_status_text) {
287 std::vector<std::pair<tSDP_STATUS, std::string>> status = {
288 std::make_pair(tSDP_STATUS::SDP_SUCCESS, "tSDP_STATUS::SDP_SUCCESS"),
289 std::make_pair(tSDP_STATUS::SDP_INVALID_VERSION, "tSDP_STATUS::SDP_INVALID_VERSION"),
290 std::make_pair(tSDP_STATUS::SDP_INVALID_SERV_REC_HDL,
291 "tSDP_STATUS::SDP_INVALID_SERV_REC_HDL"),
292 std::make_pair(tSDP_STATUS::SDP_INVALID_REQ_SYNTAX,
293 "tSDP_STATUS::SDP_INVALID_REQ_SYNTAX"),
294 std::make_pair(tSDP_STATUS::SDP_INVALID_PDU_SIZE, "tSDP_STATUS::SDP_INVALID_PDU_SIZE"),
295 std::make_pair(tSDP_STATUS::SDP_INVALID_CONT_STATE,
296 "tSDP_STATUS::SDP_INVALID_CONT_STATE"),
297 std::make_pair(tSDP_STATUS::SDP_NO_RESOURCES, "tSDP_STATUS::SDP_NO_RESOURCES"),
298 std::make_pair(tSDP_STATUS::SDP_DI_REG_FAILED, "tSDP_STATUS::SDP_DI_REG_FAILED"),
299 std::make_pair(tSDP_STATUS::SDP_DI_DISC_FAILED, "tSDP_STATUS::SDP_DI_DISC_FAILED"),
300 std::make_pair(tSDP_STATUS::SDP_NO_DI_RECORD_FOUND,
301 "tSDP_STATUS::SDP_NO_DI_RECORD_FOUND"),
302 std::make_pair(tSDP_STATUS::SDP_ERR_ATTR_NOT_PRESENT,
303 "tSDP_STATUS::SDP_ERR_ATTR_NOT_PRESENT"),
304 std::make_pair(tSDP_STATUS::SDP_ILLEGAL_PARAMETER, "tSDP_STATUS::SDP_ILLEGAL_PARAMETER"),
305 std::make_pair(tSDP_STATUS::HID_SDP_NO_SERV_UUID, "tSDP_STATUS::HID_SDP_NO_SERV_UUID"),
306 std::make_pair(tSDP_STATUS::HID_SDP_MANDATORY_MISSING,
307 "tSDP_STATUS::HID_SDP_MANDATORY_MISSING"),
308 std::make_pair(tSDP_STATUS::SDP_NO_RECS_MATCH, "tSDP_STATUS::SDP_NO_RECS_MATCH"),
309 std::make_pair(tSDP_STATUS::SDP_CONN_FAILED, "tSDP_STATUS::SDP_CONN_FAILED"),
310 std::make_pair(tSDP_STATUS::SDP_CFG_FAILED, "tSDP_STATUS::SDP_CFG_FAILED"),
311 std::make_pair(tSDP_STATUS::SDP_GENERIC_ERROR, "tSDP_STATUS::SDP_GENERIC_ERROR"),
312 std::make_pair(tSDP_STATUS::SDP_DB_FULL, "tSDP_STATUS::SDP_DB_FULL"),
313 std::make_pair(tSDP_STATUS::SDP_CANCEL, "tSDP_STATUS::SDP_CANCEL"),
314 };
315 for (const auto& stat : status) {
316 ASSERT_STREQ(stat.second.c_str(), sdp_status_text(stat.first).c_str());
317 }
318 auto unknown = base::StringPrintf("UNKNOWN[%hu]", std::numeric_limits<uint16_t>::max());
319 ASSERT_STREQ(
320 unknown.c_str(),
321 sdp_status_text(static_cast<tSDP_STATUS>(std::numeric_limits<uint16_t>::max())).c_str());
322 }
323
324 static tSDP_DISCOVERY_DB db{};
325 static tSDP_DISC_REC rec{};
326 static tSDP_DISC_ATTR uuid_desc_attr{};
327 static tSDP_DISC_ATTR client_exe_url_attr{};
328 static tSDP_DISC_ATTR service_desc_attr{};
329 static tSDP_DISC_ATTR doc_url_desc_attr{};
330 static tSDP_DISC_ATTR spec_id_attr{};
331 static tSDP_DISC_ATTR vendor_id_attr{};
332 static tSDP_DISC_ATTR vendor_id_src_attr{};
333 static tSDP_DISC_ATTR prod_id_attr{};
334 static tSDP_DISC_ATTR prod_version_attr{};
335 static tSDP_DISC_ATTR primary_rec_attr{};
336
337 class SDP_GetDiRecord_Tests : public ::testing::Test {
338 protected:
SetUp()339 void SetUp() override {
340 db.p_first_rec = &rec;
341 rec.p_first_attr = &uuid_desc_attr;
342
343 uuid_desc_attr.attr_id = ATTR_ID_SERVICE_ID;
344 uuid_desc_attr.p_next_attr = &client_exe_url_attr;
345
346 client_exe_url_attr.attr_id = ATTR_ID_CLIENT_EXE_URL;
347 client_exe_url_attr.p_next_attr = &service_desc_attr;
348
349 service_desc_attr.attr_id = ATTR_ID_SERVICE_DESCRIPTION;
350 service_desc_attr.p_next_attr = &doc_url_desc_attr;
351
352 doc_url_desc_attr.attr_id = ATTR_ID_DOCUMENTATION_URL;
353 doc_url_desc_attr.p_next_attr = &spec_id_attr;
354
355 spec_id_attr.attr_id = ATTR_ID_SPECIFICATION_ID;
356 spec_id_attr.p_next_attr = &vendor_id_attr;
357
358 vendor_id_attr.attr_id = ATTR_ID_VENDOR_ID;
359 vendor_id_attr.p_next_attr = &vendor_id_src_attr;
360
361 vendor_id_src_attr.attr_id = ATTR_ID_VENDOR_ID_SOURCE;
362 vendor_id_src_attr.p_next_attr = &prod_id_attr;
363
364 prod_id_attr.attr_id = ATTR_ID_PRODUCT_ID;
365 prod_id_attr.p_next_attr = &prod_version_attr;
366
367 prod_version_attr.attr_id = ATTR_ID_PRODUCT_VERSION;
368 prod_version_attr.p_next_attr = &primary_rec_attr;
369
370 primary_rec_attr.attr_id = ATTR_ID_PRIMARY_RECORD;
371 primary_rec_attr.p_next_attr = nullptr;
372 }
373
TearDown()374 void TearDown() override {
375 db = {};
376 rec = {};
377 uuid_desc_attr = {};
378 client_exe_url_attr = {};
379 service_desc_attr = {};
380 doc_url_desc_attr = {};
381 spec_id_attr = {};
382 vendor_id_attr = {};
383 vendor_id_src_attr = {};
384 prod_id_attr = {};
385 prod_version_attr = {};
386 primary_rec_attr = {};
387 }
388 };
389
390 // regression test for b/297831980 and others
TEST_F(SDP_GetDiRecord_Tests,SDP_GetDiRecord_Regression_test0)391 TEST_F(SDP_GetDiRecord_Tests, SDP_GetDiRecord_Regression_test0) {
392 // tune the type/len and value of each attribute in
393 // each test
394 uuid_desc_attr.attr_len_type = (UUID_DESC_TYPE << 12) | 2;
395 uuid_desc_attr.attr_value.v.u16 = UUID_SERVCLASS_PNP_INFORMATION;
396
397 // use a 2-byte string so that it can be
398 // saved in tSDP_DISC_ATVAL
399 const char* const text = "AB";
400 int len = strlen(text);
401 client_exe_url_attr.attr_len_type = (URL_DESC_TYPE << 12) | len;
402 memcpy(client_exe_url_attr.attr_value.v.array, text, len);
403
404 // make this attr not found by id
405 service_desc_attr.attr_id = ATTR_ID_SERVICE_DESCRIPTION + 1;
406 service_desc_attr.attr_len_type = (TEXT_STR_DESC_TYPE << 12) | len;
407 memcpy(service_desc_attr.attr_value.v.array, text, len);
408
409 // make a wrong type
410 doc_url_desc_attr.attr_len_type = (TEXT_STR_DESC_TYPE << 12) | len;
411 memcpy(doc_url_desc_attr.attr_value.v.array, text, len);
412
413 // setup unexpected sizes for the following attrs
414 spec_id_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
415 spec_id_attr.attr_value.v.u16 = 0x1111;
416
417 vendor_id_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
418 vendor_id_attr.attr_value.v.u16 = 0x2222;
419
420 vendor_id_src_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
421 vendor_id_src_attr.attr_value.v.u16 = 0x3333;
422
423 prod_id_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
424 prod_id_attr.attr_value.v.u16 = 0x4444;
425
426 prod_version_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
427 prod_version_attr.attr_value.v.u16 = 0x5555;
428
429 // setup wrong size for primary_rec_attr
430 primary_rec_attr.attr_len_type = (BOOLEAN_DESC_TYPE << 12) | 0;
431 primary_rec_attr.attr_value.v.u8 = 0x66;
432
433 tSDP_DI_GET_RECORD device_info{};
434
435 SDP_GetDiRecord(1, &device_info, &db);
436
437 ASSERT_STREQ(text, device_info.rec.client_executable_url);
438
439 // service description could not be found
440 ASSERT_EQ(strlen(device_info.rec.service_description), (size_t)0);
441
442 // with a wrong attr type, the attr value won't be accepted
443 ASSERT_EQ(strlen(device_info.rec.documentation_url), (size_t)0);
444
445 // none of the following values got setup
446 ASSERT_EQ(device_info.spec_id, 0);
447 ASSERT_EQ(device_info.rec.vendor, 0);
448 ASSERT_EQ(device_info.rec.vendor_id_source, 0);
449 ASSERT_EQ(device_info.rec.product, 0);
450 ASSERT_EQ(device_info.rec.version, 0);
451 ASSERT_FALSE(device_info.rec.primary_record);
452 }
453
TEST_F(StackSdpInitTest,sdpu_dump_all_ccb)454 TEST_F(StackSdpInitTest, sdpu_dump_all_ccb) {
455 uint16_t cid = L2CA_ConnectReqWithSecurity_cid;
456 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
457 .WillRepeatedly(Invoke([&cid](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
458 uint16_t /* sec_level */) -> uint16_t { return cid++; }));
459 sdpu_dump_all_ccb();
460
461 for (uint8_t i = 0; i < kSDP_MAX_CONNECTIONS; i++) {
462 RawAddress bd_addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, i});
463 ASSERT_NE(nullptr, sdp_conn_originate(bd_addr));
464 }
465 RawAddress bd_addr_fail = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0xff});
466 ASSERT_EQ(nullptr, sdp_conn_originate(bd_addr_fail));
467
468 sdpu_dump_all_ccb();
469 }
470
TEST_F(StackSdpInitTest,SDP_Dumpsys)471 TEST_F(StackSdpInitTest, SDP_Dumpsys) { SDP_Dumpsys(1); }
472
TEST_F(StackSdpInitTest,SDP_Dumpsys_ccb)473 TEST_F(StackSdpInitTest, SDP_Dumpsys_ccb) {
474 uint16_t cid = L2CA_ConnectReqWithSecurity_cid;
475 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
476 .WillRepeatedly(Invoke([&cid](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
477 uint16_t /* sec_level */) -> uint16_t { return cid++; }));
478
479 for (uint8_t i = 0; i < kSDP_MAX_CONNECTIONS; i++) {
480 RawAddress bd_addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, i});
481 ASSERT_NE(nullptr, sdp_conn_originate(bd_addr));
482 }
483 RawAddress bd_addr_fail = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0xff});
484 ASSERT_EQ(nullptr, sdp_conn_originate(bd_addr_fail));
485
486 SDP_Dumpsys(1);
487 }
488