xref: /aosp_15_r20/external/pigweed/pw_allocator/pmr_allocator_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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/pmr_allocator.h"
16 
17 #include <deque>
18 #include <forward_list>
19 #include <list>
20 #include <map>
21 #include <set>
22 #include <unordered_map>
23 #include <unordered_set>
24 #include <vector>
25 
26 #include "pw_allocator/testing.h"
27 #include "pw_unit_test/framework.h"
28 
29 namespace {
30 
31 // Test fixtures.
32 
33 using ::pw::allocator::PmrAllocator;
34 using ::pw::allocator::test::AllocatorForTest;
35 
36 struct Foo {
37   uintptr_t value;
38 
Foo__anonc77615730111::Foo39   Foo(uintptr_t value_) : value(value_) {}
40 };
41 
operator ==(const Foo & lhs,const Foo & rhs)42 bool operator==(const Foo& lhs, const Foo& rhs) {
43   return lhs.value == rhs.value;
44 }
45 
operator <(const Foo & lhs,const Foo & rhs)46 bool operator<(const Foo& lhs, const Foo& rhs) { return lhs.value < rhs.value; }
47 
48 }  // namespace
49 
50 template <>
51 struct std::hash<Foo> {
operator ()std::hash52   size_t operator()(const Foo& foo) const {
53     return std::hash<uintptr_t>()(foo.value);
54   }
55 };
56 
57 namespace {
58 
59 struct Bar {
60   std::array<std::byte, 16> buffer;
61 
Bar__anonc77615730211::Bar62   Bar(int value) { std::memset(buffer.data(), value, buffer.size()); }
63 };
64 
65 template <typename T, typename = void>
66 struct has_emplace_front : std::false_type {};
67 
68 template <typename T>
69 struct has_emplace_front<
70     T,
71     std::void_t<decltype(std::declval<T>().emplace_front())> >
72     : std::true_type {};
73 
74 template <typename T, typename = void>
75 struct has_emplace_back : std::false_type {};
76 
77 template <typename T>
78 struct has_emplace_back<
79     T,
80     std::void_t<decltype(std::declval<T>().emplace_back())> > : std::true_type {
81 };
82 
83 template <typename T, typename = void>
84 struct has_key_type : std::false_type {};
85 
86 template <typename T>
87 struct has_key_type<T, std::void_t<typename T::key_type> > : std::true_type {};
88 
89 template <typename T, typename = void>
90 struct has_mapped_type : std::false_type {};
91 
92 template <typename T>
93 struct has_mapped_type<T, std::void_t<typename T::mapped_type> >
94     : std::true_type {};
95 
96 template <typename Container, size_t kCapacity = 256>
TestPmrAllocator()97 void TestPmrAllocator() {
98   AllocatorForTest<kCapacity> underlying;
99   static_assert(sizeof(Foo) >= AllocatorForTest<kCapacity>::kMinSize);
100   auto& requested_bytes = underlying.metrics().requested_bytes;
101   EXPECT_EQ(requested_bytes.value(), 0U);
102 
103   PmrAllocator allocator(underlying);
104   {
105     Container container(allocator);
106     size_t size = 0;
107     // Sequence containers.
108     if constexpr (has_emplace_front<Container>::value) {
109       container.emplace_front(1);
110       container.emplace_front(2);
111       size += sizeof(typename Container::value_type) * 2;
112     }
113     if constexpr (has_emplace_back<Container>::value) {
114       container.emplace_back(3);
115       container.emplace_back(4);
116       size += sizeof(typename Container::value_type) * 2;
117     }
118     // Associative containers.
119     if constexpr (has_mapped_type<Container>::value) {
120       container.insert({1, 10});
121       container.insert({2, 20});
122       size += sizeof(typename Container::key_type) * 2;
123       size += sizeof(typename Container::mapped_type) * 2;
124     } else if constexpr (has_key_type<Container>::value) {
125       container.insert(3);
126       container.insert(4);
127       size += sizeof(typename Container::key_type) * 2;
128     }
129     EXPECT_GE(requested_bytes.value(), size);
130   }
131   EXPECT_EQ(requested_bytes.value(), 0U);
132 }
133 
134 // Unit tests.
135 
TEST(PmrAllocatorTest,Vector)136 TEST(PmrAllocatorTest, Vector) { TestPmrAllocator<pw::pmr::vector<Foo> >(); }
137 
TEST(PmrAllocatorTest,Deque)138 TEST(PmrAllocatorTest, Deque) {
139   // Some implementations preallocate a lot of memory.
140   TestPmrAllocator<pw::pmr::deque<Foo>, 8192>();
141 }
142 
TEST(PmrAllocatorTest,ForwardList)143 TEST(PmrAllocatorTest, ForwardList) {
144   TestPmrAllocator<pw::pmr::forward_list<Foo> >();
145 }
146 
TEST(PmrAllocatorTest,List)147 TEST(PmrAllocatorTest, List) { TestPmrAllocator<pw::pmr::list<Foo> >(); }
148 
TEST(PmrAllocatorTest,Set)149 TEST(PmrAllocatorTest, Set) { TestPmrAllocator<pw::pmr::set<Foo> >(); }
150 
TEST(PmrAllocatorTest,Map)151 TEST(PmrAllocatorTest, Map) { TestPmrAllocator<pw::pmr::map<Foo, Bar> >(); }
152 
TEST(PmrAllocatorTest,MultiSet)153 TEST(PmrAllocatorTest, MultiSet) {
154   TestPmrAllocator<pw::pmr::multiset<Foo> >();
155 }
156 
TEST(PmrAllocatorTest,MultiMap)157 TEST(PmrAllocatorTest, MultiMap) {
158   TestPmrAllocator<pw::pmr::multimap<Foo, Bar> >();
159 }
160 
TEST(PmrAllocatorTest,UnorderedSet)161 TEST(PmrAllocatorTest, UnorderedSet) {
162   // Some implementations preallocate a lot of memory.
163   TestPmrAllocator<pw::pmr::unordered_set<Foo>, 1024>();
164 }
165 
TEST(PmrAllocatorTest,UnorderedMap)166 TEST(PmrAllocatorTest, UnorderedMap) {
167   // Some implementations preallocate a lot of memory.
168   TestPmrAllocator<pw::pmr::unordered_map<Foo, Bar>, 1024>();
169 }
170 
TEST(PmrAllocatorTest,UnorderedMultiSet)171 TEST(PmrAllocatorTest, UnorderedMultiSet) {
172   // Some implementations preallocate a lot of memory.
173   TestPmrAllocator<pw::pmr::unordered_multiset<Foo>, 1024>();
174 }
175 
TEST(PmrAllocatorTest,UnorderedMultiMap)176 TEST(PmrAllocatorTest, UnorderedMultiMap) {
177   // Some implementations preallocate a lot of memory.
178   TestPmrAllocator<pw::pmr::unordered_multimap<Foo, Bar>, 1024>();
179 }
180 
181 }  // namespace
182