1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/att/attribute.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
18 #include "pw_unit_test/framework.h"
19
20 namespace bt::att {
21 namespace {
22
23 constexpr PeerId kTestPeerId(1);
24 constexpr Handle kTestHandle = 0x0001;
25 constexpr UUID kTestType1(uint16_t{0x0001});
26 constexpr UUID kTestType2(uint16_t{0x0002});
27 constexpr UUID kTestType3(uint16_t{0x0003});
28 constexpr UUID kTestType4(uint16_t{0x0004});
29
30 const StaticByteBuffer kTestValue('t', 'e', 's', 't');
31
TEST(AttributeDeathTest,OverflowingMaxHandleOnAttributeGroupDies)32 TEST(AttributeDeathTest, OverflowingMaxHandleOnAttributeGroupDies) {
33 ASSERT_DEATH_IF_SUPPORTED(
34 {
35 AttributeGrouping A(kTestType1, kHandleMax - 1, size_t{2}, kTestValue);
36 },
37 ".*attr_count.*");
38 }
39
TEST(AttributeTest,AccessRequirementsDefault)40 TEST(AttributeTest, AccessRequirementsDefault) {
41 AccessRequirements reqs;
42 EXPECT_FALSE(reqs.allowed());
43 EXPECT_FALSE(reqs.encryption_required());
44 EXPECT_FALSE(reqs.authentication_required());
45 EXPECT_FALSE(reqs.authorization_required());
46 }
47
TEST(AttributeTest,AccessRequirements)48 TEST(AttributeTest, AccessRequirements) {
49 AccessRequirements reqs0(
50 /*encryption=*/true, /*authentication=*/false, /*authorization=*/false);
51 EXPECT_TRUE(reqs0.allowed());
52 EXPECT_TRUE(reqs0.encryption_required());
53 EXPECT_FALSE(reqs0.authentication_required());
54 EXPECT_FALSE(reqs0.authorization_required());
55 EXPECT_EQ(reqs0.min_enc_key_size(), sm::kMaxEncryptionKeySize);
56
57 AccessRequirements reqs1(/*encryption=*/true,
58 /*authentication=*/false,
59 /*authorization=*/false,
60 8);
61 EXPECT_TRUE(reqs1.allowed());
62 EXPECT_TRUE(reqs1.encryption_required());
63 EXPECT_FALSE(reqs1.authentication_required());
64 EXPECT_FALSE(reqs1.authorization_required());
65 EXPECT_EQ(reqs1.min_enc_key_size(), 8u);
66
67 AccessRequirements reqs2(
68 /*encryption=*/false, /*authentication=*/true, /*authorization=*/false);
69 EXPECT_TRUE(reqs2.allowed());
70 EXPECT_FALSE(reqs2.encryption_required());
71 EXPECT_TRUE(reqs2.authentication_required());
72 EXPECT_FALSE(reqs2.authorization_required());
73
74 AccessRequirements reqs3(
75 /*encryption=*/false, /*authentication=*/false, /*authorization=*/true);
76 EXPECT_TRUE(reqs3.allowed());
77 EXPECT_FALSE(reqs3.encryption_required());
78 EXPECT_FALSE(reqs3.authentication_required());
79 EXPECT_TRUE(reqs3.authorization_required());
80
81 AccessRequirements reqs4(
82 /*encryption=*/false, /*authentication=*/false, /*authorization=*/false);
83 EXPECT_TRUE(reqs4.allowed());
84 EXPECT_FALSE(reqs4.encryption_required());
85 EXPECT_FALSE(reqs4.authentication_required());
86 EXPECT_FALSE(reqs4.authorization_required());
87 }
88
TEST(AttributeTest,GroupingDeclAttr)89 TEST(AttributeTest, GroupingDeclAttr) {
90 constexpr size_t kAttrCount = 0u;
91
92 AttributeGrouping group(kTestType1, kTestHandle, kAttrCount, kTestValue);
93
94 // The grouping consists of just the group declaration and is thus complete.
95 EXPECT_TRUE(group.complete());
96 EXPECT_EQ(kTestType1, group.group_type());
97 EXPECT_EQ(kTestHandle, group.start_handle());
98 EXPECT_EQ(kTestHandle, group.end_handle());
99 EXPECT_EQ(1u, group.attributes().size());
100
101 // The grouping is already complete.
102 EXPECT_FALSE(group.AddAttribute(
103 kTestType2, AccessRequirements(), AccessRequirements()));
104
105 const Attribute& decl_attr = group.attributes()[0];
106 EXPECT_EQ(kTestHandle, decl_attr.handle());
107 EXPECT_EQ(kTestType1, decl_attr.type());
108 ASSERT_TRUE(decl_attr.value());
109 EXPECT_TRUE(ContainersEqual(kTestValue, *decl_attr.value()));
110 EXPECT_TRUE(decl_attr.read_reqs().allowed());
111 EXPECT_FALSE(decl_attr.read_reqs().encryption_required());
112 EXPECT_FALSE(decl_attr.read_reqs().authentication_required());
113 EXPECT_FALSE(decl_attr.read_reqs().authorization_required());
114 EXPECT_FALSE(decl_attr.write_reqs().allowed());
115 EXPECT_EQ(&group, &decl_attr.group());
116 }
117
TEST(AttributeTest,GroupingAddAttribute)118 TEST(AttributeTest, GroupingAddAttribute) {
119 constexpr size_t kAttrCount = 2;
120
121 AttributeGrouping group(kTestType1, kTestHandle, kAttrCount, kTestValue);
122 EXPECT_FALSE(group.complete());
123 EXPECT_EQ(kTestHandle, group.start_handle());
124 EXPECT_EQ(kTestHandle + kAttrCount, group.end_handle());
125
126 Attribute* attr = group.AddAttribute(
127 kTestType2, AccessRequirements(), AccessRequirements());
128 ASSERT_TRUE(attr);
129 EXPECT_EQ(kTestType2, attr->type());
130 EXPECT_EQ(kTestHandle + 1, attr->handle());
131 EXPECT_EQ(&group, &attr->group());
132
133 // The attribute should have no value until assigned.
134 EXPECT_FALSE(attr->value());
135 attr->SetValue(kTestValue);
136 ASSERT_TRUE(attr->value());
137 EXPECT_TRUE(ContainersEqual(kTestValue, *attr->value()));
138
139 // The group is not complete until |kAttrCount| attributes have been added.
140 EXPECT_FALSE(group.complete());
141 EXPECT_EQ(2u, group.attributes().size());
142
143 attr = group.AddAttribute(
144 kTestType3, AccessRequirements(), AccessRequirements());
145 ASSERT_TRUE(attr);
146 EXPECT_EQ(kTestType3, attr->type());
147
148 EXPECT_TRUE(group.complete());
149 EXPECT_EQ(group.end_handle(), attr->handle());
150 EXPECT_EQ(3u, group.attributes().size());
151
152 EXPECT_FALSE(group.AddAttribute(
153 kTestType4, AccessRequirements(), AccessRequirements()));
154 }
155
TEST(AttributeTest,ReadAsyncReadNotAllowed)156 TEST(AttributeTest, ReadAsyncReadNotAllowed) {
157 AttributeGrouping group(kTestType1, kTestHandle, 1, kTestValue);
158 Attribute* attr = group.AddAttribute(
159 kTestType2, AccessRequirements(), AccessRequirements());
160 EXPECT_FALSE(attr->ReadAsync(kTestPeerId, 0, [](auto, const auto&) {}));
161 }
162
TEST(AttributeTest,ReadAsyncReadNoHandler)163 TEST(AttributeTest, ReadAsyncReadNoHandler) {
164 AttributeGrouping group(kTestType1, kTestHandle, 1, kTestValue);
165 Attribute* attr = group.AddAttribute(
166 kTestType2,
167 AccessRequirements(/*encryption=*/false,
168 /*authentication=*/false,
169 /*authorization=*/false), // read (no security)
170 AccessRequirements()); // write not allowed
171 EXPECT_FALSE(attr->ReadAsync(kTestPeerId, 0, [](auto, const auto&) {}));
172 }
173
TEST(AttributeTest,ReadAsync)174 TEST(AttributeTest, ReadAsync) {
175 constexpr uint16_t kTestOffset = 5;
176
177 AttributeGrouping group(kTestType1, kTestHandle, 1, kTestValue);
178 Attribute* attr = group.AddAttribute(
179 kTestType2,
180 AccessRequirements(/*encryption=*/false,
181 /*authentication=*/false,
182 /*authorization=*/false), // read (no security)
183 AccessRequirements()); // write not allowed
184
185 bool callback_called = false;
186 auto callback = [&](fit::result<ErrorCode> status, const auto& value) {
187 EXPECT_EQ(fit::ok(), status);
188 EXPECT_TRUE(ContainersEqual(StaticByteBuffer('h', 'i'), value));
189 callback_called = true;
190 };
191
192 auto handler =
193 [&](PeerId peer_id, Handle handle, uint16_t offset, auto result_cb) {
194 EXPECT_EQ(kTestPeerId, peer_id);
195 EXPECT_EQ(attr->handle(), handle);
196 EXPECT_EQ(kTestOffset, offset);
197 EXPECT_TRUE(result_cb);
198
199 result_cb(fit::ok(), StaticByteBuffer('h', 'i'));
200 };
201
202 attr->set_read_handler(handler);
203 EXPECT_TRUE(attr->ReadAsync(kTestPeerId, kTestOffset, callback));
204 EXPECT_TRUE(callback_called);
205 }
206
TEST(AttributeTest,WriteAsyncWriteNotAllowed)207 TEST(AttributeTest, WriteAsyncWriteNotAllowed) {
208 AttributeGrouping group(kTestType1, kTestHandle, 1, kTestValue);
209 Attribute* attr = group.AddAttribute(
210 kTestType2, AccessRequirements(), AccessRequirements());
211 EXPECT_FALSE(attr->WriteAsync(kTestPeerId, 0, BufferView(), [](auto) {}));
212 }
213
TEST(AttributeTest,WriteAsyncWriteNoHandler)214 TEST(AttributeTest, WriteAsyncWriteNoHandler) {
215 AttributeGrouping group(kTestType1, kTestHandle, 1, kTestValue);
216 Attribute* attr = group.AddAttribute(
217 kTestType2,
218 AccessRequirements(), // read not allowed
219 AccessRequirements(/*encryption=*/false,
220 /*authentication=*/false,
221 /*authorization=*/false)); // write no security
222 EXPECT_FALSE(attr->WriteAsync(kTestPeerId, 0, BufferView(), [](auto) {}));
223 }
224
TEST(AttributeTest,WriteAsync)225 TEST(AttributeTest, WriteAsync) {
226 constexpr uint16_t kTestOffset = 5;
227
228 AttributeGrouping group(kTestType1, kTestHandle, 1, kTestValue);
229 Attribute* attr = group.AddAttribute(
230 kTestType2,
231 AccessRequirements(), // read not allowed
232 AccessRequirements(/*encryption=*/false,
233 /*authentication=*/false,
234 /*authorization=*/false)); // write no security
235
236 bool callback_called = false;
237 auto callback = [&](fit::result<ErrorCode> status) {
238 EXPECT_EQ(fit::ok(), status);
239 callback_called = true;
240 };
241
242 auto handler = [&](PeerId peer_id,
243 Handle handle,
244 uint16_t offset,
245 const auto& value,
246 auto result_cb) {
247 EXPECT_EQ(kTestPeerId, peer_id);
248 EXPECT_EQ(attr->handle(), handle);
249 EXPECT_EQ(kTestOffset, offset);
250 EXPECT_TRUE(ContainersEqual(StaticByteBuffer('h', 'i'), value));
251 EXPECT_TRUE(result_cb);
252
253 result_cb(fit::ok());
254 };
255
256 attr->set_write_handler(handler);
257 EXPECT_TRUE(attr->WriteAsync(
258 kTestPeerId, kTestOffset, StaticByteBuffer('h', 'i'), callback));
259 EXPECT_TRUE(callback_called);
260 }
261
262 } // namespace
263 } // namespace bt::att
264