123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // Copyright (c) 2022 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "testing/gtest/include/gtest/gtest.h"
- #include "base/allocator/buildflags.h"
- #include "base/allocator/dispatcher/configuration.h"
- #include "base/allocator/dispatcher/dispatcher.h"
- #include "base/allocator/dispatcher/testing/dispatcher_test.h"
- #include "base/allocator/dispatcher/testing/tools.h"
- #include "build/build_config.h"
- #if BUILDFLAG(USE_PARTITION_ALLOC)
- #include "base/allocator/partition_allocator/partition_alloc.h"
- #endif
- #if BUILDFLAG(USE_ALLOCATOR_SHIM)
- #include "base/allocator/allocator_shim.h"
- #endif
- #include <tuple>
- namespace base::allocator::dispatcher {
- namespace {
- using configuration::kMaximumNumberOfObservers;
- using configuration::kMaximumNumberOfOptionalObservers;
- using partition_alloc::PartitionOptions;
- using partition_alloc::ThreadSafePartitionRoot;
- using testing::DispatcherTest;
- // A simple observer implementation. Since these tests plug in to Partition
- // Allocator and Allocator Shim, implementing an observer with Google Mock
- // results in endless recursion.
- struct ObserverMock {
- void OnAllocation(void* address,
- size_t size,
- AllocationSubsystem sub_system,
- const char* type_name) {
- ++on_allocation_calls_;
- }
- void OnFree(void* address) { ++on_free_calls_; }
- void Reset() {
- on_allocation_calls_ = 0;
- on_free_calls_ = 0;
- }
- size_t GetNumberOnAllocationCalls() const { return on_allocation_calls_; }
- size_t GetNumberOnFreeCalls() const { return on_free_calls_; }
- private:
- size_t on_allocation_calls_ = 0;
- size_t on_free_calls_ = 0;
- };
- struct DispatcherInitializerGuard {
- template <typename... Observers>
- explicit DispatcherInitializerGuard(std::tuple<Observers*...> observers) {
- Dispatcher::GetInstance().Initialize(observers);
- }
- ~DispatcherInitializerGuard() { Dispatcher::GetInstance().ResetForTesting(); }
- };
- struct BaseAllocatorDispatcherTest : public DispatcherTest {};
- template <typename A>
- void DoBasicTest(A& allocator) {
- // All we want to verify is that the Dispatcher correctly hooks into the
- // passed allocator. Therefore, we do not perform an exhaustive test but
- // just check some basics.
- std::array<ObserverMock, kMaximumNumberOfObservers> observers;
- {
- DispatcherInitializerGuard const g(
- testing::CreateTupleOfPointers(observers));
- constexpr size_t size_to_allocate = 1024;
- void* const ptr = allocator.Alloc(size_to_allocate);
- allocator.Free(ptr);
- }
- for (const auto& mock : observers) {
- EXPECT_GE(mock.GetNumberOnAllocationCalls(), 1u);
- EXPECT_GE(mock.GetNumberOnFreeCalls(), 1u);
- }
- }
- TEST_F(BaseAllocatorDispatcherTest, VerifyInitialization) {
- std::array<ObserverMock, kMaximumNumberOfObservers> observers;
- DispatcherInitializerGuard g(testing::CreateTupleOfPointers(observers));
- }
- #if BUILDFLAG(USE_PARTITION_ALLOC) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
- // Don't enable this test when MEMORY_TOOL_REPLACES_ALLOCATOR is defined,
- // because it makes PartitionAlloc take a different path that doesn't provide
- // notifications to observer hooks.
- struct PartitionAllocator {
- void* Alloc(size_t size) { return alloc_.AllocWithFlags(0, size, nullptr); }
- void Free(void* data) { alloc_.Free(data); }
- private:
- ThreadSafePartitionRoot alloc_{{
- PartitionOptions::AlignedAlloc::kDisallowed,
- PartitionOptions::ThreadCache::kDisabled,
- PartitionOptions::Quarantine::kDisallowed,
- PartitionOptions::Cookie::kAllowed,
- PartitionOptions::BackupRefPtr::kDisabled,
- PartitionOptions::BackupRefPtrZapping::kDisabled,
- PartitionOptions::UseConfigurablePool::kNo,
- }};
- };
- TEST_F(BaseAllocatorDispatcherTest, VerifyNotificationUsingPartitionAllocator) {
- PartitionAllocator allocator;
- DoBasicTest(allocator);
- }
- #endif
- #if BUILDFLAG(USE_ALLOCATOR_SHIM)
- struct AllocatorShimAllocator {
- void* Alloc(size_t size) { return base::allocator::UncheckedAlloc(size); }
- void Free(void* data) { base::allocator::UncheckedFree(data); }
- };
- #if BUILDFLAG(IS_APPLE) && !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
- // Disable the test when running on any of Apple's OSs without PartitionAlloc
- // being the default allocator. In this case, all allocations are routed to
- // MallocImpl, which then causes the test to terminate unexpectedly.
- #define MAYBE_VerifyNotificationUsingAllocatorShim \
- DISABLED_VerifyNotificationUsingAllocatorShim
- #else
- #define MAYBE_VerifyNotificationUsingAllocatorShim \
- VerifyNotificationUsingAllocatorShim
- #endif
- TEST_F(BaseAllocatorDispatcherTest, MAYBE_VerifyNotificationUsingAllocatorShim) {
- AllocatorShimAllocator allocator;
- DoBasicTest(allocator);
- }
- #endif
- } // namespace
- } // namespace base::allocator::dispatcher
|