#include "partition_alloc/pointers/raw_ptr.h"
#include <climits>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <thread>
#include <type_traits>
#include <utility>
#include <variant>
#include "base/allocator/partition_alloc_features.h"
#include "base/allocator/partition_alloc_support.h"
#include "base/cpu.h"
#include "base/metrics/histogram_base.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/memory/dangling_ptr_instrumentation.h"
#include "base/test/scoped_feature_list.h"
#include "base/types/to_address.h"
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/dangling_raw_ptr_checks.h"
#include "partition_alloc/partition_alloc-inl.h"
#include "partition_alloc/partition_alloc.h"
#include "partition_alloc/partition_alloc_base/cpu.h"
#include "partition_alloc/partition_alloc_base/logging.h"
#include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/partition_alloc_constants.h"
#include "partition_alloc/partition_alloc_hooks.h"
#include "partition_alloc/partition_root.h"
#include "partition_alloc/pointers/instance_tracer.h"
#include "partition_alloc/pointers/raw_ptr_counting_impl_for_test.h"
#include "partition_alloc/pointers/raw_ptr_test_support.h"
#include "partition_alloc/pointers/raw_ref.h"
#include "partition_alloc/tagging.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
#include <sanitizer/asan_interface.h>
#include "base/debug/asan_service.h"
#endif
AllOf;
Eq;
HasSubstr;
IsEmpty;
Ne;
SizeIs;
Test;
#if !PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER)
static_assert …;
static_assert …;
static_assert …;
#endif
#if !PA_BUILDFLAG(USE_RAW_PTR_BACKUP_REF_IMPL) && \
!PA_BUILDFLAG(USE_RAW_PTR_ASAN_UNOWNED_IMPL) && \
!PA_BUILDFLAG(USE_RAW_PTR_HOOKABLE_IMPL) && \
!PA_BUILDFLAG(RAW_PTR_ZERO_ON_MOVE) && \
!PA_BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT)
static_assert(std::is_trivially_copyable_v<raw_ptr<void>>,
"raw_ptr should be trivially copyable");
static_assert(std::is_trivially_copyable_v<raw_ptr<int>>,
"raw_ptr should be trivially copyable");
static_assert(std::is_trivially_copyable_v<raw_ptr<std::string>>,
"raw_ptr should be trivially copyable");
#endif
#if !PA_BUILDFLAG(USE_RAW_PTR_BACKUP_REF_IMPL) && \
!PA_BUILDFLAG(USE_RAW_PTR_ASAN_UNOWNED_IMPL) && \
!PA_BUILDFLAG(USE_RAW_PTR_HOOKABLE_IMPL) && \
!PA_BUILDFLAG(RAW_PTR_ZERO_ON_CONSTRUCT) && \
!PA_BUILDFLAG(RAW_PTR_ZERO_ON_DESTRUCT)
static_assert(std::is_trivially_default_constructible_v<raw_ptr<void>>,
"raw_ptr should be trivially default constructible");
static_assert(std::is_trivially_default_constructible_v<raw_ptr<int>>,
"raw_ptr should be trivially default constructible");
static_assert(std::is_trivially_default_constructible_v<raw_ptr<std::string>>,
"raw_ptr should be trivially default constructible");
#endif
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
static_assert …;
#endif
struct StructWithoutTypeBasedTraits { … };
struct BaseWithTypeBasedTraits { … };
struct DerivedWithTypeBasedTraits : BaseWithTypeBasedTraits { … };
namespace base::raw_ptr_traits {
kTypeTraits;
}
static_assert …;
static_assert …;
static_assert …;
namespace {
RawPtrCountingImpl;
CountingRawPtr;
static_assert …;
CountingRawPtrMayDangle;
static_assert …;
CountingRawPtrUninitialized;
static_assert …;
struct MyStruct { … };
struct Base1 { … };
struct Base2 { … };
struct Derived : Base1, Base2 { … };
class RawPtrTest : public Test { … };
volatile int g_volatile_int_to_ignore;
TEST_F(RawPtrTest, NullStarDereference) { … }
TEST_F(RawPtrTest, NullArrowDereference) { … }
TEST_F(RawPtrTest, NullExtractNoDereference) { … }
TEST_F(RawPtrTest, InvalidExtractNoDereference) { … }
TEST_F(RawPtrTest, NullCmpExplicit) { … }
TEST_F(RawPtrTest, NullCmpBool) { … }
void FuncThatAcceptsBool(bool b) { … }
bool IsValidNoCast(CountingRawPtr<int> ptr) { … }
bool IsValidNoCast2(CountingRawPtr<int> ptr) { … }
TEST_F(RawPtrTest, BoolOpNotCast) { … }
bool IsValidWithCast(CountingRawPtr<int> ptr) { … }
TEST_F(RawPtrTest, CastNotBoolOp) { … }
TEST_F(RawPtrTest, StarDereference) { … }
TEST_F(RawPtrTest, ArrowDereference) { … }
TEST_F(RawPtrTest, Delete) { … }
TEST_F(RawPtrTest, ClearAndDelete) { … }
TEST_F(RawPtrTest, ClearAndDeleteArray) { … }
TEST_F(RawPtrTest, ExtractAsDangling) { … }
TEST_F(RawPtrTest, ExtractAsDanglingFromDangling) { … }
TEST_F(RawPtrTest, ConstVolatileVoidPtr) { … }
TEST_F(RawPtrTest, VoidPtr) { … }
TEST_F(RawPtrTest, OperatorEQ) { … }
TEST_F(RawPtrTest, OperatorNE) { … }
TEST_F(RawPtrTest, OperatorEQCast) { … }
TEST_F(RawPtrTest, OperatorEQCastHierarchy) { … }
TEST_F(RawPtrTest, OperatorNECast) { … }
TEST_F(RawPtrTest, OperatorNECastHierarchy) { … }
TEST_F(RawPtrTest, Cast) { … }
TEST_F(RawPtrTest, UpcastConvertible) { … }
TEST_F(RawPtrTest, UpcastNotConvertible) { … }
TEST_F(RawPtrTest, UpcastPerformance) { … }
TEST_F(RawPtrTest, CustomSwap) { … }
TEST_F(RawPtrTest, StdSwap) { … }
TEST_F(RawPtrTest, PostIncrementOperator) { … }
TEST_F(RawPtrTest, PostDecrementOperator) { … }
TEST_F(RawPtrTest, PreIncrementOperator) { … }
TEST_F(RawPtrTest, PreDecrementOperator) { … }
TEST_F(RawPtrTest, PlusEqualOperator) { … }
TEST_F(RawPtrTest, PlusEqualOperatorTypes) { … }
TEST_F(RawPtrTest, MinusEqualOperator) { … }
TEST_F(RawPtrTest, MinusEqualOperatorTypes) { … }
TEST_F(RawPtrTest, PlusOperator) { … }
TEST_F(RawPtrTest, MinusOperator) { … }
TEST_F(RawPtrTest, MinusDeltaOperator) { … }
TEST_F(RawPtrTest, AdvanceString) { … }
TEST_F(RawPtrTest, AssignmentFromNullptr) { … }
void FunctionWithRawPtrParameter(raw_ptr<int> actual_ptr, int* expected_ptr) { … }
TEST_F(RawPtrTest, FunctionParameters_ImplicitlyMovedTemporary) { … }
TEST_F(RawPtrTest, FunctionParameters_ExplicitlyMovedLValue) { … }
TEST_F(RawPtrTest, FunctionParameters_Copy) { … }
TEST_F(RawPtrTest, SetLookupUsesGetForComparison) { … }
TEST_F(RawPtrTest, ComparisonOperatorUsesGetForComparison) { … }
TEST_F(RawPtrTest, OperatorsUseGetForComparison) { … }
TEST_F(RawPtrTest, TrivialRelocability) { … }
struct BaseStruct { … };
struct DerivedType1 : public BaseStruct { … };
struct DerivedType2 : public BaseStruct { … };
TEST_F(RawPtrTest, DerivedStructsComparison) { … }
class PmfTestBase { … };
class PmfTestDerived : public PmfTestBase { … };
TEST_F(RawPtrTest, PointerToMemberFunction) { … }
TEST_F(RawPtrTest, WorksWithOptional) { … }
TEST_F(RawPtrTest, WorksWithVariant) { … }
TEST_F(RawPtrTest, CrossKindConversion) { … }
TEST_F(RawPtrTest, CrossKindAssignment) { … }
TEST_F(RawPtrTest, ToAddressDoesNotDereference) { … }
TEST_F(RawPtrTest, ToAddressGivesBackRawAddress) { … }
void InOutParamFuncWithPointer(int* in, int** out) { … }
TEST_F(RawPtrTest, EphemeralRawAddrPointerPointer) { … }
void InOutParamFuncWithReference(int* in, int*& out) { … }
TEST_F(RawPtrTest, EphemeralRawAddrPointerReference) { … }
#if !PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER)
#if PA_BUILDFLAG(PA_COMPILER_GCC) && !defined(__clang__)
#pragma GCC push_options
#pragma GCC optimize("O0")
#endif
TEST_F(RawPtrTest, AllowUninitialized) { … }
#if PA_BUILDFLAG(PA_COMPILER_GCC) && !defined(__clang__)
#pragma GCC pop_options
#endif
#endif
}
namespace base::internal {
#if PA_BUILDFLAG(USE_RAW_PTR_BACKUP_REF_IMPL) && \
!defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
void HandleOOM(size_t unused_size) { … }
class BackupRefPtrTest : public testing::Test { … };
TEST_F(BackupRefPtrTest, Basic) { … }
TEST_F(BackupRefPtrTest, ZeroSized) { … }
TEST_F(BackupRefPtrTest, EndPointer) { … }
TEST_F(BackupRefPtrTest, QuarantinedBytes) { … }
TEST_F(BackupRefPtrTest, SameSlotAssignmentWhenDangling) { … }
void RunBackupRefPtrImplAdvanceTest(
partition_alloc::PartitionAllocator& allocator,
size_t requested_size) { … }
TEST_F(BackupRefPtrTest, Advance) { … }
TEST_F(BackupRefPtrTest, AdvanceAcrossPools) { … }
TEST_F(BackupRefPtrTest, GetDeltaElems) { … }
volatile char g_volatile_char_to_ignore;
TEST_F(BackupRefPtrTest, IndexOperator) { … }
bool IsQuarantineEmpty(partition_alloc::PartitionAllocator& allocator) { … }
struct BoundRawPtrTestHelper { … };
TEST_F(BackupRefPtrTest, Bind) { … }
#if PA_CONFIG(IN_SLOT_METADATA_CHECK_COOKIE)
TEST_F(BackupRefPtrTest, ReinterpretCast) {
void* ptr = allocator_.root()->Alloc(16);
allocator_.root()->Free(ptr);
raw_ptr<void>* wrapped_ptr = reinterpret_cast<raw_ptr<void>*>(&ptr);
BASE_EXPECT_DEATH(*wrapped_ptr = nullptr, "");
}
#endif
TEST_F(BackupRefPtrTest, WorksWithOptional) { … }
TEST_F(BackupRefPtrTest, WorksWithVariant) { … }
namespace {
class ScopedInstallDanglingRawPtrChecks { … };
}
TEST_F(BackupRefPtrTest, RawPtrMayDangle) { … }
TEST_F(BackupRefPtrTest, RawPtrNotDangling) { … }
TEST_F(BackupRefPtrTest, DanglingPtrComparison) { … }
TEST_F(BackupRefPtrTest, DanglingPtrAssignment) { … }
TEST_F(BackupRefPtrTest, DanglingPtrCopyContructor) { … }
TEST_F(BackupRefPtrTest, RawPtrExtractAsDangling) { … }
TEST_F(BackupRefPtrTest, RawPtrDeleteWithoutExtractAsDangling) { … }
TEST_F(BackupRefPtrTest, SpatialAlgoCompat) { … }
#if PA_BUILDFLAG(BACKUP_REF_PTR_POISON_OOB_PTR)
TEST_F(BackupRefPtrTest, Duplicate) {
size_t requested_size = allocator_.root()->AdjustSizeForExtrasSubtract(512);
char* ptr = static_cast<char*>(allocator_.root()->Alloc(requested_size));
raw_ptr<char, AllowPtrArithmetic> protected_ptr1 = ptr;
protected_ptr1 += requested_size;
raw_ptr<char, AllowPtrArithmetic> protected_ptr2 = protected_ptr1;
EXPECT_DEATH_IF_SUPPORTED(*protected_ptr2 = ' ', "");
raw_ptr<char, AllowPtrArithmetic> protected_ptr3;
protected_ptr3 = protected_ptr1;
EXPECT_DEATH_IF_SUPPORTED(*protected_ptr3 = ' ', "");
protected_ptr1 = nullptr;
protected_ptr2 = nullptr;
protected_ptr3 = nullptr;
allocator_.root()->Free(ptr);
}
#endif
#if PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON)
TEST_F(BackupRefPtrTest, WriteAfterFree) { … }
#endif
namespace {
constexpr uint8_t kCustomQuarantineByte = …;
static_assert …;
void CustomQuarantineHook(void* address, size_t size) { … }
}
TEST_F(BackupRefPtrTest, QuarantineHook) { … }
TEST_F(BackupRefPtrTest, RawPtrTraits_DisableBRP) { … }
#endif
#if PA_BUILDFLAG(USE_RAW_PTR_HOOKABLE_IMPL)
namespace {
#define FOR_EACH_RAW_PTR_OPERATION …
struct CountingHooks {
void ResetCounts() {
#define F …
FOR_EACH_RAW_PTR_OPERATION(F)
#undef F
}
static CountingHooks* Get() {
static thread_local CountingHooks instance;
return &instance;
}
#define F …
FOR_EACH_RAW_PTR_OPERATION(F)
#undef F
};
constexpr RawPtrHooks raw_ptr_hooks{
#define F …
FOR_EACH_RAW_PTR_OPERATION(F)
#undef F
};
}
class HookableRawPtrImplTest : public testing::Test {
protected:
void SetUp() override { InstallRawPtrHooks(&raw_ptr_hooks); }
void TearDown() override { ResetRawPtrHooks(); }
};
TEST_F(HookableRawPtrImplTest, WrapPtr) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
[[maybe_unused]] raw_ptr<int> interesting_ptr = ptr;
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->wrap_ptr_count, 1u);
}
TEST_F(HookableRawPtrImplTest, ReleaseWrappedPtr) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
[[maybe_unused]] raw_ptr<int> interesting_ptr = ptr;
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->release_wrapped_ptr_count, 1u);
}
TEST_F(HookableRawPtrImplTest, SafelyUnwrapForDereference) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
raw_ptr<int> interesting_ptr = ptr;
*interesting_ptr = 1;
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->safely_unwrap_for_dereference_count, 1u);
}
TEST_F(HookableRawPtrImplTest, SafelyUnwrapForExtraction) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
raw_ptr<int> interesting_ptr = ptr;
ptr = interesting_ptr;
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->safely_unwrap_for_extraction_count, 1u);
}
TEST_F(HookableRawPtrImplTest, UnsafelyUnwrapForComparison) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
raw_ptr<int> interesting_ptr = ptr;
EXPECT_EQ(interesting_ptr, ptr);
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->unsafely_unwrap_for_comparison_count, 1u);
}
TEST_F(HookableRawPtrImplTest, Advance) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int[10];
raw_ptr<int, AllowPtrArithmetic> interesting_ptr = ptr;
interesting_ptr += 1;
delete[] ptr;
}
EXPECT_EQ(CountingHooks::Get()->advance_count, 1u);
}
TEST_F(HookableRawPtrImplTest, Duplicate) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
raw_ptr<int> interesting_ptr = ptr;
raw_ptr<int> interesting_ptr2 = interesting_ptr;
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->duplicate_count, 1u);
}
TEST_F(HookableRawPtrImplTest, CrossKindCopyConstruction) {
CountingHooks::Get()->ResetCounts();
{
int* ptr = new int;
raw_ptr<int> non_dangling_ptr = ptr;
raw_ptr<int, RawPtrTraits::kMayDangle> dangling_ptr(non_dangling_ptr);
delete ptr;
}
EXPECT_EQ(CountingHooks::Get()->duplicate_count, 0u);
EXPECT_EQ(CountingHooks::Get()->wrap_ptr_for_duplication_count, 1u);
EXPECT_EQ(CountingHooks::Get()->unsafely_unwrap_for_duplication_count, 1u);
}
#endif
TEST(DanglingPtrTest, DetectAndReset) { … }
TEST(DanglingPtrTest, DetectAndDestructor) { … }
TEST(DanglingPtrTest, DetectResetAndDestructor) { … }
#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER) && \
PA_BUILDFLAG(USE_RAW_PTR_BACKUP_REF_IMPL)
TEST(RawPtrInstanceTracerTest, CreateAndDestroy) {
auto owned = std::make_unique<int>(8);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<int> ptr1 = owned.get();
const auto stacks =
InstanceTracer::GetStackTracesForAddressForTest(owned.get());
EXPECT_THAT(stacks, SizeIs(1));
{
raw_ptr<int> ptr2 = owned.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(2));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
Eq(stacks));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, CopyConstruction) {
auto owned = std::make_unique<int>(8);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<int> ptr1 = owned.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
{
raw_ptr<int> ptr2 = ptr1;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(2));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, CopyAssignment) {
auto owned1 = std::make_unique<int>(8);
auto owned2 = std::make_unique<int>(9);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
{
raw_ptr<int> ptr1 = owned1.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
raw_ptr<int> ptr2 = owned2.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
SizeIs(1));
ptr2 = ptr1;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(2));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, MoveConstruction) {
auto owned = std::make_unique<int>(8);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<int> ptr1 = owned.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
{
raw_ptr<int> ptr2 = std::move(ptr1);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
}
TEST(RawPtrInstanceTracerTest, MoveAssignment) {
auto owned1 = std::make_unique<int>(8);
auto owned2 = std::make_unique<int>(9);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
{
raw_ptr<int> ptr1 = owned1.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
raw_ptr<int> ptr2 = owned2.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
SizeIs(1));
ptr2 = std::move(ptr1);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, SelfCopy) {
auto owned = std::make_unique<int>(8);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<int> ptr = owned.get();
auto& ptr2 = ptr;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
ptr2 = ptr;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, SelfMove) {
auto owned = std::make_unique<int>(8);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<int> ptr = owned.get();
auto& ptr2 = ptr;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
ptr2 = std::move(ptr);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, ConversionCreateAndDestroy) {
auto owned = std::make_unique<Derived>(1, 2, 3);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<Base1> ptr1 = owned.get();
const auto stacks =
InstanceTracer::GetStackTracesForAddressForTest(owned.get());
EXPECT_THAT(stacks, SizeIs(1));
{
raw_ptr<Base2> ptr2 = owned.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(2));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
Eq(stacks));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, CopyConversionConstruction) {
auto owned = std::make_unique<Derived>(1, 2, 3);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<Derived> ptr1 = owned.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
{
raw_ptr<Base1> ptr2 = ptr1;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(2));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, CopyConversionAssignment) {
auto owned1 = std::make_unique<Derived>(1, 2, 3);
auto owned2 = std::make_unique<Derived>(4, 5, 6);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
{
raw_ptr<Derived> ptr1 = owned1.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
raw_ptr<Base1> ptr2 = owned2.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
SizeIs(1));
ptr2 = ptr1;
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(2));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
TEST(RawPtrInstanceTracerTest, MoveConversionConstruction) {
auto owned = std::make_unique<Derived>(1, 2, 3);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
{
raw_ptr<Derived> ptr1 = owned.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
{
raw_ptr<Base1> ptr2 = std::move(ptr1);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
SizeIs(1));
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned.get()),
IsEmpty());
}
}
TEST(RawPtrInstanceTracerTest, MoveConversionAssignment) {
auto owned1 = std::make_unique<Derived>(1, 2, 3);
auto owned2 = std::make_unique<Derived>(4, 5, 6);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
{
raw_ptr<Derived> ptr1 = owned1.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
raw_ptr<Base1> ptr2 = owned2.get();
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
SizeIs(1));
ptr2 = std::move(ptr1);
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
SizeIs(1));
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned1.get()),
IsEmpty());
EXPECT_THAT(InstanceTracer::GetStackTracesForAddressForTest(owned2.get()),
IsEmpty());
}
#endif
}