1 // Copyright 2024 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_allocator/block/result.h"
16
17 #include <array>
18 #include <cstddef>
19
20 #include "public/pw_allocator/block/basic.h"
21 #include "pw_status/status.h"
22 #include "pw_unit_test/framework.h"
23
24 namespace {
25
26 using ::pw::Status;
27
28 struct FakeBlock : public ::pw::allocator::BasicBlock<FakeBlock> {
DefaultAlignment__anon9fb06cfd0111::FakeBlock29 static constexpr size_t DefaultAlignment() { return 1; }
BlockOverhead__anon9fb06cfd0111::FakeBlock30 static constexpr size_t BlockOverhead() { return 0; }
MinInnerSize__anon9fb06cfd0111::FakeBlock31 static constexpr size_t MinInnerSize() { return 0; }
OuterSizeUnchecked__anon9fb06cfd0111::FakeBlock32 size_t OuterSizeUnchecked() const { return 1; }
33 };
34
35 using BlockResult = ::pw::allocator::BlockResult<FakeBlock>;
36
37 const std::array<Status, 17> kStatuses = {
38 pw::OkStatus(),
39 Status::Cancelled(),
40 Status::Unknown(),
41 Status::InvalidArgument(),
42 Status::DeadlineExceeded(),
43 Status::NotFound(),
44 Status::AlreadyExists(),
45 Status::PermissionDenied(),
46 Status::ResourceExhausted(),
47 Status::FailedPrecondition(),
48 Status::Aborted(),
49 Status::OutOfRange(),
50 Status::Unimplemented(),
51 Status::Internal(),
52 Status::Unavailable(),
53 Status::DataLoss(),
54 Status::Unauthenticated(),
55 };
56
57 const std::array<BlockResult::Prev, 4> kPrevs = {
58 BlockResult::Prev::kUnchanged,
59 BlockResult::Prev::kSplitNew,
60 BlockResult::Prev::kResizedSmaller,
61 BlockResult::Prev::kResizedLarger,
62 };
63
64 const std::array<BlockResult::Next, 4> kNexts = {
65 BlockResult::Next::kUnchanged,
66 BlockResult::Next::kSplitNew,
67 BlockResult::Next::kResized,
68 BlockResult::Next::kMerged,
69 };
70
71 const std::array<size_t, 4> kSizes = {
72 0,
73 1,
74 8,
75 (1U << 10) - 1,
76 };
77
TEST(BlockResultTest,ConstructWithBlockOnly)78 TEST(BlockResultTest, ConstructWithBlockOnly) {
79 FakeBlock block;
80 BlockResult result(&block);
81 EXPECT_EQ(result.block(), &block);
82 EXPECT_EQ(result.status(), pw::OkStatus());
83 EXPECT_EQ(result.prev(), BlockResult::Prev::kUnchanged);
84 EXPECT_EQ(result.next(), BlockResult::Next::kUnchanged);
85 EXPECT_EQ(result.size(), 0U);
86 }
87
TEST(BlockResultTest,ConstructWithBlockAndStatus)88 TEST(BlockResultTest, ConstructWithBlockAndStatus) {
89 FakeBlock block;
90 for (const auto& status : kStatuses) {
91 BlockResult result(&block, status);
92 EXPECT_EQ(result.block(), &block);
93 EXPECT_EQ(result.status(), status);
94 EXPECT_EQ(result.prev(), BlockResult::Prev::kUnchanged);
95 EXPECT_EQ(result.next(), BlockResult::Next::kUnchanged);
96 EXPECT_EQ(result.size(), 0U);
97 }
98 }
99
TEST(BlockResultTest,ConstructWithBlockAndPrev)100 TEST(BlockResultTest, ConstructWithBlockAndPrev) {
101 FakeBlock block;
102 for (const auto& prev : kPrevs) {
103 BlockResult result(&block, prev);
104 EXPECT_EQ(result.block(), &block);
105 EXPECT_EQ(result.status(), pw::OkStatus());
106 EXPECT_EQ(result.prev(), prev);
107 EXPECT_EQ(result.next(), BlockResult::Next::kUnchanged);
108 EXPECT_EQ(result.size(), 0U);
109 }
110 }
111
TEST(BlockResultTest,ConstructWithBlockPrevAndSize)112 TEST(BlockResultTest, ConstructWithBlockPrevAndSize) {
113 FakeBlock block;
114 for (const auto& prev : kPrevs) {
115 for (const auto& size : kSizes) {
116 BlockResult result(&block, prev, size);
117 EXPECT_EQ(result.block(), &block);
118 EXPECT_EQ(result.status(), pw::OkStatus());
119 EXPECT_EQ(result.prev(), prev);
120 EXPECT_EQ(result.next(), BlockResult::Next::kUnchanged);
121 EXPECT_EQ(result.size(), size);
122 }
123 }
124 }
125
TEST(BlockResultTest,ConstructWithBlockAndNext)126 TEST(BlockResultTest, ConstructWithBlockAndNext) {
127 FakeBlock block;
128 for (const auto& next : kNexts) {
129 BlockResult result(&block, next);
130 EXPECT_EQ(result.block(), &block);
131 EXPECT_EQ(result.status(), pw::OkStatus());
132 EXPECT_EQ(result.prev(), BlockResult::Prev::kUnchanged);
133 EXPECT_EQ(result.next(), next);
134 EXPECT_EQ(result.size(), 0U);
135 }
136 }
137
TEST(BlockResultTest,ConstructWithBlockPrevAndNext)138 TEST(BlockResultTest, ConstructWithBlockPrevAndNext) {
139 FakeBlock block;
140 for (const auto& prev : kPrevs) {
141 for (const auto& next : kNexts) {
142 BlockResult result(&block, prev, next);
143 EXPECT_EQ(result.block(), &block);
144 EXPECT_EQ(result.status(), pw::OkStatus());
145 EXPECT_EQ(result.prev(), prev);
146 EXPECT_EQ(result.next(), next);
147 EXPECT_EQ(result.size(), 0U);
148 }
149 }
150 }
151
TEST(BlockResultTest,ConstructWithBlockPrevNextAndSize)152 TEST(BlockResultTest, ConstructWithBlockPrevNextAndSize) {
153 FakeBlock block;
154 for (const auto& prev : kPrevs) {
155 for (const auto& next : kNexts) {
156 for (const auto& size : kSizes) {
157 BlockResult result(&block, prev, next, size);
158 EXPECT_EQ(result.block(), &block);
159 EXPECT_EQ(result.status(), pw::OkStatus());
160 EXPECT_EQ(result.prev(), prev);
161 EXPECT_EQ(result.next(), next);
162 EXPECT_EQ(result.size(), size);
163 }
164 }
165 }
166 }
167
168 } // namespace
169