• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "core/fxcrt/autorestorer.h"
6 #include "core/fxcrt/retain_ptr.h"
7 #include "core/fxcrt/unowned_ptr.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "testing/pseudo_retainable.h"
10 
TEST(fxcrt,AutoRestorer)11 TEST(fxcrt, AutoRestorer) {
12   int x = 5;
13   {
14     AutoRestorer<int> restorer(&x);
15     x = 6;
16     EXPECT_EQ(6, x);
17   }
18   EXPECT_EQ(5, x);
19 }
20 
TEST(fxcrt,AutoRestorerNoOp)21 TEST(fxcrt, AutoRestorerNoOp) {
22   int x = 5;
23   {
24     AutoRestorer<int> restorer(&x);
25     EXPECT_EQ(5, x);
26   }
27   EXPECT_EQ(5, x);
28 }
29 
TEST(fxcrt,AutoRestorerAbandon)30 TEST(fxcrt, AutoRestorerAbandon) {
31   int x = 5;
32   {
33     AutoRestorer<int> restorer(&x);
34     x = 6;
35     EXPECT_EQ(6, x);
36     restorer.AbandonRestoration();
37   }
38   EXPECT_EQ(6, x);
39 }
40 
TEST(fxcrt,AutoRestorerUnownedPtr)41 TEST(fxcrt, AutoRestorerUnownedPtr) {
42   int x = 5;
43   int y = 6;
44   UnownedPtr<int> ptr(&x);
45   {
46     AutoRestorer<UnownedPtr<int>> restorer(&ptr);
47     ptr = &y;
48     EXPECT_EQ(&y, ptr);
49   }
50   EXPECT_EQ(&x, ptr);
51 }
52 
TEST(fxcrt,AutoRestorerUnownedNoOp)53 TEST(fxcrt, AutoRestorerUnownedNoOp) {
54   int x = 5;
55   UnownedPtr<int> ptr(&x);
56   {
57     AutoRestorer<UnownedPtr<int>> restorer(&ptr);
58     EXPECT_EQ(&x, ptr);
59   }
60   EXPECT_EQ(&x, ptr);
61 }
62 
TEST(fxcrt,AutoRestorerUnownedPtrAbandon)63 TEST(fxcrt, AutoRestorerUnownedPtrAbandon) {
64   int x = 5;
65   int y = 6;
66   UnownedPtr<int> ptr(&x);
67   {
68     AutoRestorer<UnownedPtr<int>> restorer(&ptr);
69     ptr = &y;
70     EXPECT_EQ(&y, ptr);
71     restorer.AbandonRestoration();
72   }
73   EXPECT_EQ(&y, ptr);
74 }
75 
TEST(fxcrt,AutoRestorerRetainPtr)76 TEST(fxcrt, AutoRestorerRetainPtr) {
77   PseudoRetainable obj1;
78   PseudoRetainable obj2;
79   RetainPtr<PseudoRetainable> ptr(&obj1);
80   EXPECT_EQ(1, obj1.retain_count());
81   EXPECT_EQ(0, obj1.release_count());
82   {
83     AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
84     // |obj1| is kept alive by restorer in case it need to be restored.
85     EXPECT_EQ(2, obj1.retain_count());
86     EXPECT_EQ(0, obj1.release_count());
87     ptr.Reset(&obj2);
88     EXPECT_EQ(&obj2, ptr.Get());
89 
90     // |obj1| released by |ptr| assignment.
91     EXPECT_TRUE(obj1.alive());
92     EXPECT_EQ(2, obj1.retain_count());
93     EXPECT_EQ(1, obj1.release_count());
94 
95     // |obj2| now kept alive by |ptr|.
96     EXPECT_TRUE(obj1.alive());
97     EXPECT_EQ(1, obj2.retain_count());
98     EXPECT_EQ(0, obj2.release_count());
99   }
100   EXPECT_EQ(&obj1, ptr.Get());
101 
102   // |obj1| now kept alive again by |ptr|.
103   EXPECT_TRUE(obj1.alive());
104   EXPECT_EQ(3, obj1.retain_count());
105   EXPECT_EQ(2, obj1.release_count());
106 
107   // |obj2| dead.
108   EXPECT_FALSE(obj2.alive());
109   EXPECT_EQ(1, obj2.retain_count());
110   EXPECT_EQ(1, obj2.release_count());
111 }
112 
TEST(fxcrt,AutoRestorerRetainPtrNoOp)113 TEST(fxcrt, AutoRestorerRetainPtrNoOp) {
114   PseudoRetainable obj1;
115   RetainPtr<PseudoRetainable> ptr(&obj1);
116   EXPECT_EQ(1, obj1.retain_count());
117   EXPECT_EQ(0, obj1.release_count());
118   {
119     AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
120     EXPECT_EQ(2, obj1.retain_count());
121     EXPECT_EQ(0, obj1.release_count());
122   }
123   EXPECT_EQ(&obj1, ptr.Get());
124 
125   // Self-reassignement avoided ref churn.
126   EXPECT_TRUE(obj1.alive());
127   EXPECT_EQ(2, obj1.retain_count());
128   EXPECT_EQ(1, obj1.release_count());
129 }
130 
TEST(fxcrt,AutoRestorerRetainPtrAbandon)131 TEST(fxcrt, AutoRestorerRetainPtrAbandon) {
132   PseudoRetainable obj1;
133   PseudoRetainable obj2;
134   RetainPtr<PseudoRetainable> ptr(&obj1);
135   EXPECT_EQ(1, obj1.retain_count());
136   EXPECT_EQ(0, obj1.release_count());
137   {
138     AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
139     // |obj1| is kept alive by restorer in case it need to be restored.
140     EXPECT_EQ(2, obj1.retain_count());
141     EXPECT_EQ(0, obj1.release_count());
142     ptr.Reset(&obj2);
143     EXPECT_EQ(&obj2, ptr.Get());
144 
145     // |obj1| released by |ptr| assignment.
146     EXPECT_EQ(2, obj1.retain_count());
147     EXPECT_EQ(1, obj1.release_count());
148 
149     // |obj2| now kept alive by |ptr|.
150     EXPECT_EQ(1, obj2.retain_count());
151     EXPECT_EQ(0, obj2.release_count());
152 
153     restorer.AbandonRestoration();
154   }
155   EXPECT_EQ(&obj2, ptr.Get());
156 
157   // |obj1| now dead as a result of abandonment.
158   EXPECT_FALSE(obj1.alive());
159   EXPECT_EQ(2, obj1.retain_count());
160   EXPECT_EQ(2, obj1.release_count());
161 
162   // |obj2| kept alive by |ptr|.
163   EXPECT_TRUE(obj2.alive());
164   EXPECT_EQ(1, obj2.retain_count());
165   EXPECT_EQ(0, obj2.release_count());
166 }
167