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 <memory>
22
23 #include "absl/container/flat_hash_set.h"
24 #include "gtest/gtest.h"
25
26 #include <grpc/support/log.h>
27
28 #include "src/core/lib/gprpp/dual_ref_counted.h"
29 #include "src/core/lib/gprpp/ref_counted.h"
30 #include "test/core/util/test_config.h"
31
32 namespace grpc_core {
33 namespace testing {
34 namespace {
35
36 //
37 // RefCountedPtr<> tests
38 //
39
40 class Foo : public RefCounted<Foo> {
41 public:
Foo()42 Foo() : value_(0) {}
43
Foo(int value)44 explicit Foo(int value) : value_(value) {}
45
value() const46 int value() const { return value_; }
47
48 private:
49 int value_;
50 };
51
TEST(RefCountedPtr,DefaultConstructor)52 TEST(RefCountedPtr, DefaultConstructor) { RefCountedPtr<Foo> foo; }
53
TEST(RefCountedPtr,ExplicitConstructorEmpty)54 TEST(RefCountedPtr, ExplicitConstructorEmpty) {
55 RefCountedPtr<Foo> foo(nullptr);
56 }
57
TEST(RefCountedPtr,ExplicitConstructor)58 TEST(RefCountedPtr, ExplicitConstructor) { RefCountedPtr<Foo> foo(new Foo()); }
59
TEST(RefCountedPtr,MoveConstructor)60 TEST(RefCountedPtr, MoveConstructor) {
61 RefCountedPtr<Foo> foo(new Foo());
62 RefCountedPtr<Foo> foo2(std::move(foo));
63 // NOLINTNEXTLINE(bugprone-use-after-move)
64 EXPECT_EQ(nullptr, foo.get());
65 EXPECT_NE(nullptr, foo2.get());
66 }
67
TEST(RefCountedPtr,MoveAssignment)68 TEST(RefCountedPtr, MoveAssignment) {
69 RefCountedPtr<Foo> foo(new Foo());
70 RefCountedPtr<Foo> foo2 = std::move(foo);
71 // NOLINTNEXTLINE(bugprone-use-after-move)
72 EXPECT_EQ(nullptr, foo.get());
73 EXPECT_NE(nullptr, foo2.get());
74 }
75
TEST(RefCountedPtr,CopyConstructor)76 TEST(RefCountedPtr, CopyConstructor) {
77 RefCountedPtr<Foo> foo(new Foo());
78 RefCountedPtr<Foo> foo2(foo);
79 EXPECT_NE(nullptr, foo.get());
80 EXPECT_EQ(foo.get(), foo2.get());
81 }
82
TEST(RefCountedPtr,CopyAssignment)83 TEST(RefCountedPtr, CopyAssignment) {
84 RefCountedPtr<Foo> foo(new Foo());
85 RefCountedPtr<Foo> foo2 = foo;
86 EXPECT_NE(nullptr, foo.get());
87 EXPECT_EQ(foo.get(), foo2.get());
88 }
89
TEST(RefCountedPtr,CopyAssignmentWhenEmpty)90 TEST(RefCountedPtr, CopyAssignmentWhenEmpty) {
91 RefCountedPtr<Foo> foo;
92 RefCountedPtr<Foo> foo2;
93 foo2 = foo;
94 EXPECT_EQ(nullptr, foo.get());
95 EXPECT_EQ(nullptr, foo2.get());
96 }
97
TEST(RefCountedPtr,CopyAssignmentToSelf)98 TEST(RefCountedPtr, CopyAssignmentToSelf) {
99 RefCountedPtr<Foo> foo(new Foo());
100 foo = *&foo; // The "*&" avoids warnings from LLVM -Wself-assign.
101 }
102
TEST(RefCountedPtr,EnclosedScope)103 TEST(RefCountedPtr, EnclosedScope) {
104 RefCountedPtr<Foo> foo(new Foo());
105 {
106 RefCountedPtr<Foo> foo2(std::move(foo));
107 // NOLINTNEXTLINE(bugprone-use-after-move)
108 EXPECT_EQ(nullptr, foo.get());
109 EXPECT_NE(nullptr, foo2.get());
110 }
111 EXPECT_EQ(nullptr, foo.get());
112 }
113
TEST(RefCountedPtr,ResetFromNullToNonNull)114 TEST(RefCountedPtr, ResetFromNullToNonNull) {
115 RefCountedPtr<Foo> foo;
116 EXPECT_EQ(nullptr, foo.get());
117 foo.reset(new Foo());
118 EXPECT_NE(nullptr, foo.get());
119 }
120
TEST(RefCountedPtr,ResetFromNonNullToNonNull)121 TEST(RefCountedPtr, ResetFromNonNullToNonNull) {
122 RefCountedPtr<Foo> foo(new Foo());
123 EXPECT_NE(nullptr, foo.get());
124 Foo* original = foo.get();
125 foo.reset(new Foo());
126 EXPECT_NE(nullptr, foo.get());
127 EXPECT_NE(original, foo.get());
128 }
129
TEST(RefCountedPtr,ResetFromNonNullToNull)130 TEST(RefCountedPtr, ResetFromNonNullToNull) {
131 RefCountedPtr<Foo> foo(new Foo());
132 EXPECT_NE(nullptr, foo.get());
133 foo.reset();
134 EXPECT_EQ(nullptr, foo.get());
135 }
136
TEST(RefCountedPtr,ResetFromNullToNull)137 TEST(RefCountedPtr, ResetFromNullToNull) {
138 RefCountedPtr<Foo> foo;
139 EXPECT_EQ(nullptr, foo.get());
140 foo.reset();
141 EXPECT_EQ(nullptr, foo.get());
142 }
143
TEST(RefCountedPtr,DerefernceOperators)144 TEST(RefCountedPtr, DerefernceOperators) {
145 RefCountedPtr<Foo> foo(new Foo());
146 foo->value();
147 Foo& foo_ref = *foo;
148 foo_ref.value();
149 }
150
TEST(RefCountedPtr,EqualityOperators)151 TEST(RefCountedPtr, EqualityOperators) {
152 RefCountedPtr<Foo> foo(new Foo());
153 RefCountedPtr<Foo> bar = foo;
154 RefCountedPtr<Foo> empty;
155 // Test equality between RefCountedPtrs.
156 EXPECT_EQ(foo, bar);
157 EXPECT_NE(foo, empty);
158 // Test equality with bare pointers.
159 EXPECT_EQ(foo, foo.get());
160 EXPECT_EQ(empty, nullptr);
161 EXPECT_NE(foo, nullptr);
162 }
163
TEST(RefCountedPtr,Swap)164 TEST(RefCountedPtr, Swap) {
165 Foo* foo = new Foo();
166 Foo* bar = new Foo();
167 RefCountedPtr<Foo> ptr1(foo);
168 RefCountedPtr<Foo> ptr2(bar);
169 ptr1.swap(ptr2);
170 EXPECT_EQ(foo, ptr2.get());
171 EXPECT_EQ(bar, ptr1.get());
172 RefCountedPtr<Foo> ptr3;
173 ptr3.swap(ptr2);
174 EXPECT_EQ(nullptr, ptr2.get());
175 EXPECT_EQ(foo, ptr3.get());
176 }
177
TEST(MakeRefCounted,NoArgs)178 TEST(MakeRefCounted, NoArgs) {
179 RefCountedPtr<Foo> foo = MakeRefCounted<Foo>();
180 EXPECT_EQ(0, foo->value());
181 }
182
TEST(MakeRefCounted,Args)183 TEST(MakeRefCounted, Args) {
184 RefCountedPtr<Foo> foo = MakeRefCounted<Foo>(3);
185 EXPECT_EQ(3, foo->value());
186 }
187
188 class FooWithTracing : public RefCounted<FooWithTracing> {
189 public:
FooWithTracing()190 FooWithTracing() : RefCounted("FooWithTracing") {}
191 };
192
TEST(RefCountedPtr,RefCountedWithTracing)193 TEST(RefCountedPtr, RefCountedWithTracing) {
194 RefCountedPtr<FooWithTracing> foo(new FooWithTracing());
195 RefCountedPtr<FooWithTracing> foo2 = foo->Ref(DEBUG_LOCATION, "foo");
196 foo2.release();
197 RefCountedPtr<FooWithTracing> foo3 = foo.Ref(DEBUG_LOCATION, "foo");
198 foo3.release();
199 foo->Unref(DEBUG_LOCATION, "foo");
200 foo->Unref(DEBUG_LOCATION, "foo");
201 }
202
203 class BaseClass : public RefCounted<BaseClass> {
204 public:
BaseClass()205 BaseClass() {}
206 };
207
208 class Subclass : public BaseClass {
209 public:
Subclass()210 Subclass() {}
211 };
212
TEST(RefCountedPtr,ConstructFromSubclass)213 TEST(RefCountedPtr, ConstructFromSubclass) {
214 RefCountedPtr<BaseClass> p(new Subclass());
215 }
216
TEST(RefCountedPtr,CopyAssignFromSubclass)217 TEST(RefCountedPtr, CopyAssignFromSubclass) {
218 RefCountedPtr<BaseClass> b;
219 EXPECT_EQ(nullptr, b.get());
220 RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
221 b = s;
222 EXPECT_NE(nullptr, b.get());
223 }
224
TEST(RefCountedPtr,MoveAssignFromSubclass)225 TEST(RefCountedPtr, MoveAssignFromSubclass) {
226 RefCountedPtr<BaseClass> b;
227 EXPECT_EQ(nullptr, b.get());
228 RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
229 b = std::move(s);
230 EXPECT_NE(nullptr, b.get());
231 }
232
TEST(RefCountedPtr,ResetFromSubclass)233 TEST(RefCountedPtr, ResetFromSubclass) {
234 RefCountedPtr<BaseClass> b;
235 EXPECT_EQ(nullptr, b.get());
236 b.reset(new Subclass());
237 EXPECT_NE(nullptr, b.get());
238 }
239
TEST(RefCountedPtr,EqualityWithSubclass)240 TEST(RefCountedPtr, EqualityWithSubclass) {
241 Subclass* s = new Subclass();
242 RefCountedPtr<BaseClass> b(s);
243 EXPECT_EQ(b, s);
244 }
245
FunctionTakingBaseClass(RefCountedPtr<BaseClass>)246 void FunctionTakingBaseClass(RefCountedPtr<BaseClass>) {}
247
TEST(RefCountedPtr,CanPassSubclassToFunctionExpectingBaseClass)248 TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingBaseClass) {
249 RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
250 FunctionTakingBaseClass(p);
251 }
252
FunctionTakingSubclass(RefCountedPtr<Subclass>)253 void FunctionTakingSubclass(RefCountedPtr<Subclass>) {}
254
TEST(RefCountedPtr,CanPassSubclassToFunctionExpectingSubclass)255 TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) {
256 RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
257 FunctionTakingSubclass(p);
258 }
259
TEST(RefCountedPtr,TakeAsSubclass)260 TEST(RefCountedPtr, TakeAsSubclass) {
261 RefCountedPtr<BaseClass> p = MakeRefCounted<Subclass>();
262 auto s = p.TakeAsSubclass<Subclass>();
263 EXPECT_EQ(p.get(), nullptr);
264 EXPECT_NE(s.get(), nullptr);
265 }
266
267 //
268 // WeakRefCountedPtr<> tests
269 //
270
271 class Bar : public DualRefCounted<Bar> {
272 public:
Bar()273 Bar() : value_(0) {}
274
Bar(int value)275 explicit Bar(int value) : value_(value) {}
276
~Bar()277 ~Bar() override { GPR_ASSERT(shutting_down_); }
278
Orphaned()279 void Orphaned() override { shutting_down_ = true; }
280
value() const281 int value() const { return value_; }
282
283 private:
284 int value_;
285 bool shutting_down_ = false;
286 };
287
TEST(WeakRefCountedPtr,DefaultConstructor)288 TEST(WeakRefCountedPtr, DefaultConstructor) { WeakRefCountedPtr<Bar> bar; }
289
TEST(WeakRefCountedPtr,ExplicitConstructorEmpty)290 TEST(WeakRefCountedPtr, ExplicitConstructorEmpty) {
291 WeakRefCountedPtr<Bar> bar(nullptr);
292 }
293
TEST(WeakRefCountedPtr,ExplicitConstructor)294 TEST(WeakRefCountedPtr, ExplicitConstructor) {
295 RefCountedPtr<Bar> bar_strong(new Bar());
296 bar_strong->WeakRef().release();
297 WeakRefCountedPtr<Bar> bar(bar_strong.get());
298 }
299
TEST(WeakRefCountedPtr,MoveConstructor)300 TEST(WeakRefCountedPtr, MoveConstructor) {
301 RefCountedPtr<Bar> bar_strong(new Bar());
302 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
303 WeakRefCountedPtr<Bar> bar2(std::move(bar));
304 EXPECT_EQ(nullptr, bar.get()); // NOLINT
305 EXPECT_NE(nullptr, bar2.get());
306 }
307
TEST(WeakRefCountedPtr,MoveAssignment)308 TEST(WeakRefCountedPtr, MoveAssignment) {
309 RefCountedPtr<Bar> bar_strong(new Bar());
310 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
311 WeakRefCountedPtr<Bar> bar2 = std::move(bar);
312 EXPECT_EQ(nullptr, bar.get()); // NOLINT
313 EXPECT_NE(nullptr, bar2.get());
314 }
315
TEST(WeakRefCountedPtr,CopyConstructor)316 TEST(WeakRefCountedPtr, CopyConstructor) {
317 RefCountedPtr<Bar> bar_strong(new Bar());
318 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
319 WeakRefCountedPtr<Bar> bar2(bar);
320 EXPECT_NE(nullptr, bar.get());
321 EXPECT_EQ(bar.get(), bar2.get());
322 }
323
TEST(WeakRefCountedPtr,CopyAssignment)324 TEST(WeakRefCountedPtr, CopyAssignment) {
325 RefCountedPtr<Bar> bar_strong(new Bar());
326 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
327 WeakRefCountedPtr<Bar> bar2 = bar;
328 EXPECT_NE(nullptr, bar.get());
329 EXPECT_EQ(bar.get(), bar2.get());
330 }
331
TEST(WeakRefCountedPtr,CopyAssignmentWhenEmpty)332 TEST(WeakRefCountedPtr, CopyAssignmentWhenEmpty) {
333 WeakRefCountedPtr<Bar> bar;
334 WeakRefCountedPtr<Bar> bar2;
335 bar2 = bar;
336 EXPECT_EQ(nullptr, bar.get());
337 EXPECT_EQ(nullptr, bar2.get());
338 }
339
TEST(WeakRefCountedPtr,CopyAssignmentToSelf)340 TEST(WeakRefCountedPtr, CopyAssignmentToSelf) {
341 RefCountedPtr<Bar> bar_strong(new Bar());
342 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
343 bar = *&bar; // The "*&" avoids warnings from LLVM -Wself-assign.
344 }
345
TEST(WeakRefCountedPtr,EnclosedScope)346 TEST(WeakRefCountedPtr, EnclosedScope) {
347 RefCountedPtr<Bar> bar_strong(new Bar());
348 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
349 {
350 WeakRefCountedPtr<Bar> bar2(std::move(bar));
351 // NOLINTNEXTLINE(bugprone-use-after-move)
352 EXPECT_EQ(nullptr, bar.get());
353 EXPECT_NE(nullptr, bar2.get());
354 }
355 EXPECT_EQ(nullptr, bar.get());
356 }
357
TEST(WeakRefCountedPtr,ResetFromNullToNonNull)358 TEST(WeakRefCountedPtr, ResetFromNullToNonNull) {
359 RefCountedPtr<Bar> bar_strong(new Bar());
360 WeakRefCountedPtr<Bar> bar;
361 EXPECT_EQ(nullptr, bar.get());
362 bar_strong->WeakRef().release();
363 bar.reset(bar_strong.get());
364 EXPECT_NE(nullptr, bar.get());
365 }
366
TEST(WeakRefCountedPtr,ResetFromNonNullToNonNull)367 TEST(WeakRefCountedPtr, ResetFromNonNullToNonNull) {
368 RefCountedPtr<Bar> bar_strong(new Bar());
369 RefCountedPtr<Bar> bar2_strong(new Bar());
370 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
371 EXPECT_NE(nullptr, bar.get());
372 bar2_strong->WeakRef().release();
373 bar.reset(bar2_strong.get());
374 EXPECT_NE(nullptr, bar.get());
375 EXPECT_NE(bar_strong.get(), bar.get());
376 }
377
TEST(WeakRefCountedPtr,ResetFromNonNullToNull)378 TEST(WeakRefCountedPtr, ResetFromNonNullToNull) {
379 RefCountedPtr<Bar> bar_strong(new Bar());
380 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
381 EXPECT_NE(nullptr, bar.get());
382 bar.reset();
383 EXPECT_EQ(nullptr, bar.get());
384 }
385
TEST(WeakRefCountedPtr,ResetFromNullToNull)386 TEST(WeakRefCountedPtr, ResetFromNullToNull) {
387 WeakRefCountedPtr<Bar> bar;
388 EXPECT_EQ(nullptr, bar.get());
389 bar.reset();
390 EXPECT_EQ(nullptr, bar.get());
391 }
392
TEST(WeakRefCountedPtr,DerefernceOperators)393 TEST(WeakRefCountedPtr, DerefernceOperators) {
394 RefCountedPtr<Bar> bar_strong(new Bar());
395 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
396 bar->value();
397 Bar& bar_ref = *bar;
398 bar_ref.value();
399 }
400
TEST(WeakRefCountedPtr,EqualityOperators)401 TEST(WeakRefCountedPtr, EqualityOperators) {
402 RefCountedPtr<Bar> bar_strong(new Bar());
403 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
404 WeakRefCountedPtr<Bar> bar2 = bar;
405 WeakRefCountedPtr<Bar> empty;
406 // Test equality between RefCountedPtrs.
407 EXPECT_EQ(bar, bar2);
408 EXPECT_NE(bar, empty);
409 // Test equality with bare pointers.
410 EXPECT_EQ(bar, bar.get());
411 EXPECT_EQ(empty, nullptr);
412 EXPECT_NE(bar, nullptr);
413 }
414
TEST(WeakRefCountedPtr,Swap)415 TEST(WeakRefCountedPtr, Swap) {
416 RefCountedPtr<Bar> bar_strong(new Bar());
417 RefCountedPtr<Bar> bar2_strong(new Bar());
418 WeakRefCountedPtr<Bar> bar = bar_strong->WeakRef();
419 WeakRefCountedPtr<Bar> bar2 = bar2_strong->WeakRef();
420 bar.swap(bar2);
421 EXPECT_EQ(bar_strong.get(), bar2.get());
422 EXPECT_EQ(bar2_strong.get(), bar.get());
423 WeakRefCountedPtr<Bar> bar3;
424 bar3.swap(bar2);
425 EXPECT_EQ(nullptr, bar2.get());
426 EXPECT_EQ(bar_strong.get(), bar3.get());
427 }
428
429 class BarWithTracing : public DualRefCounted<BarWithTracing> {
430 public:
BarWithTracing()431 BarWithTracing() : DualRefCounted("BarWithTracing") {}
432
~BarWithTracing()433 ~BarWithTracing() override { GPR_ASSERT(shutting_down_); }
434
Orphaned()435 void Orphaned() override { shutting_down_ = true; }
436
437 private:
438 bool shutting_down_ = false;
439 };
440
TEST(WeakRefCountedPtr,RefCountedWithTracing)441 TEST(WeakRefCountedPtr, RefCountedWithTracing) {
442 RefCountedPtr<BarWithTracing> bar_strong(new BarWithTracing());
443 WeakRefCountedPtr<BarWithTracing> bar = bar_strong->WeakRef();
444 WeakRefCountedPtr<BarWithTracing> bar2 = bar->WeakRef(DEBUG_LOCATION, "bar");
445 bar2.release();
446 WeakRefCountedPtr<BarWithTracing> bar3 = bar.WeakRef(DEBUG_LOCATION, "bar");
447 bar3.release();
448 bar->WeakUnref(DEBUG_LOCATION, "bar");
449 bar->WeakUnref(DEBUG_LOCATION, "bar");
450 }
451
452 class WeakBaseClass : public DualRefCounted<WeakBaseClass> {
453 public:
WeakBaseClass()454 WeakBaseClass() {}
455
~WeakBaseClass()456 ~WeakBaseClass() override { GPR_ASSERT(shutting_down_); }
457
Orphaned()458 void Orphaned() override { shutting_down_ = true; }
459
460 private:
461 bool shutting_down_ = false;
462 };
463
464 class WeakSubclass : public WeakBaseClass {
465 public:
WeakSubclass()466 WeakSubclass() {}
467 };
468
TEST(WeakRefCountedPtr,ConstructFromWeakSubclass)469 TEST(WeakRefCountedPtr, ConstructFromWeakSubclass) {
470 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
471 WeakRefCountedPtr<WeakBaseClass> p(strong->WeakRef().release());
472 }
473
TEST(WeakRefCountedPtr,CopyAssignFromWeakSubclass)474 TEST(WeakRefCountedPtr, CopyAssignFromWeakSubclass) {
475 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
476 WeakRefCountedPtr<WeakBaseClass> b;
477 EXPECT_EQ(nullptr, b.get());
478 WeakRefCountedPtr<WeakSubclass> s = strong->WeakRefAsSubclass<WeakSubclass>();
479 b = s;
480 EXPECT_NE(nullptr, b.get());
481 }
482
TEST(WeakRefCountedPtr,MoveAssignFromWeakSubclass)483 TEST(WeakRefCountedPtr, MoveAssignFromWeakSubclass) {
484 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
485 WeakRefCountedPtr<WeakBaseClass> b;
486 EXPECT_EQ(nullptr, b.get());
487 WeakRefCountedPtr<WeakSubclass> s = strong->WeakRefAsSubclass<WeakSubclass>();
488 b = std::move(s);
489 EXPECT_NE(nullptr, b.get());
490 }
491
TEST(WeakRefCountedPtr,ResetFromWeakSubclass)492 TEST(WeakRefCountedPtr, ResetFromWeakSubclass) {
493 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
494 WeakRefCountedPtr<WeakBaseClass> b;
495 EXPECT_EQ(nullptr, b.get());
496 b.reset(strong->WeakRefAsSubclass<WeakSubclass>().release());
497 EXPECT_NE(nullptr, b.get());
498 }
499
TEST(WeakRefCountedPtr,EqualityWithWeakSubclass)500 TEST(WeakRefCountedPtr, EqualityWithWeakSubclass) {
501 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
502 WeakRefCountedPtr<WeakBaseClass> b = strong->WeakRef();
503 EXPECT_EQ(b, strong.get());
504 }
505
FunctionTakingWeakBaseClass(WeakRefCountedPtr<WeakBaseClass>)506 void FunctionTakingWeakBaseClass(WeakRefCountedPtr<WeakBaseClass>) {}
507
TEST(WeakRefCountedPtr,CanPassWeakSubclassToFunctionExpectingWeakBaseClass)508 TEST(WeakRefCountedPtr, CanPassWeakSubclassToFunctionExpectingWeakBaseClass) {
509 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
510 WeakRefCountedPtr<WeakSubclass> p = strong->WeakRefAsSubclass<WeakSubclass>();
511 FunctionTakingWeakBaseClass(p);
512 }
513
FunctionTakingWeakSubclass(WeakRefCountedPtr<WeakSubclass>)514 void FunctionTakingWeakSubclass(WeakRefCountedPtr<WeakSubclass>) {}
515
TEST(WeakRefCountedPtr,CanPassWeakSubclassToFunctionExpectingWeakSubclass)516 TEST(WeakRefCountedPtr, CanPassWeakSubclassToFunctionExpectingWeakSubclass) {
517 RefCountedPtr<WeakSubclass> strong(new WeakSubclass());
518 WeakRefCountedPtr<WeakSubclass> p = strong->WeakRefAsSubclass<WeakSubclass>();
519 FunctionTakingWeakSubclass(p);
520 }
521
TEST(WeakRefCountedPtr,TakeAsSubclass)522 TEST(WeakRefCountedPtr, TakeAsSubclass) {
523 RefCountedPtr<WeakBaseClass> strong = MakeRefCounted<WeakSubclass>();
524 WeakRefCountedPtr<WeakBaseClass> p = strong->WeakRef();
525 WeakRefCountedPtr<WeakSubclass> s = p.TakeAsSubclass<WeakSubclass>();
526 EXPECT_EQ(p.get(), nullptr);
527 EXPECT_NE(s.get(), nullptr);
528 }
529
530 //
531 // tests for absl hash integration
532 //
533
TEST(AbslHashIntegration,RefCountedPtr)534 TEST(AbslHashIntegration, RefCountedPtr) {
535 absl::flat_hash_set<RefCountedPtr<Foo>> set;
536 auto p = MakeRefCounted<Foo>(5);
537 set.insert(p);
538 auto it = set.find(p);
539 ASSERT_NE(it, set.end());
540 EXPECT_EQ(*it, p);
541 }
542
TEST(AbslHashIntegration,WeakRefCountedPtr)543 TEST(AbslHashIntegration, WeakRefCountedPtr) {
544 absl::flat_hash_set<WeakRefCountedPtr<Bar>> set;
545 auto p = MakeRefCounted<Bar>(5);
546 auto q = p->WeakRef();
547 set.insert(q);
548 auto it = set.find(q);
549 ASSERT_NE(it, set.end());
550 EXPECT_EQ(*it, q);
551 }
552
TEST(AbslHashIntegration,RefCountedPtrHeterogenousLookup)553 TEST(AbslHashIntegration, RefCountedPtrHeterogenousLookup) {
554 absl::flat_hash_set<RefCountedPtr<Bar>, RefCountedPtrHash<Bar>,
555 RefCountedPtrEq<Bar>>
556 set;
557 auto p = MakeRefCounted<Bar>(5);
558 set.insert(p);
559 auto it = set.find(p);
560 ASSERT_NE(it, set.end());
561 EXPECT_EQ(*it, p);
562 auto q = p->WeakRef();
563 it = set.find(q);
564 ASSERT_NE(it, set.end());
565 EXPECT_EQ(*it, p);
566 it = set.find(p.get());
567 ASSERT_NE(it, set.end());
568 EXPECT_EQ(*it, p);
569 }
570
TEST(AbslHashIntegration,WeakRefCountedPtrHeterogenousLookup)571 TEST(AbslHashIntegration, WeakRefCountedPtrHeterogenousLookup) {
572 absl::flat_hash_set<WeakRefCountedPtr<Bar>, RefCountedPtrHash<Bar>,
573 RefCountedPtrEq<Bar>>
574 set;
575 auto p = MakeRefCounted<Bar>(5);
576 auto q = p->WeakRef();
577 set.insert(q);
578 auto it = set.find(q);
579 ASSERT_NE(it, set.end());
580 EXPECT_EQ(*it, q);
581 it = set.find(p);
582 ASSERT_NE(it, set.end());
583 EXPECT_EQ(*it, q);
584 it = set.find(p.get());
585 ASSERT_NE(it, set.end());
586 EXPECT_EQ(*it, q);
587 }
588
589 } // namespace
590 } // namespace testing
591 } // namespace grpc_core
592
main(int argc,char ** argv)593 int main(int argc, char** argv) {
594 grpc::testing::TestEnvironment env(&argc, argv);
595 ::testing::InitGoogleTest(&argc, argv);
596 return RUN_ALL_TESTS();
597 }
598