• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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/buddy_allocator.h"
16 
17 #include <array>
18 #include <cstddef>
19 
20 #include "pw_allocator/fuzzing.h"
21 #include "pw_unit_test/framework.h"
22 
23 namespace {
24 
25 // Test fixtures.
26 
27 using BuddyAllocator = ::pw::allocator::BuddyAllocator<>;
28 using ::pw::allocator::Layout;
29 
30 static constexpr size_t kBufferSize = 0x400;
31 
32 // Unit tests.
33 
TEST(BuddyAllocatorTest,ExplicitlyInit)34 TEST(BuddyAllocatorTest, ExplicitlyInit) {
35   std::array<std::byte, kBufferSize> buffer;
36   BuddyAllocator allocator;
37   allocator.Init(buffer);
38 }
39 
TEST(BuddyAllocatorTest,AllocateSmall)40 TEST(BuddyAllocatorTest, AllocateSmall) {
41   std::array<std::byte, kBufferSize> buffer;
42   BuddyAllocator allocator(buffer);
43   void* ptr = allocator.Allocate(Layout(BuddyAllocator::kMinOuterSize / 2, 1));
44   ASSERT_NE(ptr, nullptr);
45   allocator.Deallocate(ptr);
46 }
47 
TEST(BuddyAllocatorTest,AllocateAllBlocks)48 TEST(BuddyAllocatorTest, AllocateAllBlocks) {
49   std::array<std::byte, kBufferSize> buffer;
50   BuddyAllocator allocator(buffer);
51   pw::Vector<void*, kBufferSize / BuddyAllocator::kMinOuterSize> ptrs;
52   while (true) {
53     void* ptr = allocator.Allocate(Layout(1, 1));
54     if (ptr == nullptr) {
55       break;
56     }
57     ptrs.push_back(ptr);
58   }
59   while (!ptrs.empty()) {
60     allocator.Deallocate(ptrs.back());
61     ptrs.pop_back();
62   }
63 }
64 
TEST(BuddyAllocatorTest,AllocateLarge)65 TEST(BuddyAllocatorTest, AllocateLarge) {
66   std::array<std::byte, kBufferSize> buffer;
67   BuddyAllocator allocator(buffer);
68   void* ptr = allocator.Allocate(Layout(48, 1));
69   ASSERT_NE(ptr, nullptr);
70   allocator.Deallocate(ptr);
71 }
72 
TEST(BuddyAllocatorTest,AllocateExcessiveSize)73 TEST(BuddyAllocatorTest, AllocateExcessiveSize) {
74   std::array<std::byte, kBufferSize> buffer;
75   BuddyAllocator allocator(buffer);
76   void* ptr = allocator.Allocate(Layout(786, 1));
77   EXPECT_EQ(ptr, nullptr);
78 }
79 
TEST(BuddyAllocatorTest,AllocateExcessiveAlignment)80 TEST(BuddyAllocatorTest, AllocateExcessiveAlignment) {
81   std::array<std::byte, kBufferSize> buffer;
82   BuddyAllocator allocator(buffer);
83   void* ptr = allocator.Allocate(Layout(48, 32));
84   EXPECT_EQ(ptr, nullptr);
85 }
86 
87 // Fuzz tests.
88 
89 using ::pw::allocator::test::DefaultArbitraryRequests;
90 using ::pw::allocator::test::Request;
91 using ::pw::allocator::test::TestHarness;
92 
NeverCrashes(const pw::Vector<Request> & requests)93 void NeverCrashes(const pw::Vector<Request>& requests) {
94   static std::array<std::byte, kBufferSize> buffer;
95   static BuddyAllocator allocator(buffer);
96   static TestHarness fuzzer(allocator);
97   fuzzer.HandleRequests(requests);
98 }
99 
100 FUZZ_TEST(BucketBlockAllocatorFuzzTest, NeverCrashes)
101     .WithDomains(DefaultArbitraryRequests());
102 
103 }  // namespace
104