Files
clang-p2996/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp
ChiaHungDuan 2dc9ec47fb [scudo] Refactor allocator config to support optional flags (#81805)
Instead of explicitly disabling a feature by declaring the variable and
set it to false, this change supports the optional flags. I.e., you can
skip certain flags if you are not using it.

This optional feature supports both forms,
  1. Value: A parameter for a feature. E.g., EnableRandomOffset
  2. Type: A C++ type implementing a feature. E.g., ConditionVariableT

On the other hand, to access the flags will be through one of the
wrappers, BaseConfig/PrimaryConfig/SecondaryConfig/CacheConfig
(CacheConfig is embedded in SecondaryConfig). These wrappers have the
getters to access the value and the type. When adding a new feature, we
need to add it to `allocator_config.def` and mark the new variable with
either *_REQUIRED_* or *_OPTIONAL_* macro so that the accessor will be
generated properly.

In addition, also remove the need of `UseConditionVariable` to flip
on/off of condition variable. Now we only need to define the type of
condition variable.
2024-03-13 16:05:24 -07:00

120 lines
4.2 KiB
C++

//===-- allocator_config_test.cpp -------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "tests/scudo_unit_test.h"
#include "allocator_config.h"
#include "allocator_config_wrapper.h"
#include "common.h"
#include "secondary.h"
#include <type_traits>
struct TestBaseConfig {
template <typename> using TSDRegistryT = void;
template <typename> using PrimaryT = void;
template <typename> using SecondaryT = void;
};
struct TestBaseConfigEnableOptionalFlag : public TestBaseConfig {
static const bool MaySupportMemoryTagging = true;
// Use the getter to avoid the test to `use` the address of static const
// variable (which requires additional explicit definition).
static bool getMaySupportMemoryTagging() { return MaySupportMemoryTagging; }
};
struct TestBasePrimaryConfig {
using SizeClassMap = void;
static const scudo::uptr RegionSizeLog = 18U;
static const scudo::uptr GroupSizeLog = 18U;
static const scudo::s32 MinReleaseToOsIntervalMs = INT32_MIN;
static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX;
typedef scudo::uptr CompactPtrT;
static const scudo::uptr CompactPtrScale = 0;
static const scudo::uptr MapSizeIncrement = 1UL << 18;
};
struct TestPrimaryConfig : public TestBaseConfig {
struct Primary : TestBasePrimaryConfig {};
};
struct TestPrimaryConfigEnableOptionalFlag : public TestBaseConfig {
struct Primary : TestBasePrimaryConfig {
static const bool EnableRandomOffset = true;
static bool getEnableRandomOffset() { return EnableRandomOffset; }
};
};
struct TestPrimaryConfigEnableOptionalType : public TestBaseConfig {
struct DummyConditionVariable {};
struct Primary : TestBasePrimaryConfig {
using ConditionVariableT = DummyConditionVariable;
};
};
struct TestSecondaryConfig : public TestPrimaryConfig {
struct Secondary {
template <typename Config>
using CacheT = scudo::MapAllocatorNoCache<Config>;
};
};
struct TestSecondaryCacheConfigEnableOptionalFlag : public TestPrimaryConfig {
struct Secondary {
struct Cache {
static const scudo::u32 EntriesArraySize = 256U;
static scudo::u32 getEntriesArraySize() { return EntriesArraySize; }
};
template <typename T> using CacheT = scudo::MapAllocatorCache<T>;
};
};
TEST(ScudoAllocatorConfigTest, VerifyOptionalFlags) {
// Test the top level allocator optional config.
//
// `MaySupportMemoryTagging` is default off.
EXPECT_FALSE(scudo::BaseConfig<TestBaseConfig>::getMaySupportMemoryTagging());
EXPECT_EQ(scudo::BaseConfig<
TestBaseConfigEnableOptionalFlag>::getMaySupportMemoryTagging(),
TestBaseConfigEnableOptionalFlag::getMaySupportMemoryTagging());
// Test primary optional config.
//
// `EnableRandomeOffset` is default off.
EXPECT_FALSE(
scudo::PrimaryConfig<TestPrimaryConfig>::getEnableRandomOffset());
EXPECT_EQ(
scudo::PrimaryConfig<
TestPrimaryConfigEnableOptionalFlag>::getEnableRandomOffset(),
TestPrimaryConfigEnableOptionalFlag::Primary::getEnableRandomOffset());
// `ConditionVariableT` is default off.
EXPECT_FALSE(
scudo::PrimaryConfig<TestPrimaryConfig>::hasConditionVariableT());
EXPECT_TRUE(scudo::PrimaryConfig<
TestPrimaryConfigEnableOptionalType>::hasConditionVariableT());
EXPECT_TRUE((std::is_same_v<
typename scudo::PrimaryConfig<
TestPrimaryConfigEnableOptionalType>::ConditionVariableT,
typename TestPrimaryConfigEnableOptionalType::Primary::
ConditionVariableT>));
// Test secondary cache optional config.
using NoCacheConfig =
scudo::SecondaryConfig<TestSecondaryConfig>::CacheConfig;
// `EntriesArraySize` is default 0.
EXPECT_EQ(NoCacheConfig::getEntriesArraySize(), 0U);
using CacheConfig = scudo::SecondaryConfig<
TestSecondaryCacheConfigEnableOptionalFlag>::CacheConfig;
EXPECT_EQ(CacheConfig::getEntriesArraySize(),
TestSecondaryCacheConfigEnableOptionalFlag::Secondary::Cache::
getEntriesArraySize());
}