chromium/base/allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "partition_alloc/thread_cache.h"

#include <algorithm>
#include <atomic>
#include <vector>

#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/extended_api.h"
#include "partition_alloc/internal_allocator.h"
#include "partition_alloc/partition_address_space.h"
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
#include "partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/partition_alloc_for_testing.h"
#include "partition_alloc/partition_freelist_entry.h"
#include "partition_alloc/partition_lock.h"
#include "partition_alloc/partition_root.h"
#include "partition_alloc/tagging.h"
#include "testing/gtest/include/gtest/gtest.h"

// With *SAN, PartitionAlloc is replaced in partition_alloc.h by ASAN, so we
// cannot test the thread cache.
//
// Finally, the thread cache is not supported on all platforms.
#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && \
    PA_CONFIG(THREAD_CACHE_SUPPORTED)

namespace partition_alloc {

BucketDistribution;
PartitionFreelistEncoding;

struct ThreadCacheTestParam {};

const std::vector<ThreadCacheTestParam> params =;

namespace {

constexpr size_t kSmallSize =;  // Must be large enough to fit extras.
constexpr size_t kDefaultCountForSmallBucket =;
constexpr size_t kFillCountForSmallBucket =;

constexpr size_t kMediumSize =;
constexpr size_t kDefaultCountForMediumBucket =;
constexpr size_t kFillCountForMediumBucket =;

static_assert;

class DeltaCounter {};

// Forbid extras, since they make finding out which bucket is used harder.
std::unique_ptr<PartitionAllocatorForTesting> CreateAllocator(
    internal::PartitionFreelistEncoding encoding =
        internal::PartitionFreelistEncoding::kEncodedFreeList) {}
}  // namespace

class PartitionAllocThreadCacheTest
    : public ::testing::TestWithParam<ThreadCacheTestParam> {};

INSTANTIATE_TEST_SUITE_P();

TEST_P(PartitionAllocThreadCacheTest, Simple) {}

TEST_P(PartitionAllocThreadCacheTest, InexactSizeMatch) {}

TEST_P(PartitionAllocThreadCacheTest, MultipleObjectsCachedPerBucket) {}

TEST_P(PartitionAllocThreadCacheTest, ObjectsCachedCountIsLimited) {}

TEST_P(PartitionAllocThreadCacheTest, Purge) {}

TEST_P(PartitionAllocThreadCacheTest, NoCrossPartitionCache) {}

// Required to record hits and misses.
#if PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS)
TEST_P(PartitionAllocThreadCacheTest, LargeAllocationsAreNotCached) {}
#endif  // PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS)

TEST_P(PartitionAllocThreadCacheTest, DirectMappedAllocationsAreNotCached) {}

// This tests that Realloc properly handles bookkeeping, specifically the path
// that reallocates in place.
TEST_P(PartitionAllocThreadCacheTest, DirectMappedReallocMetrics) {}

namespace {

size_t FillThreadCacheAndReturnIndex(PartitionRoot* root,
                                     size_t size,
                                     BucketDistribution bucket_distribution,
                                     size_t count = 1) {}

// TODO(crbug.com/40158212): To remove callback from PartitionAlloc's DEPS,
// rewrite the tests without BindLambdaForTesting and RepeatingClosure.
// However this makes a little annoying to add more tests using their
// own threads. Need to support an easier way to implement tests using
// PlatformThreadForTesting::Create().
class ThreadDelegateForMultipleThreadCaches
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

TEST_P(PartitionAllocThreadCacheTest, MultipleThreadCaches) {}

namespace {

class ThreadDelegateForThreadCacheReclaimedWhenThreadExits
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

TEST_P(PartitionAllocThreadCacheTest, ThreadCacheReclaimedWhenThreadExits) {}

namespace {

class ThreadDelegateForThreadCacheRegistry
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

TEST_P(PartitionAllocThreadCacheTest, ThreadCacheRegistry) {}

#if PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS)
TEST_P(PartitionAllocThreadCacheTest, RecordStats) {}

namespace {

class ThreadDelegateForMultipleThreadCachesAccounting
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

TEST_P(PartitionAllocThreadCacheTest, MultipleThreadCachesAccounting) {}

#endif  // PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS)

// TODO(crbug.com/40816487): Flaky on IOS.
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_PurgeAll
#else
#define MAYBE_PurgeAll
#endif

namespace {

class ThreadDelegateForPurgeAll
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

TEST_P(PartitionAllocThreadCacheTest, MAYBE_PurgeAll)
PA_NO_THREAD_SAFETY_ANALYSIS {}

TEST_P(PartitionAllocThreadCacheTest, PeriodicPurge) {}

namespace {

void FillThreadCacheWithMemory(PartitionRoot* root,
                               size_t target_cached_memory,
                               BucketDistribution bucket_distribution) {}

class ThreadDelegateForPeriodicPurgeSumsOverAllThreads
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

// Disabled due to flakiness: crbug.com/1220371
TEST_P(PartitionAllocThreadCacheTest,
       DISABLED_PeriodicPurgeSumsOverAllThreads) {}

// TODO(crbug.com/40816487): Flaky on IOS.
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_DynamicCountPerBucket
#else
#define MAYBE_DynamicCountPerBucket
#endif
TEST_P(PartitionAllocThreadCacheTest, MAYBE_DynamicCountPerBucket) {}

TEST_P(PartitionAllocThreadCacheTest, DynamicCountPerBucketClamping) {}

// TODO(crbug.com/40816487): Flaky on IOS.
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_DynamicCountPerBucketMultipleThreads
#else
#define MAYBE_DynamicCountPerBucketMultipleThreads
#endif

namespace {

class ThreadDelegateForDynamicCountPerBucketMultipleThreads
    : public internal::base::PlatformThreadForTesting::Delegate {};

}  // namespace

TEST_P(PartitionAllocThreadCacheTest,
       MAYBE_DynamicCountPerBucketMultipleThreads) {}

TEST_P(PartitionAllocThreadCacheTest, DynamicSizeThreshold) {}

// Disabled due to flakiness: crbug.com/1287811
TEST_P(PartitionAllocThreadCacheTest, DISABLED_DynamicSizeThresholdPurge) {}

TEST_P(PartitionAllocThreadCacheTest, ClearFromTail) {}

// TODO(crbug.com/40816487): Flaky on IOS.
#if PA_BUILDFLAG(IS_IOS)
#define MAYBE_Bookkeeping
#else
#define MAYBE_Bookkeeping
#endif
TEST_P(PartitionAllocThreadCacheTest, MAYBE_Bookkeeping) {}

TEST_P(PartitionAllocThreadCacheTest, TryPurgeNoAllocs) {}

TEST_P(PartitionAllocThreadCacheTest, TryPurgeMultipleCorrupted) {}

TEST(AlternateBucketDistributionTest, SizeToIndex) {}

TEST_P(PartitionAllocThreadCacheTest, AllocationRecording) {}

TEST_P(PartitionAllocThreadCacheTest, AllocationRecordingAligned) {}

TEST_P(PartitionAllocThreadCacheTest, AllocationRecordingRealloc) {}

// This test makes sure it's safe to switch to the alternate bucket distribution
// at runtime. This is intended to happen once, near the start of Chrome,
// once we have enabled features.
TEST(AlternateBucketDistributionTest, SwitchBeforeAlloc) {}

// This test makes sure it's safe to switch to the alternate bucket distribution
// at runtime. This is intended to happen once, near the start of Chrome,
// once we have enabled features.
TEST(AlternateBucketDistributionTest, SwitchAfterAlloc) {}

}  // namespace partition_alloc

#endif  // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) &&
        // PA_CONFIG(THREAD_CACHE_SUPPORTED)