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 
17 #include <gtest/gtest.h>
18 
19 #include "stack/include/sdp_api.h"
20 #include "stack/include/sdpdefs.h"
21 #include "stack/sdp/sdpint.h"
22 
23 namespace {
24 constexpr char service_name[] = "TestServiceName";
25 constexpr uint32_t kFirstRecordHandle = 0x10000;
26 }  // namespace
27 
28 using bluetooth::legacy::stack::sdp::get_legacy_stack_sdp_api;
29 
30 class StackSdpDbTest : public ::testing::Test {
31 protected:
SetUp()32   void SetUp() override {
33     // Ensure no records exist in global state
34     ASSERT_EQ((uint16_t)0, sdp_cb.server_db.num_records);
35   }
36 
TearDown()37   void TearDown() override {
38     // Ensure all records have been deleted from global state
39     ASSERT_EQ((uint16_t)0, sdp_cb.server_db.num_records);
40   }
41 };
42 
TEST_F(StackSdpDbTest,SDP_AddAttribute__create_record)43 TEST_F(StackSdpDbTest, SDP_AddAttribute__create_record) {
44   uint32_t record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
45 
46   ASSERT_NE((uint32_t)0, record_handle);
47   ASSERT_EQ((uint16_t)1, sdp_cb.server_db.num_records);
48 
49   tSDP_RECORD* record = sdp_db_find_record(record_handle);
50   ASSERT_TRUE(record != nullptr);
51 
52   // The sdp handle is always the first attribute
53   ASSERT_EQ((uint16_t)1, record->num_attributes);
54   ASSERT_EQ(kFirstRecordHandle, record->record_handle);
55   ASSERT_EQ(sizeof(uint32_t), record->free_pad_ptr);
56 
57   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
58 }
59 
TEST_F(StackSdpDbTest,SDP_AddAttribute__add_service_name)60 TEST_F(StackSdpDbTest, SDP_AddAttribute__add_service_name) {
61   uint32_t record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
62 
63   ASSERT_NE((uint32_t)0, record_handle);
64   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
65           record_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
66           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
67 
68   tSDP_RECORD* record = sdp_db_find_record(record_handle);
69   ASSERT_TRUE(record != nullptr);
70 
71   // The sdp handle is always the first attribute
72   ASSERT_EQ((uint16_t)(1 /* record_handle */ + 1 /* service name */), record->num_attributes);
73   ASSERT_EQ(kFirstRecordHandle, record->record_handle);
74   ASSERT_EQ(sizeof(uint32_t) + strlen(service_name) + 1, record->free_pad_ptr);
75 
76   const tSDP_ATTRIBUTE* attribute =
77           sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME, ATTR_ID_SERVICE_NAME);
78   ASSERT_TRUE(attribute != nullptr);
79 
80   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
81 }
82 
TEST_F(StackSdpDbTest,SDP_AddAttribute__three_attributes)83 TEST_F(StackSdpDbTest, SDP_AddAttribute__three_attributes) {
84   uint32_t record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
85 
86   ASSERT_NE((uint32_t)0, record_handle);
87 
88   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
89           record_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
90           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
91   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
92           record_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
93           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
94   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
95           record_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
96           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
97 
98   tSDP_RECORD* record = sdp_db_find_record(record_handle);
99   ASSERT_TRUE(record != nullptr);
100 
101   // The sdp handle is always the first attribute
102   ASSERT_EQ((uint16_t)(1 /* record_handle */ + 3 /* service name */), record->num_attributes);
103   ASSERT_EQ(kFirstRecordHandle, record->record_handle);
104   ASSERT_EQ(sizeof(uint32_t) + (3 * (strlen(service_name) + 1)), record->free_pad_ptr);
105 
106   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME, ATTR_ID_SERVICE_NAME) !=
107               nullptr);
108   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_DESCRIPTION,
109                                       ATTR_ID_SERVICE_DESCRIPTION) != nullptr);
110   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_PROVIDER_NAME, ATTR_ID_PROVIDER_NAME) !=
111               nullptr);
112 
113   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
114 }
115 
TEST_F(StackSdpDbTest,SDP_AddAttribute__too_many_attributes)116 TEST_F(StackSdpDbTest, SDP_AddAttribute__too_many_attributes) {
117   uint32_t record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
118   ASSERT_NE((uint32_t)0, record_handle);
119 
120   uint8_t boolean = 1;
121   for (size_t i = 0; i < SDP_MAX_REC_ATTR; i++) {
122     ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
123             record_handle, (uint16_t)i, BOOLEAN_DESC_TYPE, boolean, &boolean));
124   }
125 
126   ASSERT_FALSE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
127           record_handle, SDP_MAX_REC_ATTR + 1, BOOLEAN_DESC_TYPE, boolean, &boolean));
128   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
129 }
130 
TEST_F(StackSdpDbTest,SDP_AddAttribute__three_attributes_replace_middle)131 TEST_F(StackSdpDbTest, SDP_AddAttribute__three_attributes_replace_middle) {
132   uint32_t record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
133 
134   ASSERT_NE((uint32_t)0, record_handle);
135 
136   // Add 3 attributes to this record handle
137   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
138           record_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
139           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
140   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
141           record_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
142           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
143   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
144           record_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
145           (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
146 
147   tSDP_RECORD* record = sdp_db_find_record(record_handle);
148   ASSERT_TRUE(record != nullptr);
149 
150   // The sdp handle is always the first attribute
151   ASSERT_EQ((uint16_t)(1 /* record_handle */ + 3 /* attribute count */), record->num_attributes);
152   ASSERT_EQ(kFirstRecordHandle, record->record_handle);
153   ASSERT_EQ(sizeof(uint32_t) + (3 * (strlen(service_name) + 1)), record->free_pad_ptr);
154 
155   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME, ATTR_ID_SERVICE_NAME) !=
156               nullptr);
157   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_DESCRIPTION,
158                                       ATTR_ID_SERVICE_DESCRIPTION) != nullptr);
159   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_PROVIDER_NAME, ATTR_ID_PROVIDER_NAME) !=
160               nullptr);
161 
162   // Attempt to replace the middle attribute with an invalid attribute
163   ASSERT_FALSE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
164           record_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE, (uint32_t)0,
165           (uint8_t*)nullptr));
166 
167   // Ensure database is still intact.
168   ASSERT_EQ((uint16_t)(1 /* record_handle */ + 3 /* attribute count */), record->num_attributes);
169   ASSERT_EQ(kFirstRecordHandle, record->record_handle);
170   ASSERT_EQ(sizeof(uint32_t) + (3 * (strlen(service_name) + 1)), record->free_pad_ptr);
171 
172   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME, ATTR_ID_SERVICE_NAME) !=
173               nullptr);
174   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_DESCRIPTION,
175                                       ATTR_ID_SERVICE_DESCRIPTION) != nullptr);
176   ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_PROVIDER_NAME, ATTR_ID_PROVIDER_NAME) !=
177               nullptr);
178 
179   ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
180 }
181