brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 6da4227 Raw
157 lines · cpp
1//===- unittest/ADT/IntrusiveRefCntPtrTest.cpp ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/IntrusiveRefCntPtr.h"10#include "gtest/gtest.h"11 12namespace llvm {13 14namespace {15int NumInstances = 0;16template <template <typename> class Base>17struct SimpleRefCounted : Base<SimpleRefCounted<Base>> {18  SimpleRefCounted() { ++NumInstances; }19  SimpleRefCounted(const SimpleRefCounted &RHS) : Base<SimpleRefCounted>(RHS) {20    ++NumInstances;21  }22  ~SimpleRefCounted() { --NumInstances; }23};24} // anonymous namespace25 26template <typename T> struct IntrusiveRefCntPtrTest : testing::Test {};27 28using IntrusiveRefCntTypes =29    ::testing::Types<SimpleRefCounted<RefCountedBase>,30                     SimpleRefCounted<ThreadSafeRefCountedBase>>;31TYPED_TEST_SUITE(IntrusiveRefCntPtrTest, IntrusiveRefCntTypes, );32 33TYPED_TEST(IntrusiveRefCntPtrTest, RefCountedBaseCopyDoesNotLeak) {34  EXPECT_EQ(0, NumInstances);35  {36    TypeParam *S1 = new TypeParam;37    IntrusiveRefCntPtr<TypeParam> R1 = S1;38    TypeParam *S2 = new TypeParam(*S1);39    IntrusiveRefCntPtr<TypeParam> R2 = S2;40    EXPECT_EQ(2, NumInstances);41  }42  EXPECT_EQ(0, NumInstances);43}44 45TYPED_TEST(IntrusiveRefCntPtrTest, InteropsWithUniquePtr) {46  EXPECT_EQ(0, NumInstances);47  {48    auto S1 = std::make_unique<TypeParam>();49    IntrusiveRefCntPtr<TypeParam> R1 = std::move(S1);50    EXPECT_EQ(1, NumInstances);51    EXPECT_EQ(S1, nullptr);52  }53  EXPECT_EQ(0, NumInstances);54}55 56TYPED_TEST(IntrusiveRefCntPtrTest, MakeIntrusiveRefCnt) {57  EXPECT_EQ(0, NumInstances);58  {59    auto S1 = makeIntrusiveRefCnt<TypeParam>();60    auto S2 = makeIntrusiveRefCnt<const TypeParam>();61    EXPECT_EQ(2, NumInstances);62    static_assert(63        std::is_same<decltype(S1), IntrusiveRefCntPtr<TypeParam>>::value,64        "Non-const type mismatch");65    static_assert(66        std::is_same<decltype(S2), IntrusiveRefCntPtr<const TypeParam>>::value,67        "Const type mismatch");68  }69  EXPECT_EQ(0, NumInstances);70}71 72struct InterceptRefCounted : public RefCountedBase<InterceptRefCounted> {73  InterceptRefCounted(bool *Released, bool *Retained)74    : Released(Released), Retained(Retained) {}75  bool * const Released;76  bool * const Retained;77};78template <> struct IntrusiveRefCntPtrInfo<InterceptRefCounted> {79  static void retain(InterceptRefCounted *I) {80    *I->Retained = true;81    I->Retain();82  }83  static void release(InterceptRefCounted *I) {84    *I->Released = true;85    I->Release();86  }87};88TEST(IntrusiveRefCntPtr, UsesTraitsToRetainAndRelease) {89  bool Released = false;90  bool Retained = false;91  {92    InterceptRefCounted *I = new InterceptRefCounted(&Released, &Retained);93    IntrusiveRefCntPtr<InterceptRefCounted> R = I;94  }95  EXPECT_TRUE(Released);96  EXPECT_TRUE(Retained);97}98 99// Test that the generic constructors use SFINAE to disable invalid100// conversions.101struct X : RefCountedBase<X> {};102struct Y : X {};103struct Z : RefCountedBase<Z> {};104static_assert(105    !std::is_convertible_v<IntrusiveRefCntPtr<X> &&, IntrusiveRefCntPtr<Y>>,106    "X&& -> Y should be rejected with SFINAE");107static_assert(!std::is_convertible_v<const IntrusiveRefCntPtr<X> &,108                                     IntrusiveRefCntPtr<Y>>,109              "const X& -> Y should be rejected with SFINAE");110static_assert(!std::is_convertible_v<std::unique_ptr<X>, IntrusiveRefCntPtr<Y>>,111              "X -> Y should be rejected with SFINAE");112static_assert(113    !std::is_convertible_v<IntrusiveRefCntPtr<X> &&, IntrusiveRefCntPtr<Z>>,114    "X&& -> Z should be rejected with SFINAE");115static_assert(!std::is_convertible_v<const IntrusiveRefCntPtr<X> &,116                                     IntrusiveRefCntPtr<Z>>,117              "const X& -> Z should be rejected with SFINAE");118static_assert(!std::is_convertible_v<std::unique_ptr<X>, IntrusiveRefCntPtr<Z>>,119              "X -> Z should be rejected with SFINAE");120 121TEST(IntrusiveRefCntPtr, InteropsWithConvertible) {122  // Check converting constructors and operator=.123  auto Y1 = makeIntrusiveRefCnt<Y>();124  auto Y2 = makeIntrusiveRefCnt<Y>();125  auto Y3 = makeIntrusiveRefCnt<Y>();126  auto Y4 = makeIntrusiveRefCnt<Y>();127  const void *P1 = Y1.get();128  const void *P2 = Y2.get();129  const void *P3 = Y3.get();130  const void *P4 = Y4.get();131  IntrusiveRefCntPtr<X> X1 = std::move(Y1);132  IntrusiveRefCntPtr<X> X2 = Y2;133  IntrusiveRefCntPtr<X> X3;134  IntrusiveRefCntPtr<X> X4;135  X3 = std::move(Y3);136  X4 = Y4;137  EXPECT_EQ(P1, X1.get());138  EXPECT_EQ(P2, X2.get());139  EXPECT_EQ(P3, X3.get());140  EXPECT_EQ(P4, X4.get());141}142 143TEST(IntrusiveRefCntPtrTest, Unique) {144  IntrusiveRefCntPtr<X> X1;145  EXPECT_EQ(X1.useCount(), 0u);146  X1 = new X();147  EXPECT_EQ(X1.useCount(), 1u);148  {149    IntrusiveRefCntPtr<X> X2 = X1;150    EXPECT_EQ(X1.useCount(), 2u);151    EXPECT_EQ(X2.useCount(), 2u);152  }153  EXPECT_EQ(X1.useCount(), 1u);154}155 156} // end namespace llvm157