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