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/partition_alloc_buildflags.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 #if 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 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 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 BUILDFLAG(HAS_MEMORY_TAGGING)
79 .SetMteReportingMode(mte_mode)
80 #endif
81 ;
82 }
83 #endif // BUILDFLAG(USE_PARTITION_ALLOC)
84
85 struct AllocationEventDispatcherInternalTest : public DispatcherTest {
GetAllocatedAddressbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest86 static void* GetAllocatedAddress() {
87 return reinterpret_cast<void*>(0x12345678);
88 }
GetAllocatedSizebase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest89 static unsigned int GetAllocatedSize() { return 35; }
GetEstimatedSizebase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest90 static unsigned int GetEstimatedSize() { return 77; }
GetFreedAddressbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest91 static void* GetFreedAddress() {
92 return reinterpret_cast<void*>(0x876543210);
93 }
94
95 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
GetNextAllocatorDispatchbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest96 AllocatorDispatch* GetNextAllocatorDispatch() { return &allocator_dispatch_; }
alloc_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest97 static void* alloc_function(const AllocatorDispatch*, size_t, void*) {
98 return GetAllocatedAddress();
99 }
alloc_unchecked_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest100 static void* alloc_unchecked_function(const AllocatorDispatch*,
101 size_t,
102 void*) {
103 return GetAllocatedAddress();
104 }
alloc_zero_initialized_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest105 static void* alloc_zero_initialized_function(const AllocatorDispatch*,
106 size_t,
107 size_t,
108 void*) {
109 return GetAllocatedAddress();
110 }
alloc_aligned_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest111 static void* alloc_aligned_function(const AllocatorDispatch*,
112 size_t,
113 size_t,
114 void*) {
115 return GetAllocatedAddress();
116 }
realloc_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest117 static void* realloc_function(const AllocatorDispatch*,
118 void*,
119 size_t,
120 void*) {
121 return GetAllocatedAddress();
122 }
get_size_estimate_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest123 static size_t get_size_estimate_function(const AllocatorDispatch*,
124 void*,
125 void*) {
126 return GetEstimatedSize();
127 }
good_size_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest128 static size_t good_size_function(const AllocatorDispatch*,
129 size_t size,
130 void*) {
131 return size;
132 }
claimed_address_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest133 static bool claimed_address_function(const AllocatorDispatch*, void*, void*) {
134 return GetEstimatedSize();
135 }
batch_malloc_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest136 static unsigned batch_malloc_function(const AllocatorDispatch*,
137 size_t,
138 void**,
139 unsigned num_requested,
140 void*) {
141 return num_requested;
142 }
aligned_malloc_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest143 static void* aligned_malloc_function(const AllocatorDispatch*,
144 size_t,
145 size_t,
146 void*) {
147 return GetAllocatedAddress();
148 }
aligned_realloc_functionbase::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest149 static void* aligned_realloc_function(const AllocatorDispatch*,
150 void*,
151 size_t,
152 size_t,
153 void*) {
154 return GetAllocatedAddress();
155 }
156
157 AllocatorDispatch allocator_dispatch_ = {
158 &alloc_function,
159 &alloc_unchecked_function,
160 &alloc_zero_initialized_function,
161 &alloc_aligned_function,
162 &realloc_function,
__anon8da88cf30202base::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest163 [](const AllocatorDispatch*, void*, void*) {},
164 &get_size_estimate_function,
165 &good_size_function,
166 &claimed_address_function,
167 &batch_malloc_function,
__anon8da88cf30302base::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest168 [](const AllocatorDispatch*, void**, unsigned, void*) {},
__anon8da88cf30402base::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest169 [](const AllocatorDispatch*, void*, size_t, void*) {},
__anon8da88cf30502base::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest170 [](const AllocatorDispatch*, void*, void*) {},
171 &aligned_malloc_function,
172 &aligned_realloc_function,
__anon8da88cf30602base::allocator::dispatcher::internal::__anon8da88cf30111::AllocationEventDispatcherInternalTest173 [](const AllocatorDispatch*, void*, void*) {}};
174 #endif
175 };
176
177 } // namespace
178
179 using ::testing::NaggyMock;
180 using ::testing::StrictMock;
181
182 using ObserverMock = StrictMock<testing::ObserverMock<>>;
183
184 #if defined(GTEST_HAS_DEATH_TEST) && GTEST_HAS_DEATH_TEST && DCHECK_IS_ON()
TEST(AllocationEventDispatcherInternalDeathTest,VerifyDeathWhenObserverIsNull)185 TEST(AllocationEventDispatcherInternalDeathTest,
186 VerifyDeathWhenObserverIsNull) {
187 testing::ObserverMock<int> observer_1;
188 testing::ObserverMock<float> observer_2;
189 testing::ObserverMock<size_t>* null_observer = nullptr;
190 testing::ObserverMock<double> observer_3;
191
192 const auto observer_ptrs =
193 std::make_tuple(&observer_1, &observer_2, null_observer, &observer_3);
194
195 EXPECT_DEATH({ GetNotificationHooks(observer_ptrs); }, "");
196 }
197 #endif // defined(GTEST_HAS_DEATH_TEST) && GTEST_HAS_DEATH_TEST &&
198 // DCHECK_IS_ON()
199
200 #if BUILDFLAG(USE_PARTITION_ALLOC)
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorHooksAreSet)201 TEST_F(AllocationEventDispatcherInternalTest,
202 VerifyPartitionAllocatorHooksAreSet) {
203 std::array<ObserverMock, 1> observers;
204
205 const auto dispatch_data =
206 GetNotificationHooks(CreateTupleOfPointers(observers));
207
208 EXPECT_NE(nullptr, dispatch_data.GetAllocationObserverHook());
209 EXPECT_NE(nullptr, dispatch_data.GetFreeObserverHook());
210 }
211
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorHooksAreNullWhenNoObservers)212 TEST_F(AllocationEventDispatcherInternalTest,
213 VerifyPartitionAllocatorHooksAreNullWhenNoObservers) {
214 const auto dispatch_data = GetNotificationHooks(std::make_tuple());
215
216 EXPECT_EQ(nullptr, dispatch_data.GetAllocationObserverHook());
217 EXPECT_EQ(nullptr, dispatch_data.GetFreeObserverHook());
218 }
219
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorAllocationHooksTriggerCorrectly)220 TEST_F(AllocationEventDispatcherInternalTest,
221 VerifyPartitionAllocatorAllocationHooksTriggerCorrectly) {
222 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
223
224 for (auto& mock : observers) {
225 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
226 EXPECT_CALL(
227 mock, OnAllocation(AllocationNotificationMatches(this, sizeof(*this))))
228 .Times(1);
229 EXPECT_CALL(mock, OnFree(_)).Times(0);
230 }
231
232 const auto dispatch_data =
233 GetNotificationHooks(CreateTupleOfPointers(observers));
234
235 ::partition_alloc::AllocationNotificationData notification_data =
236 CreatePAAllocationData(this, sizeof(*this));
237
238 dispatch_data.GetAllocationObserverHook()(notification_data);
239 }
240
TEST_F(AllocationEventDispatcherInternalTest,VerifyPartitionAllocatorFreeHooksTriggerCorrectly)241 TEST_F(AllocationEventDispatcherInternalTest,
242 VerifyPartitionAllocatorFreeHooksTriggerCorrectly) {
243 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
244
245 for (auto& mock : observers) {
246 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
247 EXPECT_CALL(mock, OnFree(_)).Times(0);
248 EXPECT_CALL(mock, OnFree(FreeNotificationMatches(this))).Times(1);
249 }
250
251 const auto dispatch_data =
252 GetNotificationHooks(CreateTupleOfPointers(observers));
253
254 dispatch_data.GetFreeObserverHook()(CreatePAFreeData(this));
255 }
256 #endif // BUILDFLAG(USE_PARTITION_ALLOC)
257
258 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimDataIsSet)259 TEST_F(AllocationEventDispatcherInternalTest, VerifyAllocatorShimDataIsSet) {
260 std::array<ObserverMock, 1> observers;
261
262 const auto dispatch_data =
263 GetNotificationHooks(CreateTupleOfPointers(observers));
264 const auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
265 EXPECT_NE(nullptr, allocator_dispatch);
266 EXPECT_NE(nullptr, allocator_dispatch->alloc_function);
267 EXPECT_NE(nullptr, allocator_dispatch->alloc_unchecked_function);
268 EXPECT_NE(nullptr, allocator_dispatch->alloc_zero_initialized_function);
269 EXPECT_NE(nullptr, allocator_dispatch->alloc_aligned_function);
270 EXPECT_NE(nullptr, allocator_dispatch->realloc_function);
271 EXPECT_NE(nullptr, allocator_dispatch->free_function);
272 EXPECT_NE(nullptr, allocator_dispatch->get_size_estimate_function);
273 EXPECT_NE(nullptr, allocator_dispatch->claimed_address_function);
274 EXPECT_NE(nullptr, allocator_dispatch->batch_malloc_function);
275 EXPECT_NE(nullptr, allocator_dispatch->batch_free_function);
276 EXPECT_NE(nullptr, allocator_dispatch->free_definite_size_function);
277 EXPECT_NE(nullptr, allocator_dispatch->try_free_default_function);
278 EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_function);
279 EXPECT_NE(nullptr, allocator_dispatch->aligned_realloc_function);
280 EXPECT_NE(nullptr, allocator_dispatch->aligned_free_function);
281 }
282
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimDataIsNullWhenNoObservers)283 TEST_F(AllocationEventDispatcherInternalTest,
284 VerifyAllocatorShimDataIsNullWhenNoObservers) {
285 const auto dispatch_data = GetNotificationHooks(std::make_tuple());
286
287 EXPECT_EQ(nullptr, dispatch_data.GetAllocatorDispatch());
288 }
289
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_function)290 TEST_F(AllocationEventDispatcherInternalTest,
291 VerifyAllocatorShimHooksTriggerCorrectly_alloc_function) {
292 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
293
294 for (auto& mock : observers) {
295 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
296 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
297 GetAllocatedAddress(), GetAllocatedSize(),
298 AllocationSubsystem::kAllocatorShim)))
299 .Times(1);
300 EXPECT_CALL(mock, OnFree(_)).Times(0);
301 }
302
303 auto const dispatch_data =
304 GetNotificationHooks(CreateTupleOfPointers(observers));
305
306 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
307 allocator_dispatch->next = GetNextAllocatorDispatch();
308
309 auto* const allocated_address = allocator_dispatch->alloc_function(
310 allocator_dispatch, GetAllocatedSize(), nullptr);
311
312 EXPECT_EQ(allocated_address, GetAllocatedAddress());
313 }
314
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_unchecked_function)315 TEST_F(AllocationEventDispatcherInternalTest,
316 VerifyAllocatorShimHooksTriggerCorrectly_alloc_unchecked_function) {
317 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
318
319 for (auto& mock : observers) {
320 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
321 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
322 GetAllocatedAddress(), GetAllocatedSize(),
323 AllocationSubsystem::kAllocatorShim)))
324 .Times(1);
325 EXPECT_CALL(mock, OnFree(_)).Times(0);
326 }
327
328 auto const dispatch_data =
329 GetNotificationHooks(CreateTupleOfPointers(observers));
330
331 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
332 allocator_dispatch->next = GetNextAllocatorDispatch();
333
334 auto* const allocated_address = allocator_dispatch->alloc_unchecked_function(
335 allocator_dispatch, GetAllocatedSize(), nullptr);
336
337 EXPECT_EQ(allocated_address, GetAllocatedAddress());
338 }
339
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_zero_initialized_function)340 TEST_F(
341 AllocationEventDispatcherInternalTest,
342 VerifyAllocatorShimHooksTriggerCorrectly_alloc_zero_initialized_function) {
343 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
344 constexpr int n = 8;
345
346 for (auto& mock : observers) {
347 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
348 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
349 GetAllocatedAddress(), n * GetAllocatedSize(),
350 AllocationSubsystem::kAllocatorShim)))
351 .Times(1);
352 EXPECT_CALL(mock, OnFree(_)).Times(0);
353 }
354
355 auto const dispatch_data =
356 GetNotificationHooks(CreateTupleOfPointers(observers));
357
358 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
359 allocator_dispatch->next = GetNextAllocatorDispatch();
360
361 auto* const allocated_address =
362 allocator_dispatch->alloc_zero_initialized_function(
363 allocator_dispatch, n, GetAllocatedSize(), nullptr);
364
365 EXPECT_EQ(allocated_address, GetAllocatedAddress());
366 }
367
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_alloc_aligned_function)368 TEST_F(AllocationEventDispatcherInternalTest,
369 VerifyAllocatorShimHooksTriggerCorrectly_alloc_aligned_function) {
370 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
371
372 for (auto& mock : observers) {
373 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
374 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
375 GetAllocatedAddress(), GetAllocatedSize(),
376 AllocationSubsystem::kAllocatorShim)))
377 .Times(1);
378 EXPECT_CALL(mock, OnFree(_)).Times(0);
379 }
380
381 auto const dispatch_data =
382 GetNotificationHooks(CreateTupleOfPointers(observers));
383
384 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
385 allocator_dispatch->next = GetNextAllocatorDispatch();
386
387 auto* const allocated_address = allocator_dispatch->alloc_aligned_function(
388 allocator_dispatch, 2048, GetAllocatedSize(), nullptr);
389
390 EXPECT_EQ(allocated_address, GetAllocatedAddress());
391 }
392
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_realloc_function)393 TEST_F(AllocationEventDispatcherInternalTest,
394 VerifyAllocatorShimHooksTriggerCorrectly_realloc_function) {
395 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
396
397 for (auto& mock : observers) {
398 InSequence execution_order;
399
400 EXPECT_CALL(mock,
401 OnFree(FreeNotificationMatches(
402 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
403 .Times(1);
404 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
405 GetAllocatedAddress(), GetAllocatedSize(),
406 AllocationSubsystem::kAllocatorShim)))
407 .Times(1);
408 }
409
410 auto const dispatch_data =
411 GetNotificationHooks(CreateTupleOfPointers(observers));
412
413 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
414 allocator_dispatch->next = GetNextAllocatorDispatch();
415
416 auto* const allocated_address = allocator_dispatch->realloc_function(
417 allocator_dispatch, GetFreedAddress(), GetAllocatedSize(), nullptr);
418
419 EXPECT_EQ(allocated_address, GetAllocatedAddress());
420 }
421
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_free_function)422 TEST_F(AllocationEventDispatcherInternalTest,
423 VerifyAllocatorShimHooksTriggerCorrectly_free_function) {
424 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
425
426 for (auto& mock : observers) {
427 EXPECT_CALL(mock,
428 OnFree(FreeNotificationMatches(
429 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
430 .Times(1);
431 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
432 }
433
434 auto const dispatch_data =
435 GetNotificationHooks(CreateTupleOfPointers(observers));
436
437 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
438 allocator_dispatch->next = GetNextAllocatorDispatch();
439
440 allocator_dispatch->free_function(allocator_dispatch, GetFreedAddress(),
441 nullptr);
442 }
443
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_get_size_estimate_function)444 TEST_F(AllocationEventDispatcherInternalTest,
445 VerifyAllocatorShimHooksTriggerCorrectly_get_size_estimate_function) {
446 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
447
448 for (auto& mock : observers) {
449 EXPECT_CALL(mock, OnFree(_)).Times(0);
450 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
451 }
452
453 auto const dispatch_data =
454 GetNotificationHooks(CreateTupleOfPointers(observers));
455
456 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
457 allocator_dispatch->next = GetNextAllocatorDispatch();
458
459 auto const estimated_size = allocator_dispatch->get_size_estimate_function(
460 allocator_dispatch, GetAllocatedAddress(), nullptr);
461
462 EXPECT_EQ(estimated_size, GetEstimatedSize());
463 }
464
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_batch_malloc_function)465 TEST_F(AllocationEventDispatcherInternalTest,
466 VerifyAllocatorShimHooksTriggerCorrectly_batch_malloc_function) {
467 constexpr size_t allocation_batch_size = 10;
468 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
469 std::array<void*, allocation_batch_size> allocation_batch = {nullptr};
470
471 for (auto& mock : observers) {
472 EXPECT_CALL(mock, OnFree(_)).Times(0);
473 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
474 nullptr, GetAllocatedSize(),
475 AllocationSubsystem::kAllocatorShim)))
476 .Times(allocation_batch_size);
477 }
478
479 auto const dispatch_data =
480 GetNotificationHooks(CreateTupleOfPointers(observers));
481
482 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
483 EXPECT_NE(allocator_dispatch->batch_malloc_function, nullptr);
484
485 allocator_dispatch->next = GetNextAllocatorDispatch();
486
487 auto const number_allocated = allocator_dispatch->batch_malloc_function(
488 allocator_dispatch, GetAllocatedSize(), allocation_batch.data(),
489 allocation_batch_size, nullptr);
490
491 EXPECT_EQ(number_allocated, allocation_batch_size);
492 }
493
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_batch_free_function)494 TEST_F(AllocationEventDispatcherInternalTest,
495 VerifyAllocatorShimHooksTriggerCorrectly_batch_free_function) {
496 constexpr size_t allocation_batch_size = 10;
497 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
498 std::array<void*, allocation_batch_size> allocation_batch;
499 allocation_batch.fill(GetFreedAddress());
500
501 for (auto& mock : observers) {
502 EXPECT_CALL(mock,
503 OnFree(FreeNotificationMatches(
504 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
505 .Times(allocation_batch_size);
506 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
507 }
508
509 auto const dispatch_data =
510 GetNotificationHooks(CreateTupleOfPointers(observers));
511
512 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
513 EXPECT_NE(allocator_dispatch->batch_free_function, nullptr);
514
515 allocator_dispatch->next = GetNextAllocatorDispatch();
516
517 allocator_dispatch->batch_free_function(allocator_dispatch,
518 allocation_batch.data(),
519 allocation_batch_size, nullptr);
520 }
521
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_free_definite_size_function)522 TEST_F(AllocationEventDispatcherInternalTest,
523 VerifyAllocatorShimHooksTriggerCorrectly_free_definite_size_function) {
524 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
525
526 for (auto& mock : observers) {
527 EXPECT_CALL(
528 mock, OnFree(FreeNotificationMatches(
529 GetAllocatedAddress(), AllocationSubsystem::kAllocatorShim)))
530 .Times(1);
531 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
532 }
533
534 DispatchData const dispatch_data =
535 GetNotificationHooks(CreateTupleOfPointers(observers));
536
537 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
538 EXPECT_NE(allocator_dispatch->free_definite_size_function, nullptr);
539
540 allocator_dispatch->next = GetNextAllocatorDispatch();
541
542 allocator_dispatch->free_definite_size_function(
543 allocator_dispatch, GetAllocatedAddress(), GetAllocatedSize(), nullptr);
544 }
545
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_try_free_default_function)546 TEST_F(AllocationEventDispatcherInternalTest,
547 VerifyAllocatorShimHooksTriggerCorrectly_try_free_default_function) {
548 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
549
550 for (auto& mock : observers) {
551 EXPECT_CALL(
552 mock, OnFree(FreeNotificationMatches(
553 GetAllocatedAddress(), AllocationSubsystem::kAllocatorShim)))
554 .Times(1);
555 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
556 }
557
558 DispatchData const dispatch_data =
559 GetNotificationHooks(CreateTupleOfPointers(observers));
560
561 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
562 EXPECT_NE(allocator_dispatch->try_free_default_function, nullptr);
563
564 allocator_dispatch->next = GetNextAllocatorDispatch();
565
566 allocator_dispatch->try_free_default_function(allocator_dispatch,
567 GetAllocatedAddress(), nullptr);
568 }
569
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_malloc_function)570 TEST_F(AllocationEventDispatcherInternalTest,
571 VerifyAllocatorShimHooksTriggerCorrectly_aligned_malloc_function) {
572 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
573
574 for (auto& mock : observers) {
575 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
576 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
577 GetAllocatedAddress(), GetAllocatedSize(),
578 AllocationSubsystem::kAllocatorShim)))
579 .Times(1);
580 EXPECT_CALL(mock, OnFree(_)).Times(0);
581 }
582
583 auto const dispatch_data =
584 GetNotificationHooks(CreateTupleOfPointers(observers));
585
586 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
587 allocator_dispatch->next = GetNextAllocatorDispatch();
588
589 auto* const allocated_address = allocator_dispatch->aligned_malloc_function(
590 allocator_dispatch, GetAllocatedSize(), 2048, nullptr);
591
592 EXPECT_EQ(allocated_address, GetAllocatedAddress());
593 }
594
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_realloc_function)595 TEST_F(AllocationEventDispatcherInternalTest,
596 VerifyAllocatorShimHooksTriggerCorrectly_aligned_realloc_function) {
597 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
598
599 for (auto& mock : observers) {
600 InSequence execution_order;
601
602 EXPECT_CALL(mock,
603 OnFree(FreeNotificationMatches(
604 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
605 .Times(1);
606 EXPECT_CALL(mock, OnAllocation(AllocationNotificationMatches(
607 GetAllocatedAddress(), GetAllocatedSize(),
608 AllocationSubsystem::kAllocatorShim)))
609 .Times(1);
610 }
611
612 auto const dispatch_data =
613 GetNotificationHooks(CreateTupleOfPointers(observers));
614
615 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
616 allocator_dispatch->next = GetNextAllocatorDispatch();
617
618 auto* const allocated_address = allocator_dispatch->aligned_realloc_function(
619 allocator_dispatch, GetFreedAddress(), GetAllocatedSize(), 2048, nullptr);
620
621 EXPECT_EQ(allocated_address, GetAllocatedAddress());
622 }
623
TEST_F(AllocationEventDispatcherInternalTest,VerifyAllocatorShimHooksTriggerCorrectly_aligned_free_function)624 TEST_F(AllocationEventDispatcherInternalTest,
625 VerifyAllocatorShimHooksTriggerCorrectly_aligned_free_function) {
626 std::array<ObserverMock, kMaximumNumberOfObservers> observers;
627
628 for (auto& mock : observers) {
629 EXPECT_CALL(mock,
630 OnFree(FreeNotificationMatches(
631 GetFreedAddress(), AllocationSubsystem::kAllocatorShim)))
632 .Times(1);
633 EXPECT_CALL(mock, OnAllocation(_)).Times(0);
634 }
635
636 auto const dispatch_data =
637 GetNotificationHooks(CreateTupleOfPointers(observers));
638
639 auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
640 allocator_dispatch->next = GetNextAllocatorDispatch();
641
642 allocator_dispatch->aligned_free_function(allocator_dispatch,
643 GetFreedAddress(), nullptr);
644 }
645 #endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
646 } // namespace base::allocator::dispatcher::internal
647