xref: /aosp_15_r20/external/pigweed/pw_allocator/fallback_allocator_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_allocator/fallback_allocator.h"
16 
17 #include "pw_allocator/block/basic.h"
18 #include "pw_allocator/testing.h"
19 #include "pw_status/status.h"
20 #include "pw_unit_test/framework.h"
21 
22 namespace {
23 
24 using ::pw::allocator::FallbackAllocator;
25 using ::pw::allocator::Layout;
26 using ::pw::allocator::test::AllocatorForTest;
27 
28 // Test fixtures.
29 
30 class FallbackAllocatorTest : public ::testing::Test {
31  protected:
32   constexpr static size_t kCapacity = 256;
33   static_assert(sizeof(uintptr_t) >= AllocatorForTest<kCapacity>::kMinSize);
34 
FallbackAllocatorTest()35   FallbackAllocatorTest() : allocator_(primary_, secondary_) {}
36 
37   AllocatorForTest<kCapacity> primary_;
38   AllocatorForTest<kCapacity> secondary_;
39   FallbackAllocator allocator_;
40 };
41 
42 // Unit tests.
43 
TEST_F(FallbackAllocatorTest,GetCapacity)44 TEST_F(FallbackAllocatorTest, GetCapacity) {
45   pw::StatusWithSize capacity = allocator_.GetCapacity();
46   EXPECT_EQ(capacity.status(), pw::OkStatus());
47   EXPECT_EQ(capacity.size(), kCapacity);
48 }
49 
TEST_F(FallbackAllocatorTest,AllocateFromPrimary)50 TEST_F(FallbackAllocatorTest, AllocateFromPrimary) {
51   Layout layout = Layout::Of<uintptr_t>();
52   void* ptr = allocator_.Allocate(layout);
53   EXPECT_NE(ptr, nullptr);
54   EXPECT_EQ(primary_.allocate_size(), layout.size());
55   EXPECT_EQ(secondary_.allocate_size(), 0U);
56 }
57 
TEST_F(FallbackAllocatorTest,AllocateFromSecondary)58 TEST_F(FallbackAllocatorTest, AllocateFromSecondary) {
59   primary_.Exhaust();
60   Layout layout = Layout::Of<uintptr_t>();
61   void* ptr = allocator_.Allocate(layout);
62   EXPECT_NE(ptr, nullptr);
63   EXPECT_EQ(primary_.allocate_size(), layout.size());
64   EXPECT_EQ(secondary_.allocate_size(), layout.size());
65 }
66 
TEST_F(FallbackAllocatorTest,AllocateFailure)67 TEST_F(FallbackAllocatorTest, AllocateFailure) {
68   Layout layout = Layout::Of<uintptr_t[0x10000]>();
69   void* ptr = allocator_.Allocate(layout);
70   EXPECT_EQ(ptr, nullptr);
71   EXPECT_EQ(primary_.allocate_size(), layout.size());
72   EXPECT_EQ(secondary_.allocate_size(), layout.size());
73 }
74 
TEST_F(FallbackAllocatorTest,DeallocateUsingPrimary)75 TEST_F(FallbackAllocatorTest, DeallocateUsingPrimary) {
76   Layout layout = Layout::Of<uintptr_t>();
77   void* ptr = allocator_.Allocate(layout);
78   ASSERT_NE(ptr, nullptr);
79   allocator_.Deallocate(ptr);
80   EXPECT_EQ(primary_.deallocate_ptr(), ptr);
81   EXPECT_EQ(primary_.deallocate_size(), layout.size());
82   EXPECT_EQ(secondary_.deallocate_ptr(), nullptr);
83   EXPECT_EQ(secondary_.deallocate_size(), 0U);
84 }
85 
TEST_F(FallbackAllocatorTest,DeallocateUsingSecondary)86 TEST_F(FallbackAllocatorTest, DeallocateUsingSecondary) {
87   primary_.Exhaust();
88   Layout layout = Layout::Of<uintptr_t>();
89   void* ptr = allocator_.Allocate(layout);
90   ASSERT_NE(ptr, nullptr);
91   allocator_.Deallocate(ptr);
92   EXPECT_EQ(primary_.deallocate_ptr(), nullptr);
93   EXPECT_EQ(primary_.deallocate_size(), 0U);
94   EXPECT_EQ(secondary_.deallocate_ptr(), ptr);
95   EXPECT_EQ(secondary_.deallocate_size(), layout.size());
96 }
97 
TEST_F(FallbackAllocatorTest,ResizePrimary)98 TEST_F(FallbackAllocatorTest, ResizePrimary) {
99   Layout old_layout = Layout::Of<uintptr_t>();
100   void* ptr = allocator_.Allocate(old_layout);
101   ASSERT_NE(ptr, nullptr);
102 
103   size_t new_size = sizeof(uintptr_t[3]);
104   EXPECT_TRUE(allocator_.Resize(ptr, new_size));
105   EXPECT_EQ(primary_.resize_ptr(), ptr);
106   EXPECT_EQ(primary_.resize_old_size(), old_layout.size());
107   EXPECT_EQ(primary_.resize_new_size(), new_size);
108 
109   // Secondary should not be touched.
110   EXPECT_EQ(secondary_.resize_ptr(), nullptr);
111   EXPECT_EQ(secondary_.resize_old_size(), 0U);
112   EXPECT_EQ(secondary_.resize_new_size(), 0U);
113 }
114 
TEST_F(FallbackAllocatorTest,ResizePrimaryFailure)115 TEST_F(FallbackAllocatorTest, ResizePrimaryFailure) {
116   Layout old_layout = Layout::Of<uintptr_t>();
117   void* ptr = allocator_.Allocate(old_layout);
118   ASSERT_NE(ptr, nullptr);
119   primary_.Exhaust();
120 
121   size_t new_size = sizeof(uintptr_t[3]);
122   EXPECT_FALSE(allocator_.Resize(ptr, new_size));
123   EXPECT_EQ(primary_.resize_ptr(), ptr);
124   EXPECT_EQ(primary_.resize_old_size(), old_layout.size());
125   EXPECT_EQ(primary_.resize_new_size(), new_size);
126 
127   // Secondary should not be touched.
128   EXPECT_EQ(secondary_.resize_ptr(), nullptr);
129   EXPECT_EQ(secondary_.resize_old_size(), 0U);
130   EXPECT_EQ(secondary_.resize_new_size(), 0U);
131 }
132 
TEST_F(FallbackAllocatorTest,ResizeSecondary)133 TEST_F(FallbackAllocatorTest, ResizeSecondary) {
134   primary_.Exhaust();
135   Layout old_layout = Layout::Of<uintptr_t>();
136   void* ptr = allocator_.Allocate(old_layout);
137   ASSERT_NE(ptr, nullptr);
138 
139   size_t new_size = sizeof(uintptr_t[3]);
140   EXPECT_TRUE(allocator_.Resize(ptr, new_size));
141   EXPECT_EQ(secondary_.resize_ptr(), ptr);
142   EXPECT_EQ(secondary_.resize_old_size(), old_layout.size());
143   EXPECT_EQ(secondary_.resize_new_size(), new_size);
144 
145   // Primary should not be touched.
146   EXPECT_EQ(primary_.resize_ptr(), nullptr);
147   EXPECT_EQ(primary_.resize_old_size(), 0U);
148   EXPECT_EQ(primary_.resize_new_size(), 0U);
149 }
150 
TEST_F(FallbackAllocatorTest,ResizeSecondaryFailure)151 TEST_F(FallbackAllocatorTest, ResizeSecondaryFailure) {
152   primary_.Exhaust();
153   Layout old_layout = Layout::Of<uintptr_t>();
154   void* ptr = allocator_.Allocate(old_layout);
155   ASSERT_NE(ptr, nullptr);
156   secondary_.Exhaust();
157 
158   size_t new_size = sizeof(uintptr_t[3]);
159   EXPECT_FALSE(allocator_.Resize(ptr, new_size));
160   EXPECT_EQ(secondary_.resize_ptr(), ptr);
161   EXPECT_EQ(secondary_.resize_old_size(), old_layout.size());
162   EXPECT_EQ(secondary_.resize_new_size(), new_size);
163 
164   // Primary should not be touched.
165   EXPECT_EQ(primary_.resize_ptr(), nullptr);
166   EXPECT_EQ(primary_.resize_old_size(), 0U);
167   EXPECT_EQ(primary_.resize_new_size(), 0U);
168 }
169 
TEST_F(FallbackAllocatorTest,ReallocateSameAllocator)170 TEST_F(FallbackAllocatorTest, ReallocateSameAllocator) {
171   Layout old_layout = Layout::Of<uintptr_t>();
172   void* ptr1 = allocator_.Allocate(old_layout);
173   ASSERT_NE(ptr1, nullptr);
174 
175   // Claim subsequent memeory to force reallocation.
176   void* ptr2 = allocator_.Allocate(old_layout);
177   ASSERT_NE(ptr2, nullptr);
178 
179   Layout new_layout = Layout::Of<uintptr_t[3]>();
180   void* new_ptr = allocator_.Reallocate(ptr1, new_layout);
181   EXPECT_NE(new_ptr, nullptr);
182   EXPECT_EQ(primary_.deallocate_ptr(), ptr1);
183   EXPECT_EQ(primary_.deallocate_size(), old_layout.size());
184   EXPECT_EQ(primary_.allocate_size(), new_layout.size());
185 }
186 
TEST_F(FallbackAllocatorTest,ReallocateDifferentAllocator)187 TEST_F(FallbackAllocatorTest, ReallocateDifferentAllocator) {
188   Layout old_layout = Layout::Of<uintptr_t>();
189   void* ptr = allocator_.Allocate(old_layout);
190   primary_.Exhaust();
191 
192   Layout new_layout = Layout::Of<uintptr_t[3]>();
193   void* new_ptr = allocator_.Reallocate(ptr, new_layout);
194   EXPECT_NE(new_ptr, nullptr);
195   EXPECT_EQ(primary_.deallocate_ptr(), ptr);
196   EXPECT_EQ(primary_.deallocate_size(), old_layout.size());
197   EXPECT_EQ(secondary_.allocate_size(), new_layout.size());
198 }
199 
200 }  // namespace
201