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 =
45 get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
46
47 ASSERT_NE((uint32_t)0, record_handle);
48 ASSERT_EQ((uint16_t)1, sdp_cb.server_db.num_records);
49
50 tSDP_RECORD* record = sdp_db_find_record(record_handle);
51 ASSERT_TRUE(record != nullptr);
52
53 // The sdp handle is always the first attribute
54 ASSERT_EQ((uint16_t)1, record->num_attributes);
55 ASSERT_EQ(kFirstRecordHandle, record->record_handle);
56 ASSERT_EQ(sizeof(uint32_t), record->free_pad_ptr);
57
58 ASSERT_TRUE(
59 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
60 }
61
TEST_F(StackSdpDbTest,SDP_AddAttribute__add_service_name)62 TEST_F(StackSdpDbTest, SDP_AddAttribute__add_service_name) {
63 uint32_t record_handle =
64 get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
65
66 ASSERT_NE((uint32_t)0, record_handle);
67 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
68 record_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
69 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
70
71 tSDP_RECORD* record = sdp_db_find_record(record_handle);
72 ASSERT_TRUE(record != nullptr);
73
74 // The sdp handle is always the first attribute
75 ASSERT_EQ((uint16_t)(1 /* record_handle */ + 1 /* service name */),
76 record->num_attributes);
77 ASSERT_EQ(kFirstRecordHandle, record->record_handle);
78 ASSERT_EQ(sizeof(uint32_t) + strlen(service_name) + 1, record->free_pad_ptr);
79
80 const tSDP_ATTRIBUTE* attribute = sdp_db_find_attr_in_rec(
81 record, ATTR_ID_SERVICE_NAME, ATTR_ID_SERVICE_NAME);
82 ASSERT_TRUE(attribute != nullptr);
83
84 ASSERT_TRUE(
85 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
86 }
87
TEST_F(StackSdpDbTest,SDP_AddAttribute__three_attributes)88 TEST_F(StackSdpDbTest, SDP_AddAttribute__three_attributes) {
89 uint32_t record_handle =
90 get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
91
92 ASSERT_NE((uint32_t)0, record_handle);
93
94 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
95 record_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
96 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
97 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
98 record_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
99 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
100 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
101 record_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
102 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
103
104 tSDP_RECORD* record = sdp_db_find_record(record_handle);
105 ASSERT_TRUE(record != nullptr);
106
107 // The sdp handle is always the first attribute
108 ASSERT_EQ((uint16_t)(1 /* record_handle */ + 3 /* service name */),
109 record->num_attributes);
110 ASSERT_EQ(kFirstRecordHandle, record->record_handle);
111 ASSERT_EQ(sizeof(uint32_t) + (3 * (strlen(service_name) + 1)),
112 record->free_pad_ptr);
113
114 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME,
115 ATTR_ID_SERVICE_NAME) != nullptr);
116 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_DESCRIPTION,
117 ATTR_ID_SERVICE_DESCRIPTION) != nullptr);
118 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_PROVIDER_NAME,
119 ATTR_ID_PROVIDER_NAME) != nullptr);
120
121 ASSERT_TRUE(
122 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
123 }
124
TEST_F(StackSdpDbTest,SDP_AddAttribute__too_many_attributes)125 TEST_F(StackSdpDbTest, SDP_AddAttribute__too_many_attributes) {
126 uint32_t record_handle =
127 get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
128 ASSERT_NE((uint32_t)0, record_handle);
129
130 uint8_t boolean = 1;
131 for (size_t i = 0; i < SDP_MAX_REC_ATTR; i++) {
132 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
133 record_handle, (uint16_t)i, BOOLEAN_DESC_TYPE, boolean, &boolean));
134 }
135
136 ASSERT_FALSE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
137 record_handle, SDP_MAX_REC_ATTR + 1, BOOLEAN_DESC_TYPE, boolean,
138 &boolean));
139 ASSERT_TRUE(
140 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
141 }
142
TEST_F(StackSdpDbTest,SDP_AddAttribute__three_attributes_replace_middle)143 TEST_F(StackSdpDbTest, SDP_AddAttribute__three_attributes_replace_middle) {
144 uint32_t record_handle =
145 get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
146
147 ASSERT_NE((uint32_t)0, record_handle);
148
149 // Add 3 attributes to this record handle
150 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
151 record_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
152 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
153 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
154 record_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
155 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
156 ASSERT_TRUE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
157 record_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
158 (uint32_t)(strlen(service_name) + 1), (uint8_t*)service_name));
159
160 tSDP_RECORD* record = sdp_db_find_record(record_handle);
161 ASSERT_TRUE(record != nullptr);
162
163 // The sdp handle is always the first attribute
164 ASSERT_EQ((uint16_t)(1 /* record_handle */ + 3 /* attribute count */),
165 record->num_attributes);
166 ASSERT_EQ(kFirstRecordHandle, record->record_handle);
167 ASSERT_EQ(sizeof(uint32_t) + (3 * (strlen(service_name) + 1)),
168 record->free_pad_ptr);
169
170 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME,
171 ATTR_ID_SERVICE_NAME) != nullptr);
172 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_DESCRIPTION,
173 ATTR_ID_SERVICE_DESCRIPTION) != nullptr);
174 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_PROVIDER_NAME,
175 ATTR_ID_PROVIDER_NAME) != nullptr);
176
177 // Attempt to replace the middle attribute with an invalid attribute
178 ASSERT_FALSE(get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
179 record_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
180 (uint32_t)0, (uint8_t*)nullptr));
181
182 // Ensure database is still intact.
183 ASSERT_EQ((uint16_t)(1 /* record_handle */ + 3 /* attribute count */),
184 record->num_attributes);
185 ASSERT_EQ(kFirstRecordHandle, record->record_handle);
186 ASSERT_EQ(sizeof(uint32_t) + (3 * (strlen(service_name) + 1)),
187 record->free_pad_ptr);
188
189 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_NAME,
190 ATTR_ID_SERVICE_NAME) != nullptr);
191 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_SERVICE_DESCRIPTION,
192 ATTR_ID_SERVICE_DESCRIPTION) != nullptr);
193 ASSERT_TRUE(sdp_db_find_attr_in_rec(record, ATTR_ID_PROVIDER_NAME,
194 ATTR_ID_PROVIDER_NAME) != nullptr);
195
196 ASSERT_TRUE(
197 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(record_handle));
198 }
199