blob: abeb1e9e67580715888d172417adf64be6e09681 [file] [log] [blame]
perkj0489e492016-10-20 07:24:011/*
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 17:08:3311#include "rtc_base/ref_counted_object.h"
12
Yves Gerey3e707812018-11-28 15:47:4913#include <memory>
perkj0489e492016-10-20 07:24:0114#include <string>
Danil Chapovalov8df643b2021-01-22 15:11:1015#include <type_traits>
Yves Gerey3e707812018-11-28 15:47:4916#include <utility>
perkj0489e492016-10-20 07:24:0117
Ali Tofigh7fa90572022-03-17 14:47:4918#include "absl/strings/string_view.h"
Niels Möller105711e2022-06-14 13:48:2619#include "api/make_ref_counted.h"
Mirko Bonadeid9708072019-01-25 19:26:4820#include "api/scoped_refptr.h"
Steve Anton10542f22019-01-11 17:11:0021#include "rtc_base/ref_count.h"
Yves Gerey3e707812018-11-28 15:47:4922#include "test/gtest.h"
perkj0489e492016-10-20 07:24:0123
24namespace rtc {
25
26namespace {
27
28class A {
29 public:
30 A() {}
31
Byoungchan Lee14af7622022-01-11 20:24:5832 A(const A&) = delete;
33 A& operator=(const A&) = delete;
perkj0489e492016-10-20 07:24:0134};
35
36class RefClass : public RefCountInterface {
37 public:
38 RefClass() {}
39
40 protected:
ehmaldonadoda8dcfb2017-01-04 15:11:2341 ~RefClass() override {}
perkj0489e492016-10-20 07:24:0142};
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 15:11:2349 ~RefClassWithRvalue() override {}
perkj0489e492016-10-20 07:24:0150
51 public:
52 std::unique_ptr<A> a_;
53};
54
55class RefClassWithMixedValues : public RefCountInterface {
56 public:
Ali Tofigh7fa90572022-03-17 14:47:4957 RefClassWithMixedValues(std::unique_ptr<A> a, int b, absl::string_view c)
perkj0489e492016-10-20 07:24:0158 : a_(std::move(a)), b_(b), c_(c) {}
59
60 protected:
ehmaldonadoda8dcfb2017-01-04 15:11:2361 ~RefClassWithMixedValues() override {}
perkj0489e492016-10-20 07:24:0162
63 public:
64 std::unique_ptr<A> a_;
65 int b_;
66 std::string c_;
67};
68
Tomas Gunnarssond7842002021-04-22 15:41:3369class 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 07:24:0183} // namespace
84
Niels Möller6f72f562017-10-19 11:15:1785TEST(RefCountedObject, HasOneRef) {
perkj0489e492016-10-20 07:24:0186 scoped_refptr<RefCountedObject<RefClass>> aref(
87 new RefCountedObject<RefClass>());
88 EXPECT_TRUE(aref->HasOneRef());
Niels Möller6f72f562017-10-19 11:15:1789 aref->AddRef();
90 EXPECT_FALSE(aref->HasOneRef());
91 EXPECT_EQ(aref->Release(), RefCountReleaseStatus::kOtherRefsRemained);
92 EXPECT_TRUE(aref->HasOneRef());
perkj0489e492016-10-20 07:24:0193}
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 15:11:10115TEST(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 14:32:27130TEST(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 15:41:33146// 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 15:41:33155 {
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 10:30:16162 // Declaring what should result in the same type as `p` is of.
163 scoped_refptr<FooItf> p2 = p;
Tomas Gunnarssond7842002021-04-22 15:41:33164 }
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 10:30:16171 scoped_refptr<FinalRefCountedObject<Foo>> p2 = p;
Tomas Gunnarssond7842002021-04-22 15:41:33172 }
173}
174
perkj0489e492016-10-20 07:24:01175} // namespace rtc