1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/allocator/dispatcher/internal/dispatcher_internal.h"
6
7 #include <iostream>
8 #include <tuple>
9 #include <utility>
10
11 #include "base/allocator/dispatcher/subsystem.h"
12 #include "base/allocator/dispatcher/testing/dispatcher_test.h"
13 #include "base/allocator/dispatcher/testing/observer_mock.h"
14 #include "base/allocator/dispatcher/testing/tools.h"
15 #include "base/dcheck_is_on.h"
16 #include "partition_alloc/buildflags.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 #if PA_BUILDFLAG(USE_PARTITION_ALLOC)
20 #include "partition_alloc/partition_alloc_allocation_data.h"
21 #endif
22
23 using ::base::allocator::dispatcher::AllocationSubsystem;
24 using ::base::allocator::dispatcher::configuration::kMaximumNumberOfObservers;
25 using ::base::allocator::dispatcher::testing::CreateTupleOfPointers;
26 using ::base::allocator::dispatcher::testing::DispatcherTest;
27 using ::testing::_;
28 using ::testing::AllOf;
29 using ::testing::InSequence;
30 using ::testing::Matcher;
31 using ::testing::Property;
32
33 namespace base::allocator::dispatcher::internal {
34
35 namespace {
36
AllocationNotificationMatches(Matcher<void * > address_matcher,Matcher<size_t> size_matcher,Matcher<AllocationSubsystem> subsystem_matcher=_)37 auto AllocationNotificationMatches(
38 Matcher<void*> address_matcher,
39 Matcher<size_t> size_matcher,
40 Matcher<AllocationSubsystem> subsystem_matcher = _) {
41 return AllOf(Property("address", &AllocationNotificationData::address,
42 std::move(address_matcher)),
43 Property("size", &AllocationNotificationData::size,
44 std::move(size_matcher)),
45 Property("allocation_subsystem",
46 &AllocationNotificationData::allocation_subsystem,
47 std::move(subsystem_matcher)));
48 }
49
FreeNotificationMatches(Matcher<void * > address_matcher,Matcher<AllocationSubsystem> subsystem_matcher=_)50 auto FreeNotificationMatches(
51 Matcher<void*> address_matcher,
52 Matcher<AllocationSubsystem> subsystem_matcher = _) {
53 return AllOf(Property("address", &FreeNotificationData::address,
54 std::move(address_matcher)),
55 Property("allocation_subsystem",
56 &FreeNotificationData::allocation_subsystem,
57 std::move(subsystem_matcher)));
58 }
59
60 #if PA_BUILDFLAG(USE_PARTITION_ALLOC)
CreatePAAllocationData(void * address,size_t size,partition_alloc::TagViolationReportingMode mte_mode=partition_alloc::TagViolationReportingMode::kUndefined)61 ::partition_alloc::AllocationNotificationData CreatePAAllocationData(
62 void* address,
63 size_t size,
64 partition_alloc::TagViolationReportingMode mte_mode =
65 partition_alloc::TagViolationReportingMode::kUndefined) {
66 return ::partition_alloc::AllocationNotificationData(address, size, nullptr)
67 #if PA_BUILDFLAG(HAS_MEMORY_TAGGING)
68 .SetMteReportingMode(mte_mode)
69 #endif
70 ;
71 }
72
CreatePAFreeData(void * address,partition_alloc::TagViolationReportingMode mte_mode=partition_alloc::TagViolationReportingMode::kUndefined)73 ::partition_alloc::FreeNotificationData CreatePAFreeData(
74 void* address,
75 partition_alloc::TagViolationReportingMode mte_mode =
76 partition_alloc::TagViolationReportingMode::kUndefined) {
77 return ::partition_alloc::FreeNotificationData(address)
78 #if PA_BUILDFLAG(HAS_MEMORY_TAGGING)
79 .SetMteReportingMode(mte_mode)
80 #endif
81 ;
82 }
83 #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC)
84
85 struct AllocationEventDispatcherInternalTest : public DispatcherTest {
GetAllocatedAddressbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest86 static void* GetAllocatedAddress() {
87 return reinterpret_cast<void*>(0x12345678);
88 }
GetAllocatedSizebase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest89 static unsigned int GetAllocatedSize() { return 35; }
GetEstimatedSizebase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest90 static unsigned int GetEstimatedSize() { return 77; }
GetFreedAddressbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest91 static void* GetFreedAddress() {
92 return reinterpret_cast<void*>(0x876543210);
93 }
94
95 #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
GetNextAllocatorDispatchbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest96 AllocatorDispatch* GetNextAllocatorDispatch() { return &allocator_dispatch_; }
alloc_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest97 static void* alloc_function(size_t, void*) { return GetAllocatedAddress(); }
alloc_unchecked_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest98 static void* alloc_unchecked_function(size_t, void*) {
99 return GetAllocatedAddress();
100 }
alloc_zero_initialized_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest101 static void* alloc_zero_initialized_function(size_t, size_t, void*) {
102 return GetAllocatedAddress();
103 }
alloc_aligned_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest104 static void* alloc_aligned_function(size_t, size_t, void*) {
105 return GetAllocatedAddress();
106 }
realloc_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest107 static void* realloc_function(void*, size_t, void*) {
108 return GetAllocatedAddress();
109 }
realloc_unchecked_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest110 static void* realloc_unchecked_function(void*, size_t, void*) {
111 return GetAllocatedAddress();
112 }
get_size_estimate_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest113 static size_t get_size_estimate_function(void*, void*) {
114 return GetEstimatedSize();
115 }
good_size_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest116 static size_t good_size_function(size_t size, void*) { return size; }
claimed_address_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest117 static bool claimed_address_function(void*, void*) {
118 return GetEstimatedSize();
119 }
batch_malloc_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest120 static unsigned batch_malloc_function(size_t,
121 void**,
122 unsigned num_requested,
123 void*) {
124 return num_requested;
125 }
aligned_malloc_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest126 static void* aligned_malloc_function(size_t, size_t, void*) {
127 return GetAllocatedAddress();
128 }
aligned_malloc_unchecked_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest129 static void* aligned_malloc_unchecked_function(size_t, size_t, void*) {
130 return GetAllocatedAddress();
131 }
aligned_realloc_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest132 static void* aligned_realloc_function(void*, size_t, size_t, void*) {
133 return GetAllocatedAddress();
134 }
aligned_realloc_unchecked_functionbase::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest135 static void* aligned_realloc_unchecked_function(void*,
136 size_t,
137 size_t,
138 void*) {
139 return GetAllocatedAddress();
140 }
141
142 AllocatorDispatch allocator_dispatch_ = {&alloc_function,
143 &alloc_unchecked_function,
144 &alloc_zero_initialized_function,
145 &alloc_aligned_function,
146 &realloc_function,
147 &realloc_unchecked_function,
__anonb8b4cd1d0202base::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest148 [](void*, void*) {},
149 &get_size_estimate_function,
150 &good_size_function,
151 &claimed_address_function,
152 &batch_malloc_function,
__anonb8b4cd1d0302base::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest153 [](void**, unsigned, void*) {},
__anonb8b4cd1d0402base::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest154 [](void*, size_t, void*) {},
__anonb8b4cd1d0502base::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest155 [](void*, void*) {},
156 &aligned_malloc_function,
157 &aligned_malloc_unchecked_function,
158 &aligned_realloc_function,
159 &aligned_realloc_unchecked_function,
__anonb8b4cd1d0602base::allocator::dispatcher::internal::__anonb8b4cd1d0111::AllocationEventDispatcherInternalTest160 [](void*, void*) {}};
161 #endif
162 };
163
164 } // namespace
165
166 using ::testing::NaggyMock;
167 using ::testing::StrictMock;
168
169 using ObserverMock = StrictMock<testing::ObserverMock<>>;
170
171 #if defined(GTEST_HAS_DEATH_TEST) && GTEST_HAS_DEATH_TEST && DCHECK_IS_ON()
TEST(AllocationEventDispatcherInternalDeathTest,VerifyDeathWhenObserverIsNull)172 TEST(AllocationEventDispatcherInternalDeathTest,
173 VerifyDeathWhenObserverIsNull) {
174 testing::ObserverMock<int> observer_1;
175 testing::ObserverMock<float> observer_2;
176 testing::ObserverMock<size_t>* null_observer = nullptr;
177 testing::ObserverMock<double> observer_3;
178
179 const auto observer_ptrs =
180 std::make_tuple(&observer_1, &observer_2, null_observer, &observer_3);
181
182 EXPECT_DEATH({ GetNotificationHooks(observer_ptrs); }, "");
183 }
184 #endif // defined(GTEST_HAS_DEATH_TEST) && GTEST_HAS_DEATH_TEST &&
185 // DCHECK_IS_ON()
186
187 #if PA_BUILDFLAG(USE_PARTITION_ALLOC)
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorHooksAreSet)188 TEST_F(AllocationEventDispatcherInternalTest,
189 VerifyPartitionAllocatorHooksAreSet) {
190 std::array<ObserverMock, 1> observers;
191
192 const auto dispatch_data =
193 GetNotificationHooks(CreateTupleOfPointers(observers));
194
195 EXPECT_NE(nullptr, dispatch_data.GetAllocationObserverHook());
196 EXPECT_NE(nullptr, dispatch_data.GetFreeObserverHook());
197 }
198
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorHooksAreNullWhenNoObservers)199 TEST_F(AllocationEventDispatcherInternalTest,
200 VerifyPartitionAllocatorHooksAreNullWhenNoObservers) {
201 const auto dispatch_data = GetNotificationHooks(std::make_tuple());
202
203 EXPECT_EQ(nullptr, dispatch_data.GetAllocationObserverHook());
204 EXPECT_EQ(nullptr, dispatch_data.GetFreeObserverHook());
205 }
206
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorAllocationHooksTriggerCorrectly)207 TEST_F(AllocationEventDispatcherInternalTest,
208 VerifyPartitionAllocatorAllocationHooksTriggerCorrectly) {
209 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
210
211 for (auto& mock : observers) {
212 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
213 EXPECT_CALL(
214 mock, OnAllocation(AllocationNotificationMatches(this, sizeof(*this))))
215 .Times(1);
216 EXPECT_CALL(mock, OnFree(_)).Times(0);
217 }
218
219 const auto dispatch_data =
220 GetNotificationHooks(CreateTupleOfPointers(observers));
221
222 ::partition_alloc::AllocationNotificationData notification_data =
223 CreatePAAllocationData(this, sizeof(*this));
224
225 dispatch_data.GetAllocationObserverHook()(notification_data);
226 }
227
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorFreeHooksTriggerCorrectly)228 TEST_F(AllocationEventDispatcherInternalTest,
229 VerifyPartitionAllocatorFreeHooksTriggerCorrectly) {
230 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
231
232 for (auto& mock : observers) {
233 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
234 EXPECT_CALL(mock, OnFree(_)).Times(0);
235 EXPECT_CALL(mock, OnFree(FreeNotificationMatches(this))).Times(1);
236 }
237
238 const auto dispatch_data =
239 GetNotificationHooks(CreateTupleOfPointers(observers));
240
241 dispatch_data.GetFreeObserverHook()(CreatePAFreeData(this));
242 }
243 #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC)
244
245 #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimDataIsSet)246 TEST_F(AllocationEventDispatcherInternalTest, VerifyAllocatorShimDataIsSet) {
247 std::array<ObserverMock, 1> observers;
248
249 const auto dispatch_data =
250 GetNotificationHooks(CreateTupleOfPointers(observers));
251 const auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
252 EXPECT_NE(nullptr, allocator_dispatch);
253 EXPECT_NE(nullptr, allocator_dispatch->alloc_function);
254 EXPECT_NE(nullptr, allocator_dispatch->alloc_unchecked_function);
255 EXPECT_NE(nullptr, allocator_dispatch->alloc_zero_initialized_function);
256 EXPECT_NE(nullptr, allocator_dispatch->alloc_aligned_function);
257 EXPECT_NE(nullptr, allocator_dispatch->realloc_function);
258 EXPECT_NE(nullptr, allocator_dispatch->realloc_unchecked_function);
259 EXPECT_NE(nullptr, allocator_dispatch->free_function);
260 EXPECT_NE(nullptr, allocator_dispatch->batch_malloc_function);
261 EXPECT_NE(nullptr, allocator_dispatch->batch_free_function);
262 EXPECT_NE(nullptr, allocator_dispatch->free_definite_size_function);
263 EXPECT_NE(nullptr, allocator_dispatch->try_free_default_function);
264 EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_function);
265 EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_unchecked_function);
266 EXPECT_NE(nullptr, allocator_dispatch->aligned_realloc_function);
267 EXPECT_NE(nullptr, allocator_dispatch->aligned_realloc_unchecked_function);
268 EXPECT_NE(nullptr, allocator_dispatch->aligned_free_function);
269 }
270
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimDataIsNullWhenNoObservers)271 TEST_F(AllocationEventDispatcherInternalTest,
272 VerifyAllocatorShimDataIsNullWhenNoObservers) {
273 const auto dispatch_data = GetNotificationHooks(std::make_tuple());
274
275 EXPECT_EQ(nullptr, dispatch_data.GetAllocatorDispatch());
276 }
277
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_function)278 TEST_F(AllocationEventDispatcherInternalTest,
279 VerifyAllocatorShimHooksTriggerCorrectly_alloc_function) {
280 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
281
282 for (auto& mock : observers) {
283 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
284 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
285 GetAllocatedAddress(), GetAllocatedSize(),
286 AllocationSubsystem::kAllocatorShim)))
287 .Times(1);
288 EXPECT_CALL(mock, OnFree(_)).Times(0);
289 }
290
291 auto const dispatch_data =
292 GetNotificationHooks(CreateTupleOfPointers(observers));
293
294 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
295 allocator_dispatch->next = GetNextAllocatorDispatch();
296
297 auto* const allocated_address =
298 allocator_dispatch->alloc_function(GetAllocatedSize(), nullptr);
299
300 EXPECT_EQ(allocated_address, GetAllocatedAddress());
301 }
302
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_unchecked_function)303 TEST_F(AllocationEventDispatcherInternalTest,
304 VerifyAllocatorShimHooksTriggerCorrectly_alloc_unchecked_function) {
305 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
306
307 for (auto& mock : observers) {
308 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
309 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
310 GetAllocatedAddress(), GetAllocatedSize(),
311 AllocationSubsystem::kAllocatorShim)))
312 .Times(1);
313 EXPECT_CALL(mock, OnFree(_)).Times(0);
314 }
315
316 auto const dispatch_data =
317 GetNotificationHooks(CreateTupleOfPointers(observers));
318
319 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
320 allocator_dispatch->next = GetNextAllocatorDispatch();
321
322 auto* const allocated_address =
323 allocator_dispatch->alloc_unchecked_function(GetAllocatedSize(), nullptr);
324
325 EXPECT_EQ(allocated_address, GetAllocatedAddress());
326 }
327
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_zero_initialized_function)328 TEST_F(
329 AllocationEventDispatcherInternalTest,
330 VerifyAllocatorShimHooksTriggerCorrectly_alloc_zero_initialized_function) {
331 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
332 constexpr int n = 8;
333
334 for (auto& mock : observers) {
335 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
336 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
337 GetAllocatedAddress(), n * GetAllocatedSize(),
338 AllocationSubsystem::kAllocatorShim)))
339 .Times(1);
340 EXPECT_CALL(mock, OnFree(_)).Times(0);
341 }
342
343 auto const dispatch_data =
344 GetNotificationHooks(CreateTupleOfPointers(observers));
345
346 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
347 allocator_dispatch->next = GetNextAllocatorDispatch();
348
349 auto* const allocated_address =
350 allocator_dispatch->alloc_zero_initialized_function(n, GetAllocatedSize(),
351 nullptr);
352
353 EXPECT_EQ(allocated_address, GetAllocatedAddress());
354 }
355
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_aligned_function)356 TEST_F(AllocationEventDispatcherInternalTest,
357 VerifyAllocatorShimHooksTriggerCorrectly_alloc_aligned_function) {
358 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
359
360 for (auto& mock : observers) {
361 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
362 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
363 GetAllocatedAddress(), GetAllocatedSize(),
364 AllocationSubsystem::kAllocatorShim)))
365 .Times(1);
366 EXPECT_CALL(mock, OnFree(_)).Times(0);
367 }
368
369 auto const dispatch_data =
370 GetNotificationHooks(CreateTupleOfPointers(observers));
371
372 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
373 allocator_dispatch->next = GetNextAllocatorDispatch();
374
375 auto* const allocated_address = allocator_dispatch->alloc_aligned_function(
376 2048, GetAllocatedSize(), nullptr);
377
378 EXPECT_EQ(allocated_address, GetAllocatedAddress());
379 }
380
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_realloc_function)381 TEST_F(AllocationEventDispatcherInternalTest,
382 VerifyAllocatorShimHooksTriggerCorrectly_realloc_function) {
383 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
384
385 for (auto& mock : observers) {
386 InSequence execution_order;
387
388 EXPECT_CALL(mock,
389 OnFree(FreeNotificationMatches(
390 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
391 .Times(1);
392 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
393 GetAllocatedAddress(), GetAllocatedSize(),
394 AllocationSubsystem::kAllocatorShim)))
395 .Times(1);
396 }
397
398 auto const dispatch_data =
399 GetNotificationHooks(CreateTupleOfPointers(observers));
400
401 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
402 allocator_dispatch->next = GetNextAllocatorDispatch();
403
404 auto* const allocated_address = allocator_dispatch->realloc_function(
405 GetFreedAddress(), GetAllocatedSize(), nullptr);
406
407 EXPECT_EQ(allocated_address, GetAllocatedAddress());
408 }
409
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_realloc_unchecked_function)410 TEST_F(AllocationEventDispatcherInternalTest,
411 VerifyAllocatorShimHooksTriggerCorrectly_realloc_unchecked_function) {
412 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
413
414 for (auto& mock : observers) {
415 InSequence execution_order;
416
417 EXPECT_CALL(mock,
418 OnFree(FreeNotificationMatches(
419 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
420 .Times(1);
421 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
422 GetAllocatedAddress(), GetAllocatedSize(),
423 AllocationSubsystem::kAllocatorShim)))
424 .Times(1);
425 }
426
427 auto const dispatch_data =
428 GetNotificationHooks(CreateTupleOfPointers(observers));
429
430 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
431 allocator_dispatch->next = GetNextAllocatorDispatch();
432
433 auto* const allocated_address =
434 allocator_dispatch->realloc_unchecked_function(
435 GetFreedAddress(), GetAllocatedSize(), nullptr);
436
437 EXPECT_EQ(allocated_address, GetAllocatedAddress());
438 }
439
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_free_function)440 TEST_F(AllocationEventDispatcherInternalTest,
441 VerifyAllocatorShimHooksTriggerCorrectly_free_function) {
442 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
443
444 for (auto& mock : observers) {
445 EXPECT_CALL(mock,
446 OnFree(FreeNotificationMatches(
447 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
448 .Times(1);
449 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
450 }
451
452 auto const dispatch_data =
453 GetNotificationHooks(CreateTupleOfPointers(observers));
454
455 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
456 allocator_dispatch->next = GetNextAllocatorDispatch();
457
458 allocator_dispatch->free_function(GetFreedAddress(), nullptr);
459 }
460
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_batch_malloc_function)461 TEST_F(AllocationEventDispatcherInternalTest,
462 VerifyAllocatorShimHooksTriggerCorrectly_batch_malloc_function) {
463 constexpr size_t allocation_batch_size = 10;
464 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
465 std::array<void*, allocation_batch_size> allocation_batch = {nullptr};
466
467 for (auto& mock : observers) {
468 EXPECT_CALL(mock, OnFree(_)).Times(0);
469 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
470 nullptr, GetAllocatedSize(),
471 AllocationSubsystem::kAllocatorShim)))
472 .Times(allocation_batch_size);
473 }
474
475 auto const dispatch_data =
476 GetNotificationHooks(CreateTupleOfPointers(observers));
477
478 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
479 EXPECT_NE(allocator_dispatch->batch_malloc_function, nullptr);
480
481 allocator_dispatch->next = GetNextAllocatorDispatch();
482
483 auto const number_allocated = allocator_dispatch->batch_malloc_function(
484 GetAllocatedSize(), allocation_batch.data(), allocation_batch_size,
485 nullptr);
486
487 EXPECT_EQ(number_allocated, allocation_batch_size);
488 }
489
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_batch_free_function)490 TEST_F(AllocationEventDispatcherInternalTest,
491 VerifyAllocatorShimHooksTriggerCorrectly_batch_free_function) {
492 constexpr size_t allocation_batch_size = 10;
493 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
494 std::array<void*, allocation_batch_size> allocation_batch;
495 allocation_batch.fill(GetFreedAddress());
496
497 for (auto& mock : observers) {
498 EXPECT_CALL(mock,
499 OnFree(FreeNotificationMatches(
500 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
501 .Times(allocation_batch_size);
502 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
503 }
504
505 auto const dispatch_data =
506 GetNotificationHooks(CreateTupleOfPointers(observers));
507
508 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
509 EXPECT_NE(allocator_dispatch->batch_free_function, nullptr);
510
511 allocator_dispatch->next = GetNextAllocatorDispatch();
512
513 allocator_dispatch->batch_free_function(allocation_batch.data(),
514 allocation_batch_size, nullptr);
515 }
516
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_free_definite_size_function)517 TEST_F(AllocationEventDispatcherInternalTest,
518 VerifyAllocatorShimHooksTriggerCorrectly_free_definite_size_function) {
519 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
520
521 for (auto& mock : observers) {
522 EXPECT_CALL(
523 mock, OnFree(FreeNotificationMatches(
524 GetAllocatedAddress(), AllocationSubsystem::kAllocatorShim)))
525 .Times(1);
526 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
527 }
528
529 DispatchData const dispatch_data =
530 GetNotificationHooks(CreateTupleOfPointers(observers));
531
532 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
533 EXPECT_NE(allocator_dispatch->free_definite_size_function, nullptr);
534
535 allocator_dispatch->next = GetNextAllocatorDispatch();
536
537 allocator_dispatch->free_definite_size_function(GetAllocatedAddress(),
538 GetAllocatedSize(), nullptr);
539 }
540
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_try_free_default_function)541 TEST_F(AllocationEventDispatcherInternalTest,
542 VerifyAllocatorShimHooksTriggerCorrectly_try_free_default_function) {
543 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
544
545 for (auto& mock : observers) {
546 EXPECT_CALL(
547 mock, OnFree(FreeNotificationMatches(
548 GetAllocatedAddress(), AllocationSubsystem::kAllocatorShim)))
549 .Times(1);
550 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
551 }
552
553 DispatchData const dispatch_data =
554 GetNotificationHooks(CreateTupleOfPointers(observers));
555
556 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
557 EXPECT_NE(allocator_dispatch->try_free_default_function, nullptr);
558
559 allocator_dispatch->next = GetNextAllocatorDispatch();
560
561 allocator_dispatch->try_free_default_function(GetAllocatedAddress(), nullptr);
562 }
563
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_malloc_function)564 TEST_F(AllocationEventDispatcherInternalTest,
565 VerifyAllocatorShimHooksTriggerCorrectly_aligned_malloc_function) {
566 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
567
568 for (auto& mock : observers) {
569 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
570 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
571 GetAllocatedAddress(), GetAllocatedSize(),
572 AllocationSubsystem::kAllocatorShim)))
573 .Times(1);
574 EXPECT_CALL(mock, OnFree(_)).Times(0);
575 }
576
577 auto const dispatch_data =
578 GetNotificationHooks(CreateTupleOfPointers(observers));
579
580 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
581 allocator_dispatch->next = GetNextAllocatorDispatch();
582
583 auto* const allocated_address = allocator_dispatch->aligned_malloc_function(
584 GetAllocatedSize(), 2048, nullptr);
585
586 EXPECT_EQ(allocated_address, GetAllocatedAddress());
587 }
588
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_malloc_unchecked_function)589 TEST_F(
590 AllocationEventDispatcherInternalTest,
591 VerifyAllocatorShimHooksTriggerCorrectly_aligned_malloc_unchecked_function) {
592 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
593
594 for (auto& mock : observers) {
595 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
596 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
597 GetAllocatedAddress(), GetAllocatedSize(),
598 AllocationSubsystem::kAllocatorShim)))
599 .Times(1);
600 EXPECT_CALL(mock, OnFree(_)).Times(0);
601 }
602
603 auto const dispatch_data =
604 GetNotificationHooks(CreateTupleOfPointers(observers));
605
606 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
607 allocator_dispatch->next = GetNextAllocatorDispatch();
608
609 auto* const allocated_address =
610 allocator_dispatch->aligned_malloc_unchecked_function(GetAllocatedSize(),
611 2048, nullptr);
612
613 EXPECT_EQ(allocated_address, GetAllocatedAddress());
614 }
615
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_realloc_function)616 TEST_F(AllocationEventDispatcherInternalTest,
617 VerifyAllocatorShimHooksTriggerCorrectly_aligned_realloc_function) {
618 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
619
620 for (auto& mock : observers) {
621 InSequence execution_order;
622
623 EXPECT_CALL(mock,
624 OnFree(FreeNotificationMatches(
625 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
626 .Times(1);
627 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
628 GetAllocatedAddress(), GetAllocatedSize(),
629 AllocationSubsystem::kAllocatorShim)))
630 .Times(1);
631 }
632
633 auto const dispatch_data =
634 GetNotificationHooks(CreateTupleOfPointers(observers));
635
636 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
637 allocator_dispatch->next = GetNextAllocatorDispatch();
638
639 auto* const allocated_address = allocator_dispatch->aligned_realloc_function(
640 GetFreedAddress(), GetAllocatedSize(), 2048, nullptr);
641
642 EXPECT_EQ(allocated_address, GetAllocatedAddress());
643 }
644
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_realloc_unchecked_function)645 TEST_F(
646 AllocationEventDispatcherInternalTest,
647 VerifyAllocatorShimHooksTriggerCorrectly_aligned_realloc_unchecked_function) {
648 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
649
650 for (auto& mock : observers) {
651 InSequence execution_order;
652
653 EXPECT_CALL(mock,
654 OnFree(FreeNotificationMatches(
655 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
656 .Times(1);
657 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
658 GetAllocatedAddress(), GetAllocatedSize(),
659 AllocationSubsystem::kAllocatorShim)))
660 .Times(1);
661 }
662
663 auto const dispatch_data =
664 GetNotificationHooks(CreateTupleOfPointers(observers));
665
666 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
667 allocator_dispatch->next = GetNextAllocatorDispatch();
668
669 auto* const allocated_address =
670 allocator_dispatch->aligned_realloc_unchecked_function(
671 GetFreedAddress(), GetAllocatedSize(), 2048, nullptr);
672
673 EXPECT_EQ(allocated_address, GetAllocatedAddress());
674 }
675
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_free_function)676 TEST_F(AllocationEventDispatcherInternalTest,
677 VerifyAllocatorShimHooksTriggerCorrectly_aligned_free_function) {
678 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
679
680 for (auto& mock : observers) {
681 EXPECT_CALL(mock,
682 OnFree(FreeNotificationMatches(
683 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
684 .Times(1);
685 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
686 }
687
688 auto const dispatch_data =
689 GetNotificationHooks(CreateTupleOfPointers(observers));
690
691 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
692 allocator_dispatch->next = GetNextAllocatorDispatch();
693
694 allocator_dispatch->aligned_free_function(GetFreedAddress(), nullptr);
695 }
696 #endif // PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
697 } // namespace base::allocator::dispatcher::internal
698