blob: e397314e98750321e3eff76fc1cc491503ca33fe [file] [log] [blame]
Jamie Garside558e1442020-03-27 17:05:55 +00001// Copyright 2020 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.h"
16
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -040017#include <cstring>
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070018#include <span>
19
Jamie Garside558e1442020-03-27 17:05:55 +000020#include "gtest/gtest.h"
Jamie Garside558e1442020-03-27 17:05:55 +000021
22using std::byte;
23
24namespace pw::allocator {
25
26TEST(Block, CanCreateSingleBlock) {
27 constexpr size_t kN = 200;
28 alignas(Block*) byte bytes[kN];
29
30 Block* block = nullptr;
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070031 auto status = Block::Init(std::span(bytes, kN), &block);
Jamie Garside558e1442020-03-27 17:05:55 +000032
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080033 ASSERT_EQ(status, OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +000034 EXPECT_EQ(block->OuterSize(), kN);
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -040035 EXPECT_EQ(block->InnerSize(),
36 kN - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET);
37 EXPECT_EQ(block->Prev(), nullptr);
38 EXPECT_EQ(block->Next(), (Block*)((uintptr_t)block + kN));
Jamie Garside558e1442020-03-27 17:05:55 +000039 EXPECT_EQ(block->Used(), false);
40 EXPECT_EQ(block->Last(), true);
41}
42
43TEST(Block, CannotCreateUnalignedSingleBlock) {
44 constexpr size_t kN = 1024;
45
46 // Force alignment, so we can un-force it below
47 alignas(Block*) byte bytes[kN];
48 byte* byte_ptr = bytes;
49
50 Block* block = nullptr;
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070051 auto status = Block::Init(std::span(byte_ptr + 1, kN - 1), &block);
Jamie Garside558e1442020-03-27 17:05:55 +000052
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070053 EXPECT_EQ(status, Status::InvalidArgument());
Jamie Garside558e1442020-03-27 17:05:55 +000054}
55
56TEST(Block, CannotCreateTooSmallBlock) {
57 constexpr size_t kN = 2;
58 alignas(Block*) byte bytes[kN];
59 Block* block = nullptr;
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070060 auto status = Block::Init(std::span(bytes, kN), &block);
Jamie Garside558e1442020-03-27 17:05:55 +000061
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070062 EXPECT_EQ(status, Status::InvalidArgument());
Jamie Garside558e1442020-03-27 17:05:55 +000063}
64
65TEST(Block, CanSplitBlock) {
66 constexpr size_t kN = 1024;
67 constexpr size_t kSplitN = 512;
68 alignas(Block*) byte bytes[kN];
69
70 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -070071 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +000072
73 Block* next_block = nullptr;
74 auto status = block->Split(kSplitN, &next_block);
75
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080076 ASSERT_EQ(status, OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +000077 EXPECT_EQ(block->InnerSize(), kSplitN);
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -040078 EXPECT_EQ(block->OuterSize(),
79 kSplitN + sizeof(Block) + 2 * PW_ALLOCATOR_POISON_OFFSET);
Jamie Garside558e1442020-03-27 17:05:55 +000080 EXPECT_EQ(block->Last(), false);
81
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -040082 EXPECT_EQ(next_block->OuterSize(),
83 kN - kSplitN - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET);
Jamie Garside558e1442020-03-27 17:05:55 +000084 EXPECT_EQ(next_block->Used(), false);
85 EXPECT_EQ(next_block->Last(), true);
86
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -040087 EXPECT_EQ(block->Next(), next_block);
88 EXPECT_EQ(next_block->Prev(), block);
Jamie Garside558e1442020-03-27 17:05:55 +000089}
90
91TEST(Block, CanSplitBlockUnaligned) {
92 constexpr size_t kN = 1024;
93 constexpr size_t kSplitN = 513;
94
95 alignas(Block*) byte bytes[kN];
96
97 // We should split at sizeof(Block) + kSplitN bytes. Then
98 // we need to round that up to an alignof(Block*) boundary.
99 uintptr_t split_addr = ((uintptr_t)&bytes) + kSplitN;
100 split_addr += alignof(Block*) - (split_addr % alignof(Block*));
101 uintptr_t split_len = split_addr - (uintptr_t)&bytes;
102
103 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700104 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000105
106 Block* next_block = nullptr;
107 auto status = block->Split(kSplitN, &next_block);
108
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800109 ASSERT_EQ(status, OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000110 EXPECT_EQ(block->InnerSize(), split_len);
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400111 EXPECT_EQ(block->OuterSize(),
112 split_len + sizeof(Block) + 2 * PW_ALLOCATOR_POISON_OFFSET);
113 EXPECT_EQ(next_block->OuterSize(),
114 kN - split_len - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET);
Jamie Garside558e1442020-03-27 17:05:55 +0000115 EXPECT_EQ(next_block->Used(), false);
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400116 EXPECT_EQ(block->Next(), next_block);
117 EXPECT_EQ(next_block->Prev(), block);
Jamie Garside558e1442020-03-27 17:05:55 +0000118}
119
120TEST(Block, CanSplitMidBlock) {
121 // Split once, then split the original block again to ensure that the
122 // pointers get rewired properly.
123 // I.e.
124 // [[ BLOCK 1 ]]
125 // block1->Split()
126 // [[ BLOCK1 ]][[ BLOCK2 ]]
127 // block1->Split()
128 // [[ BLOCK1 ]][[ BLOCK3 ]][[ BLOCK2 ]]
129
130 constexpr size_t kN = 1024;
131 constexpr size_t kSplit1 = 512;
132 constexpr size_t kSplit2 = 256;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700133 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000134
135 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700136 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000137
138 Block* block2 = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000139 block->Split(kSplit1, &block2)
140 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Jamie Garside558e1442020-03-27 17:05:55 +0000141
142 Block* block3 = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000143 block->Split(kSplit2, &block3)
144 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Jamie Garside558e1442020-03-27 17:05:55 +0000145
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400146 EXPECT_EQ(block->Next(), block3);
147 EXPECT_EQ(block3->Next(), block2);
148 EXPECT_EQ(block2->Prev(), block3);
149 EXPECT_EQ(block3->Prev(), block);
Jamie Garside558e1442020-03-27 17:05:55 +0000150}
151
152TEST(Block, CannotSplitBlockWithoutHeaderSpace) {
153 constexpr size_t kN = 1024;
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400154 constexpr size_t kSplitN =
155 kN - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET - 1;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700156 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000157
158 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700159 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000160
161 Block* next_block = nullptr;
162 auto status = block->Split(kSplitN, &next_block);
163
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700164 EXPECT_EQ(status, Status::ResourceExhausted());
Jamie Garside558e1442020-03-27 17:05:55 +0000165 EXPECT_EQ(next_block, nullptr);
166}
167
168TEST(Block, MustProvideNextBlockPointer) {
169 constexpr size_t kN = 1024;
170 constexpr size_t kSplitN = kN - sizeof(Block) - 1;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700171 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000172
173 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700174 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000175
176 auto status = block->Split(kSplitN, nullptr);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700177 EXPECT_EQ(status, Status::InvalidArgument());
Jamie Garside558e1442020-03-27 17:05:55 +0000178}
179
180TEST(Block, CannotMakeBlockLargerInSplit) {
181 // Ensure that we can't ask for more space than the block actually has...
182 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700183 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000184
185 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700186 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000187
188 Block* next_block = nullptr;
189 auto status = block->Split(block->InnerSize() + 1, &next_block);
190
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700191 EXPECT_EQ(status, Status::OutOfRange());
Jamie Garside558e1442020-03-27 17:05:55 +0000192}
193
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400194TEST(Block, CannotMakeSecondBlockLargerInSplit) {
195 // Ensure that the second block in split is at least of the size of header.
196 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700197 alignas(Block*) byte bytes[kN];
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400198
199 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700200 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400201
202 Block* next_block = nullptr;
203 auto status = block->Split(
204 block->InnerSize() - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET + 1,
205 &next_block);
206
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700207 ASSERT_EQ(status, Status::ResourceExhausted());
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400208 EXPECT_EQ(next_block, nullptr);
209}
210
Jamie Garside558e1442020-03-27 17:05:55 +0000211TEST(Block, CanMakeZeroSizeFirstBlock) {
212 // This block does support splitting with zero payload size.
213 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700214 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000215
216 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700217 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000218
219 Block* next_block = nullptr;
220 auto status = block->Split(0, &next_block);
221
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800222 ASSERT_EQ(status, OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000223 EXPECT_EQ(block->InnerSize(), static_cast<size_t>(0));
224}
225
226TEST(Block, CanMakeZeroSizeSecondBlock) {
227 // Likewise, the split block can be zero-width.
228 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700229 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000230
231 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700232 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000233
234 Block* next_block = nullptr;
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400235 auto status = block->Split(
236 block->InnerSize() - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET,
237 &next_block);
Jamie Garside558e1442020-03-27 17:05:55 +0000238
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800239 ASSERT_EQ(status, OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000240 EXPECT_EQ(next_block->InnerSize(), static_cast<size_t>(0));
241}
242
243TEST(Block, CanMarkBlockUsed) {
244 constexpr size_t kN = 1024;
245 alignas(Block*) byte bytes[kN];
246
247 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700248 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000249
250 block->MarkUsed();
251 EXPECT_EQ(block->Used(), true);
252
253 // Mark used packs that data into the next pointer. Check that it's still
254 // valid
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400255 EXPECT_EQ(block->Next(), (Block*)((uintptr_t)block + kN));
Jamie Garside558e1442020-03-27 17:05:55 +0000256
257 block->MarkFree();
258 EXPECT_EQ(block->Used(), false);
259}
260
261TEST(Block, CannotSplitUsedBlock) {
262 constexpr size_t kN = 1024;
263 alignas(Block*) byte bytes[kN];
264
265 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700266 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000267
268 block->MarkUsed();
269
270 Block* next_block = nullptr;
271 auto status = block->Split(512, &next_block);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700272 EXPECT_EQ(status, Status::FailedPrecondition());
Jamie Garside558e1442020-03-27 17:05:55 +0000273}
274
275TEST(Block, CanMergeWithNextBlock) {
276 // Do the three way merge from "CanSplitMidBlock", and let's
277 // merge block 3 and 2
278 constexpr size_t kN = 1024;
279 constexpr size_t kSplit1 = 512;
280 constexpr size_t kSplit2 = 256;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700281 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000282
283 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700284 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000285
286 Block* block2 = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000287 block->Split(kSplit1, &block2)
288 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Jamie Garside558e1442020-03-27 17:05:55 +0000289
290 Block* block3 = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000291 block->Split(kSplit2, &block3)
292 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Jamie Garside558e1442020-03-27 17:05:55 +0000293
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800294 EXPECT_EQ(block3->MergeNext(), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000295
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400296 EXPECT_EQ(block->Next(), block3);
297 EXPECT_EQ(block3->Prev(), block);
Jamie Garside558e1442020-03-27 17:05:55 +0000298 EXPECT_EQ(block->InnerSize(), kSplit2);
299
300 // The resulting "right hand" block should have an outer size of 1024 - 256 -
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400301 // sizeof(Block) - 2*PW_ALLOCATOR_POISON_OFFSET, which accounts for the first
302 // block.
303 EXPECT_EQ(block3->OuterSize(),
304 kN - kSplit2 - sizeof(Block) - 2 * PW_ALLOCATOR_POISON_OFFSET);
Jamie Garside558e1442020-03-27 17:05:55 +0000305}
306
307TEST(Block, CannotMergeWithFirstOrLastBlock) {
308 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700309 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000310
Rob Mohrde9cc1b2021-05-21 15:58:44 -0700311 // Do a split, just to check that the checks on Next/Prev are
Jamie Garside558e1442020-03-27 17:05:55 +0000312 // different...
313 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700314 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000315
316 Block* next_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000317 block->Split(512, &next_block)
318 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Jamie Garside558e1442020-03-27 17:05:55 +0000319
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700320 EXPECT_EQ(next_block->MergeNext(), Status::OutOfRange());
321 EXPECT_EQ(block->MergePrev(), Status::OutOfRange());
Jamie Garside558e1442020-03-27 17:05:55 +0000322}
323
324TEST(Block, CannotMergeUsedBlock) {
325 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700326 alignas(Block*) byte bytes[kN];
Jamie Garside558e1442020-03-27 17:05:55 +0000327
Rob Mohrde9cc1b2021-05-21 15:58:44 -0700328 // Do a split, just to check that the checks on Next/Prev are
Jamie Garside558e1442020-03-27 17:05:55 +0000329 // different...
330 Block* block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700331 EXPECT_EQ(Block::Init(std::span(bytes, kN), &block), OkStatus());
Jamie Garside558e1442020-03-27 17:05:55 +0000332
333 Block* next_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000334 block->Split(512, &next_block)
335 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Jamie Garside558e1442020-03-27 17:05:55 +0000336
337 block->MarkUsed();
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700338 EXPECT_EQ(block->MergeNext(), Status::FailedPrecondition());
339 EXPECT_EQ(next_block->MergePrev(), Status::FailedPrecondition());
Jamie Garside558e1442020-03-27 17:05:55 +0000340}
341
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400342TEST(Block, CanCheckValidBlock) {
343 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700344 alignas(Block*) byte bytes[kN];
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400345
346 Block* first_block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700347 EXPECT_EQ(Block::Init(std::span(bytes, kN), &first_block), OkStatus());
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400348
349 Block* second_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000350 first_block->Split(512, &second_block)
351 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400352
353 Block* third_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000354 second_block->Split(256, &third_block)
355 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400356
357 EXPECT_EQ(first_block->IsValid(), true);
358 EXPECT_EQ(second_block->IsValid(), true);
359 EXPECT_EQ(third_block->IsValid(), true);
360}
361
362TEST(Block, CanCheckInalidBlock) {
363 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700364 alignas(Block*) byte bytes[kN];
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400365
366 Block* first_block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700367 EXPECT_EQ(Block::Init(std::span(bytes, kN), &first_block), OkStatus());
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400368
369 Block* second_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000370 first_block->Split(512, &second_block)
371 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400372
373 Block* third_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000374 second_block->Split(256, &third_block)
375 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400376
377 Block* fourth_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000378 third_block->Split(128, &fourth_block)
379 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400380
381 std::byte* next_ptr = reinterpret_cast<std::byte*>(first_block);
382 memcpy(next_ptr, second_block, sizeof(void*));
383 EXPECT_EQ(first_block->IsValid(), false);
384 EXPECT_EQ(second_block->IsValid(), false);
385 EXPECT_EQ(third_block->IsValid(), true);
386 EXPECT_EQ(fourth_block->IsValid(), true);
387
Ewout van Bekkume4d7b692020-10-15 13:12:30 -0700388#if defined(PW_ALLOCATOR_POISON_ENABLE) && PW_ALLOCATOR_POISON_ENABLE
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400389 std::byte fault_poison[PW_ALLOCATOR_POISON_OFFSET] = {std::byte(0)};
390 std::byte* front_poison =
391 reinterpret_cast<std::byte*>(third_block) + sizeof(*third_block);
392 memcpy(front_poison, fault_poison, PW_ALLOCATOR_POISON_OFFSET);
393 EXPECT_EQ(third_block->IsValid(), false);
394
395 std::byte* end_poison =
396 reinterpret_cast<std::byte*>(fourth_block) + sizeof(*fourth_block);
397 memcpy(end_poison, fault_poison, PW_ALLOCATOR_POISON_OFFSET);
398 EXPECT_EQ(fourth_block->IsValid(), false);
399#endif // PW_ALLOCATOR_POISON_ENABLE
400}
401
402TEST(Block, CanPoisonBlock) {
Ewout van Bekkume4d7b692020-10-15 13:12:30 -0700403#if defined(PW_ALLOCATOR_POISON_ENABLE) && PW_ALLOCATOR_POISON_ENABLE
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400404 constexpr size_t kN = 1024;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700405 alignas(Block*) byte bytes[kN];
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400406
407 Block* first_block = nullptr;
Armando Montanez1ee925c2020-06-29 13:15:28 -0700408 EXPECT_EQ(Block::Init(std::span(bytes, kN), &first_block), OkStatus());
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400409
410 Block* second_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000411 first_block->Split(512, &second_block)
412 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400413
414 Block* third_block = nullptr;
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000415 second_block->Split(256, &third_block)
416 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Chenghan Zhouea0f7ad2020-07-29 18:20:37 -0400417
418 EXPECT_EQ(first_block->IsValid(), true);
419 EXPECT_EQ(second_block->IsValid(), true);
420 EXPECT_EQ(third_block->IsValid(), true);
421#endif // PW_ALLOCATOR_POISON_ENABLE
422}
423
Jamie Garside558e1442020-03-27 17:05:55 +0000424} // namespace pw::allocator