xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/att/database_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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