• 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/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