xref: /aosp_15_r20/external/grpc-grpc/test/core/gprpp/orphanable_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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