• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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