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