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/database.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
18 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
19 #include "pw_unit_test/framework.h"
20
21 namespace bt::att {
22 namespace {
23
24 constexpr Handle kTestRangeStart = 1;
25 constexpr Handle kTestRangeEnd = 10;
26
27 constexpr UUID kTestType1(uint16_t{1});
28 constexpr UUID kTestType2(uint16_t{2});
29 constexpr UUID kTestType3(uint16_t{3});
30
31 const AccessRequirements kAllowed(/*encryption=*/false,
32 /*authentication=*/false,
33 /*authorization=*/false);
34 const sm::SecurityProperties kNoSecurity(sm::SecurityLevel::kNoSecurity,
35 16,
36 /*secure_connections=*/false);
37
38 // Values with different lengths
39 const StaticByteBuffer kTestValue1('x', 'x');
40 const StaticByteBuffer kTestValue2('x', 'x', 'x');
41
42 // Returns the handles of each attribute visited by advancing |iter| until the
43 // end.
IterHandles(Database::Iterator * iter)44 std::vector<Handle> IterHandles(Database::Iterator* iter) {
45 PW_DCHECK(iter);
46
47 std::vector<Handle> handles;
48 for (; !iter->AtEnd(); iter->Advance()) {
49 handles.push_back(iter->get()->handle());
50 }
51 return handles;
52 }
53
TEST(DatabaseTest,NewGroupingWhileEmptyError)54 TEST(DatabaseTest, NewGroupingWhileEmptyError) {
55 constexpr size_t kTooLarge = kTestRangeEnd - kTestRangeStart + 1;
56 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
57 EXPECT_FALSE(db->NewGrouping(kTestType1, kTooLarge, kTestValue1));
58 }
59
TEST(DatabaseTest,NewGroupingWhileEmptyFill)60 TEST(DatabaseTest, NewGroupingWhileEmptyFill) {
61 constexpr size_t kExact = kTestRangeEnd - kTestRangeStart;
62
63 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
64 auto* grp = db->NewGrouping(kTestType1, kExact, kTestValue1);
65 ASSERT_TRUE(grp);
66 EXPECT_EQ(kTestType1, grp->group_type());
67 EXPECT_EQ(kTestRangeStart, grp->start_handle());
68 EXPECT_EQ(kTestRangeEnd, grp->end_handle());
69
70 // Ran out of space.
71 EXPECT_FALSE(db->NewGrouping(kTestType1, 0, kTestValue1));
72 }
73
74 // This test case performs multiple insertions and removals on the same
75 // database.
TEST(DatabaseTest,NewGroupingMultipleInsertions)76 TEST(DatabaseTest, NewGroupingMultipleInsertions) {
77 // [__________]
78 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
79
80 // Insert to empty db
81 // [XXX_______] (insert X)
82 auto* grp = db->NewGrouping(kTestType1, 2, kTestValue1);
83 ASSERT_TRUE(grp);
84 EXPECT_EQ(1, grp->start_handle());
85 EXPECT_EQ(3, grp->end_handle());
86
87 // Not enough space
88 grp = db->NewGrouping(kTestType1, 7, kTestValue1);
89 EXPECT_FALSE(grp);
90
91 // Insert back
92 // [XXXYYYYY__] (insert Y)
93 grp = db->NewGrouping(kTestType1, 4, kTestValue1);
94 ASSERT_TRUE(grp);
95 EXPECT_EQ(4, grp->start_handle());
96 EXPECT_EQ(8, grp->end_handle());
97
98 // Not enough space
99 grp = db->NewGrouping(kTestType1, 2, kTestValue1);
100 EXPECT_FALSE(grp);
101
102 // Insert back
103 // [XXXYYYYYZZ] (insert Z)
104 grp = db->NewGrouping(kTestType1, 1, kTestValue1);
105 ASSERT_TRUE(grp);
106 EXPECT_EQ(9, grp->start_handle());
107 EXPECT_EQ(10, grp->end_handle());
108
109 // Out of space
110 EXPECT_FALSE(db->NewGrouping(kTestType1, 0, kTestValue1));
111
112 // Remove first grouping. It should be possible to reinsert a smaller group.
113 // [___YYYYYZZ]
114 EXPECT_TRUE(db->RemoveGrouping(1));
115
116 // Not enough space
117 grp = db->NewGrouping(kTestType1, 3, kTestValue1);
118 EXPECT_FALSE(grp);
119
120 // Insert front
121 // [XX_YYYYYZZ] (insert X)
122 grp = db->NewGrouping(kTestType1, 1, kTestValue1);
123 ASSERT_TRUE(grp);
124 EXPECT_EQ(1, grp->start_handle());
125 EXPECT_EQ(2, grp->end_handle());
126
127 // Handle doesn't exist.
128 EXPECT_FALSE(db->RemoveGrouping(3));
129
130 // Insert in the middle
131 // [XXWYYYYYZZ] (insert W)
132 grp = db->NewGrouping(kTestType1, 0, kTestValue1);
133 ASSERT_TRUE(grp);
134 EXPECT_EQ(3, grp->start_handle());
135 EXPECT_EQ(3, grp->end_handle());
136
137 // [XXW_____ZZ] (remove Y)
138 EXPECT_TRUE(db->RemoveGrouping(4));
139
140 // Insert in the middle
141 // [XXWAAA__ZZ] (insert A)
142 grp = db->NewGrouping(kTestType1, 2, kTestValue1);
143 ASSERT_TRUE(grp);
144 EXPECT_EQ(4, grp->start_handle());
145 EXPECT_EQ(6, grp->end_handle());
146
147 // Insert in the middle
148 // [XXWAAABBZZ] (insert B)
149 grp = db->NewGrouping(kTestType1, 1, kTestValue1);
150 ASSERT_TRUE(grp);
151 EXPECT_EQ(7, grp->start_handle());
152 EXPECT_EQ(8, grp->end_handle());
153
154 // Out of space
155 EXPECT_FALSE(db->NewGrouping(kTestType1, 0, kTestValue1));
156 }
157
TEST(DatabaseTest,RemoveWhileEmpty)158 TEST(DatabaseTest, RemoveWhileEmpty) {
159 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
160 EXPECT_FALSE(db->RemoveGrouping(kTestRangeStart));
161 }
162
TEST(DatabaseTest,FindAttributeInvalidHandle)163 TEST(DatabaseTest, FindAttributeInvalidHandle) {
164 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
165 EXPECT_EQ(nullptr, db->FindAttribute(kInvalidHandle));
166 }
167
TEST(DatabaseTest,FindAttributeGroupingNotFound)168 TEST(DatabaseTest, FindAttributeGroupingNotFound) {
169 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
170
171 // Create the following layout:
172 //
173 // handle 0x0001: occupied
174 // handle 0x0002: empty
175 // handle 0x0003: occupied
176 db->NewGrouping(kTestType1, 0, kTestValue1)->set_active(true);
177 auto* grp = db->NewGrouping(kTestType1, 0, kTestValue1);
178 grp->set_active(true);
179 db->NewGrouping(kTestType1, 0, kTestValue1)->set_active(true);
180 db->RemoveGrouping(grp->start_handle());
181
182 EXPECT_EQ(nullptr, db->FindAttribute(0xFFFF));
183 EXPECT_EQ(nullptr, db->FindAttribute(0x0002));
184 EXPECT_NE(nullptr, db->FindAttribute(0x0001));
185 EXPECT_NE(nullptr, db->FindAttribute(0x0003));
186 }
187
TEST(DatabaseTest,FindAttributeIncompleteGrouping)188 TEST(DatabaseTest, FindAttributeIncompleteGrouping) {
189 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
190 auto* grp = db->NewGrouping(kTestType1, 1, kTestValue1);
191 EXPECT_EQ(nullptr, db->FindAttribute(grp->start_handle()));
192 }
193
TEST(DatabaseTest,FindAttributeInactiveGrouping)194 TEST(DatabaseTest, FindAttributeInactiveGrouping) {
195 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
196 auto* grp = db->NewGrouping(kTestType1, 0, kTestValue1);
197 EXPECT_EQ(nullptr, db->FindAttribute(grp->start_handle()));
198 }
199
TEST(DatabaseTest,FindAttributeOnePerGrouping)200 TEST(DatabaseTest, FindAttributeOnePerGrouping) {
201 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
202 auto* grp1 = db->NewGrouping(kTestType1, 0, kTestValue1);
203 grp1->set_active(true);
204 auto* grp2 = db->NewGrouping(kTestType1, 0, kTestValue1);
205 grp2->set_active(true);
206
207 EXPECT_EQ(&grp1->attributes()[0], db->FindAttribute(grp1->start_handle()));
208 EXPECT_EQ(&grp2->attributes()[0], db->FindAttribute(grp2->start_handle()));
209 }
210
TEST(DatabaseTest,FindAttributeIndexIntoGrouping)211 TEST(DatabaseTest, FindAttributeIndexIntoGrouping) {
212 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
213
214 auto* grp = db->NewGrouping(kTestType1, 1, kTestValue1);
215 auto* attr =
216 grp->AddAttribute(kTestType2, AccessRequirements(), AccessRequirements());
217 grp->set_active(true);
218
219 EXPECT_EQ(attr, db->FindAttribute(grp->end_handle()));
220 }
221
TEST(DatabaseTest,IteratorEmpty)222 TEST(DatabaseTest, IteratorEmpty) {
223 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
224 auto iter = db->GetIterator(kTestRangeStart, kTestRangeEnd);
225 EXPECT_TRUE(iter.AtEnd());
226 EXPECT_FALSE(iter.get());
227
228 // Advance should have no effect.
229 iter.Advance();
230 EXPECT_TRUE(iter.AtEnd());
231 }
232
TEST(DatabaseTest,IteratorGroupOnlySingleInactive)233 TEST(DatabaseTest, IteratorGroupOnlySingleInactive) {
234 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
235 db->NewGrouping(kTestType1, 0, kTestValue1);
236
237 // |grp| is not active
238 auto iter = db->GetIterator(
239 kTestRangeStart, kTestRangeEnd, /*type=*/nullptr, /*groups_only=*/true);
240 EXPECT_TRUE(iter.AtEnd());
241 EXPECT_FALSE(iter.get());
242 }
243
TEST(DatabaseTest,IteratorGroupOnlySingle)244 TEST(DatabaseTest, IteratorGroupOnlySingle) {
245 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
246 auto grp = db->NewGrouping(kTestType1, 0, kTestValue1);
247 grp->set_active(true);
248
249 // Not within range.
250 auto iter = db->GetIterator(grp->start_handle() + 1,
251 kTestRangeEnd,
252 /*type=*/nullptr,
253 /*groups_only=*/true);
254 EXPECT_TRUE(iter.AtEnd());
255 EXPECT_FALSE(iter.get());
256
257 iter = db->GetIterator(
258 kTestRangeStart, kTestRangeEnd, /*type=*/nullptr, /*groups_only=*/true);
259 EXPECT_FALSE(iter.AtEnd());
260
261 auto handles = IterHandles(&iter);
262 ASSERT_EQ(1u, handles.size());
263 EXPECT_EQ(grp->start_handle(), handles[0]);
264 }
265
TEST(DatabaseTest,IteratorGroupOnlyMultiple)266 TEST(DatabaseTest, IteratorGroupOnlyMultiple) {
267 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
268 auto grp1 = db->NewGrouping(kTestType1, 0, kTestValue1);
269 auto grp2 = db->NewGrouping(kTestType1, 0, kTestValue1);
270 auto grp3 = db->NewGrouping(kTestType1, 0, kTestValue1);
271 auto grp4 = db->NewGrouping(kTestType1, 0, kTestValue1);
272
273 // Leave |grp2| as inactive.
274 grp1->set_active(true);
275 grp3->set_active(true);
276 grp4->set_active(true);
277
278 auto iter = db->GetIterator(
279 kTestRangeStart, kTestRangeEnd, /*type=*/nullptr, /*groups_only=*/true);
280 EXPECT_FALSE(iter.AtEnd());
281
282 // |grp2| should be omitted.
283 auto handles = IterHandles(&iter);
284 ASSERT_EQ(3u, handles.size());
285 EXPECT_EQ(grp1->start_handle(), handles[0]);
286 EXPECT_EQ(grp3->start_handle(), handles[1]);
287 EXPECT_EQ(grp4->start_handle(), handles[2]);
288
289 grp2->set_active(true);
290
291 // Pick a narrow range that excludes |grp1| and |grp4|.
292 iter = db->GetIterator(grp2->start_handle(),
293 grp3->end_handle(),
294 /*type=*/nullptr,
295 /*groups_only=*/true);
296 handles = IterHandles(&iter);
297 ASSERT_EQ(2u, handles.size());
298 EXPECT_EQ(grp2->start_handle(), handles[0]);
299 EXPECT_EQ(grp3->start_handle(), handles[1]);
300 }
301
TEST(DatabaseTest,IteratorGroupOnlySingleWithFilter)302 TEST(DatabaseTest, IteratorGroupOnlySingleWithFilter) {
303 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
304
305 auto grp = db->NewGrouping(kTestType1, 0, kTestValue1);
306 grp->set_active(true);
307
308 // No match.
309 auto iter = db->GetIterator(
310 kTestRangeStart, kTestRangeEnd, &kTestType2, /*groups_only=*/true);
311 EXPECT_TRUE(iter.AtEnd());
312
313 iter = db->GetIterator(
314 kTestRangeStart, kTestRangeEnd, &kTestType1, /*groups_only=*/true);
315 EXPECT_FALSE(iter.AtEnd());
316
317 auto handles = IterHandles(&iter);
318 ASSERT_EQ(1u, handles.size());
319 EXPECT_EQ(grp->start_handle(), handles[0]);
320 }
321
TEST(DatabaseTest,IteratorGroupOnlyManyWithFilter)322 TEST(DatabaseTest, IteratorGroupOnlyManyWithFilter) {
323 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
324
325 auto grp1 = db->NewGrouping(kTestType1, 1, kTestValue1); // match
326 grp1->AddAttribute(kTestType1); // match but skipped - not group decl.
327 grp1->set_active(true);
328
329 // Matching but inactive.
330 db->NewGrouping(kTestType1, 0, kTestValue1);
331
332 auto grp2 = db->NewGrouping(kTestType2, 0, kTestValue1);
333 grp2->set_active(true);
334 auto grp3 = db->NewGrouping(kTestType1, 0, kTestValue1);
335 grp3->set_active(true);
336 auto grp4 = db->NewGrouping(kTestType2, 0, kTestValue1);
337 grp4->set_active(true);
338 auto grp5 = db->NewGrouping(kTestType2, 0, kTestValue1);
339 grp5->set_active(true);
340 auto grp6 = db->NewGrouping(kTestType1, 0, kTestValue1);
341 grp6->set_active(true);
342
343 // Filter by |kTestType1|
344 auto iter = db->GetIterator(
345 kTestRangeStart, kTestRangeEnd, &kTestType1, /*groups_only=*/true);
346 EXPECT_FALSE(iter.AtEnd());
347
348 auto handles = IterHandles(&iter);
349 ASSERT_EQ(3u, handles.size());
350 EXPECT_EQ(grp1->start_handle(), handles[0]);
351 EXPECT_EQ(grp3->start_handle(), handles[1]);
352 EXPECT_EQ(grp6->start_handle(), handles[2]);
353
354 // Filter by |kTestType2|
355 iter = db->GetIterator(
356 kTestRangeStart, kTestRangeEnd, &kTestType2, /*groups_only=*/true);
357 EXPECT_FALSE(iter.AtEnd());
358
359 handles = IterHandles(&iter);
360 ASSERT_EQ(3u, handles.size());
361 EXPECT_EQ(grp2->start_handle(), handles[0]);
362 EXPECT_EQ(grp4->start_handle(), handles[1]);
363 EXPECT_EQ(grp5->start_handle(), handles[2]);
364
365 // Search narrower range.
366 iter = db->GetIterator(grp1->end_handle(),
367 grp5->end_handle(),
368 &kTestType1,
369 /*groups_only=*/true);
370 EXPECT_FALSE(iter.AtEnd());
371
372 handles = IterHandles(&iter);
373 ASSERT_EQ(1u, handles.size());
374 EXPECT_EQ(grp3->start_handle(), handles[0]);
375 }
376
TEST(DatabaseTest,IteratorSingleInactive)377 TEST(DatabaseTest, IteratorSingleInactive) {
378 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
379 auto grp = db->NewGrouping(kTestType1, 1, kTestValue1);
380
381 auto iter = db->GetIterator(kTestRangeStart, kTestRangeEnd);
382 EXPECT_TRUE(iter.AtEnd());
383 EXPECT_FALSE(iter.get());
384
385 // Complete but still inactive.
386 grp->AddAttribute(kTestType1);
387 iter = db->GetIterator(kTestRangeStart, kTestRangeEnd);
388 EXPECT_TRUE(iter.AtEnd());
389 EXPECT_FALSE(iter.get());
390 }
391
TEST(DatabaseTest,IteratorSingle)392 TEST(DatabaseTest, IteratorSingle) {
393 auto db = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
394 auto grp = db->NewGrouping(kTestType1, 0, kTestValue1);
395 grp->set_active(true);
396
397 // Not within range.
398 auto iter = db->GetIterator(grp->start_handle() + 1, kTestRangeEnd);
399 EXPECT_TRUE(iter.AtEnd());
400 EXPECT_FALSE(iter.get());
401
402 iter = db->GetIterator(kTestRangeStart, kTestRangeEnd);
403 EXPECT_FALSE(iter.AtEnd());
404
405 auto handles = IterHandles(&iter);
406 ASSERT_EQ(1u, handles.size());
407 EXPECT_EQ(grp->start_handle(), handles[0]);
408 }
409
410 class DatabaseIteratorManyTest : public ::testing::Test {
411 public:
412 DatabaseIteratorManyTest() = default;
413 ~DatabaseIteratorManyTest() override = default;
414
415 protected:
416 static constexpr size_t kActiveAttrCount = 8;
417
SetUp()418 void SetUp() override {
419 db_ = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
420
421 auto grp1 = db()->NewGrouping(kTestType1, 3, kTestValue1); // 1
422 grp1->AddAttribute(kTestType2); // 2
423 grp1->AddAttribute(kTestType2); // 3
424 grp1->AddAttribute(kTestType1); // 4
425 grp1->set_active(true);
426
427 auto grp2 = db()->NewGrouping(kTestType2, 2, kTestValue1); // 5
428 grp2->AddAttribute(kTestType1); // 6
429 grp2->AddAttribute(kTestType2); // 7
430 grp2->set_active(true);
431
432 auto grp3 = db()->NewGrouping(kTestType1, 1, kTestValue1); // 8 (inactive)
433 grp3->AddAttribute(kTestType2); // 9 (inactive)
434
435 auto grp4 = db()->NewGrouping(kTestType1, 0, kTestValue1); // 10
436 grp4->set_active(true);
437 }
438
db() const439 Database::WeakPtr db() const { return db_->GetWeakPtr(); }
440
441 private:
442 std::unique_ptr<Database> db_;
443
444 BT_DISALLOW_COPY_ASSIGN_AND_MOVE(DatabaseIteratorManyTest);
445 };
446
TEST_F(DatabaseIteratorManyTest,NoFilter)447 TEST_F(DatabaseIteratorManyTest, NoFilter) {
448 auto iter = db()->GetIterator(kTestRangeStart, kTestRangeEnd);
449 EXPECT_FALSE(iter.AtEnd());
450
451 // Should cover all but the inactive attribute.
452 auto handles = IterHandles(&iter);
453
454 // All active attribute handles.
455 const std::array<Handle, kActiveAttrCount> kExpected = {
456 1, 2, 3, 4, 5, 6, 7, 10};
457 ASSERT_EQ(kExpected.size(), handles.size());
458
459 for (size_t i = 0; i < handles.size(); i++) {
460 EXPECT_EQ(kExpected[i], handles[i]);
461 }
462 }
463
TEST_F(DatabaseIteratorManyTest,FilterTestType1)464 TEST_F(DatabaseIteratorManyTest, FilterTestType1) {
465 // Filter by |kTestType1|.
466 auto iter = db()->GetIterator(kTestRangeStart, kTestRangeEnd, &kTestType1);
467 EXPECT_FALSE(iter.AtEnd());
468
469 auto handles = IterHandles(&iter);
470
471 // Handles of attributes with type |kTestType1|.
472 const std::array<Handle, 4u> kExpected = {1, 4, 6, 10};
473 ASSERT_EQ(kExpected.size(), handles.size());
474
475 for (size_t i = 0; i < handles.size(); i++) {
476 EXPECT_EQ(kExpected[i], handles[i]);
477 }
478 }
479
TEST_F(DatabaseIteratorManyTest,FilterTestType2)480 TEST_F(DatabaseIteratorManyTest, FilterTestType2) {
481 // Filter by |kTestType2|.
482 auto iter = db()->GetIterator(kTestRangeStart, kTestRangeEnd, &kTestType2);
483 EXPECT_FALSE(iter.AtEnd());
484
485 auto handles = IterHandles(&iter);
486
487 // Handles of attributes with type |kTestType2|.
488 const std::array<Handle, 4u> kExpected = {2, 3, 5, 7};
489 ASSERT_EQ(kExpected.size(), handles.size());
490
491 for (size_t i = 0; i < handles.size(); i++) {
492 EXPECT_EQ(kExpected[i], handles[i]);
493 }
494 }
495
TEST_F(DatabaseIteratorManyTest,FilterTestType3)496 TEST_F(DatabaseIteratorManyTest, FilterTestType3) {
497 // Filter by |kTestType3|.
498 auto iter = db()->GetIterator(kTestRangeStart, kTestRangeEnd, &kTestType3);
499 EXPECT_TRUE(iter.AtEnd());
500 }
501
TEST_F(DatabaseIteratorManyTest,UnaryRange)502 TEST_F(DatabaseIteratorManyTest, UnaryRange) {
503 // Test ranges with a single attribute. Test group begin, middle, and end
504 // cases.
505 constexpr Handle kBegin = 5;
506 constexpr Handle kMiddle = 6;
507 constexpr Handle kEnd = 7;
508
509 auto iter = db()->GetIterator(kBegin, kBegin);
510 EXPECT_FALSE(iter.AtEnd());
511 auto handles = IterHandles(&iter);
512 ASSERT_EQ(1u, handles.size());
513 EXPECT_EQ(kBegin, handles[0]);
514
515 iter = db()->GetIterator(kMiddle, kMiddle);
516 EXPECT_FALSE(iter.AtEnd());
517 handles = IterHandles(&iter);
518 ASSERT_EQ(1u, handles.size());
519 EXPECT_EQ(kMiddle, handles[0]);
520
521 iter = db()->GetIterator(kEnd, kEnd);
522 EXPECT_FALSE(iter.AtEnd());
523 handles = IterHandles(&iter);
524 ASSERT_EQ(1u, handles.size());
525 EXPECT_EQ(kEnd, handles[0]);
526 }
527
TEST_F(DatabaseIteratorManyTest,Range)528 TEST_F(DatabaseIteratorManyTest, Range) {
529 auto iter = db()->GetIterator(4, 6);
530 EXPECT_FALSE(iter.AtEnd());
531
532 auto handles = IterHandles(&iter);
533
534 // All active attribute handles.
535 const std::array<Handle, 3> kExpected = {4, 5, 6};
536 ASSERT_EQ(kExpected.size(), handles.size());
537
538 for (size_t i = 0; i < handles.size(); i++) {
539 EXPECT_EQ(kExpected[i], handles[i]);
540 }
541 }
542
543 class DatabaseExecuteWriteQueueTest : public ::testing::Test {
544 public:
545 DatabaseExecuteWriteQueueTest() = default;
546 ~DatabaseExecuteWriteQueueTest() override = default;
547
548 protected:
549 struct PendingWrite {
550 PeerId peer_id;
551 Handle handle;
552 uint16_t offset;
553 DynamicByteBuffer value;
554 Attribute::WriteResultCallback result_callback;
555 };
556
SetUp()557 void SetUp() override {
558 db_ = std::make_unique<Database>(kTestRangeStart, kTestRangeEnd);
559 }
560
ExecuteWriteQueue(PeerId peer_id,PrepareWriteQueue wq,const sm::SecurityProperties & security=kNoSecurity)561 void ExecuteWriteQueue(PeerId peer_id,
562 PrepareWriteQueue wq,
563 const sm::SecurityProperties& security = kNoSecurity) {
564 db_->ExecuteWriteQueue(peer_id,
565 std::move(wq),
566 security,
567 [this](Database::WriteQueueResult result) {
568 callback_count_++;
569 result_.emplace(result);
570 });
571 }
572
573 // Sets up an attribute grouping with 4 attributes.
SetUpAttributes()574 void SetUpAttributes() {
575 auto* grp = db()->NewGrouping(kTestType1, 3, kTestValue1); // handle: 1
576 group_decl_handle_ = grp->start_handle();
577
578 auto* attr =
579 grp->AddAttribute(kTestType2, kAllowed, kAllowed); // handle: 2
580 SetAttributeWriteHandler(attr);
581 test_handle1_ = attr->handle();
582
583 attr = grp->AddAttribute(kTestType2, kAllowed, kAllowed); // handle: 3
584 SetAttributeWriteHandler(attr);
585 test_handle2_ = attr->handle();
586
587 attr = grp->AddAttribute(kTestType2, kAllowed, kAllowed); // handle: 4
588 SetAttributeWriteHandler(attr);
589 test_handle3_ = attr->handle();
590
591 grp->set_active(true);
592 }
593
ResolveNextPendingWrite(fit::result<ErrorCode> status)594 void ResolveNextPendingWrite(fit::result<ErrorCode> status) {
595 ASSERT_FALSE(pending_writes_.empty());
596 auto pw = std::move(pending_writes_.front());
597 pending_writes_.pop();
598
599 pw.result_callback(status);
600 }
601
result() const602 std::optional<Database::WriteQueueResult> result() const { return result_; }
callback_count() const603 int callback_count() const { return callback_count_; }
604
group_decl_handle() const605 Handle group_decl_handle() const { return group_decl_handle_; }
test_handle1() const606 Handle test_handle1() const { return test_handle1_; }
test_handle2() const607 Handle test_handle2() const { return test_handle2_; }
test_handle3() const608 Handle test_handle3() const { return test_handle3_; }
609
SetAttributeWriteHandler(Attribute * attribute)610 void SetAttributeWriteHandler(Attribute* attribute) {
611 attribute->set_write_handler(
612 fit::bind_member<&DatabaseExecuteWriteQueueTest::WriteHandler>(this));
613 }
614
pending_writes() const615 const std::queue<PendingWrite>& pending_writes() const {
616 return pending_writes_;
617 }
618
db()619 Database::WeakPtr db() { return db_->GetWeakPtr(); }
620
621 private:
WriteHandler(PeerId peer_id,Handle handle,uint16_t offset,const ByteBuffer & value,Attribute::WriteResultCallback result_callback)622 void WriteHandler(PeerId peer_id,
623 Handle handle,
624 uint16_t offset,
625 const ByteBuffer& value,
626 Attribute::WriteResultCallback result_callback) {
627 PendingWrite pw;
628 pw.peer_id = peer_id;
629 pw.handle = handle;
630 pw.offset = offset;
631 pw.value = DynamicByteBuffer(value);
632 pw.result_callback = std::move(result_callback);
633
634 pending_writes_.push(std::move(pw));
635 }
636
637 std::optional<Database::WriteQueueResult> result_;
638 int callback_count_ = 0;
639 std::unique_ptr<Database> db_;
640 std::queue<PendingWrite> pending_writes_;
641
642 // Handles of the test attributes.
643 Handle group_decl_handle_ = kInvalidHandle;
644 Handle test_handle1_ = kInvalidHandle;
645 Handle test_handle2_ = kInvalidHandle;
646 Handle test_handle3_ = kInvalidHandle;
647
648 BT_DISALLOW_COPY_ASSIGN_AND_MOVE(DatabaseExecuteWriteQueueTest);
649 };
650
651 constexpr PeerId kPeerId(1);
652
TEST_F(DatabaseExecuteWriteQueueTest,EmptyQueueSucceedsImmediately)653 TEST_F(DatabaseExecuteWriteQueueTest, EmptyQueueSucceedsImmediately) {
654 ExecuteWriteQueue(kPeerId, {});
655 EXPECT_EQ(1, callback_count());
656 EXPECT_EQ(fit::ok(), result());
657 }
658
TEST_F(DatabaseExecuteWriteQueueTest,InvalidHandle)659 TEST_F(DatabaseExecuteWriteQueueTest, InvalidHandle) {
660 constexpr Handle kHandle = 1;
661 PrepareWriteQueue wq;
662 wq.push(QueuedWrite(kHandle, 0, BufferView()));
663
664 ExecuteWriteQueue(kPeerId, std::move(wq));
665 EXPECT_EQ(1, callback_count());
666 ASSERT_EQ(fit::failed(), result());
667 EXPECT_EQ(std::tuple(kHandle, ErrorCode::kInvalidHandle),
668 result()->error_value());
669 }
670
TEST_F(DatabaseExecuteWriteQueueTest,ValueLength)671 TEST_F(DatabaseExecuteWriteQueueTest, ValueLength) {
672 auto* grp = db()->NewGrouping(kTestType1, 1, kTestValue1);
673 auto* attr = grp->AddAttribute(kTestType2);
674 grp->set_active(true);
675
676 PrepareWriteQueue wq;
677 wq.push(QueuedWrite(
678 attr->handle(), 0, DynamicByteBuffer(kMaxAttributeValueLength + 1)));
679
680 ExecuteWriteQueue(kPeerId, std::move(wq));
681 EXPECT_EQ(1, callback_count());
682 ASSERT_EQ(fit::failed(), result());
683 EXPECT_EQ(std::tuple(attr->handle(), ErrorCode::kInvalidAttributeValueLength),
684 result()->error_value());
685 }
686
TEST_F(DatabaseExecuteWriteQueueTest,WritingStaticValueNotPermitted)687 TEST_F(DatabaseExecuteWriteQueueTest, WritingStaticValueNotPermitted) {
688 auto* grp = db()->NewGrouping(kTestType1, 1, kTestValue1);
689 auto* attr = grp->AddAttribute(kTestType2); // read/write not permitted
690 grp->set_active(true);
691
692 PrepareWriteQueue wq;
693 wq.push(QueuedWrite(attr->handle(), 0, kTestValue1));
694
695 ExecuteWriteQueue(kPeerId, std::move(wq));
696 EXPECT_EQ(1, callback_count());
697 ASSERT_EQ(fit::failed(), result());
698 EXPECT_EQ(std::tuple(attr->handle(), ErrorCode::kWriteNotPermitted),
699 result()->error_value());
700 }
701
TEST_F(DatabaseExecuteWriteQueueTest,SecurityChecks)702 TEST_F(DatabaseExecuteWriteQueueTest, SecurityChecks) {
703 auto* grp = db()->NewGrouping(kTestType1, 1, kTestValue1);
704 auto* attr = grp->AddAttribute(
705 kTestType2,
706 att::AccessRequirements(),
707 att::AccessRequirements(
708 /*encryption=*/true,
709 /*authentication=*/false,
710 /*authorization=*/false)); // write requires encryption
711 SetAttributeWriteHandler(attr);
712 grp->set_active(true);
713
714 PrepareWriteQueue wq;
715 wq.push(QueuedWrite(attr->handle(), 0, kTestValue1));
716
717 ExecuteWriteQueue(kPeerId, std::move(wq), kNoSecurity);
718 EXPECT_EQ(1, callback_count());
719 ASSERT_EQ(fit::failed(), result());
720 EXPECT_EQ(std::tuple(attr->handle(), ErrorCode::kInsufficientAuthentication),
721 result()->error_value());
722
723 wq = PrepareWriteQueue();
724 wq.push(QueuedWrite(attr->handle(), 0, kTestValue1));
725
726 // Request should succeed with an encrypted link.
727 ExecuteWriteQueue(
728 kPeerId,
729 std::move(wq),
730 sm::SecurityProperties(
731 sm::SecurityLevel::kEncrypted, 16, /*secure_connections=*/false));
732 ResolveNextPendingWrite(fit::ok());
733 EXPECT_EQ(2, callback_count());
734 EXPECT_EQ(fit::ok(), result());
735 }
736
737 // If an error is caught before delivering the request to the delegate then we
738 // expect subsequent entries to not be delivered.
TEST_F(DatabaseExecuteWriteQueueTest,UndelegatedWriteErrorAborts)739 TEST_F(DatabaseExecuteWriteQueueTest, UndelegatedWriteErrorAborts) {
740 SetUpAttributes();
741 PrepareWriteQueue wq;
742
743 // Queue a request to one of the delegated handles. This won't generate a
744 // result until we explicitly send a reply via ResolveNextPendingWrite().
745 wq.push(QueuedWrite(test_handle1(), 0, kTestValue1));
746
747 // Queue a write to the group declaration handle. This should get rejected
748 // right away since it's not writable. Since the database catches this error
749 // internally, we expect the following queued writes to get aborted.
750 wq.push(QueuedWrite(group_decl_handle(), 0, kTestValue1));
751
752 // Queue more writes.
753 wq.push(QueuedWrite(test_handle2(), 1, kTestValue2));
754 wq.push(QueuedWrite(test_handle3(), 2, kTestValue1));
755 wq.push(QueuedWrite(test_handle1(), 3, kTestValue2));
756
757 ExecuteWriteQueue(kPeerId, std::move(wq));
758
759 // The database should have generated an error response.
760 EXPECT_EQ(1, callback_count());
761 ASSERT_EQ(fit::failed(), result());
762 EXPECT_EQ(std::tuple(group_decl_handle(), ErrorCode::kWriteNotPermitted),
763 result()->error_value());
764
765 // Only the first write should have been delivered.
766 ASSERT_EQ(1u, pending_writes().size());
767 EXPECT_EQ(test_handle1(), pending_writes().front().handle);
768 EXPECT_EQ(0, pending_writes().front().offset);
769 EXPECT_TRUE(ContainersEqual(kTestValue1, pending_writes().front().value));
770
771 // Resolving the request should have no effect.
772 ResolveNextPendingWrite(fit::error(ErrorCode::kUnlikelyError));
773 EXPECT_EQ(1, callback_count()); // still 1
774 }
775
TEST_F(DatabaseExecuteWriteQueueTest,ErrorInMultipleQueuedWrites)776 TEST_F(DatabaseExecuteWriteQueueTest, ErrorInMultipleQueuedWrites) {
777 SetUpAttributes();
778 PrepareWriteQueue wq;
779
780 // Queue writes to the writable handles in arbitrary order. We expect all of
781 // them to be delivered to the delegate.
782 wq.push(QueuedWrite(test_handle1(), 0, kTestValue1));
783 wq.push(QueuedWrite(test_handle2(), 1, kTestValue2));
784 wq.push(QueuedWrite(test_handle3(), 2, kTestValue1));
785 wq.push(QueuedWrite(test_handle1(), 3, kTestValue2));
786
787 ExecuteWriteQueue(kPeerId, std::move(wq));
788
789 // The execute write request should be pending.
790 EXPECT_EQ(0, callback_count());
791
792 // All 4 requests should have been delivered.
793 ASSERT_EQ(4u, pending_writes().size());
794
795 // Resolve the first request with success. The execute write request should
796 // remain pending.
797 {
798 const auto& next = pending_writes().front();
799 EXPECT_EQ(kPeerId, next.peer_id);
800 EXPECT_EQ(test_handle1(), next.handle);
801 EXPECT_EQ(0, next.offset);
802 EXPECT_TRUE(ContainersEqual(kTestValue1, next.value));
803
804 ResolveNextPendingWrite(fit::ok());
805 EXPECT_EQ(0, callback_count());
806 }
807
808 // Resolve the second request with an error.
809 {
810 const auto& next = pending_writes().front();
811 EXPECT_EQ(kPeerId, next.peer_id);
812 EXPECT_EQ(test_handle2(), next.handle);
813 EXPECT_EQ(1, next.offset);
814 EXPECT_TRUE(ContainersEqual(kTestValue2, next.value));
815
816 ResolveNextPendingWrite(fit::error(ErrorCode::kUnlikelyError));
817 EXPECT_EQ(1, callback_count());
818 ASSERT_EQ(fit::failed(), result());
819 EXPECT_EQ(std::tuple(test_handle2(), ErrorCode::kUnlikelyError),
820 result()->error_value());
821 }
822
823 // Resolving the remaining writes should have no effect.
824 ResolveNextPendingWrite(fit::ok());
825 ResolveNextPendingWrite(fit::error(ErrorCode::kUnlikelyError));
826 EXPECT_EQ(1, callback_count());
827 }
828
TEST_F(DatabaseExecuteWriteQueueTest,MultipleQueuedWritesSucceed)829 TEST_F(DatabaseExecuteWriteQueueTest, MultipleQueuedWritesSucceed) {
830 SetUpAttributes();
831 PrepareWriteQueue wq;
832
833 // Queue writes to the writable handles in arbitrary order. We expect all of
834 // them to be delivered to the delegate.
835 wq.push(QueuedWrite(test_handle1(), 0, kTestValue1));
836 wq.push(QueuedWrite(test_handle2(), 1, kTestValue2));
837 wq.push(QueuedWrite(test_handle3(), 2, kTestValue1));
838 wq.push(QueuedWrite(test_handle1(), 3, kTestValue2));
839
840 ExecuteWriteQueue(kPeerId, std::move(wq));
841
842 // The execute write request should be pending.
843 EXPECT_EQ(0, callback_count());
844
845 // All 4 requests should have been delivered.
846 ASSERT_EQ(4u, pending_writes().size());
847
848 // Resolve all requests with success.
849 {
850 const auto& next = pending_writes().front();
851 EXPECT_EQ(kPeerId, next.peer_id);
852 EXPECT_EQ(test_handle1(), next.handle);
853 EXPECT_EQ(0, next.offset);
854 EXPECT_TRUE(ContainersEqual(kTestValue1, next.value));
855
856 ResolveNextPendingWrite(fit::ok());
857 EXPECT_EQ(0, callback_count());
858 }
859 {
860 const auto& next = pending_writes().front();
861 EXPECT_EQ(kPeerId, next.peer_id);
862 EXPECT_EQ(test_handle2(), next.handle);
863 EXPECT_EQ(1, next.offset);
864 EXPECT_TRUE(ContainersEqual(kTestValue2, next.value));
865
866 ResolveNextPendingWrite(fit::ok());
867 EXPECT_EQ(0, callback_count());
868 }
869 {
870 const auto& next = pending_writes().front();
871 EXPECT_EQ(kPeerId, next.peer_id);
872 EXPECT_EQ(test_handle3(), next.handle);
873 EXPECT_EQ(2, next.offset);
874 EXPECT_TRUE(ContainersEqual(kTestValue1, next.value));
875
876 ResolveNextPendingWrite(fit::ok());
877 EXPECT_EQ(0, callback_count());
878 }
879
880 // Resolving the last request should complete the execute write request.
881 {
882 const auto& next = pending_writes().front();
883 EXPECT_EQ(kPeerId, next.peer_id);
884 EXPECT_EQ(test_handle1(), next.handle);
885 EXPECT_EQ(3, next.offset);
886 EXPECT_TRUE(ContainersEqual(kTestValue2, next.value));
887
888 ResolveNextPendingWrite(fit::ok());
889 EXPECT_EQ(1, callback_count());
890 EXPECT_EQ(fit::ok(), result());
891 }
892 }
893
894 } // namespace
895 } // namespace bt::att
896