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(MakeRefCounted,NoArgs)154 TEST(MakeRefCounted, NoArgs) {
155 RefCountedPtr<Foo> foo = MakeRefCounted<Foo>();
156 EXPECT_EQ(0, foo->value());
157 }
158
TEST(MakeRefCounted,Args)159 TEST(MakeRefCounted, Args) {
160 RefCountedPtr<Foo> foo = MakeRefCounted<Foo>(3);
161 EXPECT_EQ(3, foo->value());
162 }
163
164 TraceFlag foo_tracer(true, "foo");
165
166 class FooWithTracing : public RefCountedWithTracing<FooWithTracing> {
167 public:
FooWithTracing()168 FooWithTracing() : RefCountedWithTracing(&foo_tracer) {}
169 };
170
TEST(RefCountedPtr,RefCountedWithTracing)171 TEST(RefCountedPtr, RefCountedWithTracing) {
172 RefCountedPtr<FooWithTracing> foo(New<FooWithTracing>());
173 RefCountedPtr<FooWithTracing> foo2 = foo->Ref(DEBUG_LOCATION, "foo");
174 foo2.release();
175 foo->Unref(DEBUG_LOCATION, "foo");
176 }
177
178 class BaseClass : public RefCounted<BaseClass> {
179 public:
BaseClass()180 BaseClass() {}
181 };
182
183 class Subclass : public BaseClass {
184 public:
Subclass()185 Subclass() {}
186 };
187
TEST(RefCountedPtr,ConstructFromSubclass)188 TEST(RefCountedPtr, ConstructFromSubclass) {
189 RefCountedPtr<BaseClass> p(New<Subclass>());
190 }
191
TEST(RefCountedPtr,CopyAssignFromSubclass)192 TEST(RefCountedPtr, CopyAssignFromSubclass) {
193 RefCountedPtr<BaseClass> b;
194 EXPECT_EQ(nullptr, b.get());
195 RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
196 b = s;
197 EXPECT_NE(nullptr, b.get());
198 }
199
TEST(RefCountedPtr,MoveAssignFromSubclass)200 TEST(RefCountedPtr, MoveAssignFromSubclass) {
201 RefCountedPtr<BaseClass> b;
202 EXPECT_EQ(nullptr, b.get());
203 RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
204 b = std::move(s);
205 EXPECT_NE(nullptr, b.get());
206 }
207
TEST(RefCountedPtr,ResetFromSubclass)208 TEST(RefCountedPtr, ResetFromSubclass) {
209 RefCountedPtr<BaseClass> b;
210 EXPECT_EQ(nullptr, b.get());
211 b.reset(New<Subclass>());
212 EXPECT_NE(nullptr, b.get());
213 }
214
TEST(RefCountedPtr,EqualityWithSubclass)215 TEST(RefCountedPtr, EqualityWithSubclass) {
216 Subclass* s = New<Subclass>();
217 RefCountedPtr<BaseClass> b(s);
218 EXPECT_EQ(b, s);
219 }
220
FunctionTakingBaseClass(RefCountedPtr<BaseClass> p)221 void FunctionTakingBaseClass(RefCountedPtr<BaseClass> p) {
222 p.reset(); // To appease clang-tidy.
223 }
224
TEST(RefCountedPtr,CanPassSubclassToFunctionExpectingBaseClass)225 TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingBaseClass) {
226 RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
227 FunctionTakingBaseClass(p);
228 }
229
FunctionTakingSubclass(RefCountedPtr<Subclass> p)230 void FunctionTakingSubclass(RefCountedPtr<Subclass> p) {
231 p.reset(); // To appease clang-tidy.
232 }
233
TEST(RefCountedPtr,CanPassSubclassToFunctionExpectingSubclass)234 TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) {
235 RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
236 FunctionTakingSubclass(p);
237 }
238
239 } // namespace
240 } // namespace testing
241 } // namespace grpc_core
242
main(int argc,char ** argv)243 int main(int argc, char** argv) {
244 grpc_test_init(argc, argv);
245 ::testing::InitGoogleTest(&argc, argv);
246 return RUN_ALL_TESTS();
247 }
248