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/orphanable.h"
20
21 #include "gtest/gtest.h"
22
23 #include "test/core/util/test_config.h"
24
25 namespace grpc_core {
26 namespace testing {
27 namespace {
28
29 class Foo : public Orphanable {
30 public:
Foo()31 Foo() : Foo(0) {}
Foo(int value)32 explicit Foo(int value) : value_(value) {}
Orphan()33 void Orphan() override { delete this; }
value() const34 int value() const { return value_; }
35
36 private:
37 int value_;
38 };
39
TEST(Orphanable,Basic)40 TEST(Orphanable, Basic) {
41 Foo* foo = new Foo();
42 foo->Orphan();
43 }
44
TEST(OrphanablePtr,Basic)45 TEST(OrphanablePtr, Basic) {
46 OrphanablePtr<Foo> foo(new Foo());
47 EXPECT_EQ(0, foo->value());
48 }
49
TEST(MakeOrphanable,DefaultConstructor)50 TEST(MakeOrphanable, DefaultConstructor) {
51 auto foo = MakeOrphanable<Foo>();
52 EXPECT_EQ(0, foo->value());
53 }
54
TEST(MakeOrphanable,WithParameters)55 TEST(MakeOrphanable, WithParameters) {
56 auto foo = MakeOrphanable<Foo>(5);
57 EXPECT_EQ(5, foo->value());
58 }
59
60 class Bar : public InternallyRefCounted<Bar> {
61 public:
Bar()62 Bar() : Bar(0) {}
Bar(int value)63 explicit Bar(int value) : value_(value) {}
Orphan()64 void Orphan() override { Unref(); }
value() const65 int value() const { return value_; }
66
StartWork()67 void StartWork() { self_ref_ = Ref(); }
FinishWork()68 void FinishWork() { self_ref_.reset(); }
69
70 private:
71 int value_;
72 RefCountedPtr<Bar> self_ref_;
73 };
74
TEST(OrphanablePtr,InternallyRefCounted)75 TEST(OrphanablePtr, InternallyRefCounted) {
76 auto bar = MakeOrphanable<Bar>();
77 bar->StartWork();
78 bar->FinishWork();
79 }
80
TEST(OrphanablePtr,InternallyRefCountedRefAsSubclass)81 TEST(OrphanablePtr, InternallyRefCountedRefAsSubclass) {
82 class Subclass : public Bar {
83 public:
84 void StartWork() { self_ref_ = RefAsSubclass<Subclass>(); }
85 void FinishWork() { self_ref_.reset(); }
86
87 private:
88 RefCountedPtr<Subclass> self_ref_;
89 };
90 auto bar = MakeOrphanable<Subclass>();
91 bar->StartWork();
92 bar->FinishWork();
93 }
94
95 class Baz : public InternallyRefCounted<Baz> {
96 public:
Baz()97 Baz() : Baz(0) {}
Baz(int value)98 explicit Baz(int value) : InternallyRefCounted<Baz>("Baz"), value_(value) {}
Orphan()99 void Orphan() override { Unref(); }
value() const100 int value() const { return value_; }
101
StartWork()102 void StartWork() { self_ref_ = Ref(DEBUG_LOCATION, "work"); }
FinishWork()103 void FinishWork() {
104 // This is a little ugly, but it makes the logged ref and unref match up.
105 self_ref_.release();
106 Unref(DEBUG_LOCATION, "work");
107 }
108
109 private:
110 int value_;
111 RefCountedPtr<Baz> self_ref_;
112 };
113
TEST(OrphanablePtr,InternallyRefCountedWithTracing)114 TEST(OrphanablePtr, InternallyRefCountedWithTracing) {
115 auto baz = MakeOrphanable<Baz>();
116 baz->StartWork();
117 baz->FinishWork();
118 }
119
120 class Qux : public InternallyRefCounted<Qux> {
121 public:
Qux()122 Qux() : Qux(0) {}
Qux(int value)123 explicit Qux(int value) : InternallyRefCounted<Qux>("Qux"), value_(value) {}
~Qux()124 ~Qux() override { self_ref_ = RefIfNonZero(DEBUG_LOCATION, "extra_work"); }
Orphan()125 void Orphan() override { Unref(); }
value() const126 int value() const { return value_; }
127
StartWork()128 void StartWork() { self_ref_ = RefIfNonZero(DEBUG_LOCATION, "work"); }
FinishWork()129 void FinishWork() {
130 // This is a little ugly, but it makes the logged ref and unref match up.
131 self_ref_.release();
132 Unref(DEBUG_LOCATION, "work");
133 }
134
135 private:
136 int value_;
137 RefCountedPtr<Qux> self_ref_;
138 };
139
TEST(OrphanablePtr,InternallyRefCountedIfNonZero)140 TEST(OrphanablePtr, InternallyRefCountedIfNonZero) {
141 auto qux = MakeOrphanable<Qux>();
142 qux->StartWork();
143 qux->FinishWork();
144 }
145
146 } // namespace
147 } // namespace testing
148 } // namespace grpc_core
149
main(int argc,char ** argv)150 int main(int argc, char** argv) {
151 grpc::testing::TestEnvironment env(&argc, argv);
152 ::testing::InitGoogleTest(&argc, argv);
153 return RUN_ALL_TESTS();
154 }
155