19#include "pw_allocator/allocator.h"
20#include "pw_allocator/first_fit.h"
21#include "pw_allocator/hardening.h"
22#include "pw_allocator/metrics.h"
23#include "pw_allocator/tracking_allocator.h"
24#include "pw_assert/assert.h"
25#include "pw_bytes/span.h"
26#include "pw_result/result.h"
27#include "pw_status/status.h"
28#include "pw_tokenizer/tokenize.h"
29#include "pw_unit_test/framework.h"
31namespace pw::allocator::test {
35static_assert(Hardening::kIncludesDebugChecks,
36 "Tests must use a config that enables strict validation");
42template <
typename BlockType>
43void FreeAll(
typename BlockType::Range range) {
44 BlockType* block = *(range.begin());
45 if (block ==
nullptr) {
50 BlockType* prev = block->Prev();
51 while (prev !=
nullptr) {
57 while (block !=
nullptr) {
58 if (!block->IsFree()) {
59 auto result = BlockType::Free(std::move(block));
60 block = result.block();
62 block = block->Next();
67template <
size_t kBufferSize,
72 using BlockType = BlockType_;
73 using MetricsType = MetricsType_;
78 static constexpr size_t kMinSize = BlockType::kAlignment;
81 :
Allocator(AllocatorType::kCapabilities),
83 tracker_(kToken, allocator_) {
89 typename BlockType::Range blocks()
const {
return allocator_.
blocks(); }
90 typename BlockType::Range blocks() {
return allocator_.
blocks(); }
92 const metric::Group& metric_group()
const {
return tracker_.metric_group(); }
93 metric::Group& metric_group() {
return tracker_.metric_group(); }
95 const MetricsType& metrics()
const {
return tracker_.metrics(); }
97 size_t allocate_size()
const {
return allocate_size_; }
98 void* deallocate_ptr()
const {
return deallocate_ptr_; }
99 size_t deallocate_size()
const {
return deallocate_size_; }
100 void* resize_ptr()
const {
return resize_ptr_; }
101 size_t resize_old_size()
const {
return resize_old_size_; }
102 size_t resize_new_size()
const {
return resize_new_size_; }
107 deallocate_ptr_ =
nullptr;
108 deallocate_size_ = 0;
109 resize_ptr_ =
nullptr;
110 resize_old_size_ = 0;
111 resize_new_size_ = 0;
112 enable_measure_fragmentation_ =
true;
113 fragmentation_ = std::nullopt;
118 for (
auto* block : allocator_.
blocks()) {
119 if (block->IsFree()) {
120 auto result = BlockType::AllocLast(std::move(block),
121 Layout(block->InnerSize(), 1));
122 PW_ASSERT(result.status() ==
OkStatus());
125 PW_ASSERT(result.prev() == Prev::kUnchanged);
128 PW_ASSERT(result.next() == Next::kUnchanged);
136 enable_measure_fragmentation_ = enabled;
144 fragmentation_ = fragmentation;
153 if (!enable_measure_fragmentation_) {
156 if (fragmentation_.has_value()) {
157 return fragmentation_;
165 allocate_size_ = layout.size();
166 void* ptr = tracker_.Allocate(layout);
173 deallocate_ptr_ = ptr;
174 deallocate_size_ = requested.
ok() ? requested->size() : 0;
175 tracker_.Deallocate(ptr);
179 bool DoResize(
void* ptr,
size_t new_size)
override {
182 resize_old_size_ = requested.
ok() ? requested->size() : 0;
183 resize_new_size_ = new_size;
184 return tracker_.Resize(ptr, new_size);
192 return GetInfo(tracker_, info_type, ptr);
195 alignas(BlockType::kAlignment) std::array<std::byte, kBufferSize> buffer_{};
196 AllocatorType allocator_;
198 size_t allocate_size_;
199 void* deallocate_ptr_;
200 size_t deallocate_size_;
202 size_t resize_old_size_;
203 size_t resize_new_size_;
205 bool enable_measure_fragmentation_;
206 std::optional<Fragmentation> fragmentation_;
Definition: allocator.h:42
constexpr Allocator()=default
TODO(b/326509341): Remove when downstream consumers migrate.
std::optional< Fragmentation > MeasureFragmentation() const
Returns fragmentation information for the allocator's memory region.
Definition: allocator.h:280
constexpr bool ok() const
Definition: result.h:451
Range blocks() const
Returns a Range of blocks tracking the memory of this allocator.
Definition: block_allocator.h:113
Definition: detailed_block.h:88
Definition: tracking_allocator.h:55
Next
Definition: result.h:45
Prev
Definition: result.h:36
An AllocatorForTest that is automatically initialized on construction.
Definition: testing.h:70
size_t DoGetAllocated() const override
Definition: testing.h:188
void SetMeasureFragmentationEnabled(bool enabled)
Definition: testing.h:135
void ResetParameters()
Resets the recorded parameters to an initial state.
Definition: testing.h:105
std::optional< Fragmentation > DoMeasureFragmentation() const override
Returns fragmentation information for the allocator's memory region.
Definition: testing.h:152
void DoDeallocate(void *ptr) override
Definition: testing.h:171
void * DoAllocate(Layout layout) override
Definition: testing.h:164
void Exhaust()
Allocates all the memory from this object.
Definition: testing.h:117
bool DoResize(void *ptr, size_t new_size) override
Definition: testing.h:179
void SetFragmentation(const Fragmentation &fragmentation)
Definition: testing.h:143
TrackingAllocator< MetricsType > & GetTracker()
Returns the underlying tracking allocator.
Definition: testing.h:149
Result< Layout > DoGetInfo(InfoType info_type, const void *ptr) const override
Definition: testing.h:191
void FreeAll(typename BlockType::Range range)
Free all the blocks reachable by the given block. Useful for test cleanup.
Definition: testing.h:43
constexpr Status OkStatus()
Definition: status.h:450
#define PW_TOKENIZE_STRING(...)
Definition: tokenize.h:67
Definition: fragmentation.h:47
Definition: metrics.h:173