1 /*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include "src/core/lib/gprpp/ref_counted_ptr.h"
20
21 #include <gtest/gtest.h>
22
23 #include <grpc/support/log.h>
24
25 #include "src/core/lib/gprpp/memory.h"
26 #include "src/core/lib/gprpp/ref_counted.h"
27 #include "test/core/util/test_config.h"
28
29 namespace grpc_core {
30 namespace testing {
31 namespace {
32
33 class Foo : public RefCounted<Foo> {
34 public:
Foo()35 Foo() : value_(0) {}
36
Foo(int value)37 explicit Foo(int value) : value_(value) {}
38
value() const39 int value() const { return value_; }
40
41 private:
42 int value_;
43 };
44
TEST(RefCountedPtr,DefaultConstructor)45 TEST(RefCountedPtr, DefaultConstructor) { RefCountedPtr<Foo> foo; }
46
TEST(RefCountedPtr,ExplicitConstructorEmpty)47 TEST(RefCountedPtr, ExplicitConstructorEmpty) {
48 RefCountedPtr<Foo> foo(nullptr);
49 }
50
TEST(RefCountedPtr,ExplicitConstructor)51 TEST(RefCountedPtr, ExplicitConstructor) { RefCountedPtr<Foo> foo(new Foo()); }
52
TEST(RefCountedPtr,MoveConstructor)53 TEST(RefCountedPtr, MoveConstructor) {
54 RefCountedPtr<Foo> foo(new Foo());
55 RefCountedPtr<Foo> foo2(std::move(foo));
56 EXPECT_EQ(nullptr, foo.get());
57 EXPECT_NE(nullptr, foo2.get());
58 }
59
TEST(RefCountedPtr,MoveAssignment)60 TEST(RefCountedPtr, MoveAssignment) {
61 RefCountedPtr<Foo> foo(new Foo());
62 RefCountedPtr<Foo> foo2 = std::move(foo);
63 EXPECT_EQ(nullptr, foo.get());
64 EXPECT_NE(nullptr, foo2.get());
65 }
66
TEST(RefCountedPtr,CopyConstructor)67 TEST(RefCountedPtr, CopyConstructor) {
68 RefCountedPtr<Foo> foo(new Foo());
69 const RefCountedPtr<Foo>& foo2(foo);
70 EXPECT_NE(nullptr, foo.get());
71 EXPECT_EQ(foo.get(), foo2.get());
72 }
73
TEST(RefCountedPtr,CopyAssignment)74 TEST(RefCountedPtr, CopyAssignment) {
75 RefCountedPtr<Foo> foo(new Foo());
76 const RefCountedPtr<Foo>& foo2 = foo;
77 EXPECT_NE(nullptr, foo.get());
78 EXPECT_EQ(foo.get(), foo2.get());
79 }
80
TEST(RefCountedPtr,CopyAssignmentWhenEmpty)81 TEST(RefCountedPtr, CopyAssignmentWhenEmpty) {
82 RefCountedPtr<Foo> foo;
83 RefCountedPtr<Foo> foo2;
84 foo2 = foo;
85 EXPECT_EQ(nullptr, foo.get());
86 EXPECT_EQ(nullptr, foo2.get());
87 }
88
TEST(RefCountedPtr,CopyAssignmentToSelf)89 TEST(RefCountedPtr, CopyAssignmentToSelf) {
90 RefCountedPtr<Foo> foo(new Foo());
91 foo = *&foo; // The "*&" avoids warnings from LLVM -Wself-assign.
92 }
93
TEST(RefCountedPtr,EnclosedScope)94 TEST(RefCountedPtr, EnclosedScope) {
95 RefCountedPtr<Foo> foo(new Foo());
96 {
97 RefCountedPtr<Foo> foo2(std::move(foo));
98 EXPECT_EQ(nullptr, foo.get());
99 EXPECT_NE(nullptr, foo2.get());
100 }
101 EXPECT_EQ(nullptr, foo.get());
102 }
103
TEST(RefCountedPtr,ResetFromNullToNonNull)104 TEST(RefCountedPtr, ResetFromNullToNonNull) {
105 RefCountedPtr<Foo> foo;
106 EXPECT_EQ(nullptr, foo.get());
107 foo.reset(new Foo());
108 EXPECT_NE(nullptr, foo.get());
109 }
110
TEST(RefCountedPtr,ResetFromNonNullToNonNull)111 TEST(RefCountedPtr, ResetFromNonNullToNonNull) {
112 RefCountedPtr<Foo> foo(new Foo());
113 EXPECT_NE(nullptr, foo.get());
114 Foo* original = foo.get();
115 foo.reset(new Foo());
116 EXPECT_NE(nullptr, foo.get());
117 EXPECT_NE(original, foo.get());
118 }
119
TEST(RefCountedPtr,ResetFromNonNullToNull)120 TEST(RefCountedPtr, ResetFromNonNullToNull) {
121 RefCountedPtr<Foo> foo(new Foo());
122 EXPECT_NE(nullptr, foo.get());
123 foo.reset();
124 EXPECT_EQ(nullptr, foo.get());
125 }
126
TEST(RefCountedPtr,ResetFromNullToNull)127 TEST(RefCountedPtr, ResetFromNullToNull) {
128 RefCountedPtr<Foo> foo;
129 EXPECT_EQ(nullptr, foo.get());
130 foo.reset();
131 EXPECT_EQ(nullptr, foo.get());
132 }
133
TEST(RefCountedPtr,DerefernceOperators)134 TEST(RefCountedPtr, DerefernceOperators) {
135 RefCountedPtr<Foo> foo(new Foo());
136 foo->value();
137 Foo& foo_ref = *foo;
138 foo_ref.value();
139 }
140
TEST(RefCountedPtr,EqualityOperators)141 TEST(RefCountedPtr, EqualityOperators) {
142 RefCountedPtr<Foo> foo(new Foo());
143 RefCountedPtr<Foo> bar = foo;
144 RefCountedPtr<Foo> empty;
145 // Test equality between RefCountedPtrs.
146 EXPECT_EQ(foo, bar);
147 EXPECT_NE(foo, empty);
148 // Test equality with bare pointers.
149 EXPECT_EQ(foo, foo.get());
150 EXPECT_EQ(empty, nullptr);
151 EXPECT_NE(foo, nullptr);
152 }
153
TEST(RefCountedPtr,Swap)154 TEST(RefCountedPtr, Swap) {
155 Foo* foo = new Foo();
156 Foo* bar = new Foo();
157 RefCountedPtr<Foo> ptr1(foo);
158 RefCountedPtr<Foo> ptr2(bar);
159 ptr1.swap(ptr2);
160 EXPECT_EQ(foo, ptr2.get());
161 EXPECT_EQ(bar, ptr1.get());
162 RefCountedPtr<Foo> ptr3;
163 ptr3.swap(ptr2);
164 EXPECT_EQ(nullptr, ptr2.get());
165 EXPECT_EQ(foo, ptr3.get());
166 }
167
TEST(MakeRefCounted,NoArgs)168 TEST(MakeRefCounted, NoArgs) {
169 RefCountedPtr<Foo> foo = MakeRefCounted<Foo>();
170 EXPECT_EQ(0, foo->value());
171 }
172
TEST(MakeRefCounted,Args)173 TEST(MakeRefCounted, Args) {
174 RefCountedPtr<Foo> foo = MakeRefCounted<Foo>(3);
175 EXPECT_EQ(3, foo->value());
176 }
177
178 TraceFlag foo_tracer(true, "foo");
179
180 class FooWithTracing : public RefCounted<FooWithTracing> {
181 public:
FooWithTracing()182 FooWithTracing() : RefCounted(&foo_tracer) {}
183 };
184
TEST(RefCountedPtr,RefCountedWithTracing)185 TEST(RefCountedPtr, RefCountedWithTracing) {
186 RefCountedPtr<FooWithTracing> foo(new FooWithTracing());
187 RefCountedPtr<FooWithTracing> foo2 = foo->Ref(DEBUG_LOCATION, "foo");
188 foo2.release();
189 foo->Unref(DEBUG_LOCATION, "foo");
190 }
191
192 class BaseClass : public RefCounted<BaseClass> {
193 public:
BaseClass()194 BaseClass() {}
195 };
196
197 class Subclass : public BaseClass {
198 public:
Subclass()199 Subclass() {}
200 };
201
TEST(RefCountedPtr,ConstructFromSubclass)202 TEST(RefCountedPtr, ConstructFromSubclass) {
203 RefCountedPtr<BaseClass> p(new Subclass());
204 }
205
TEST(RefCountedPtr,CopyAssignFromSubclass)206 TEST(RefCountedPtr, CopyAssignFromSubclass) {
207 RefCountedPtr<BaseClass> b;
208 EXPECT_EQ(nullptr, b.get());
209 RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
210 b = s;
211 EXPECT_NE(nullptr, b.get());
212 }
213
TEST(RefCountedPtr,MoveAssignFromSubclass)214 TEST(RefCountedPtr, MoveAssignFromSubclass) {
215 RefCountedPtr<BaseClass> b;
216 EXPECT_EQ(nullptr, b.get());
217 RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
218 b = std::move(s);
219 EXPECT_NE(nullptr, b.get());
220 }
221
TEST(RefCountedPtr,ResetFromSubclass)222 TEST(RefCountedPtr, ResetFromSubclass) {
223 RefCountedPtr<BaseClass> b;
224 EXPECT_EQ(nullptr, b.get());
225 b.reset(new Subclass());
226 EXPECT_NE(nullptr, b.get());
227 }
228
TEST(RefCountedPtr,EqualityWithSubclass)229 TEST(RefCountedPtr, EqualityWithSubclass) {
230 Subclass* s = new Subclass();
231 RefCountedPtr<BaseClass> b(s);
232 EXPECT_EQ(b, s);
233 }
234
FunctionTakingBaseClass(RefCountedPtr<BaseClass> p)235 void FunctionTakingBaseClass(RefCountedPtr<BaseClass> p) {
236 p.reset(); // To appease clang-tidy.
237 }
238
TEST(RefCountedPtr,CanPassSubclassToFunctionExpectingBaseClass)239 TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingBaseClass) {
240 RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
241 FunctionTakingBaseClass(p);
242 }
243
FunctionTakingSubclass(RefCountedPtr<Subclass> p)244 void FunctionTakingSubclass(RefCountedPtr<Subclass> p) {
245 p.reset(); // To appease clang-tidy.
246 }
247
TEST(RefCountedPtr,CanPassSubclassToFunctionExpectingSubclass)248 TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) {
249 RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
250 FunctionTakingSubclass(p);
251 }
252
253 } // namespace
254 } // namespace testing
255 } // namespace grpc_core
256
main(int argc,char ** argv)257 int main(int argc, char** argv) {
258 grpc::testing::TestEnvironment env(argc, argv);
259 ::testing::InitGoogleTest(&argc, argv);
260 return RUN_ALL_TESTS();
261 }
262