xref: /aosp_15_r20/external/webrtc/rtc_base/ref_counted_object_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/ref_counted_object.h"
12 
13 #include <memory>
14 #include <string>
15 #include <type_traits>
16 #include <utility>
17 
18 #include "absl/strings/string_view.h"
19 #include "api/make_ref_counted.h"
20 #include "api/scoped_refptr.h"
21 #include "rtc_base/ref_count.h"
22 #include "test/gtest.h"
23 
24 namespace rtc {
25 
26 namespace {
27 
28 class A {
29  public:
A()30   A() {}
31 
32   A(const A&) = delete;
33   A& operator=(const A&) = delete;
34 };
35 
36 class RefClass : public RefCountInterface {
37  public:
RefClass()38   RefClass() {}
39 
40  protected:
~RefClass()41   ~RefClass() override {}
42 };
43 
44 class RefClassWithRvalue : public RefCountInterface {
45  public:
RefClassWithRvalue(std::unique_ptr<A> a)46   explicit RefClassWithRvalue(std::unique_ptr<A> a) : a_(std::move(a)) {}
47 
48  protected:
~RefClassWithRvalue()49   ~RefClassWithRvalue() override {}
50 
51  public:
52   std::unique_ptr<A> a_;
53 };
54 
55 class RefClassWithMixedValues : public RefCountInterface {
56  public:
RefClassWithMixedValues(std::unique_ptr<A> a,int b,absl::string_view c)57   RefClassWithMixedValues(std::unique_ptr<A> a, int b, absl::string_view c)
58       : a_(std::move(a)), b_(b), c_(c) {}
59 
60  protected:
~RefClassWithMixedValues()61   ~RefClassWithMixedValues() override {}
62 
63  public:
64   std::unique_ptr<A> a_;
65   int b_;
66   std::string c_;
67 };
68 
69 class Foo {
70  public:
Foo()71   Foo() {}
Foo(int i,int j)72   Foo(int i, int j) : foo_(i + j) {}
73   int foo_ = 0;
74 };
75 
76 class FooItf : public RefCountInterface {
77  public:
FooItf()78   FooItf() {}
FooItf(int i,int j)79   FooItf(int i, int j) : foo_(i + j) {}
80   int foo_ = 0;
81 };
82 
83 }  // namespace
84 
TEST(RefCountedObject,HasOneRef)85 TEST(RefCountedObject, HasOneRef) {
86   scoped_refptr<RefCountedObject<RefClass>> aref(
87       new RefCountedObject<RefClass>());
88   EXPECT_TRUE(aref->HasOneRef());
89   aref->AddRef();
90   EXPECT_FALSE(aref->HasOneRef());
91   EXPECT_EQ(aref->Release(), RefCountReleaseStatus::kOtherRefsRemained);
92   EXPECT_TRUE(aref->HasOneRef());
93 }
94 
TEST(RefCountedObject,SupportRValuesInCtor)95 TEST(RefCountedObject, SupportRValuesInCtor) {
96   std::unique_ptr<A> a(new A());
97   scoped_refptr<RefClassWithRvalue> ref(
98       new RefCountedObject<RefClassWithRvalue>(std::move(a)));
99   EXPECT_TRUE(ref->a_.get() != nullptr);
100   EXPECT_TRUE(a.get() == nullptr);
101 }
102 
TEST(RefCountedObject,SupportMixedTypesInCtor)103 TEST(RefCountedObject, SupportMixedTypesInCtor) {
104   std::unique_ptr<A> a(new A());
105   int b = 9;
106   std::string c = "hello";
107   scoped_refptr<RefClassWithMixedValues> ref(
108       new RefCountedObject<RefClassWithMixedValues>(std::move(a), b, c));
109   EXPECT_TRUE(ref->a_.get() != nullptr);
110   EXPECT_TRUE(a.get() == nullptr);
111   EXPECT_EQ(b, ref->b_);
112   EXPECT_EQ(c, ref->c_);
113 }
114 
TEST(FinalRefCountedObject,CanWrapIntoScopedRefptr)115 TEST(FinalRefCountedObject, CanWrapIntoScopedRefptr) {
116   using WrappedTyped = FinalRefCountedObject<A>;
117   static_assert(!std::is_polymorphic<WrappedTyped>::value, "");
118   scoped_refptr<WrappedTyped> ref(new WrappedTyped());
119   EXPECT_TRUE(ref.get());
120   EXPECT_TRUE(ref->HasOneRef());
121   // Test reference counter is updated on some simple operations.
122   scoped_refptr<WrappedTyped> ref2 = ref;
123   EXPECT_FALSE(ref->HasOneRef());
124   EXPECT_FALSE(ref2->HasOneRef());
125 
126   ref = nullptr;
127   EXPECT_TRUE(ref2->HasOneRef());
128 }
129 
TEST(FinalRefCountedObject,CanCreateFromMovedType)130 TEST(FinalRefCountedObject, CanCreateFromMovedType) {
131   class MoveOnly {
132    public:
133     MoveOnly(int a) : a_(a) {}
134     MoveOnly(MoveOnly&&) = default;
135 
136     int a() { return a_; }
137 
138    private:
139     int a_;
140   };
141   MoveOnly foo(5);
142   auto ref = make_ref_counted<MoveOnly>(std::move(foo));
143   EXPECT_EQ(ref->a(), 5);
144 }
145 
146 // This test is mostly a compile-time test for scoped_refptr compatibility.
TEST(RefCounted,SmartPointers)147 TEST(RefCounted, SmartPointers) {
148   // Sanity compile-time tests. FooItf is virtual, Foo is not, FooItf inherits
149   // from RefCountInterface, Foo does not.
150   static_assert(std::is_base_of<RefCountInterface, FooItf>::value, "");
151   static_assert(!std::is_base_of<RefCountInterface, Foo>::value, "");
152   static_assert(std::is_polymorphic<FooItf>::value, "");
153   static_assert(!std::is_polymorphic<Foo>::value, "");
154 
155   {
156     // Test with FooItf, a class that inherits from RefCountInterface.
157     // Check that we get a valid FooItf reference counted object.
158     auto p = make_ref_counted<FooItf>(2, 3);
159     EXPECT_NE(p.get(), nullptr);
160     EXPECT_EQ(p->foo_, 5);  // the FooItf ctor just stores 2+3 in foo_.
161 
162     // Declaring what should result in the same type as `p` is of.
163     scoped_refptr<FooItf> p2 = p;
164   }
165 
166   {
167     // Same for `Foo`
168     auto p = make_ref_counted<Foo>(2, 3);
169     EXPECT_NE(p.get(), nullptr);
170     EXPECT_EQ(p->foo_, 5);
171     scoped_refptr<FinalRefCountedObject<Foo>> p2 = p;
172   }
173 }
174 
175 }  // namespace rtc
176