Pigweed
Loading...
Searching...
No Matches
testing.h
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#pragma once
15
16#include <cstddef>
17
18#include "pw_allocator/allocator.h"
19#include "pw_allocator/block.h"
20#include "pw_allocator/buffer.h"
21#include "pw_allocator/first_fit_block_allocator.h"
22#include "pw_allocator/metrics.h"
23#include "pw_allocator/tracking_allocator.h"
24#include "pw_bytes/span.h"
25#include "pw_result/result.h"
26#include "pw_status/status.h"
27#include "pw_sync/interrupt_spin_lock.h"
28#include "pw_tokenizer/tokenize.h"
29#include "pw_unit_test/framework.h"
30
31namespace pw::allocator {
32namespace test {
33
34// A token that can be used in tests.
35constexpr pw::tokenizer::Token kToken = PW_TOKENIZE_STRING("test");
36
38template <size_t kBufferSize, typename MetricsType = internal::AllMetrics>
40 public:
42 using BlockType = AllocatorType::BlockType;
43
45 : Allocator(AllocatorType::kCapabilities), tracker_(kToken, *allocator_) {
47 allocator_->Init(allocator_.as_bytes());
48 }
49
50 ~AllocatorForTest() override {
51 for (auto* block : allocator_->blocks()) {
52 BlockType::Free(block);
53 }
54 allocator_->Reset();
55 }
56
57 AllocatorType::Range blocks() const { return allocator_->blocks(); }
58 AllocatorType::Range blocks() { return allocator_->blocks(); }
59
60 const metric::Group& metric_group() const { return tracker_.metric_group(); }
61 metric::Group& metric_group() { return tracker_.metric_group(); }
62
63 const MetricsType& metrics() const { return tracker_.metrics(); }
64
65 size_t allocate_size() const { return allocate_size_; }
66 void* deallocate_ptr() const { return deallocate_ptr_; }
67 size_t deallocate_size() const { return deallocate_size_; }
68 void* resize_ptr() const { return resize_ptr_; }
69 size_t resize_old_size() const { return resize_old_size_; }
70 size_t resize_new_size() const { return resize_new_size_; }
71
74 allocate_size_ = 0;
75 deallocate_ptr_ = nullptr;
76 deallocate_size_ = 0;
77 resize_ptr_ = nullptr;
78 resize_old_size_ = 0;
79 resize_new_size_ = 0;
80 }
81
83 void Exhaust() {
84 for (auto* block : allocator_->blocks()) {
85 block->MarkUsed();
86 }
87 }
88
89 private:
91 void* DoAllocate(Layout layout) override {
92 allocate_size_ = layout.size();
93 return tracker_.Allocate(layout);
94 }
95
97 void DoDeallocate(void* ptr) override {
98 Result<Layout> requested = GetRequestedLayout(tracker_, ptr);
99 deallocate_ptr_ = ptr;
100 deallocate_size_ = requested.ok() ? requested->size() : 0;
101 tracker_.Deallocate(ptr);
102 }
103
105 void DoDeallocate(void* ptr, Layout) override { DoDeallocate(ptr); }
106
108 bool DoResize(void* ptr, size_t new_size) override {
109 Result<Layout> requested = GetRequestedLayout(tracker_, ptr);
110 resize_ptr_ = ptr;
111 resize_old_size_ = requested.ok() ? requested->size() : 0;
112 resize_new_size_ = new_size;
113 return tracker_.Resize(ptr, new_size);
114 }
115
117 Result<Layout> DoGetInfo(InfoType info_type, const void* ptr) const override {
118 return GetInfo(tracker_, info_type, ptr);
119 }
120
121 WithBuffer<AllocatorType, kBufferSize> allocator_;
122 TrackingAllocator<MetricsType> tracker_;
123 size_t allocate_size_;
124 void* deallocate_ptr_;
125 size_t deallocate_size_;
126 void* resize_ptr_;
127 size_t resize_old_size_;
128 size_t resize_new_size_;
129};
130
133template <size_t kBufferSize, typename MetricsType = internal::AllMetrics>
135 private:
137
139 void* DoAllocate(Layout layout) override {
140 std::lock_guard lock(lock_);
141 return base_.Allocate(layout);
142 }
143
145 void DoDeallocate(void* ptr) override {
146 std::lock_guard lock(lock_);
147 base_.Deallocate(ptr);
148 }
149
151 void DoDeallocate(void* ptr, Layout) override { DoDeallocate(ptr); }
152
154 bool DoResize(void* ptr, size_t new_size) override {
155 std::lock_guard lock(lock_);
156 return base_.Resize(ptr, new_size);
157 }
158
160 Result<Layout> DoGetInfo(InfoType info_type, const void* ptr) const override {
161 std::lock_guard lock(lock_);
162 return GetInfo(base_, info_type, ptr);
163 }
164
165 mutable pw::sync::InterruptSpinLock lock_;
166 Base base_;
167};
168
169} // namespace test
170} // namespace pw::allocator
Definition: allocator.h:32
constexpr Allocator()=default
TODO(b/326509341): Remove when downstream consumers migrate.
bool Resize(void *ptr, size_t new_size)
Definition: allocator.h:81
void * Allocate(Layout layout)
Definition: allocator.h:40
void Deallocate(void *ptr)
Definition: deallocator.h:47
Definition: first_fit_block_allocator.h:33
Definition: layout.h:39
An AllocatorForTest that is automatically initialized on construction.
Definition: testing.h:39
void ResetParameters()
Resets the recorded parameters to an initial state.
Definition: testing.h:73
void Exhaust()
Allocates all the memory from this object.
Definition: testing.h:83
Definition: interrupt_spin_lock.h:48