blob: abeb1e9e67580715888d172417adf64be6e09681 [file] [log] [blame]
perkj0489e492016-10-20 00:24:01 -07001/*
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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/ref_counted_object.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <memory>
perkj0489e492016-10-20 00:24:01 -070014#include <string>
Danil Chapovalov8df643b2021-01-22 16:11:10 +010015#include <type_traits>
Yves Gerey3e707812018-11-28 16:47:49 +010016#include <utility>
perkj0489e492016-10-20 00:24:01 -070017
Ali Tofigh7fa90572022-03-17 15:47:49 +010018#include "absl/strings/string_view.h"
Niels Möller105711e2022-06-14 15:48:26 +020019#include "api/make_ref_counted.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010020#include "api/scoped_refptr.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/ref_count.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "test/gtest.h"
perkj0489e492016-10-20 00:24:01 -070023
24namespace rtc {
25
26namespace {
27
28class A {
29 public:
30 A() {}
31
Byoungchan Lee14af7622022-01-12 05:24:58 +090032 A(const A&) = delete;
33 A& operator=(const A&) = delete;
perkj0489e492016-10-20 00:24:01 -070034};
35
36class RefClass : public RefCountInterface {
37 public:
38 RefClass() {}
39
40 protected:
ehmaldonadoda8dcfb2017-01-04 07:11:23 -080041 ~RefClass() override {}
perkj0489e492016-10-20 00:24:01 -070042};
43
44class RefClassWithRvalue : public RefCountInterface {
45 public:
46 explicit RefClassWithRvalue(std::unique_ptr<A> a) : a_(std::move(a)) {}
47
48 protected:
ehmaldonadoda8dcfb2017-01-04 07:11:23 -080049 ~RefClassWithRvalue() override {}
perkj0489e492016-10-20 00:24:01 -070050
51 public:
52 std::unique_ptr<A> a_;
53};
54
55class RefClassWithMixedValues : public RefCountInterface {
56 public:
Ali Tofigh7fa90572022-03-17 15:47:49 +010057 RefClassWithMixedValues(std::unique_ptr<A> a, int b, absl::string_view c)
perkj0489e492016-10-20 00:24:01 -070058 : a_(std::move(a)), b_(b), c_(c) {}
59
60 protected:
ehmaldonadoda8dcfb2017-01-04 07:11:23 -080061 ~RefClassWithMixedValues() override {}
perkj0489e492016-10-20 00:24:01 -070062
63 public:
64 std::unique_ptr<A> a_;
65 int b_;
66 std::string c_;
67};
68
Tomas Gunnarssond7842002021-04-22 17:41:33 +020069class Foo {
70 public:
71 Foo() {}
72 Foo(int i, int j) : foo_(i + j) {}
73 int foo_ = 0;
74};
75
76class FooItf : public RefCountInterface {
77 public:
78 FooItf() {}
79 FooItf(int i, int j) : foo_(i + j) {}
80 int foo_ = 0;
81};
82
perkj0489e492016-10-20 00:24:01 -070083} // namespace
84
Niels Möller6f72f562017-10-19 13:15:17 +020085TEST(RefCountedObject, HasOneRef) {
perkj0489e492016-10-20 00:24:01 -070086 scoped_refptr<RefCountedObject<RefClass>> aref(
87 new RefCountedObject<RefClass>());
88 EXPECT_TRUE(aref->HasOneRef());
Niels Möller6f72f562017-10-19 13:15:17 +020089 aref->AddRef();
90 EXPECT_FALSE(aref->HasOneRef());
91 EXPECT_EQ(aref->Release(), RefCountReleaseStatus::kOtherRefsRemained);
92 EXPECT_TRUE(aref->HasOneRef());
perkj0489e492016-10-20 00:24:01 -070093}
94
95TEST(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
103TEST(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
Danil Chapovalov8df643b2021-01-22 16:11:10 +0100115TEST(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
Danil Chapovalov80b76282021-04-26 16:32:27 +0200130TEST(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
Tomas Gunnarssond7842002021-04-22 17:41:33 +0200146// This test is mostly a compile-time test for scoped_refptr compatibility.
147TEST(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
Tomas Gunnarssond7842002021-04-22 17:41:33 +0200155 {
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
Niels Möllerbed85072022-06-14 12:30:16 +0200162 // Declaring what should result in the same type as `p` is of.
163 scoped_refptr<FooItf> p2 = p;
Tomas Gunnarssond7842002021-04-22 17:41:33 +0200164 }
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);
Niels Möllerbed85072022-06-14 12:30:16 +0200171 scoped_refptr<FinalRefCountedObject<Foo>> p2 = p;
Tomas Gunnarssond7842002021-04-22 17:41:33 +0200172 }
173}
174
perkj0489e492016-10-20 00:24:01 -0700175} // namespace rtc