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